project setup with core files including configuration, package management, and basic structure. Added .gitignore, README, and various TypeScript types for CMS components. Implemented initial components and layouts for the application.

This commit is contained in:
Peter Meier
2025-12-13 23:26:13 +01:00
parent ea288a5bbc
commit b1a556dc6d
167 changed files with 19057 additions and 131 deletions

View File

@@ -0,0 +1,140 @@
import type {
User,
UserRole,
LoginCredentials,
RegisterData,
} from "../types/user.js";
import { hashPassword, comparePassword } from "./password.js";
import { createToken, verifyToken } from "./jwt.js";
import { logger } from "../monitoring/logger.js";
/**
* Mock User Store (später durch Datenbank ersetzen)
*/
const users = new Map<string, User & { passwordHash: string }>();
/**
* User Service für Authentication
*/
export class UserService {
/**
* Registriert einen neuen User
*/
async register(
data: RegisterData,
role: UserRole = "customer"
): Promise<{
user: User;
token: string;
}> {
// Prüfe ob User bereits existiert
const existingUser = Array.from(users.values()).find(
(u) => u.email === data.email
);
if (existingUser) {
throw new Error("User mit dieser E-Mail existiert bereits");
}
// Hashe Passwort
const passwordHash = await hashPassword(data.password);
// Erstelle User
const user: User = {
id: `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
email: data.email,
name: data.name,
role,
createdAt: new Date(),
};
// Speichere User
users.set(user.id, { ...user, passwordHash });
// Erstelle Token
const token = createToken({
userId: user.id,
email: user.email,
role: user.role,
});
logger.info("User registered", { userId: user.id, email: user.email });
return { user, token };
}
/**
* Login eines Users
*/
async login(credentials: LoginCredentials): Promise<{
user: User;
token: string;
}> {
// Finde User
const userEntry = Array.from(users.values()).find(
(u) => u.email === credentials.email
);
if (!userEntry) {
throw new Error("Ungültige E-Mail oder Passwort");
}
// Vergleiche Passwort
const isValid = await comparePassword(
credentials.password,
userEntry.passwordHash
);
if (!isValid) {
throw new Error("Ungültige E-Mail oder Passwort");
}
// Erstelle User-Objekt ohne Passwort
const user: User = {
id: userEntry.id,
email: userEntry.email,
name: userEntry.name,
role: userEntry.role,
createdAt: userEntry.createdAt,
};
// Erstelle Token
const token = createToken({
userId: user.id,
email: user.email,
role: user.role,
});
logger.info("User logged in", { userId: user.id, email: user.email });
return { user, token };
}
/**
* Holt User anhand der ID
*/
async getUserById(userId: string): Promise<User | null> {
const userEntry = users.get(userId);
if (!userEntry) return null;
return {
id: userEntry.id,
email: userEntry.email,
name: userEntry.name,
role: userEntry.role,
createdAt: userEntry.createdAt,
};
}
/**
* Holt User anhand des Tokens
*/
async getUserFromToken(token: string): Promise<User | null> {
const payload = verifyToken(token);
if (!payload) return null;
return this.getUserById(payload.userId);
}
}
// Singleton-Instanz
export const userService = new UserService();