aboutsummaryrefslogtreecommitdiffstats
path: root/code/frontend/src/services/account-service.ts
diff options
context:
space:
mode:
authorivar <i@oiee.no>2024-04-28 22:37:30 +0200
committerivar <i@oiee.no>2024-04-28 22:37:30 +0200
commitced66c5807575cd29f6aa5632e8ad02b38c8448a (patch)
tree01760648ee293a2aef2288328014b5747d2192b4 /code/frontend/src/services/account-service.ts
parent691ad60d7bff5934053d87267c4e303ef3ed5f97 (diff)
downloadgreatoffice-ced66c5807575cd29f6aa5632e8ad02b38c8448a.tar.xz
greatoffice-ced66c5807575cd29f6aa5632e8ad02b38c8448a.zip
WIP new frontend
Diffstat (limited to 'code/frontend/src/services/account-service.ts')
-rw-r--r--code/frontend/src/services/account-service.ts123
1 files changed, 123 insertions, 0 deletions
diff --git a/code/frontend/src/services/account-service.ts b/code/frontend/src/services/account-service.ts
new file mode 100644
index 0000000..96e75f5
--- /dev/null
+++ b/code/frontend/src/services/account-service.ts
@@ -0,0 +1,123 @@
+import {http_delete_async, http_get_async, http_post_async} from "$utils/_fetch";
+import {browser} from "$app/environment";
+import {api_base, CookieNames, StorageKeys} from "$configuration";
+import {is_known_problem} from "$models/internal/KnownProblem";
+import {StoreType, create_writable_persistent} from "$utils/persistent-store";
+import {get} from "svelte/store";
+import type {Writable} from "svelte/store";
+import {Temporal} from "temporal-polyfill";
+import type {
+ CreateAccountPayload,
+ CreateAccountResponse,
+ DeleteAccountResponse,
+ IAccountService,
+ LoginPayload,
+ LoginResponse,
+ Session,
+ UpdateAccountPayload,
+ UpdateAccountResponse,
+} from "./abstractions/IAccountService";
+
+export class AccountService implements IAccountService {
+ session: Writable<Session> | undefined;
+ private sessionCooldown = 3600;
+
+ constructor() {
+ if (browser) {
+ this.session = create_writable_persistent({
+ name: StorageKeys.session,
+ initialState: {} as Session,
+ options: {
+ store: StoreType.LOCAL,
+ },
+ });
+ this.refresh_session();
+ } else {
+ this.session = undefined;
+ }
+ }
+
+ static resolve(): IAccountService {
+ return new AccountService();
+ }
+
+ async refresh_session(forceRefresh: boolean = false): Promise<void> {
+ if (!this.session) return;
+ const currentValue = get(this.session);
+ const currentEpoch = Temporal.Now.instant().epochSeconds;
+ if (!forceRefresh && ((currentValue?._lastUpdated ?? 0) + this.sessionCooldown) > currentEpoch) {
+ console.debug("Session is not stale yet", {
+ currentEpoch,
+ staleEpoch: currentValue?._lastUpdated + this.sessionCooldown,
+ });
+ return;
+ }
+ const sessionResponse = await http_get_async(api_base("_/session-data"));
+ if (sessionResponse.ok) {
+ this.session.set(await sessionResponse.json());
+ } else {
+ this.session.set(null);
+ }
+ }
+
+ async end_session_async(callback: Function = undefined): Promise<void> {
+ if (!this.session) return;
+ await this.logout_async();
+ this.session.set(null);
+ if (callback && typeof callback === "function") callback();
+ }
+
+ async login_async(payload: LoginPayload): Promise<LoginResponse> {
+ const response = await http_post_async(api_base("_/account/login"), payload);
+ if (response.ok) return {isLoggedIn: true};
+ if (is_known_problem(response)) return {
+ isLoggedIn: false,
+ knownProblem: await response.json(),
+ };
+ return {
+ isLoggedIn: false,
+ };
+ }
+
+ async logout_async(): Promise<void> {
+ const response = await http_get_async(api_base("_/account/logout"));
+ if (!response.ok) {
+ const deleteCookieResponse = await fetch("/delete-cookie?key=" + CookieNames.session);
+ if (!deleteCookieResponse.ok) {
+ throw new Error("Could neither logout nor delete session cookie.");
+ }
+ }
+ return;
+ }
+
+ async create_account_async(payload: CreateAccountPayload): Promise<CreateAccountResponse> {
+ const response = await http_post_async(api_base("_/account/create"), payload);
+ if (response.ok) return {isCreated: true};
+ if (is_known_problem(response)) return {
+ isCreated: false,
+ knownProblem: await response.json(),
+ };
+ return {
+ isCreated: false,
+ };
+ }
+
+ async delete_current_async(): Promise<DeleteAccountResponse> {
+ const response = await http_delete_async(api_base("_/account/delete"));
+ return {
+ isDeleted: response.ok,
+ };
+ }
+
+ async update_current_async(payload: UpdateAccountPayload): Promise<UpdateAccountResponse> {
+ const response = await http_post_async(api_base("_/account/update"), payload);
+ if (response.ok) return {isUpdated: true};
+ if (is_known_problem(response)) return {
+ isUpdated: false,
+ knownProblem: await response.json(),
+ };
+ return {
+ isUpdated: false,
+ };
+ }
+} \ No newline at end of file