V 2.1.0 Verbesserungen von Claud Code eingefügt
This commit is contained in:
@@ -12,7 +12,7 @@ export async function login(prevState: any, formData: FormData) {
|
|||||||
return { error: 'Bitte Benutzername und Passwort eingeben' };
|
return { error: 'Bitte Benutzername und Passwort eingeben' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const isValid = verifyCredentials(username, password);
|
const isValid = await verifyCredentials(username, password);
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
return { error: 'Ungültige Anmeldedaten' };
|
return { error: 'Ungültige Anmeldedaten' };
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export default function Home() {
|
|||||||
'Cache-Control': 'no-cache',
|
'Cache-Control': 'no-cache',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setEntries(data.data);
|
setEntries(data.data);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export default function MonatsStatistik({ typ, refreshKey }: MonatsStatistikProp
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/ausgaben/stats?year=${y}&month=${m}&typ=${typ}`);
|
const response = await fetch(`/api/ausgaben/stats?year=${y}&month=${m}&typ=${typ}`);
|
||||||
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.success) setStats(data.data);
|
if (data.success) setStats(data.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ echo "Registry: ${REGISTRY}"
|
|||||||
echo "Image: ${IMAGE_NAME}"
|
echo "Image: ${IMAGE_NAME}"
|
||||||
echo "Tag: ${TAG}"
|
echo "Tag: ${TAG}"
|
||||||
echo "Build-Datum: ${BUILD_DATE}"
|
echo "Build-Datum: ${BUILD_DATE}"
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
|||||||
22
lib/auth.ts
22
lib/auth.ts
@@ -1,20 +1,10 @@
|
|||||||
/**
|
import bcrypt from 'bcryptjs';
|
||||||
* Reusable authentication library
|
|
||||||
* Configure users via environment variables in .env:
|
|
||||||
* AUTH_USERS=user1:$2a$10$hash1,user2:$2a$10$hash2
|
|
||||||
*
|
|
||||||
* Use scripts/generate-password.js to generate password hashes
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse users from environment variable
|
|
||||||
* Format: username:password,username2:password2
|
|
||||||
*/
|
|
||||||
export function getUsers(): User[] {
|
export function getUsers(): User[] {
|
||||||
const usersString = process.env.AUTH_USERS || '';
|
const usersString = process.env.AUTH_USERS || '';
|
||||||
if (!usersString) {
|
if (!usersString) {
|
||||||
@@ -30,21 +20,15 @@ export function getUsers(): User[] {
|
|||||||
.filter((user) => user.username && user.password);
|
.filter((user) => user.username && user.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export async function verifyCredentials(username: string, password: string): Promise<boolean> {
|
||||||
* Verify user credentials
|
|
||||||
*/
|
|
||||||
export function verifyCredentials(username: string, password: string): boolean {
|
|
||||||
const users = getUsers();
|
const users = getUsers();
|
||||||
const user = users.find(u => u.username === username);
|
const user = users.find(u => u.username === username);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return user.password === password;
|
return bcrypt.compare(password, user.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if authentication is enabled
|
|
||||||
*/
|
|
||||||
export function isAuthEnabled(): boolean {
|
export function isAuthEnabled(): boolean {
|
||||||
return !!process.env.AUTH_USERS;
|
return !!process.env.AUTH_USERS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,20 @@ import type { NextConfig } from "next";
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/(.*)',
|
||||||
|
headers: [
|
||||||
|
{ key: 'X-Frame-Options', value: 'DENY' },
|
||||||
|
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
||||||
|
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
||||||
|
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
|
||||||
|
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ausgaben_next",
|
"name": "ausgaben_next",
|
||||||
"version": "2.0.2",
|
"version": "2.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3005",
|
"dev": "next dev -p 3005",
|
||||||
|
|||||||
Reference in New Issue
Block a user