Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions lib/auth/authService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { describe, it, expect } from 'vitest';
import { authService } from './authService';

describe('Authentication Service', () => {
it('should register a new user', async () => {
const result = await authService.register({
email: 'test@example.com',
password: 'password123',
confirmPassword: 'password123'
});

expect(result.success).toBe(true);
expect(result.user?.email).toBe('test@example.com');
expect(result.token).toBeTruthy();
});

it('should not register a user with mismatched passwords', async () => {
const result = await authService.register({
email: 'test2@example.com',
password: 'password123',
confirmPassword: 'differentpassword'
});

expect(result.success).toBe(false);
expect(result.message).toBe('Passwords do not match');
});

it('should not register a user with existing email', async () => {
await authService.register({
email: 'duplicate@example.com',
password: 'password123',
confirmPassword: 'password123'
});

const result = await authService.register({
email: 'duplicate@example.com',
password: 'password456',
confirmPassword: 'password456'
});

expect(result.success).toBe(false);
expect(result.message).toBe('User already exists');
});

it('should login a registered user', async () => {
await authService.register({
email: 'login@example.com',
password: 'password123',
confirmPassword: 'password123'
});

const result = await authService.login({
email: 'login@example.com',
password: 'password123'
});

expect(result.success).toBe(true);
expect(result.user?.email).toBe('login@example.com');
expect(result.token).toBeTruthy();
});

it('should not login with incorrect password', async () => {
await authService.register({
email: 'logintest@example.com',
password: 'password123',
confirmPassword: 'password123'
});

const result = await authService.login({
email: 'logintest@example.com',
password: 'wrongpassword'
});

expect(result.success).toBe(false);
expect(result.message).toBe('Invalid email or password');
});
});
90 changes: 90 additions & 0 deletions lib/auth/authService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { LoginCredentials, RegisterCredentials, AuthResponse, User } from '../../types/auth';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';

const JWT_SECRET = process.env.JWT_SECRET || 'fallback_secret';
const SALT_ROUNDS = 10;

// In-memory user store (replace with database in production)
const users: User[] = [];

export const authService = {
async register(credentials: RegisterCredentials): Promise<AuthResponse> {
const { email, password, confirmPassword } = credentials;

// Validate inputs
if (!email || !password) {
return { success: false, message: 'Email and password are required' };
}

if (password !== confirmPassword) {
return { success: false, message: 'Passwords do not match' };
}

// Check if user already exists
const existingUser = users.find(u => u.email === email);
if (existingUser) {
return { success: false, message: 'User already exists' };
}

// Hash password
const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS);

// Create user
const newUser: User = {
id: Date.now().toString(),
email,
password: hashedPassword,
createdAt: new Date(),
updatedAt: new Date()
};

users.push(newUser);

// Generate token
const token = jwt.sign({ id: newUser.id, email: newUser.email }, JWT_SECRET, { expiresIn: '1h' });

return {
success: true,
message: 'User registered successfully',
user: {
id: newUser.id,
email: newUser.email,
createdAt: newUser.createdAt,
updatedAt: newUser.updatedAt
},
token
};
},

async login(credentials: LoginCredentials): Promise<AuthResponse> {
const { email, password } = credentials;

// Find user
const user = users.find(u => u.email === email);
if (!user) {
return { success: false, message: 'Invalid email or password' };
}

// Check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return { success: false, message: 'Invalid email or password' };
}

// Generate token
const token = jwt.sign({ id: user.id, email: user.email }, JWT_SECRET, { expiresIn: '1h' });

return {
success: true,
message: 'Login successful',
user: {
id: user.id,
email: user.email,
createdAt: user.createdAt,
updatedAt: user.updatedAt
},
token
};
}
};
Loading