105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import { container } from '../config/dependency-injector.config.js';
|
|
import { Request, Response } from 'express';
|
|
import { AuthService } from '../services/auth.service.js';
|
|
import { TokenService } from '../services/token.service.js';
|
|
import { LoggerService } from '../services/logger.service.js';
|
|
import {
|
|
ACCESS_TOKEN_COOKIE_NAME,
|
|
MEET_ACCESS_TOKEN_EXPIRATION,
|
|
MEET_API_BASE_PATH_V1,
|
|
MEET_REFRESH_TOKEN_EXPIRATION,
|
|
REFRESH_TOKEN_COOKIE_NAME
|
|
} from '../environment.js';
|
|
import { ClaimGrants } from 'livekit-server-sdk';
|
|
import { getCookieOptions } from '../utils/cookie-utils.js';
|
|
import { UserService } from '../services/user.service.js';
|
|
|
|
export const login = async (req: Request, res: Response) => {
|
|
const logger = container.get(LoggerService);
|
|
logger.verbose('Login request received');
|
|
const { username, password } = req.body as { username: string; password: string };
|
|
|
|
const authService = container.get(AuthService);
|
|
const user = await authService.authenticate(username, password);
|
|
|
|
if (!user) {
|
|
logger.warn('Login failed');
|
|
return res.status(404).json({ message: 'Login failed. Invalid username or password' });
|
|
}
|
|
|
|
try {
|
|
const tokenService = container.get(TokenService);
|
|
const accessToken = await tokenService.generateAccessToken(user);
|
|
const refreshToken = await tokenService.generateRefreshToken(user);
|
|
res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, getCookieOptions('/', MEET_ACCESS_TOKEN_EXPIRATION));
|
|
res.cookie(
|
|
REFRESH_TOKEN_COOKIE_NAME,
|
|
refreshToken,
|
|
getCookieOptions(`${MEET_API_BASE_PATH_V1}/auth`, MEET_REFRESH_TOKEN_EXPIRATION)
|
|
);
|
|
logger.info(`Login succeeded for user ${username}`);
|
|
return res.status(200).json({ message: 'Login succeeded' });
|
|
} catch (error) {
|
|
logger.error('Error generating token' + error);
|
|
return res.status(500).json({ message: 'Internal server error' });
|
|
}
|
|
};
|
|
|
|
export const logout = (_req: Request, res: Response) => {
|
|
res.clearCookie(ACCESS_TOKEN_COOKIE_NAME);
|
|
res.clearCookie(REFRESH_TOKEN_COOKIE_NAME, {
|
|
path: `${MEET_API_BASE_PATH_V1}/auth`
|
|
});
|
|
return res.status(200).json({ message: 'Logout successful' });
|
|
};
|
|
|
|
export const refreshToken = async (req: Request, res: Response) => {
|
|
const logger = container.get(LoggerService);
|
|
logger.verbose('Refresh token request received');
|
|
const refreshToken = req.cookies[REFRESH_TOKEN_COOKIE_NAME];
|
|
|
|
if (!refreshToken) {
|
|
logger.warn('No refresh token provided');
|
|
return res.status(400).json({ message: 'No refresh token provided' });
|
|
}
|
|
|
|
const tokenService = container.get(TokenService);
|
|
let payload: ClaimGrants;
|
|
|
|
try {
|
|
payload = await tokenService.verifyToken(refreshToken);
|
|
} catch (error) {
|
|
logger.error('Error verifying refresh token' + error);
|
|
return res.status(400).json({ message: 'Invalid refresh token' });
|
|
}
|
|
|
|
const username = payload.sub;
|
|
const userService = container.get(UserService);
|
|
const user = username ? await userService.getUser(username) : null;
|
|
|
|
if (!user) {
|
|
logger.warn('Invalid refresh token subject');
|
|
return res.status(403).json({ message: 'Invalid refresh token subject' });
|
|
}
|
|
|
|
try {
|
|
const accessToken = await tokenService.generateAccessToken(user);
|
|
res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, getCookieOptions('/', MEET_ACCESS_TOKEN_EXPIRATION));
|
|
logger.info(`Token refreshed for user ${username}`);
|
|
return res.status(200).json({ message: 'Token refreshed' });
|
|
} catch (error) {
|
|
logger.error('Error refreshing token' + error);
|
|
return res.status(500).json({ message: 'Internal server error' });
|
|
}
|
|
};
|
|
|
|
export const getProfile = (req: Request, res: Response) => {
|
|
const user = req.session?.user;
|
|
|
|
if (!user) {
|
|
return res.status(401).json({ message: 'Unauthorized' });
|
|
}
|
|
|
|
return res.status(200).json(user);
|
|
};
|