diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts
index b9b668be..099e23ea 100644
--- a/front/packages/models/src/login.ts
+++ b/front/packages/models/src/login.ts
@@ -18,102 +18,74 @@
* along with Kyoo. If not, see .
*/
-import { z } from "zod";
-import { deleteSecureItem, getSecureItem, setSecureItem } from "./secure-store";
-import { zdate } from "./utils";
import { queryFn } from "./query";
import { KyooErrors } from "./kyoo-errors";
-import { Platform } from "react-native";
-
-const TokenP = z.object({
- token_type: z.literal("Bearer"),
- access_token: z.string(),
- refresh_token: z.string(),
- expire_in: z.string(),
- expire_at: zdate(),
-});
-type Token = z.infer;
+import { Account, Token, TokenP } from "./accounts";
+import { UserP } from "./resources";
+import { addAccount, getCurrentAccount, removeAccounts, updateAccount } from "./account-internal";
type Result =
| { ok: true; value: A; error?: undefined }
| { ok: false; value?: undefined; error: B };
-export type Account = Token & { apiUrl: string; username: string };
-
-const addAccount = (token: Token, apiUrl: string, username: string | null) => {
- const accounts: Account[] = JSON.parse(getSecureItem("accounts") ?? "[]");
- if (accounts.find((x) => x.username === username && x.apiUrl === apiUrl)) return;
- accounts.push({ ...token, username: username!, apiUrl });
- setSecureItem("accounts", JSON.stringify(accounts));
- setSecureItem("selected", (accounts.length - 1).toString());
-};
-
-const setCurrentAccountToken = (token: Token) => {
- const accounts: Account[] = JSON.parse(getSecureItem("accounts") ?? "[]");
- const selected = parseInt(getSecureItem("selected") ?? "0");
- if (selected >= accounts.length) return;
-
- accounts[selected] = { ...accounts[selected], ...token };
- setSecureItem("accounts", JSON.stringify(accounts));
-};
-
-export const loginFunc = async (
- action: "register" | "login" | "refresh",
- body: { username: string; password: string; email?: string } | string,
- apiUrl?: string,
+export const login = async (
+ action: "register" | "login",
+ { apiUrl, ...body }: { username: string; password: string; email?: string; apiUrl?: string },
timeout?: number,
-): Promise> => {
+): Promise> => {
try {
- const controller = timeout !== undefined ? new AbortController() : undefined;
- if (controller) setTimeout(() => controller.abort(), timeout);
const token = await queryFn(
{
- path: ["auth", action, typeof body === "string" && `?token=${body}`],
- method: typeof body === "string" ? "GET" : "POST",
- body: typeof body === "object" ? body : undefined,
+ path: ["auth", action],
+ method: "POST",
+ body,
authenticated: false,
apiUrl,
- abortSignal: controller?.signal,
+ timeout,
},
TokenP,
);
-
- if (typeof window !== "undefined") setSecureItem("auth", JSON.stringify(token));
- if (Platform.OS !== "web" && apiUrl && typeof body !== "string")
- addAccount(token, apiUrl, body.username);
- else if (Platform.OS !== "web" && action === "refresh") setCurrentAccountToken(token);
- return { ok: true, value: token };
+ const user = await queryFn(
+ { path: ["auth", "me"], method: "GET", apiUrl },
+ UserP,
+ token.access_token,
+ );
+ const account: Account = { ...user, apiUrl: apiUrl ?? "/api", token, selected: true };
+ addAccount(account);
+ return { ok: true, value: account };
} catch (e) {
console.error(action, e);
return { ok: false, error: (e as KyooErrors).errors[0] };
}
};
-export const getTokenWJ = async (cookies?: string): Promise<[string, Token] | [null, null]> => {
- const tokenStr = getSecureItem("auth", cookies);
- if (!tokenStr) return [null, null];
- let token = TokenP.parse(JSON.parse(tokenStr));
+export const getTokenWJ = async (account?: Account | null): Promise<[string, Token] | [null, null]> => {
+ if (account === null)
+ account = getCurrentAccount();
+ if (!account) return [null, null];
- if (token.expire_at <= new Date(new Date().getTime() + 10 * 1000)) {
- const { ok, value: nToken, error } = await loginFunc("refresh", token.refresh_token);
- if (!ok) console.error("Error refreshing token durring ssr:", error);
- else token = nToken;
+ if (account.token.expire_at <= new Date(new Date().getTime() + 10 * 1000)) {
+ try {
+ const token = await queryFn(
+ {
+ path: ["auth", "refresh", `?token=${account.token.refresh_token}`],
+ method: "GET",
+ },
+ TokenP,
+ );
+ updateAccount(account.id, { ...account, token });
+ } catch (e) {
+ console.error("Error refreshing token durring ssr:", e);
+ }
}
- return [`${token.token_type} ${token.access_token}`, token];
+ return [`${account.token.token_type} ${account.token.access_token}`, account.token];
};
-export const getToken = async (cookies?: string): Promise =>
- (await getTokenWJ(cookies))[0];
+export const getToken = async (): Promise =>
+ (await getTokenWJ())[0];
export const logout = () => {
- if (Platform.OS !== "web") {
- let accounts: Account[] = JSON.parse(getSecureItem("accounts") ?? "[]");
- const selected = parseInt(getSecureItem("selected") ?? "0");
- accounts.splice(selected, 1);
- setSecureItem("accounts", JSON.stringify(accounts));
- }
-
- deleteSecureItem("auth");
+ removeAccounts((x) => x.selected);
};
export const deleteAccount = async () => {
diff --git a/front/packages/ui/src/login/login.tsx b/front/packages/ui/src/login/login.tsx
index 6de27869..ebac322a 100644
--- a/front/packages/ui/src/login/login.tsx
+++ b/front/packages/ui/src/login/login.tsx
@@ -18,7 +18,7 @@
* along with Kyoo. If not, see .
*/
-import { loginFunc, QueryPage } from "@kyoo/models";
+import { login, QueryPage } from "@kyoo/models";
import { Button, P, Input, ts, H1, A } from "@kyoo/primitives";
import { useState } from "react";
import { useTranslation } from "react-i18next";
@@ -74,10 +74,9 @@ export const LoginPage: QueryPage = () => {