flaschengeist-frontend/api/src/stores/main.ts

157 lines
4.5 KiB
TypeScript

import { LocalStorage, SessionStorage } from 'quasar';
import { FG_Plugin } from '@flaschengeist/types';
import { fixSession, useSessionStore, useUserStore } from '.';
import { AxiosResponse } from 'axios';
import { api } from '../internal';
import { defineStore } from 'pinia';
function loadCurrentSession() {
const session = LocalStorage.getItem<FG.Session>('session');
if (session) session.expires = new Date(session.expires);
return session || undefined;
}
function loadUser() {
const user = SessionStorage.getItem<FG.User>('user');
if (user && user.birthday) user.birthday = new Date(user.birthday);
return user || undefined;
}
export const useMainStore = defineStore({
id: 'main',
state: () => ({
session: loadCurrentSession(),
user: loadUser(),
notifications: [] as Array<FG_Plugin.Notification>,
shortcuts: [] as Array<FG_Plugin.MenuLink>,
}),
getters: {
loggedIn(): boolean {
return this.session !== undefined;
},
currentUser(): FG.User {
if (this.user === undefined) throw 'Not logged in, this should not be called';
return this.user;
},
permissions(): string[] {
return this.user?.permissions || [];
},
},
actions: {
/** Ininitalize store from saved session
* Updates session and loads current user
*/
async init() {
if (this.session) {
const sessionStore = useSessionStore();
const session = await sessionStore.getSession(this.session.token);
if (session) {
this.session = session;
const userStore = useUserStore();
const user = await userStore.getUser(this.session.userid);
if (user) {
this.user = user;
SessionStorage.set('user', user);
}
}
}
},
async login(userid: string, password: string) {
try {
const { data } = await api.post<FG.Session>('/auth', { userid, password });
this.session = fixSession(data);
return true;
} catch ({ response }) {
return (<AxiosResponse | undefined>response)?.status || false;
}
},
async logout() {
if (!this.session || !this.session.token) return false;
try {
const token = this.session.token;
await api.delete(`/auth/${token}`);
} catch (error) {
return false;
} finally {
this.handleLoggedOut();
}
return true;
},
async requestReset(userid: string) {
return await api
.post('/auth/reset', { userid })
.then(() => true)
.catch(() => false);
},
async resetPassword(token: string, password: string) {
return await api
.post('/auth/reset', { token, password })
.then(() => true)
.catch(({ response }) =>
response && 'status' in response ? (<AxiosResponse>response).status : false
);
},
async loadNotifications(flaschengeist: FG_Plugin.Flaschengeist) {
const { data } = await api.get<FG.Notification[]>('/notifications', {
params:
this.notifications.length > 0
? { from: this.notifications[this.notifications.length - 1].time }
: {},
});
const notes = [] as FG_Plugin.Notification[];
data.forEach((n) => {
n.time = new Date(n.time);
const plugin = flaschengeist?.plugins.filter((p) => p.id === n.plugin)[0];
if (!plugin) console.debug('Could not find a parser for this notification', n);
else notes.push(plugin.notification(n));
});
this.notifications.push(...notes);
return notes;
},
async removeNotification(id: number) {
const idx = this.notifications.findIndex((n) => n.id === id);
if (idx >= 0)
try {
this.notifications.splice(idx, 1);
await api.delete(`/notifications/${id}`);
} catch (error) {
if (this.notifications.length > idx)
this.notifications.splice(idx, this.notifications.length - idx - 1);
}
},
async getShortcuts() {
const { data } = await api.get<Array<FG_Plugin.MenuLink>>(
`users/${this.currentUser.userid}/shortcuts`
);
this.shortcuts = data;
},
async setShortcuts() {
await api.put(`users/${this.currentUser.userid}/shortcuts`, this.shortcuts);
},
handleLoggedOut() {
LocalStorage.clear();
this.$patch({
session: undefined,
user: undefined,
});
SessionStorage.clear();
},
},
});
export default () => useMainStore;