Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { UserSupervisorAuthenticated } from "../model/users/user-supervisor";

export const USER_SUPERVISOR_AUTH: UserSupervisorAuthenticated = {
id: 1,
uuid: "admin-uuid-123",
nom: "Admin",
prenom: "Test",
email: "admin@test.com",
role: "national",
verified: true,
createdAt: new Date(),
lastLogin: new Date(),
acceptTerms: new Date(),
_userProfile: "supervisor",
_userId: 1,
};
3 changes: 3 additions & 0 deletions packages/backend/src/_common/model/app-log/LogAction.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export type LogAction =
| "IMPORT_USAGERS_FAILED" // Import échoué
| "DOWNLOAD_IMPORT_TEMPLATE" // Téléchargement modèle Excel
| "DOWNLOAD_IMPORT_GUIDE" // Téléchargement guide PDF
| "USER_ROLE_CHANGE"
| "USER_CREATE"
| "USER_DELETE"
// ADMIN
| "ADMIN_STRUCTURE_VALIDATE"
| "ADMIN_STRUCTURE_DELETE"
Expand Down
15 changes: 15 additions & 0 deletions packages/backend/src/modules/app-logs/app-log-context.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,18 @@ export type AdminUserRoleChangeLogContext = {
oldRole: UserSupervisorRole;
newRole: UserSupervisorRole;
};

export type UserStructureRoleChangeLogContext = {
// USER_ROLE_CHANGE
userId: number;
structureId: number;
oldRole: UserStructureRole;
newRole: UserStructureRole;
};

