Admin Passwort in die db und in Backen konfiguriebar
This commit is contained in:
@@ -39,6 +39,9 @@
|
||||
<a href="/admin/dienststellen" class="bg-green-600 text-white px-4 py-3 rounded text-center hover:bg-green-700">
|
||||
🏢 Dienststellen verwalten
|
||||
</a>
|
||||
<a href="/admin/change-password" class="bg-cyan-600 text-white px-4 py-3 rounded text-center hover:bg-green-700">
|
||||
👨💼 Passwort ädern
|
||||
</a>
|
||||
</div>
|
||||
<button
|
||||
on:click={async () => {
|
||||
|
||||
82
src/routes/admin/change-password/+page.svelte
Normal file
82
src/routes/admin/change-password/+page.svelte
Normal file
@@ -0,0 +1,82 @@
|
||||
<script lang="ts">
|
||||
let oldPassword = '';
|
||||
let newPassword = '';
|
||||
let confirmPassword = '';
|
||||
let message = '';
|
||||
let error = '';
|
||||
|
||||
async function changePassword() {
|
||||
message = '';
|
||||
error = '';
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
error = 'Die neuen Passwörter stimmen nicht überein.';
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch('/api/admin/change-password', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ oldPassword, newPassword })
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!res.ok) {
|
||||
error = data.error || 'Fehler beim Ändern des Passworts.';
|
||||
} else {
|
||||
message = '✅ Passwort erfolgreich geändert.';
|
||||
oldPassword = newPassword = confirmPassword = '';
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="max-w-lg mx-auto bg-white p-6 rounded-2xl shadow-md space-y-6 border border-gray-200">
|
||||
<h2 class="text-2xl font-bold text-gray-800">🔐 Admin-Passwort ändern</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Altes Passwort</label>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={oldPassword}
|
||||
class="mt-1 w-full px-4 py-2 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Neues Passwort</label>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={newPassword}
|
||||
class="mt-1 w-full px-4 py-2 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Neues Passwort wiederholen</label>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={confirmPassword}
|
||||
class="mt-1 w-full px-4 py-2 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<div class="text-red-600 text-sm font-medium">{error}</div>
|
||||
{/if}
|
||||
{#if message}
|
||||
<div class="text-green-600 text-sm font-medium">{message}</div>
|
||||
{/if}
|
||||
|
||||
<div class="pt-4">
|
||||
<button
|
||||
on:click={changePassword}
|
||||
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-xl transition duration-150"
|
||||
>
|
||||
Passwort ändern
|
||||
</button>
|
||||
</div>
|
||||
30
src/routes/api/admin/change-password/+server.ts
Normal file
30
src/routes/api/admin/change-password/+server.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
function checkAuth(cookies: any) {
|
||||
return cookies.get('admin_session') === 'true';
|
||||
}
|
||||
|
||||
export const POST: RequestHandler = async ({ request, cookies }) => {
|
||||
if (!checkAuth(cookies)) return new Response('Nicht erlaubt', { status: 401 });
|
||||
|
||||
const { oldPassword, newPassword } = await request.json();
|
||||
|
||||
const admin = await prisma.admin.findUnique({ where: { id: 1 } });
|
||||
if (!admin) return json({ error: 'Admin nicht gefunden' }, { status: 500 });
|
||||
|
||||
const isValid = await bcrypt.compare(oldPassword, admin.password);
|
||||
if (!isValid) return json({ error: 'Falsches Passwort' }, { status: 401 });
|
||||
|
||||
const newHashed = await bcrypt.hash(newPassword, 10);
|
||||
await prisma.admin.update({
|
||||
where: { id: 1 },
|
||||
data: { password: newHashed }
|
||||
});
|
||||
|
||||
return json({ success: true });
|
||||
};
|
||||
@@ -1,20 +1,29 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
const ADMIN_PASS = import.meta.env.VITE_ADMIN_PASS;
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export const POST: RequestHandler = async ({ request, cookies }) => {
|
||||
const { passwort } = await request.json();
|
||||
|
||||
if (passwort === ADMIN_PASS) {
|
||||
cookies.set('admin_session', 'true', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'strict',
|
||||
maxAge: 60 * 60 * 4 // 4 Stunden
|
||||
});
|
||||
return json({ success: true });
|
||||
const admin = await prisma.admin.findUnique({ where: { id: 1 } });
|
||||
if (!admin) {
|
||||
return json({ error: 'Kein Admin gefunden' }, { status: 500 });
|
||||
}
|
||||
|
||||
return json({ error: 'Falsches Passwort' }, { status: 401 });
|
||||
};
|
||||
const isValid = await bcrypt.compare(passwort, admin.password);
|
||||
if (!isValid) {
|
||||
return json({ error: 'Falsches Passwort' }, { status: 401 });
|
||||
}
|
||||
|
||||
cookies.set('admin_session', 'true', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'strict',
|
||||
maxAge: 60 * 60 * 4 // 4 Stunden
|
||||
});
|
||||
|
||||
return json({ success: true });
|
||||
};
|
||||
Reference in New Issue
Block a user