fix: add custom endpoint for getVideoBySlug to bypass permissions

- Add GET /sexy/videos/:slug endpoint in bundle that bypasses Directus permissions
- Simplify getVideoBySlug to use the new custom endpoint instead of direct API call
- Fixes "Video not found" error on production for public video pages
- Custom endpoint uses database query like other public endpoints (/sexy/models, etc)
- Ensures videos are accessible to unauthenticated users while respecting upload_date

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Valknar XXX
2025-11-03 17:13:56 +01:00
parent b2aa8a57ca
commit 036fc35c9a
2 changed files with 49 additions and 35 deletions

View File

@@ -204,6 +204,48 @@ export default {
}
});
// GET /sexy/videos/:slug - Get single video by slug
router.get("/videos/:slug", async (req, res) => {
try {
const { slug } = req.params;
const video = await database
.select("v.*")
.from("sexy_videos as v")
.where("v.slug", slug)
.where("v.upload_date", "<=", new Date().toISOString())
.first();
if (!video) {
return res.status(404).json({ error: "Video not found" });
}
// Fetch models
const models = await database
.select("u.*")
.from("sexy_videos_models as vm")
.leftJoin("directus_users as u", "vm.directus_users_id", "u.id")
.where("vm.sexy_videos_id", video.id);
video.models = models;
// Fetch movie file
if (video.movie) {
const movie = await database
.select("*")
.from("directus_files")
.where("id", video.movie)
.first();
video.movie = movie;
}
res.json(video);
} catch (error: any) {
console.error("Video by slug error:", error);
res.status(500).json({ error: error.message || "Failed to fetch video" });
}
});
// GET /sexy/articles - List articles
router.get("/articles", async (req, res) => {
try {

View File

@@ -242,41 +242,13 @@ export async function getVideoBySlug(
return loggedApiCall(
"getVideoBySlug",
async () => {
const fetchFn = fetch || globalThis.fetch;
return fetchFn(
`${directusApiUrl}/items/sexy_videos?${new URLSearchParams({
filter: JSON.stringify({ slug: { _eq: slug } }),
fields: JSON.stringify([
"*",
{
models: [
"*",
{
directus_users_id: ["*"],
},
],
},
"movie.*",
]),
})}`,
)
.then((res) => res.json())
.then((response) => {
const videos = response.data;
if (!videos || videos.length === 0) {
throw new Error("Video not found");
}
// Handle models array - filter out null/undefined and map to user objects
if (Array.isArray(videos[0].models)) {
videos[0].models = videos[0].models
.filter((u) => u && u.directus_users_id)
.map((u) => u.directus_users_id!);
} else {
videos[0].models = [];
}
return videos[0];
});
const directus = getDirectusInstance(fetch);
return directus.request<Video>(
customEndpoint({
method: "GET",
path: `/sexy/videos/${slug}`,
}),
);
},
{ slug },
);