From c05d9a3adc244c5ad186d951b782aa9445c5ef09 Mon Sep 17 00:00:00 2001 From: alexa Date: Sat, 8 Jun 2024 12:12:47 +0200 Subject: [PATCH] save settings to db --- src/enums/settings.ts | 7 ++++ src/features/authentication/endpoints.ts | 36 ++++++++++++++++++ src/features/authenticationFeature.ts | 1 + src/features/database/mariaDbDatabase.ts | 10 ++++- src/models/ownUser.ts | 3 ++ src/swagger.ts | 47 ++++++++++++++++++++++++ tools/apiBuilder.mjs | 2 +- 7 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/enums/settings.ts diff --git a/src/enums/settings.ts b/src/enums/settings.ts new file mode 100644 index 0000000..c21b028 --- /dev/null +++ b/src/enums/settings.ts @@ -0,0 +1,7 @@ +export enum Settings { + notifications = "notifications", + systemNotifications = "systemNotifications", + sound = "sound", + currentSound = "currentSound", + currentCallSound = "currentCallSound", +} \ No newline at end of file diff --git a/src/features/authentication/endpoints.ts b/src/features/authentication/endpoints.ts index ef1177d..c385f7d 100644 --- a/src/features/authentication/endpoints.ts +++ b/src/features/authentication/endpoints.ts @@ -11,6 +11,7 @@ import Jimp from "jimp"; import {OwnUser} from "../../models/ownUser"; import {AdminPanelUser} from "../../models/adminPanelUser"; import {DefaultRoles} from "../../enums/defaultRoles"; +import {Settings} from "../../enums/settings"; export class AuthEndpoints { static logout(): (arg0: Request, arg1: Response) => void { @@ -44,6 +45,14 @@ export class AuthEndpoints { permissions = []; } user.permissions = permissions; + const rows = await db.getUserSettings(user.id); + if (rows) { + // @ts-ignore + user.settings = {}; + for (const row of rows) { + user.settings[row.settingKey] = row.value; + } + } res.send({ user }); }; @@ -521,6 +530,33 @@ export class AuthEndpoints { } } + static updateSetting(db: MariaDbDatabase) { + return async (req: Request, res: Response) => { + const user = req.user as User; + let {setting, value} = req.body; + if (!setting || value === null || value === undefined) { + res.status(400).send({error: "setting and value are required"}); + return; + } + + if (!Object.values(Settings).includes(setting)) { + res.status(400).send({error: `Invalid setting, must be one of ${Object.values(Settings).join(", ")}`}); + return; + } + + if (value === true) { + value = "true"; + } + if (value === false) { + value = "false"; + } + + CLI.debug(`Updating setting ${setting} to ${value} for user ${user.id}`); + await db.updateUserSetting(user.id, setting, value); + res.send({message: "Setting updated successfully"}); + } + } + static getConnectionSid() { return (req: Request, res: Response) => { let connectSid = req.headers.cookie?.split(';').find((c: string) => c.trim().startsWith('connect.sid=')); diff --git a/src/features/authenticationFeature.ts b/src/features/authenticationFeature.ts index b91e207..eb3d6ea 100644 --- a/src/features/authenticationFeature.ts +++ b/src/features/authenticationFeature.ts @@ -53,6 +53,7 @@ export class AuthenticationFeature { app.patch(`${prefix}/updateUser`, AuthActions.checkAuthenticated, AuthEndpoints.updateUser(db)); app.post(`${prefix}/updateAvatar`, AuthActions.checkAuthenticated, AuthEndpoints.updateAvatar(db)); app.delete(`${prefix}/deleteUser`, AuthActions.checkAuthenticated, AuthEndpoints.deleteUser(db)); + app.patch(`${prefix}/updateSetting`, AuthActions.checkAuthenticated, AuthEndpoints.updateSetting(db)); app.get(`${prefix}/getConnectionSid`, AuthActions.checkAuthenticated, AuthEndpoints.getConnectionSid()); // Permissions and roles diff --git a/src/features/database/mariaDbDatabase.ts b/src/features/database/mariaDbDatabase.ts index 867a7c3..35f6a56 100644 --- a/src/features/database/mariaDbDatabase.ts +++ b/src/features/database/mariaDbDatabase.ts @@ -10,7 +10,7 @@ import { Reaction, ReactionGroup, Role, - User + User, UserSetting } from "./models"; import {SafeUser} from "../../models/safeUser"; @@ -317,4 +317,12 @@ WHERE ur.userId = ?`, [userId]); async removeReaction(userId: Id, messageId: Id, reactionId: Id) { await this.query("DELETE FROM venel.messageReactions WHERE userId = ? AND messageId = ? AND reactionId = ?", [userId, messageId, reactionId]); } + + async updateUserSetting(id: Id, setting: string, value: string) { + await this.query("INSERT INTO venel.userSettings (userId, settingKey, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?", [id, setting, value, value]); + } + + async getUserSettings(id: Id): Promise { + return await this.query("SELECT * FROM venel.userSettings WHERE userId = ?", [id]); + } } \ No newline at end of file diff --git a/src/models/ownUser.ts b/src/models/ownUser.ts index dd64292..a61267c 100644 --- a/src/models/ownUser.ts +++ b/src/models/ownUser.ts @@ -3,4 +3,7 @@ import {Permission, Role, User} from "../features/database/models"; export interface OwnUser extends User { 'roles': Role[]; 'permissions': Permission[]; + 'settings': { + [key: string]: any; + } } \ No newline at end of file diff --git a/src/swagger.ts b/src/swagger.ts index 76e319e..1cbe6af 100644 --- a/src/swagger.ts +++ b/src/swagger.ts @@ -377,6 +377,53 @@ export const swaggerOptions = { ] } }, + "/api/auth/updateSetting": { + patch: { + summary: "Update a user's setting", + tags: [ + "User Management" + ], + description: "Update a user's setting", + requestBody: { + description: "Setting's entity", + required: true, + content: { + "application/json": { + schema: { + type: "object", + required: [ + "setting", + "value" + ], + properties: { + setting: { + type: "string", + description: "The setting to update" + }, + value: { + type: "string", + description: "The new value for the setting" + } + } + } + } + } + }, + responses: { + 200: { + description: "Setting updated successfully" + }, + 401: { + description: "Unauthorized" + } + }, + security: [ + { + cookieAuth: [] + } + ] + } + }, "/api/auth/roles": { get: { summary: "Get a list of roles", diff --git a/tools/apiBuilder.mjs b/tools/apiBuilder.mjs index a3ce441..a85bf35 100644 --- a/tools/apiBuilder.mjs +++ b/tools/apiBuilder.mjs @@ -1,5 +1,5 @@ import fs from "fs"; -import {swaggerOptions} from "../src/swagger.ts"; +import {swaggerOptions} from "../src/swagger.js"; const start = `import {ApiBase} from "./ApiBase.mjs";