Files
Termix/src/backend/database/routes/credential-sidebar-preferences.ts
T

116 lines
4.0 KiB
TypeScript
Raw Normal View History

+5
2026-08-19 14:12:06 -05:00
import type { AuthenticatedRequest } from "../../../types/index.js";
import express, { type Request, type Response } from "express";
import { databaseLogger } from "../../utils/logger.js";
import { AuthManager } from "../../utils/auth-manager.js";
import { createCurrentCredentialSidebarPreferenceRepository } from "../repositories/factory.js";
import {
defaultCredentialSidebarPreferences,
sanitizeCredentialSidebarPreferences,
} from "../../../types/credential-sidebar-preferences.js";
const router = express.Router();
const authManager = AuthManager.getInstance();
const authenticateJWT = authManager.createAuthMiddleware();
/**
* @openapi
* /credential-sidebar/preferences:
* get:
* summary: Get the credential sidebar preferences for the current user
* description: Returns the current user's saved credential sidebar preferences (sort, filters, open folders, display settings). Unlike /host-sidebar/preferences, there is no legacy-column migration to perform here — credentials never had exploded preference columns on userPreferences — so a first-time GET simply returns the defaults without writing a row; a row is only created once the user actually changes something via PUT.
* tags:
* - Credential Sidebar
* responses:
* 200:
* description: The current user's credential sidebar preferences.
*/
router.get("/", authenticateJWT, async (req: Request, res: Response) => {
const userId = (req as AuthenticatedRequest).userId;
try {
const existing =
await createCurrentCredentialSidebarPreferenceRepository().findByUserId(
userId,
);
if (existing) {
const preferences = sanitizeCredentialSidebarPreferences(
JSON.parse(existing.data),
);
return res.json({ preferences });
}
return res.json({ preferences: defaultCredentialSidebarPreferences() });
} catch (e) {
databaseLogger.error("Failed to get credential sidebar preferences", e, {
operation: "get_credential_sidebar_preferences",
userId,
});
return res
.status(500)
.json({ error: "Failed to get credential sidebar preferences" });
}
});
/**
* @openapi
* /credential-sidebar/preferences:
* put:
* summary: Update the credential sidebar preferences for the current user
* description: Persists the current user's credential sidebar preferences (sort, filters, open folders, display settings) as a single JSON document.
* tags:
* - Credential Sidebar
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* responses:
* 200:
* description: Preferences updated successfully.
* 400:
* description: Invalid preferences payload.
*/
router.put("/", authenticateJWT, async (req: Request, res: Response) => {
const userId = (req as AuthenticatedRequest).userId;
if (!req.body || typeof req.body !== "object") {
return res.status(400).json({ error: "Invalid preferences payload" });
}
try {
const existing =
await createCurrentCredentialSidebarPreferenceRepository().findByUserId(
userId,
);
const base = existing
? sanitizeCredentialSidebarPreferences(JSON.parse(existing.data))
: defaultCredentialSidebarPreferences();
const merged = sanitizeCredentialSidebarPreferences({
...base,
...req.body,
display: { ...base.display, ...(req.body.display ?? {}) },
sort: { ...base.sort, ...(req.body.sort ?? {}) },
filters: { ...base.filters, ...(req.body.filters ?? {}) },
});
await createCurrentCredentialSidebarPreferenceRepository().upsert(
userId,
JSON.stringify(merged),
);
return res.json({ success: true, preferences: merged });
} catch (e) {
databaseLogger.error("Failed to update credential sidebar preferences", e, {
operation: "update_credential_sidebar_preferences",
userId,
});
return res
.status(500)
.json({ error: "Failed to update credential sidebar preferences" });
}
});
export default router;