Android CI / RC / Android · lint, tests, debug APK, release compile (push) Failing after 1m25s
DH V2 CI / API · typecheck, tests, build (push) Successful in 34s
DH V2 CI / WEB · typecheck, build (push) Successful in 20s
Production dependency audit / API · production dependencies (push) Successful in 9s
Production dependency audit / WEB · production dependencies (push) Successful in 9s
DH V2 CI / Docker / scripts contract (push) Successful in 1m16s
174 lines
5.7 KiB
TypeScript
174 lines
5.7 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Get,
|
|
Param,
|
|
ParseUUIDPipe,
|
|
Patch,
|
|
Post,
|
|
Put,
|
|
Query,
|
|
Req,
|
|
} from '@nestjs/common';
|
|
import { AuditService } from '../../audit/audit.service';
|
|
import { RequirePermissions } from '../../authorization/decorators/require-permissions.decorator';
|
|
import { CurrentAuth } from '../../auth/decorators/current-auth.decorator';
|
|
import type {
|
|
AuthPrincipal,
|
|
RequestWithContext,
|
|
} from '../../common/http/request-context';
|
|
import { AuditAction } from '../../database/entities';
|
|
import { SmtpDeliveryService } from '../../inspection-reports/smtp-delivery.service';
|
|
import { administrationAuditContext } from '../common/administration-audit';
|
|
import { ChangeUserStatusDto } from './dto/change-user-status.dto';
|
|
import { CreateUserDto } from './dto/create-user.dto';
|
|
import { ListUsersQueryDto } from './dto/list-users-query.dto';
|
|
import { ReplaceUserRolesDto } from './dto/replace-user-roles.dto';
|
|
import { ResetUserPasswordDto } from './dto/reset-user-password.dto';
|
|
import { UpdateSelfProfileDto } from './dto/update-self-profile.dto';
|
|
import { UpdateUserSmtpSettingsDto } from './dto/update-user-smtp-settings.dto';
|
|
import { UpdateUserDto } from './dto/update-user.dto';
|
|
import { UsersService } from './users.service';
|
|
|
|
@Controller('users')
|
|
export class UsersController {
|
|
constructor(
|
|
private readonly users: UsersService,
|
|
private readonly smtp: SmtpDeliveryService,
|
|
private readonly audit: AuditService,
|
|
) {}
|
|
|
|
@Get()
|
|
@RequirePermissions('users.read')
|
|
list(@Query() query: ListUsersQueryDto) {
|
|
return this.users.list(query);
|
|
}
|
|
|
|
@Get('self/profile')
|
|
selfProfile(@CurrentAuth() principal: AuthPrincipal) {
|
|
return this.users.getSelfProfile(principal.userId);
|
|
}
|
|
|
|
@Patch('self/profile')
|
|
updateSelfProfile(
|
|
@Body() dto: UpdateSelfProfileDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.updateSelfProfile(dto, principal, request);
|
|
}
|
|
|
|
@Get('self/smtp')
|
|
selfSmtp(@CurrentAuth() principal: AuthPrincipal) {
|
|
return this.smtp.publicUserSettings(principal.userId);
|
|
}
|
|
|
|
@Put('self/smtp')
|
|
async updateSelfSmtp(
|
|
@Body() dto: UpdateUserSmtpSettingsDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
const before = await this.smtp.publicUserSettings(principal.userId);
|
|
const after = await this.smtp.saveUserSettings(principal.userId, dto);
|
|
await this.audit.record({
|
|
...administrationAuditContext(principal, request),
|
|
action: AuditAction.USER_SMTP_SETTINGS_UPDATED,
|
|
entityType: 'user_smtp_settings',
|
|
entityId: principal.userId,
|
|
beforeData: before as Record<string, unknown>,
|
|
afterData: after as Record<string, unknown>,
|
|
metadata: { passwordNeverReturned: true, scope: 'SELF' },
|
|
});
|
|
return after;
|
|
}
|
|
|
|
@Post('self/smtp/test')
|
|
async testSelfSmtp(
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
const profile = await this.users.getSelfProfile(principal.userId);
|
|
if (!profile.email) throw new Error('El usuario no tiene email configurado');
|
|
const sent = await this.smtp.send({
|
|
to: profile.email,
|
|
subject: 'DH Inspección · Prueba de correo personal',
|
|
text: 'Este correo confirma que tu configuración de correo en DH Inspección funciona correctamente.',
|
|
attachment: {
|
|
filename: 'dh-inspeccion-prueba-correo.txt',
|
|
mimeType: 'text/plain',
|
|
content: Buffer.from('DH Inspección · Correo personal OK\n', 'utf8'),
|
|
},
|
|
}, principal.userId);
|
|
await this.audit.record({
|
|
...administrationAuditContext(principal, request),
|
|
action: AuditAction.USER_SMTP_TEST_SENT,
|
|
entityType: 'user_smtp_settings',
|
|
entityId: principal.userId,
|
|
afterData: { recipient: profile.email, messageId: sent.messageId },
|
|
metadata: { scope: 'SELF' },
|
|
});
|
|
return { ok: true, recipient: profile.email, messageId: sent.messageId };
|
|
}
|
|
|
|
@Post()
|
|
@RequirePermissions('users.create')
|
|
create(
|
|
@Body() dto: CreateUserDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.create(dto, principal, request);
|
|
}
|
|
|
|
@Get(':id')
|
|
@RequirePermissions('users.read')
|
|
getById(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) {
|
|
return this.users.getById(id);
|
|
}
|
|
|
|
@Patch(':id')
|
|
@RequirePermissions('users.update')
|
|
update(
|
|
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
|
|
@Body() dto: UpdateUserDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.update(id, dto, principal, request);
|
|
}
|
|
|
|
@Patch(':id/status')
|
|
@RequirePermissions('users.change_status')
|
|
changeStatus(
|
|
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
|
|
@Body() dto: ChangeUserStatusDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.changeStatus(id, dto, principal, request);
|
|
}
|
|
|
|
@Post(':id/reset-password')
|
|
@RequirePermissions('users.update')
|
|
resetPassword(
|
|
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
|
|
@Body() dto: ResetUserPasswordDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.resetPassword(id, dto, principal, request);
|
|
}
|
|
|
|
@Put(':id/roles')
|
|
@RequirePermissions('users.assign_roles')
|
|
replaceRoles(
|
|
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
|
|
@Body() dto: ReplaceUserRolesDto,
|
|
@CurrentAuth() principal: AuthPrincipal,
|
|
@Req() request: RequestWithContext,
|
|
) {
|
|
return this.users.replaceRoles(id, dto, principal, request);
|
|
}
|
|
}
|