Handle watchstatus on movies/series

This commit is contained in:
Zoe Roux 2025-04-06 18:25:28 +02:00
parent 22754442ad
commit 11e1c59698
No known key found for this signature in database
5 changed files with 35 additions and 32 deletions

View File

@ -96,7 +96,7 @@ RABBITMQ_DEFAULT_PASS=aohohunuhouhuhhoahothonseuhaoensuthoaentsuhha
# v5 stuff, does absolutely nothing on master (aka: you can delete this)
EXTRA_CLAIMS='{"permissions": [], "verified": false}'
FIRST_USER_CLAIMS='{"permissions": ["user.read", "users.write", "users.delete"], "verified": true}'
GUEST_CLAIMS='{"permissions": []}'
EXTRA_CLAIMS='{"permissions": ["core.read"], "verified": false}'
FIRST_USER_CLAIMS='{"permissions": ["user.read", "users.write", "users.delete", "core.read"], "verified": true}'
GUEST_CLAIMS='{"permissions": ["core.read"]}'
PROTECTED_CLAIMS="permissions,verified"

View File

@ -26,35 +26,36 @@ export const auth = new Elysia({ name: "auth" })
authorization: t.TemplateLiteral("Bearer ${string}"),
}),
})
.resolve(async ({ headers: { authorization }, error }) => {
const bearer = authorization?.slice(7);
if (!bearer) {
return error(500, {
status: 500,
message: "No jwt, auth server configuration error.",
});
}
// @ts-expect-error ts can't understand that there's two overload idk why
const { payload } = await jwtVerify(bearer, jwtSecret ?? jwks, {
issuer: process.env.JWT_ISSUER,
});
const jwt = validator.Decode(payload);
return { jwt };
})
.macro({
permissions(perms: string[]) {
return {
resolve: async ({ headers: { authorization }, error }) => {
const bearer = authorization?.slice(7);
if (!bearer) {
return error(500, {
status: 500,
message: "No jwt, auth server configuration error.",
});
}
// @ts-expect-error ts can't understand that there's two overload idk why
const { payload } = await jwtVerify(bearer, jwtSecret ?? jwks, {
issuer: process.env.JWT_ISSUER,
});
const jwt = validator.Decode(payload);
beforeHandle: ({ jwt, error }) => {
for (const perm of perms) {
if (!jwt.permissions.includes(perm)) {
if (!jwt!.permissions.includes(perm)) {
return error(403, {
status: 403,
message: `Missing permission: '${perm}'.`,
details: { current: jwt.permissions, required: perms },
details: { current: jwt!.permissions, required: perms },
});
}
}
return { jwt };
},
};
},

View File

@ -6,6 +6,7 @@ import {
entryTranslations,
entryVideoJoin,
history,
profiles,
showStudioJoin,
showTranslations,
shows,
@ -36,7 +37,7 @@ import {
sortToSql,
} from "~/models/utils";
import type { EmbeddedVideo } from "~/models/video";
import { entryVideosQ, getEntryProgressQ } from "../entries";
import { entryVideosQ, getEntryProgressQ, mapProgress } from "../entries";
export const showFilters: FilterDef = {
genres: {
@ -151,7 +152,7 @@ const showRelations = {
firstEntry: ({
languages,
userId,
}: { languages: string[]; userId: number }) => {
}: { languages: string[]; userId: string }) => {
const transQ = db
.selectDistinctOn([entryTranslations.pk])
.from(entryTranslations)
@ -171,7 +172,7 @@ const showRelations = {
...transCol,
number: entries.episodeNumber,
videos: entryVideosQ.videos,
progress: getColumns(progressQ),
progress: mapProgress(progressQ),
}).as("firstEntry"),
})
.from(entries)
@ -189,7 +190,7 @@ const showRelations = {
watchStatusQ,
}: {
languages: string[];
userId: number;
userId: string;
watchStatusQ: PgSelect<typeof watchlist>;
}) => {
const transQ = db
@ -211,7 +212,7 @@ const showRelations = {
...transCol,
number: entries.episodeNumber,
videos: entryVideosQ.videos,
progress: getColumns(progressQ),
progress: mapProgress(progressQ),
}).as("nextEntry"),
})
.from(entries)
@ -244,7 +245,7 @@ export async function getShows({
fallbackLanguage?: boolean;
preferOriginal?: boolean;
relations?: (keyof typeof showRelations)[];
userId: number;
userId: string;
}) {
const transQ = db
.selectDistinctOn([showTranslations.pk])
@ -263,10 +264,11 @@ export async function getShows({
const watchStatusQ = db
.select({
...getColumns(watchlist),
percent: watchlist.seenCount,
percent: sql`${watchlist.seenCount}`.as("percent"),
})
.from(watchlist)
.where(eq(watchlist.profilePk, userId))
.leftJoin(profiles, eq(watchlist.profilePk, profiles.pk))
.where(eq(profiles.id, userId))
.as("watchstatus");
return await db

View File

@ -56,7 +56,7 @@ export const Movie = t.Intersect([
t.Object({
original: Original,
isAvailable: t.Boolean(),
watchStatus: t.Omit(WatchStatus, ["seenCount"]),
watchStatus: t.Nullable(t.Omit(WatchStatus, ["seenCount"])),
}),
]);
export type Movie = Prettify<typeof Movie.static>;

View File

@ -71,7 +71,7 @@ export const Serie = t.Intersect([
availableCount: t.Integer({
description: "The number of episodes that can be played right away",
}),
watchStatus: t.Omit(WatchStatus, ["percent"]),
watchStatus: t.Nullable(t.Omit(WatchStatus, ["percent"])),
}),
]);
export type Serie = Prettify<typeof Serie.static>;