diff --git a/back/src/Kyoo.Authentication/AuthenticationModule.cs b/back/src/Kyoo.Authentication/AuthenticationModule.cs index 542356b0..caf5d345 100644 --- a/back/src/Kyoo.Authentication/AuthenticationModule.cs +++ b/back/src/Kyoo.Authentication/AuthenticationModule.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Autofac; using Kyoo.Abstractions.Controllers; using Kyoo.Authentication.Models; @@ -86,6 +87,14 @@ namespace Kyoo.Authentication .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { + options.Events = new() + { + OnMessageReceived = (ctx) => + { + ctx.Token ??= ctx.Request.Cookies["X-Bearer"]; + return Task.CompletedTask; + } + }; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, diff --git a/front/packages/models/src/account-internal.ts b/front/packages/models/src/account-internal.ts index 7c57a3c7..392cd48c 100644 --- a/front/packages/models/src/account-internal.ts +++ b/front/packages/models/src/account-internal.ts @@ -35,7 +35,7 @@ const writeAccounts = (accounts: Account[]) => { }; export const setCookie = (key: string, val?: unknown) => { - let value = JSON.stringify(val); + let value = typeof val !== "string" ? JSON.stringify(val) : val; // Remove illegal values from json. There should not be one in the account anyways. value = value?.replaceAll(";", ""); const d = new Date(); diff --git a/front/packages/models/src/accounts.tsx b/front/packages/models/src/accounts.tsx index d3413da2..edea2b41 100644 --- a/front/packages/models/src/accounts.tsx +++ b/front/packages/models/src/accounts.tsx @@ -38,7 +38,7 @@ export const TokenP = z.object({ }); export type Token = z.infer; -export const AccountP = UserP.merge( +export const AccountP = UserP.and( z.object({ // set it optional for accounts logged in before the kind was present kind: z.literal("user").optional(), @@ -126,7 +126,10 @@ export const AccountProvider = ({ oldSelectedId.current = selected?.id; // update cookies for ssr (needs to contains token, theme, language...) - if (Platform.OS === "web") setCookie("account", selected); + if (Platform.OS === "web") { + setCookie("account", selected); + setCookie("X-Bearer", selected?.token.access_token); + } }, [selected, queryClient]); return ( diff --git a/front/packages/models/src/resources/user.ts b/front/packages/models/src/resources/user.ts index 8e8be388..eaa56067 100644 --- a/front/packages/models/src/resources/user.ts +++ b/front/packages/models/src/resources/user.ts @@ -20,44 +20,47 @@ import { z } from "zod"; import { ResourceP } from "../traits/resource"; +import { imageFn } from "../traits/images"; -export const UserP = ResourceP("user").extend({ - /** - * The name of this user. - */ - username: z.string(), - /** - * The user email address. - */ - email: z.string(), - /** - * The list of permissions of the user. The format of this is implementation dependent. - */ - permissions: z.array(z.string()), - /** - * User settings - */ - settings: z - .object({ - downloadQuality: z - .union([ - z.literal("original"), - z.literal("8k"), - z.literal("4k"), - z.literal("1440p"), - z.literal("1080p"), - z.literal("720p"), - z.literal("480p"), - z.literal("360p"), - z.literal("240p"), - ]) - .default("original") - .catch("original"), - audioLanguage: z.string().default("default").catch("default"), - subtitleLanguage: z.string().nullable().default(null).catch(null), - }) - // keep a default for older versions of the api - .default({}), -}); +export const UserP = ResourceP("user") + .extend({ + /** + * The name of this user. + */ + username: z.string(), + /** + * The user email address. + */ + email: z.string(), + /** + * The list of permissions of the user. The format of this is implementation dependent. + */ + permissions: z.array(z.string()), + /** + * User settings + */ + settings: z + .object({ + downloadQuality: z + .union([ + z.literal("original"), + z.literal("8k"), + z.literal("4k"), + z.literal("1440p"), + z.literal("1080p"), + z.literal("720p"), + z.literal("480p"), + z.literal("360p"), + z.literal("240p"), + ]) + .default("original") + .catch("original"), + audioLanguage: z.string().default("default").catch("default"), + subtitleLanguage: z.string().nullable().default(null).catch(null), + }) + // keep a default for older versions of the api + .default({}), + }) + .transform((x) => ({ ...x, logo: imageFn(`/user/${x.slug}/logo`) })); export type User = z.infer;