export type UserStructureCreateLogContext = {
// USER_CREATE
userId: number;
structureId: number;
role: UserStructureRole;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AdminSuperivorUsersService } from "../../services/admin-superivor-users
import { ElevateUserRoleDto } from "../../dto/elevate-user-role.dto";
import { userStructureRepository } from "../../../../database";
import { EntityNotFoundError } from "typeorm";
import { USER_STRUCTURE_AUTH } from "../../../../_common/mocks/USER_STRUCTURE_AUTHENTIFICATED.mock";
import { USER_SUPERVISOR_AUTH } from "../../../../_common/mocks/USER_SUPERVISOR_AUTHENTIFICATED.mock";
// Mock the repository
jest.mock("../../../../database", () => ({
userStructureRepository: {
Expand All @@ -25,7 +25,7 @@ describe("AdminUsersController", () => {
let controller: AdminUsersController;
let mockUserStructureRepository: jest.Mocked<typeof userStructureRepository>;
let appLogService: AppLogsService;
const mockCurrentUser = USER_STRUCTURE_AUTH;
const mockCurrentUser = USER_SUPERVISOR_AUTH;

const mockUserToElevate = {
id: 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import {
} from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { ApiTags, ApiBearerAuth, ApiOperation } from "@nestjs/swagger";
import { UserStructureAuthenticated } from "../../../../_common/model";
import { UserAdminAuthenticated } from "../../../../_common/model";
import {
AllowUserProfiles,
AllowUserSupervisorRoles,
CurrentUser,
} from "../../../../auth/decorators";
import { AppUserGuard } from "../../../../auth/guards";
import { appLogger, ExpressResponse } from "../../../../util";
Expand All @@ -44,6 +43,7 @@ import {
AdminUserCrudLogContext,
AdminUserRoleChangeLogContext,
} from "../../../app-logs/app-log-context.types";
import { CurrentSupervisor } from "../../../../auth/decorators/current-supervisor.decorator";

@UseGuards(AuthGuard("jwt"), AppUserGuard)
@ApiTags("dashboard")
Expand All @@ -59,11 +59,11 @@ export class AdminUsersController {

@Post("register-user-structure")
public async registerUserStructureAdmin(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentSupervisor() user: UserAdminAuthenticated,
@Res() res: ExpressResponse,
@Body() registerUserDto: RegisterUserStructureAdminDto
): Promise<ExpressResponse> {
const userController = new UsersController();
const userController = new UsersController(this.appLogsService);
await this.appLogsService.create({
userId: user.id,
action: "ADMIN_CREATE_USER_STRUCTURE",
Expand All @@ -73,7 +73,7 @@ export class AdminUsersController {

@Patch("elevate-user-role")
public async elevateUserRoleToAdmin(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentSupervisor() user: UserAdminAuthenticated,
@Res() res: ExpressResponse,
@Body() elevateRoleDto: ElevateUserRoleDto
): Promise<ExpressResponse> {
Expand Down Expand Up @@ -113,7 +113,7 @@ export class AdminUsersController {

@Post("register-user-supervisor")
public async registerNewSupervisor(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentSupervisor() user: UserAdminAuthenticated,
@Res() res: ExpressResponse,
@Body() registerUserDto: RegisterUserSupervisorDto
): Promise<ExpressResponse> {
Expand Down Expand Up @@ -202,7 +202,7 @@ export class AdminUsersController {

@Patch(":uuid")
public async patchUserSupervisor(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentSupervisor() user: UserAdminAuthenticated,
@Res() res: ExpressResponse,
@Body() patchUserDto: PatchUserSupervisorDto,
@Param("uuid", new ParseUUIDPipe()) uuid: string
Expand Down Expand Up @@ -239,7 +239,7 @@ export class AdminUsersController {

@Delete(":uuid")
public async deleteUserSupervisor(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentSupervisor() user: UserAdminAuthenticated,
@Res() res: ExpressResponse,
@Param("uuid", new ParseUUIDPipe()) uuid: string
): Promise<ExpressResponse> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,26 @@ import { POST_USER_STRUCTURE_BODY } from "../../../_common/mocks";
import { TESTS_USERS_STRUCTURE } from "../../../_tests";
import { usersDeletor } from "../services/users-deletor.service";
import { MailsModule } from "../../mails/mails.module";
import { AppLogsService } from "../../app-logs/app-logs.service";
import { userStructureRepository } from "../../../database";

describe("Users Controller", () => {
let controller: UsersController;
let context: AppTestContext;

let appLogService: AppLogsService;
beforeAll(async () => {
appLogService = {
create: jest.fn(),
};
context = await AppTestHelper.bootstrapTestApp({
controllers: [UsersController],
imports: [MailsModule, StructuresModule, UsagersModule, HttpModule],
providers: [
{
provide: AppLogsService,
useValue: appLogService,
},
],
});

const authInfo =
Expand Down Expand Up @@ -55,6 +66,18 @@ describe("Users Controller", () => {
},
});

const user = await userStructureRepository.findOneByOrFail({
email: "test@test.com",
});
expect(appLogService.create).toHaveBeenCalledWith({
action: "USER_CREATE",
userId: context.user.userId,
context: {
role: POST_USER_STRUCTURE_BODY.role,
structureId: 1,
userId: user.id,
},
});
expect(response.status).toBe(200);
expect(response.text).toBe('{"message":"OK"}');
});
Expand Down
42 changes: 40 additions & 2 deletions packages/backend/src/modules/users/controllers/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger";
import { Response } from "express";
import {
USER_STRUCTURE_ROLE_ALL,
UserAdminAuthenticated,
UserProfile,
UserStructureAuthenticated,
} from "../../../_common/model";
Expand Down Expand Up @@ -46,6 +47,11 @@ import {
} from "../services";
import { userAccountCreatedByAdminEmailSender } from "../../mails/services/templates-renderers";
import { RegisterUserStructureAdminDto } from "../../portail-admin";
import { AppLogsService } from "../../app-logs/app-logs.service";
import {
UserStructureCreateLogContext,
UserStructureRoleChangeLogContext,
} from "../../app-logs/app-log-context.types";

const userProfile: UserProfile = "structure";

Expand All @@ -55,6 +61,7 @@ const userProfile: UserProfile = "structure";
@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL)
@UseGuards(AuthGuard("jwt"), AppUserGuard)
export class UsersController {
constructor(private readonly appLogService: AppLogsService) {}
@ApiBearerAuth()
@ApiOperation({ summary: "Liste des utilisateurs" })
@Get("")
Expand Down Expand Up @@ -125,6 +132,17 @@ export class UsersController {
},
{ role: updateRoleDto.role }
);
await this.appLogService.create<UserStructureRoleChangeLogContext>({
action: "USER_ROLE_CHANGE",
userId: userStructureAuth.id,
role: userStructureAuth.role,
context: {
newRole: updateRoleDto.role,
oldRole: chosenUserStructure.role,
userId: chosenUserStructure.id,
structureId: chosenUserStructure.structureId,
},
});
return userStructureRepository.findOneBy({
uuid: chosenUserStructure.uuid,
});
Expand Down Expand Up @@ -200,6 +218,17 @@ export class UsersController {
userId: chosenUserStructure.id,
structureId: userStructureAuth.structureId,
});
await this.appLogService.create<UserStructureCreateLogContext>({
action: "USER_DELETE",
userId: userStructureAuth._userId,
role: userStructureAuth.role,
structureId: userStructureAuth.structureId,
context: {
role: chosenUserStructure.role,
userId: chosenUserStructure.id,
structureId: userStructureAuth.structureId,
},
});

return res.status(HttpStatus.OK).json({ message: "OK" });
}
Expand Down Expand Up @@ -237,7 +266,7 @@ export class UsersController {
@Post("register")
@AllowUserStructureRoles("admin")
public async registerUser(
@CurrentUser() user: UserStructureAuthenticated,
@CurrentUser() user: UserStructureAuthenticated | UserAdminAuthenticated, // workaround : this controller is called in another controller
@Res() res: Response,
@Body() registerUserDto: RegisterUserStructureAdminDto
): Promise<any> {
Expand Down Expand Up @@ -266,7 +295,16 @@ export class UsersController {
userProfile,
})
.then(
() => {
async () => {
await this.appLogService.create<UserStructureCreateLogContext>({
action: "USER_CREATE",
userId: user.id,
context: {
role: newUser.role,
userId: newUser.id,
structureId: newUser.structureId,
},
});
return res.status(HttpStatus.OK).json({ message: "OK" });
},
() => {
Expand Down
Loading