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:
@@ -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
|
// GET /sexy/articles - List articles
|
||||||
router.get("/articles", async (req, res) => {
|
router.get("/articles", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -242,41 +242,13 @@ export async function getVideoBySlug(
|
|||||||
return loggedApiCall(
|
return loggedApiCall(
|
||||||
"getVideoBySlug",
|
"getVideoBySlug",
|
||||||
async () => {
|
async () => {
|
||||||
const fetchFn = fetch || globalThis.fetch;
|
const directus = getDirectusInstance(fetch);
|
||||||
return fetchFn(
|
return directus.request<Video>(
|
||||||
`${directusApiUrl}/items/sexy_videos?${new URLSearchParams({
|
customEndpoint({
|
||||||
filter: JSON.stringify({ slug: { _eq: slug } }),
|
method: "GET",
|
||||||
fields: JSON.stringify([
|
path: `/sexy/videos/${slug}`,
|
||||||
"*",
|
}),
|
||||||
{
|
);
|
||||||
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];
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
{ slug },
|
{ slug },
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user