Skip to content
This repository was archived by the owner on Feb 11, 2026. It is now read-only.
Merged
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
78 changes: 78 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
"@node-rs/argon2": "^2.0.2",
"@prisma/adapter-mariadb": "^7.1.0",
"@prisma/client": "^7.1.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"cookie-parser": "^1.4.7",
"dotenv": "^17.2.3",
"express-session": "^1.18.2",
"helmet": "^8.1.0",
"prisma": "^7.1.0",
"reflect-metadata": "^0.2.2",
Expand Down
7 changes: 6 additions & 1 deletion src/application/ports/user.port.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export interface IUserService {}
import { Result } from '@/result';
import { User } from '@/domain/user/user.model';

export interface IUserService {
findById(id: string): Promise<Result<User>>;
}
6 changes: 6 additions & 0 deletions src/application/services/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { type IUserRepository } from '@/domain/user/user-repository.interface';
import { IUserService } from '@/application/ports/user.port';
import { Inject, Injectable } from '@nestjs/common';
import { Result } from '@/result';
import { User } from '@/domain/user/user.model';

@Injectable()
export class UserService implements IUserService {
Expand All @@ -9,4 +11,8 @@ export class UserService implements IUserService {
constructor(@Inject('REPO.USER') _userRepository: IUserRepository) {
this.userRepository = _userRepository;
}

async findById(id: string): Promise<Result<User>> {
return this.userRepository.findById(id);
}
}
5 changes: 3 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ async function bootstrap() {
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
resave: true,
saveUninitialized: false,
rolling: true, // Reset maxAge on every request
cookie: {
// For cross-site requests (frontend != backend) browsers require SameSite='None' and Secure=true
sameSite: isProduction ? 'none' : 'lax',
secure: isProduction,
httpOnly: true,
maxAge: 1000 * 60 * 60 * 1, // One hour
maxAge: 1000 * 60 * 60 * 24, // 24 hours
},
}),
);
Expand Down
54 changes: 52 additions & 2 deletions src/presentation/controllers/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
import { Controller } from '@nestjs/common';
import { SessionData } from '@/types/session.types';
import { UserDTO } from '@/presentation/dtos/user.dto';
import { IUserService } from '@/application/ports/user.port';
import { User } from '@/domain/user/user.model';
import { Result } from '@/result';
import {
Controller,
Get,
Inject,
NotFoundException,
Session,
UnauthorizedException,
} from '@nestjs/common';

@Controller('user')
export class UserController {}
export class UserController {
private readonly userService: IUserService;

constructor(@Inject('SERVICE.USER') _userService: IUserService) {
this.userService = _userService;
}

@Get('profile')
async getProfile(
@Session() session: SessionData,
): Promise<{ user: UserDTO }> {
if (!session || !session.user) {
throw new UnauthorizedException('No active session');
}

const result: Result<User> = await this.userService.findById(
session.user.id,
);
if (result._tag === 'Failure' || !result.data) {
throw new NotFoundException('User not found');
}

const freshUser = result.data;
session.user = freshUser;

return { user: this.toUserDto(freshUser) };
}

private toUserDto(user: User): UserDTO {
const dto = new UserDTO();
dto.id = user.id;
dto.name = user.name;
dto.email = user.email;
dto.role = user.role;
dto.createdAt = user.createdAt;
dto.updatedAt = user.updatedAt;
return dto;
}
}