OpenAuth_server/Frontend/src/pages/login/state.ts

184 lines
4.2 KiB
TypeScript

import type { LoginState } from "@hibas123/openauth-internalapi";
import { derived, get, writable } from "svelte/store";
import InternalAPI from "../../helper/api";
import sha from "../../helper/sha512";
interface LocalLoginState extends LoginState {
loading: boolean;
error?: string;
username?: string;
}
class LoginStore {
state = writable<LocalLoginState>({
username: undefined,
password: false,
passwordSalt: undefined,
requireTwoFactor: [],
success: false,
loading: true,
error: undefined
})
isFinished = derived(this.state, $state => $state.success);
constructor() {
this.state.subscribe((state) => {
if (state.success) {
setTimeout(() => {
this.finish();
}, 2000);
}
})
this.getState();
}
setLoading(loading: boolean) {
this.state.update(current => ({
...current,
loading,
error: loading ? undefined : current.error,
}));
}
setError(error: string) {
this.state.update(current => ({
...current,
error,
}));
}
async getState() {
try {
this.setLoading(true);
let state = await InternalAPI.Login.GetState();
this.state.update(current => ({
...current,
...state,
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async setUsername(username: string) {
try {
this.setLoading(true);
let state = await InternalAPI.Login.Start(username);
this.state.update(current => ({
...current,
...state,
username
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async setPassword(password: string) {
try {
this.setLoading(true);
const date = new Date().valueOf();
let salt = get(this.state).passwordSalt
let pw = sha(sha(salt + password) + date.toString());
let state = await InternalAPI.Login.UsePassword(pw, date);
this.state.update(current => ({
...current,
...state,
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async useTOTP(id: string, code: string) {
try {
this.setLoading(true);
let state = await InternalAPI.Login.UseTOTP(id, code);
this.state.update(current => ({
...current,
...state,
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async useBackupCode(id: string, code: string) {
try {
this.setLoading(true);
let state = await InternalAPI.Login.UseBackupCode(id, code);
this.state.update(current => ({
...current,
...state,
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async getWebAuthnChallenge(id: string) {
try {
this.setLoading(true);
let challenge = await InternalAPI.Login.GetWebAuthnChallenge(id);
return challenge;
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async useWebAuthn(id: string, response: any) {
try {
this.setLoading(true);
let state = await InternalAPI.Login.UseWebAuthn(id, JSON.stringify(response));
this.state.update(current => ({
...current,
...state,
}));
} catch (err) {
this.setError(err.message);
} finally {
this.setLoading(false);
}
}
async finish() {
let url = new URL(window.location.href);
let state = url.searchParams.get("state");
let red = "/";
if (state) {
let base64 = url.searchParams.get("base64");
if (base64) red = atob(state);
else red = state;
}
setTimeout(() => (window.location.href = red), 200);
}
}
const loginState = new LoginStore();
export default loginState;