/
auth.services.ts
110 lines (85 loc) · 3.08 KB
/
auth.services.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { Identity } from "@dfinity/agent";
import { get } from "svelte/store";
import { authStore } from "../stores/auth.store";
import { themeStore } from "../stores/theme.store";
import { toastsStore } from "../stores/toasts.store";
import type { ToastLevel, ToastMsg } from "../types/toast";
import { replaceHistory } from "../utils/route.utils";
const msgParam: string = "msg";
const levelParam: string = "level";
export const logout = async ({
msg = undefined,
}: {
msg?: Pick<ToastMsg, "labelKey" | "level">;
}) => {
await authStore.signOut();
if (msg) {
appendMsgToUrl(msg);
}
// We preserve the anonymous theme information only so that user sign-in with same theme next time
const { theme: storageTheme }: Storage = localStorage;
window.localStorage.clear();
themeStore.select(storageTheme);
// We reload the page to make sure all the states are cleared
window.location.reload();
};
/**
* Provide the identity that has been authorized.
* If none is provided logout the user automatically. Services that are using this getter need an identity no matter what.
*/
export const getIdentity = async (): Promise<Identity> => {
/* eslint-disable-next-line no-async-promise-executor */
return new Promise<Identity>(async (resolve) => {
const identity: Identity | undefined | null = get(authStore).identity;
if (!identity) {
await logout({
msg: { labelKey: "error.missing_identity", level: "error" },
});
// We do not resolve on purpose. logout() does reload the browser
return;
}
resolve(identity);
});
};
/**
* If a message was provided to the logout process - e.g. a message informing the logout happened because the session timedout - append the information to the url as query params
*/
const appendMsgToUrl = (msg: Pick<ToastMsg, "labelKey" | "level">) => {
const { labelKey, level } = msg;
const urlParams: URLSearchParams = new URLSearchParams(
window.location.search
);
urlParams.append(msgParam, encodeURI(labelKey));
urlParams.append(levelParam, level);
updateAuthUrl(urlParams);
};
/**
* If the url contains a msg that has been provided on logout, display it as a toast message. Cleanup url afterwards - we don't want the user to see the message again if reloads the browser
*/
export const displayAndCleanLogoutMsg = () => {
const urlParams: URLSearchParams = new URLSearchParams(
window.location.search
);
const msg: string | null = urlParams.get(msgParam);
if (msg === null) {
return;
}
// For simplicity reason we assume the level pass as query params is one of the type ToastLevel
const level: ToastLevel =
(urlParams.get(levelParam) as ToastLevel | null) ?? "success";
toastsStore.show({ labelKey: msg, level });
cleanUpMsgUrl();
};
const cleanUpMsgUrl = () => {
const urlParams: URLSearchParams = new URLSearchParams(
window.location.search
);
urlParams.delete(msgParam);
urlParams.delete(levelParam);
updateAuthUrl(urlParams);
};
const updateAuthUrl = (urlParams: URLSearchParams) =>
replaceHistory({
path: "/",
query: urlParams.toString(),
});