mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-03-25 02:47:50 -04:00
Fix websocket auth
This commit is contained in:
parent
6d21eeab07
commit
41e00532d8
@ -450,6 +450,12 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
"/profiles/me/history",
|
||||
async ({ body, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
if (!profilePk) {
|
||||
return status(401, {
|
||||
status: 401,
|
||||
message: "Guest don't have history",
|
||||
});
|
||||
}
|
||||
|
||||
const ret = await updateProgress(profilePk, body);
|
||||
return status(ret.status, ret);
|
||||
@ -465,6 +471,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
description: "The number of history entry inserted",
|
||||
}),
|
||||
}),
|
||||
401: { ...KError, description: "Non logged users don't have history" },
|
||||
404: {
|
||||
...KError,
|
||||
description: "No entry found with the given id or slug.",
|
||||
|
||||
@ -3,6 +3,9 @@ import { db } from "~/db";
|
||||
import { profiles } from "~/db/schema";
|
||||
|
||||
export async function getOrCreateProfile(userId: string) {
|
||||
// id of the guest user
|
||||
if (userId === "00000000-0000-0000-0000-000000000000") return null;
|
||||
|
||||
let [profile] = await db
|
||||
.select({ pk: profiles.pk })
|
||||
.from(profiles)
|
||||
|
||||
@ -34,21 +34,17 @@ import {
|
||||
} from "~/models/watchlist";
|
||||
import { getOrCreateProfile } from "./profile";
|
||||
|
||||
console.log();
|
||||
|
||||
async function setWatchStatus({
|
||||
show,
|
||||
status,
|
||||
userId,
|
||||
userPk,
|
||||
}: {
|
||||
show:
|
||||
| { pk: number; kind: "movie" }
|
||||
| { pk: number; kind: "serie"; entriesCount: number };
|
||||
status: SeedSerieWatchStatus;
|
||||
userId: string;
|
||||
userPk: number;
|
||||
}) {
|
||||
const profilePk = await getOrCreateProfile(userId);
|
||||
|
||||
const firstEntryQ = db
|
||||
.select({ pk: entries.pk })
|
||||
.from(entries)
|
||||
@ -61,7 +57,7 @@ async function setWatchStatus({
|
||||
.values({
|
||||
...status,
|
||||
startedAt: coalesce(sql`${status.startedAt ?? null}`, sql`now()`),
|
||||
profilePk: profilePk,
|
||||
profilePk: userPk,
|
||||
seenCount:
|
||||
status.status === "completed"
|
||||
? show.kind === "movie"
|
||||
@ -269,6 +265,14 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
.post(
|
||||
"/series/:id/watchstatus",
|
||||
async ({ params: { id }, body, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
if (!profilePk) {
|
||||
return status(401, {
|
||||
status: 401,
|
||||
message: "Guest can't set watchstatus",
|
||||
});
|
||||
}
|
||||
|
||||
const [show] = await db
|
||||
.select({ pk: shows.pk, entriesCount: shows.entriesCount })
|
||||
.from(shows)
|
||||
@ -287,7 +291,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
}
|
||||
return await setWatchStatus({
|
||||
show: { pk: show.pk, kind: "serie", entriesCount: show.entriesCount },
|
||||
userId: sub,
|
||||
userPk: profilePk,
|
||||
status: body,
|
||||
});
|
||||
},
|
||||
@ -302,6 +306,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
body: SeedSerieWatchStatus,
|
||||
response: {
|
||||
200: t.Intersect([SerieWatchStatus, DbMetadata]),
|
||||
401: { ...KError, description: "Guest can't set their watchstatus" },
|
||||
404: KError,
|
||||
},
|
||||
permissions: ["core.read"],
|
||||
@ -310,6 +315,14 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
.post(
|
||||
"/movies/:id/watchstatus",
|
||||
async ({ params: { id }, body, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
if (!profilePk) {
|
||||
return status(401, {
|
||||
status: 401,
|
||||
message: "Guest can't set watchstatus",
|
||||
});
|
||||
}
|
||||
|
||||
const [show] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
@ -329,7 +342,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
|
||||
return await setWatchStatus({
|
||||
show: { pk: show.pk, kind: "movie" },
|
||||
userId: sub,
|
||||
userPk: profilePk,
|
||||
status: {
|
||||
...body,
|
||||
startedAt: body.completedAt,
|
||||
@ -347,6 +360,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
body: SeedMovieWatchStatus,
|
||||
response: {
|
||||
200: t.Intersect([MovieWatchStatus, DbMetadata]),
|
||||
401: { ...KError, description: "Guest can't set their watchstatus" },
|
||||
404: KError,
|
||||
},
|
||||
permissions: ["core.read"],
|
||||
@ -356,6 +370,12 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
"/series/:id/watchstatus",
|
||||
async ({ params: { id }, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
if (!profilePk) {
|
||||
return status(401, {
|
||||
status: 401,
|
||||
message: "Guest can't set watchstatus",
|
||||
});
|
||||
}
|
||||
|
||||
const rows = await db.execute(sql`
|
||||
delete from ${watchlist} using ${shows}
|
||||
@ -396,6 +416,12 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
"/movies/:id/watchstatus",
|
||||
async ({ params: { id }, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
if (!profilePk) {
|
||||
return status(401, {
|
||||
status: 401,
|
||||
message: "Guest can't set watchstatus",
|
||||
});
|
||||
}
|
||||
|
||||
const rows = await db.execute(sql`
|
||||
delete from ${watchlist} using ${shows}
|
||||
@ -428,6 +454,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
}),
|
||||
response: {
|
||||
200: t.Intersect([MovieWatchStatus, DbMetadata]),
|
||||
401: { ...KError, description: "Guest can't set their watchstatus" },
|
||||
404: KError,
|
||||
},
|
||||
permissions: ["core.read"],
|
||||
|
||||
@ -26,6 +26,14 @@ const actionMap = {
|
||||
permissions: ["core.read"],
|
||||
async message(ws, body) {
|
||||
const profilePk = await getOrCreateProfile(ws.data.jwt.sub);
|
||||
if (!profilePk) {
|
||||
ws.send({
|
||||
action: "watch",
|
||||
status: 401,
|
||||
message: "Guest can't set watchstatus",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const ret = await updateProgress(profilePk, [
|
||||
{ ...body, playedDate: null },
|
||||
|
||||
18
auth/jwt.go
18
auth/jwt.go
@ -44,16 +44,16 @@ func (h *Handler) CreateJwt(c echo.Context) error {
|
||||
var token string
|
||||
|
||||
if auth == "" {
|
||||
cookie, _ := c.Request().Cookie("X-Bearer")
|
||||
if cookie != nil {
|
||||
token = cookie.Value
|
||||
protocol, ok := c.Request().Header["Sec-Websocket-Protocol"]
|
||||
if ok &&
|
||||
len(protocol) == 2 &&
|
||||
protocol[0] == "kyoo" &&
|
||||
strings.HasPrefix(protocol[1], "Bearer ") {
|
||||
token = protocol[1][len("Bearer "):]
|
||||
} else {
|
||||
protocol, ok := c.Request().Header["Sec-Websocket-Protocol"]
|
||||
if ok &&
|
||||
len(protocol) == 2 &&
|
||||
protocol[0] == "kyoo" &&
|
||||
strings.HasPrefix(protocol[1], "Bearer") {
|
||||
token = protocol[1][len("Bearer "):]
|
||||
cookie, _ := c.Request().Cookie("X-Bearer")
|
||||
if cookie != nil {
|
||||
token = cookie.Value
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(auth, "Bearer ") {
|
||||
|
||||
@ -66,6 +66,7 @@ data:
|
||||
- "Authorization"
|
||||
- "X-Api-Key"
|
||||
- "Cookie"
|
||||
- "Sec-WebSocket-Protocol"
|
||||
authResponseHeaders:
|
||||
- Authorization
|
||||
services:
|
||||
|
||||
@ -23,7 +23,7 @@ x-transcoder: &transcoder-base
|
||||
- "traefik.http.routers.transcoder.rule=PathPrefix(`/video`)"
|
||||
- "traefik.http.routers.transcoder.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
develop:
|
||||
watch:
|
||||
@ -95,7 +95,7 @@ services:
|
||||
- "traefik.http.routers.api.rule=PathPrefix(`/api/`)"
|
||||
- "traefik.http.routers.api.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
develop:
|
||||
watch:
|
||||
@ -131,7 +131,7 @@ services:
|
||||
- "traefik.http.routers.scanner.rule=PathPrefix(`/scanner/`)"
|
||||
- "traefik.http.routers.scanner.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
command: fastapi dev scanner --host 0.0.0.0 --port 4389
|
||||
develop:
|
||||
|
||||
@ -19,7 +19,7 @@ x-transcoder: &transcoder-base
|
||||
- "traefik.http.routers.transcoder.rule=PathPrefix(`/video`)"
|
||||
- "traefik.http.routers.transcoder.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
|
||||
services:
|
||||
@ -65,7 +65,7 @@ services:
|
||||
- "traefik.http.routers.api.rule=PathPrefix(`/api/`)"
|
||||
- "traefik.http.routers.api.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
|
||||
scanner:
|
||||
@ -88,7 +88,7 @@ services:
|
||||
- "traefik.http.routers.scanner.rule=PathPrefix(`/scanner/`)"
|
||||
- "traefik.http.routers.scanner.middlewares=phantom-token"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.address=http://auth:4568/auth/jwt"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authRequestHeaders=Authorization,Cookie,X-Api-Key,Sec-WebSocket-Protocol"
|
||||
- "traefik.http.middlewares.phantom-token.forwardauth.authResponseHeaders=Authorization"
|
||||
|
||||
transcoder:
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Platform } from "react-native";
|
||||
import useWebSocket from "react-use-websocket";
|
||||
import { useToken } from "~/providers/account-context";
|
||||
|
||||
@ -9,13 +10,17 @@ export const useWebsockets = ({
|
||||
}) => {
|
||||
const { apiUrl, authToken } = useToken();
|
||||
const ret = useWebSocket(`${apiUrl}/api/ws`, {
|
||||
protocols: authToken ? ["kyoo", `Bearer ${authToken}`] : undefined,
|
||||
// on web use cookies, firefox doesn't like protocols idk why
|
||||
protocols:
|
||||
Platform.OS !== "web" && authToken
|
||||
? ["kyoo", `Bearer ${authToken}`]
|
||||
: ["kyoo"],
|
||||
filter: (msg) => filterActions.includes(msg.data.action),
|
||||
share: true,
|
||||
retryOnError: true,
|
||||
heartbeat: {
|
||||
message: `{ "action": "ping" }`,
|
||||
returnMessage: `{ "response": "pong" }`,
|
||||
message: `{"action": "ping"}`,
|
||||
returnMessage: `{"action":"ping","response":"pong"}`,
|
||||
interval: 25_000,
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user