aboutsummaryrefslogtreecommitdiffstats
path: root/code/app/src/services
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-12-09 03:57:12 +0100
committerivarlovlie <git@ivarlovlie.no>2022-12-09 03:57:12 +0100
commit4dbef3fcd7a14437d55c555cf10d50de8e50d7d1 (patch)
tree632589ecfcfb4dfddeafb71d0077257584b5e7ec /code/app/src/services
parent914c75e0ceeb3e11ddd55e94bb461c26b0db5b7a (diff)
downloadgreatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.tar.xz
greatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.zip
feat: Move everything out of $lib
Diffstat (limited to 'code/app/src/services')
-rw-r--r--code/app/src/services/abstractions/IAccountService.ts58
-rw-r--r--code/app/src/services/abstractions/IPasswordResetService.ts21
-rw-r--r--code/app/src/services/abstractions/ISettingsService.ts3
-rw-r--r--code/app/src/services/account-service.ts116
-rw-r--r--code/app/src/services/password-reset-service.ts45
-rw-r--r--code/app/src/services/settings-service.ts7
6 files changed, 250 insertions, 0 deletions
diff --git a/code/app/src/services/abstractions/IAccountService.ts b/code/app/src/services/abstractions/IAccountService.ts
new file mode 100644
index 0000000..0645eb6
--- /dev/null
+++ b/code/app/src/services/abstractions/IAccountService.ts
@@ -0,0 +1,58 @@
+import type {KnownProblem} from "$models/internal/KnownProblem";
+import type {Writable} from "svelte/store";
+
+export interface IAccountService {
+ session: Writable<Session>,
+
+ login_async(payload: LoginPayload): Promise<LoginResponse>,
+
+ logout_async(): Promise<void>,
+
+ create_account_async(payload: CreateAccountPayload): Promise<CreateAccountResponse>,
+
+ delete_current_async(): Promise<DeleteAccountResponse>,
+
+ update_current_async(payload: UpdateAccountPayload): Promise<UpdateAccountResponse>,
+}
+
+export type Session = {
+ username: string,
+ displayName: string,
+ id: string,
+ _lastUpdated: number
+}
+
+export type LoginPayload = {
+ username: string,
+ password: string,
+ persist: boolean
+}
+
+export type LoginResponse = {
+ isLoggedIn: boolean,
+ knownProblem?: KnownProblem
+}
+
+export type CreateAccountPayload = {
+ username: string,
+ password: string,
+}
+
+export type CreateAccountResponse = {
+ isCreated: boolean,
+ knownProblem?: KnownProblem
+}
+
+export type DeleteAccountResponse = {
+ isDeleted: boolean
+}
+
+export type UpdateAccountPayload = {
+ username: string,
+ password: string
+}
+
+export type UpdateAccountResponse = {
+ isUpdated: boolean,
+ knownProblem?: KnownProblem
+} \ No newline at end of file
diff --git a/code/app/src/services/abstractions/IPasswordResetService.ts b/code/app/src/services/abstractions/IPasswordResetService.ts
new file mode 100644
index 0000000..59d2bc6
--- /dev/null
+++ b/code/app/src/services/abstractions/IPasswordResetService.ts
@@ -0,0 +1,21 @@
+import type { KnownProblem } from "$models/internal/KnownProblem"
+
+export interface IPasswordResetService {
+ create_request_async(email: string): Promise<CreateRequestResponse>,
+ fulfill_request_async(id: string, newPassword: string): Promise<FulfillRequestResponse>,
+ request_is_valid_async(id: string): Promise<RequestIsValidResponse>
+}
+
+export type RequestIsValidResponse = {
+ isValid: boolean
+}
+
+export type FulfillRequestResponse = {
+ isFulfilled: boolean,
+ knownProblem?: KnownProblem
+}
+
+export type CreateRequestResponse = {
+ isCreated: boolean,
+ knownProblem?: KnownProblem
+} \ No newline at end of file
diff --git a/code/app/src/services/abstractions/ISettingsService.ts b/code/app/src/services/abstractions/ISettingsService.ts
new file mode 100644
index 0000000..366e337
--- /dev/null
+++ b/code/app/src/services/abstractions/ISettingsService.ts
@@ -0,0 +1,3 @@
+export interface ISettingsService {
+ get_user_settings(): Promise<void>,
+} \ No newline at end of file
diff --git a/code/app/src/services/account-service.ts b/code/app/src/services/account-service.ts
new file mode 100644
index 0000000..9d45950
--- /dev/null
+++ b/code/app/src/services/account-service.ts
@@ -0,0 +1,116 @@
+import {http_delete_async, http_get_async, http_post_async} from "$api/_fetch";
+import {api_base, CookieNames, StorageKeys} from "$configuration";
+import {is_known_problem} from "$models/internal/KnownProblem";
+import {log_debug} from "$help/logger";
+import {StoreType, writable_persistent} from "$help/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>;
+ private sessionCooldown = 3600;
+
+ constructor() {
+ this.session = writable_persistent({
+ name: StorageKeys.session,
+ initialState: {} as Session,
+ options: {
+ store: StoreType.LOCAL,
+ },
+ });
+ this.refresh_session();
+ }
+
+ async refresh_session(forceRefresh: boolean = false): Promise<void> {
+ const currentValue = get(this.session);
+ const currentEpoch = Temporal.Now.instant().epochSeconds;
+ if (currentValue?._lastUpdated + this.sessionCooldown < currentEpoch) {
+ log_debug("Session is not stale yet", {
+ currentEpoch,
+ staleEpoch: currentValue?._lastUpdated + this.sessionCooldown,
+ });
+ return;
+ }
+ const sessionResponse = await http_get_async(api_base("_/account/session"));
+ if (sessionResponse.ok) {
+
+ }
+ }
+
+ async end_session(callback: Function): Promise<void> {
+ await this.logout_async();
+ this.session.set(null);
+ if (typeof callback === "function") callback();
+ return;
+ }
+
+ 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
diff --git a/code/app/src/services/password-reset-service.ts b/code/app/src/services/password-reset-service.ts
new file mode 100644
index 0000000..ab3a953
--- /dev/null
+++ b/code/app/src/services/password-reset-service.ts
@@ -0,0 +1,45 @@
+import {http_get_async, http_post_async} from "$api/_fetch";
+import {api_base} from "$configuration";
+import {is_known_problem} from "$models/internal/KnownProblem";
+import type {
+ CreateRequestResponse,
+ FulfillRequestResponse,
+ IPasswordResetService,
+ RequestIsValidResponse,
+} from "./abstractions/IPasswordResetService";
+
+export class PasswordResetService implements IPasswordResetService {
+ async create_request_async(email: string): Promise<CreateRequestResponse> {
+ const response = await http_post_async(api_base("_/password-reset-request/create"), {email});
+ if (response.ok) return {isCreated: true};
+ if (is_known_problem(response)) return {
+ isCreated: false,
+ knownProblem: await response.json(),
+ };
+
+ return {
+ isCreated: false,
+ };
+ }
+
+ async fulfill_request_async(id: string, newPassword: string): Promise<FulfillRequestResponse> {
+ const response = await http_post_async(api_base("_/password-reset-request/fulfill"), {id: id, newPassword});
+ if (response.ok) return {isFulfilled: true};
+ if (is_known_problem(response)) return {
+ isFulfilled: false,
+ knownProblem: await response.json(),
+ };
+
+ return {
+ isFulfilled: false,
+ };
+ }
+
+ async request_is_valid_async(id: string): Promise<RequestIsValidResponse> {
+ const response = await http_get_async(api_base("_/password-reset-request/is-valid?id=" + id));
+ const responseBody = await response.json() as { isValid: boolean };
+ return {
+ isValid: responseBody.isValid,
+ };
+ }
+} \ No newline at end of file
diff --git a/code/app/src/services/settings-service.ts b/code/app/src/services/settings-service.ts
new file mode 100644
index 0000000..20053a9
--- /dev/null
+++ b/code/app/src/services/settings-service.ts
@@ -0,0 +1,7 @@
+import type {ISettingsService} from "./abstractions/ISettingsService";
+
+export class SettingsService implements ISettingsService {
+ get_user_settings(): Promise<void> {
+ throw new Error("Method not implemented.");
+ }
+} \ No newline at end of file