Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ on:
pull_request:
branches: [main, master]

permissions:
contents: read
issues: read
pull-requests: read

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.VWC_GITHUB_TOKEN }}

jobs:
test:
Expand Down
66 changes: 35 additions & 31 deletions src/pages/admin/blog-images.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/**
* Admin page for managing blog images
* Accessible at /admin/blog-images
* Protected by server-side authentication
*/

import React, { useEffect, useState } from 'react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import type { GetServerSideProps } from 'next';
import { getServerSession } from 'next-auth/next';
import { options } from '@/pages/api/auth/options';
import BlogImageManager from '@/components/blog-image-manager';
import {
getAllBlogImages,
Expand All @@ -15,44 +17,17 @@ import {
} from '@/lib/blog-images';

const BlogImagesAdminPage: React.FC = () => {
const { data: session, status } = useSession();
const router = useRouter();
const [stats, setStats] = useState<ReturnType<typeof getBlogImageStats> | null>(null);
const [allImages, setAllImages] = useState<BlogImageInfo[]>([]);
const [nonCloudinaryImages, setNonCloudinaryImages] = useState<BlogImageInfo[]>([]);
const [activeTab, setActiveTab] = useState<'manager' | 'stats' | 'list'>('manager');

useEffect(() => {
if (status === 'loading') return;

if (!session) {
router.push('/login');
return;
}

// Check if user is admin
if (session.user?.role !== 'ADMIN') {
router.push('/dashboard');
return;
}

// Load blog image data
// Load blog image data on mount
setStats(getBlogImageStats());
setAllImages(getAllBlogImages());
setNonCloudinaryImages(getBlogsWithoutCloudinaryImages());
}, [session, status, router]);

if (status === 'loading') {
return (
<div style={{ padding: '40px', textAlign: 'center' }}>
<p>Loading...</p>
</div>
);
}

if (!session || session.user?.role !== 'ADMIN') {
return null;
}
}, []);

return (
<div style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
Expand Down Expand Up @@ -290,4 +265,33 @@ const BlogImagesAdminPage: React.FC = () => {
);
};

export const getServerSideProps: GetServerSideProps = async (context) => {
// Check authentication
const session = await getServerSession(context.req, context.res, options);

// Redirect if not authenticated
if (!session?.user) {
return {
redirect: {
destination: '/login?callbackUrl=/admin/blog-images',
permanent: false,
},
};
}

// Check for ADMIN role
if (session.user.role !== 'ADMIN') {
return {
redirect: {
destination: '/',
permanent: false,
},
};
}

return {
props: {},
};
};

export default BlogImagesAdminPage;
Loading