184 lines
4.2 KiB
TypeScript
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;
|