diff --git a/README.md b/README.md
index 9efebb3..36baed5 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,24 @@ Open [http://localhost:3000](http://localhost:3000) in your browser.
4. Review and run `npm run db:push`
5. Update relevant server actions and components
+## Admin Signup System
+
+The platform automatically generates a one-time admin token on startup if no admin exists in the database. This token is logged to the console and can only be used once.
+
+### Upgrading to Admin Account
+
+1. Sign in with your regular account
+2. Try to access `/admin`
+3. You'll see a form asking for the admin token
+4. Paste the token from the console output
+5. Click "Admin aktivieren" to upgrade your account
+
+After successful upgrade:
+- The token becomes invalid
+- Your account gains full admin privileges
+- No new token is generated (admin now exists)
+- Trying to upgrade another account will fail (token is spent)
+
## Development Notes
- Database schema is defined in `src/lib/model/`
diff --git a/src/app/actions/set-user-admin.ts b/src/app/actions/set-user-admin.ts
new file mode 100644
index 0000000..6697ad7
--- /dev/null
+++ b/src/app/actions/set-user-admin.ts
@@ -0,0 +1,30 @@
+'use server';
+
+import { auth } from '@/lib/auth';
+import db from '@/lib/db';
+import { user } from '@/lib/model/auth-schema';
+import { eq } from 'drizzle-orm';
+import { headers } from 'next/headers';
+import { verifyAdminToken } from './verify-admin-token';
+
+export async function setUserAsAdmin(email: string, adminToken: string): Promise<{ success: boolean; error?: string }> {
+ // Verify the token is valid
+ const tokenResult = await verifyAdminToken(adminToken);
+
+ if (!tokenResult.valid) {
+ return { success: false, error: 'Invalid or expired admin token' };
+ }
+
+ try {
+ // Update user admin flag
+ await db.update(user).set({ admin: true }).where(eq(user.email, email));
+
+ // Clear the token so it can't be used again
+ delete process.env.ADMIN_SIGNUP_TOKEN;
+
+ return { success: true };
+ } catch (error) {
+ console.error('Error setting admin:', error);
+ return { success: false, error: 'Failed to set admin status' };
+ }
+}
diff --git a/src/app/actions/verify-admin-token.ts b/src/app/actions/verify-admin-token.ts
new file mode 100644
index 0000000..528d666
--- /dev/null
+++ b/src/app/actions/verify-admin-token.ts
@@ -0,0 +1,14 @@
+'use server';
+
+export async function verifyAdminToken(token: string): Promise<{ valid: boolean }> {
+ const storedToken = process.env.ADMIN_SIGNUP_TOKEN;
+
+ // Token is invalid if:
+ // 1. No token exists (already used or no token was generated)
+ // 2. Provided token doesn't match
+ if (!storedToken || token !== storedToken) {
+ return { valid: false };
+ }
+
+ return { valid: true };
+}
diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index 2a718b0..53a729b 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -1,5 +1,6 @@
import DatasetsList from "@/components/DatasetsList";
import CreateDatasetModal from "@/components/CreateDatasetModal";
+import { AdminTokenForm } from "@/components/AdminTokenForm";
import { requireAdmin } from "@/lib/auth";
import { redirect } from "next/navigation";
import Link from "next/link";
@@ -12,7 +13,7 @@ export default async function AdminPage() {
}
if (!result.admin) {
- redirect("/");
+ return
+ Sie benötigen Admin-Rechte, um diese Seite zu besuchen +
+