feat: implement user authentication with login and register
- Add login screen with email/username support - Add register screen with email validation - Implement AuthStore with expo-secure-store (native) / localStorage (web) - Add X-User-Id header authentication (simple auth without JWT) - Rename displayName to userName across codebase - Add findByUserName() to UserRepository - Check for existing email AND username on registration - Add AuthButton component with shadow effect - Add logout button to Header - Add hash-password.js utility script for manual password resets - Update CORS to allow X-User-Id header
This commit is contained in:
@@ -7,7 +7,12 @@ export class AuthService {
|
||||
constructor(private userRepo: UserRepository) {}
|
||||
|
||||
async login(data: LoginDTO): Promise<AuthResponse> {
|
||||
const user = await this.userRepo.findByEmail(data.email);
|
||||
// Try email first, then userName
|
||||
let user = await this.userRepo.findByEmail(data.identifier);
|
||||
if (!user) {
|
||||
user = await this.userRepo.findByUserName(data.identifier);
|
||||
}
|
||||
|
||||
if (!user || !user.passwordHash) {
|
||||
throw new Error("Invalid credentials");
|
||||
}
|
||||
@@ -21,15 +26,20 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async register(data: CreateUserDTO): Promise<AuthResponse> {
|
||||
const existingUser = await this.userRepo.findByEmail(data.email);
|
||||
if (existingUser) {
|
||||
const existingEmail = await this.userRepo.findByEmail(data.email);
|
||||
if (existingEmail) {
|
||||
throw new Error("Email already exists");
|
||||
}
|
||||
|
||||
const existingUserName = await this.userRepo.findByUserName(data.userName);
|
||||
if (existingUserName) {
|
||||
throw new Error("Username already exists");
|
||||
}
|
||||
|
||||
const passwordHash = await password.hash(data.password);
|
||||
const user = await this.userRepo.create({
|
||||
email: data.email,
|
||||
displayName: data.displayName,
|
||||
userName: data.userName,
|
||||
passwordHash,
|
||||
});
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ import { User } from "@caldav/shared";
|
||||
|
||||
export interface CreateUserData {
|
||||
email: string;
|
||||
displayName: string;
|
||||
userName: string;
|
||||
passwordHash: string;
|
||||
}
|
||||
|
||||
export interface UserRepository {
|
||||
findById(id: string): Promise<User | null>;
|
||||
findByEmail(email: string): Promise<User | null>;
|
||||
findByUserName(userName: string): Promise<User | null>;
|
||||
create(data: CreateUserData): Promise<User>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user