diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts index 7f1b8276..17cf5c9c 100644 --- a/front/packages/models/src/login.ts +++ b/front/packages/models/src/login.ts @@ -20,7 +20,7 @@ import { queryFn } from "./query"; import { KyooErrors } from "./kyoo-errors"; -import { Account, TokenP, getCurrentApiUrl } from "./accounts"; +import { Account, Token, TokenP, getCurrentApiUrl } from "./accounts"; import { UserP } from "./resources"; import { addAccount, getCurrentAccount, removeAccounts, updateAccount } from "./account-internal"; import { Platform } from "react-native"; @@ -88,16 +88,21 @@ export const oidcLogin = async (provider: string, code: string, apiUrl?: string) } }; +let running_id: string | null = null; let running: ReturnType | null = null; -export const getTokenWJ = async (account?: Account | null): ReturnType => { - async function run() { - if (account === undefined) account = getCurrentAccount(); - if (!account) return [null, null, null] as const; +export const getTokenWJ = async ( + acc?: Account | null, + forceRefresh: boolean = false, +): Promise => { + if (acc === undefined) acc = getCurrentAccount(); + if (!acc) return [null, null, null] as const; + const account = acc; + async function run() { let token = account.token; - if (account.token.expire_at <= new Date(new Date().getTime() + 10 * 1000)) { + if (forceRefresh || account.token.expire_at <= new Date(new Date().getTime() + 10 * 1000)) { console.log("refreshing token for account", account.slug); try { token = await queryFn( @@ -121,9 +126,11 @@ export const getTokenWJ = async (account?: Account | null): ReturnType( } & Partial) ), type?: Parser, - token?: string | null, + iToken?: string | null, ): Promise> => { const url = context.apiUrl && context.apiUrl.length > 0 ? context.apiUrl : getCurrentApiUrl(); lastUsedUrl = url!; - if (token === undefined && context.authenticated !== false) token = await getToken(); + const token = + iToken === undefined && context.authenticated !== false ? await getToken() : undefined; const path = [url] .concat( "path" in context @@ -90,6 +91,14 @@ export const queryFn = async ( if (resp.status === 404) { throw { errors: ["Resource not found."], status: 404 } as KyooErrors; } + // If we got a forbidden, try to refresh the token + // if we got a token as an argument, it either means we already retried or we go one provided that's fresh + // so we can't retry either ways. + if (resp.status === 403 && iToken === undefined && token) { + const [newToken, _, error] = await getTokenWJ(undefined, true); + if (newToken) return await queryFn(context, type, newToken); + else console.error("refresh error while retrying a forbidden", error); + } if (!resp.ok) { const error = await resp.text(); let data; @@ -128,7 +137,7 @@ export const queryFn = async ( errors: [ "Invalid response from kyoo. Possible version mismatch between the server and the application.", ], - status: "parse" + status: "parse", } as KyooErrors; } return parsed.data;