From 9bd663f266d514b533d7a5558277c922c1f4ebd2 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 26 Apr 2025 09:21:27 +0200 Subject: [PATCH] base settings operations --- src/stores/admin/management/setting.ts | 53 ++++++++++++ src/types/settingTypes.ts | 80 +++++++++++++++++++ .../admin/management/setting/Setting.vue | 9 ++- 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/stores/admin/management/setting.ts create mode 100644 src/types/settingTypes.ts diff --git a/src/stores/admin/management/setting.ts b/src/stores/admin/management/setting.ts new file mode 100644 index 0000000..c57cf69 --- /dev/null +++ b/src/stores/admin/management/setting.ts @@ -0,0 +1,53 @@ +import { defineStore } from "pinia"; +import { http } from "@/serverCom"; +import { type SettingString, type SettingValueMapping } from "@/types/settingTypes"; +import type { AxiosResponse } from "axios"; + +export const useSettingStore = defineStore("setting", { + state: () => { + return { + settings: {} as { [key in SettingString]: SettingValueMapping[key] }, + loading: "loading" as "loading" | "fetched" | "failed", + }; + }, + getters: { + readSetting: + (state) => + (key: K): SettingValueMapping[K] => { + return state.settings[key]; + }, + }, + actions: { + fetchSettings() { + this.loading = "loading"; + http + .get("/admin/setting") + .then((result) => { + this.settings = result.data; + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + async getSetting(key: SettingString): Promise> { + return await http.get(`/admin/setting/${key}`).then((res) => { + //@ts-expect-error + this.settings[key] = res.data; + return res; + }); + }, + async updateSetting( + key: K, + val: SettingValueMapping[K] + ): Promise> { + return await http.put("/admin/setting", { + setting: key, + value: val, + }); + }, + async resetSetting(key: SettingString): Promise> { + return await http.delete(`/admin/setting/${key}`); + }, + }, +}); diff --git a/src/types/settingTypes.ts b/src/types/settingTypes.ts new file mode 100644 index 0000000..43d77a3 --- /dev/null +++ b/src/types/settingTypes.ts @@ -0,0 +1,80 @@ +export type SettingTopic = "club" | "app" | "session" | "mail" | "backup" | "security"; +export type SettingString = + | "club.icon" + | "club.logo" + | "club.name" + | "club.imprint" + | "club.privacy" + | "club.website" + | "app.custom_login_message" + | "app.show_link_to_calendar" + | "session.jwt_expiration" + | "session.refresh_expiration" + | "session.pwa_refresh_expiration" + | "mail.email" + | "mail.username" + | "mail.password" + | "mail.host" + | "mail.port" + | "mail.secure" + | "backup.interval" + | "backup.copies"; + +export type SettingTypeAtom = "longstring" | "string" | "ms" | "number" | "boolean" | "url" | "email"; +export type SettingType = SettingTypeAtom | `${SettingTypeAtom}/crypt` | `${SettingTypeAtom}/rand`; + +export type SettingValueMapping = { + "club.icon": string; + "club.logo": string; + "club.name": string; + "club.imprint": string; + "club.privacy": string; + "club.website": string; + "app.custom_login_message": string; + "app.show_link_to_calendar": boolean; + "session.jwt_expiration": string; + "session.refresh_expiration": string; + "session.pwa_refresh_expiration": string; + "mail.email": string; + "mail.username": string; + "mail.password": string; + "mail.host": string; + "mail.port": number; + "mail.secure": boolean; + "backup.interval": number; + "backup.copies": number; +}; + +// Typsicherer Zugriff auf Settings +export type SettingDefinition = { + type: T; + default?: string | number | boolean; + optional?: boolean; + min?: T extends "number" | `number/crypt` | `number/rand` ? number : never; +}; + +export type SettingsSchema = { + [key in SettingString]: SettingDefinition; +}; + +export const settingsType: SettingsSchema = { + "club.icon": { type: "string", optional: true }, + "club.logo": { type: "string", optional: true }, + "club.name": { type: "string", default: "FF Admin" }, + "club.imprint": { type: "url", optional: true }, + "club.privacy": { type: "url", optional: true }, + "club.website": { type: "url", optional: true }, + "app.custom_login_message": { type: "string", optional: true }, + "app.show_link_to_calendar": { type: "boolean", default: true }, + "session.jwt_expiration": { type: "ms", default: "15m" }, + "session.refresh_expiration": { type: "ms", default: "1d" }, + "session.pwa_refresh_expiration": { type: "ms", default: "5d" }, + "mail.email": { type: "email", optional: false }, + "mail.username": { type: "string", optional: false }, + "mail.password": { type: "string/crypt", optional: false }, + "mail.host": { type: "url", optional: false }, + "mail.port": { type: "number", default: 587 }, + "mail.secure": { type: "boolean", default: false }, + "backup.interval": { type: "number", default: 1, min: 1 }, + "backup.copies": { type: "number", default: 7, min: 1 }, +}; diff --git a/src/views/admin/management/setting/Setting.vue b/src/views/admin/management/setting/Setting.vue index 0577ce7..1911343 100644 --- a/src/views/admin/management/setting/Setting.vue +++ b/src/views/admin/management/setting/Setting.vue @@ -18,6 +18,7 @@ import { defineComponent } from "vue"; import { mapState, mapActions } from "pinia"; import MainTemplate from "@/templates/Main.vue"; import { useAbilityStore } from "@/stores/ability"; +import { useSettingStore } from "@/stores/admin/management/setting";