-
Daniel Göbel authoredDaniel Göbel authored
users.ts 5.81 KiB
import { defineStore } from "pinia";
import type { UserOutExtended, UserOut, UserIn } from "@/client";
import { OpenAPI, UserService, RoleEnum } from "@/client";
import { useWorkflowExecutionStore } from "@/stores/workflowExecutions";
import { useBucketStore } from "@/stores/buckets";
import { useWorkflowStore } from "@/stores/workflows";
import { useS3KeyStore } from "@/stores/s3keys";
import { useS3ObjectStore } from "@/stores/s3objects";
import { clear as dbclear } from "idb-keyval";
import { useNameStore } from "@/stores/names";
type DecodedToken = {
exp: number;
iss: string;
sub: string;
};
function parseJwt(token: string): DecodedToken {
const base64Url = token.split(".")[1];
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
const jsonPayload = decodeURIComponent(
window
.atob(base64)
.split("")
.map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join(""),
);
return JSON.parse(jsonPayload) as DecodedToken;
}
export const useUserStore = defineStore({
id: "user",
state: () =>
({
token: null,
decodedToken: null,
user: null,
}) as {
token: string | null;
decodedToken: DecodedToken | null;
user: UserOutExtended | null;
},
getters: {
roles(): string[] {
return this.user?.roles?.map((role) => role.toString()) ?? [];
},
authenticated: (state) => state.token != null,
currentUID(): string {
return this.user?.uid ?? this.decodedToken?.["sub"] ?? "";
},
foreignUser: (state) => (state.user?.roles ?? []).length == 0,
normalUser: (state) => state.user?.roles.includes(RoleEnum.USER) ?? false,
rewiewer: (state) => state.user?.roles.includes(RoleEnum.REVIEWER) ?? false,
workflowDev: (state) =>
state.user?.roles.includes(RoleEnum.DEVELOPER) ?? false,
resourceMaintainer: (state) =>
state.user?.roles.includes(RoleEnum.DB_MAINTAINER) ?? false,
admin: (state) =>
state.user?.roles.includes(RoleEnum.ADMINISTRATOR) ?? false,
},
actions: {
setToken(token: string | null) {
if (token != null) {
this.token = token;
this.decodedToken = parseJwt(token);
OpenAPI.TOKEN = token;
UserService.userGetLoggedInUser()
.then((user) => {
this.updateUser(user);
})
.catch(() => {
this.token = null;
});
} else {
this.logout();
}
},
updateUser(user: UserOutExtended) {
this.user = user;
useNameStore().addNameToMapping(user.uid, user.display_name);
},
logout() {
window._paq.push(["resetUserId"]);
OpenAPI.TOKEN = undefined;
this.$reset();
localStorage.clear();
dbclear();
useWorkflowExecutionStore().$reset();
useBucketStore().$reset();
useWorkflowStore().$reset();
useS3KeyStore().$reset();
useS3ObjectStore().$reset();
},
fetchUsers(
searchString?: string,
filterRoles?: RoleEnum[],
): Promise<UserOutExtended[]> {
return UserService.userListUsers(searchString, filterRoles).then(
(users) => {
const nameStore = useNameStore();
for (const user of users) {
nameStore.addNameToMapping(user.uid, user.display_name);
}
return users;
},
);
},
updateUserRoles(uid: string, roles: RoleEnum[]): Promise<UserOutExtended> {
return UserService.userUpdateRoles(uid, {
roles: roles,
});
},
inviteUser(userIn: UserIn): Promise<UserOutExtended> {
return UserService.userCreateUser(userIn).then((user) => {
useNameStore().addNameToMapping(user.uid, user.display_name);
return user;
});
},
resendInvitationEmail(uid: string): Promise<UserOutExtended> {
return UserService.userResendInvitation(uid).then((user) => {
useNameStore().addNameToMapping(user.uid, user.display_name);
return user;
});
},
searchUser(searchString: string): Promise<UserOut[]> {
return UserService.userSearchUsers(searchString).then((users) => {
const nameStore = useNameStore();
for (const user of users) {
nameStore.addNameToMapping(user.uid, user.display_name);
}
return users;
});
},
async fetchUsernames(uids: string[]): Promise<string[]> {
const nameStore = useNameStore();
const filteredIds = uids
.filter((uid) => !nameStore.getName(uid)) // filter already present UIDs
.filter(
// filter unique UIDs
(modeId, index, array) =>
array.findIndex((val) => val === modeId) === index,
);
// If all uids are already in the store, then return them
if (filteredIds.length === 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return uids.map((uid) => nameStore.getName(uid)!);
}
const missingIds: string[] = [];
const storedNames = filteredIds.map((uid) => localStorage.getItem(uid));
for (const index in storedNames) {
// if uid was not cached, mark it to fetch it from backend
if (storedNames[index] == null) {
missingIds.push(filteredIds[index]);
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
nameStore.addNameToMapping(filteredIds[index], storedNames[index]!);
}
}
// fetch missing users from backend
const fetchedUsers = await Promise.all(
missingIds.map((uid) => UserService.userGetUser(uid)),
);
// Put users in store
for (const user of fetchedUsers) {
nameStore.addNameToMapping(user.uid, user.display_name);
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return uids.map((uid) => nameStore.getName(uid)!);
},
},
});