refactor for monolog user activateStatus

This commit is contained in:
Charles 2025-12-03 14:33:28 +01:00
parent 47724734a2
commit 3c789dc68e
2 changed files with 153 additions and 113 deletions

View File

@ -53,7 +53,8 @@ class UserController extends AbstractController
private readonly LoggerInterface $userManagementLogger,
private readonly LoggerInterface $organizationManagementLogger,
private readonly LoggerInterface $errorLogger,
private readonly LoggerService $loggerService,
private readonly LoggerInterface $securityLogger,
private readonly LoggerService $loggerService,
private readonly EmailService $emailService,
private readonly AwsService $awsService,
private readonly OrganizationsService $organizationsService,
@ -169,29 +170,22 @@ class UserController extends AbstractController
public function edit(int $id, Request $request): Response
{
$this->denyAccessUnlessGranted('ROLE_USER');
try{
try {
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
if ($this->userService->hasAccessTo($actingUser)) {
$user = $this->userRepository->find($id);
if (!$user) {
$this->userManagementLogger->notice('User not found for edit', [
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
'timestamp' => (new \DateTimeImmutable('now'))->format(DATE_ATOM),
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
'timestamp' => (new \DateTimeImmutable('now'))->format(DATE_ATOM),
]);
throw $this->createNotFoundException(self::NOT_FOUND);
}
$form = $this->createForm(UserForm::class, $user);
$form->handleRequest($request);
$this->userManagementLogger->notice('Format test', [
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
'timestamp' => (new \DateTimeImmutable('now'))->format(DATE_ATOM),
]);
if ($form->isSubmitted() && $form->isValid()) {
// Handle user edit
@ -204,21 +198,21 @@ class UserController extends AbstractController
//log and action
$this->userManagementLogger->notice('User information edited', [
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'organization_id' => $request->get('organizationId'),
'ip' => $request->getClientIp(),
'timestamp' => (new \DateTimeImmutable('now'))->format(DATE_ATOM),
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'organization_id' => $request->get('organizationId'),
'ip' => $request->getClientIp(),
'timestamp' => (new \DateTimeImmutable('now'))->format(DATE_ATOM),
]);
if ($request->get('organizationId')) {
$org = $this->organizationRepository->find($request->get('organizationId'));
if ($org) {
$this->actionService->createAction("Edit user information", $actingUser, $org, $user->getUserIdentifier());
$this->organizationManagementLogger->info('User edited within organization context', [
'target_user_id' => $user->getId(),
'target_user_id' => $user->getId(),
'organization_id' => $org->getId(),
'acting_user' => $actingUser->getUserIdentifier(),
'ip' => $request->getClientIp(),
'acting_user' => $actingUser->getUserIdentifier(),
'ip' => $request->getClientIp(),
]);
return $this->redirectToRoute('user_show', ['id' => $user->getId(), 'organizationId' => $request->get('organizationId')]);
}
@ -234,13 +228,13 @@ class UserController extends AbstractController
'organizationId' => $request->get('organizationId')
]);
}
}catch (\Exception $e){
} catch (\Exception $e) {
$this->errorLogger->critical($e->getMessage());
}
$this->SecurityLogger->warning('Access denied on user edit', [
$this->securityLogger->warning('Access denied on user edit', [
'target_user_id' => $id,
'acting_user' => $actingUser?->getId(),
'ip' => $request->getClientIp(),
'acting_user' => $actingUser?->getId(),
'ip' => $request->getClientIp(),
]);
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
}
@ -267,8 +261,8 @@ class UserController extends AbstractController
if (!$org && $orgId) {
$this->loggerService->logCritical('Organization not found for user creation', [
'organization_id' => $orgId,
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
]);
throw $this->createNotFoundException('Organization not found');
}
@ -302,8 +296,8 @@ class UserController extends AbstractController
if ($existingUser) {
$this->loggerService->logError('Attempt to create user with existing email without organization', [
'target_user_email' => $user->getid(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
'acting_user_id' => $actingUser->getId(),
'ip' => $request->getClientIp(),
]);
$form->get('email')->addError(
@ -313,8 +307,8 @@ class UserController extends AbstractController
);
return $this->render('user/new.html.twig', [
'user' => $user,
'form' => $form->createView(),
'user' => $user,
'form' => $form->createView(),
'organizationId' => $orgId,
]);
}
@ -359,8 +353,8 @@ class UserController extends AbstractController
}
return $this->render('user/new.html.twig', [
'user' => $user,
'form' => $form->createView(),
'user' => $user,
'form' => $form->createView(),
'organizationId' => $orgId,
]);
@ -382,90 +376,136 @@ class UserController extends AbstractController
public function activeStatus(int $id, Request $request): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
try{
if ($this->userService->hasAccessTo($actingUser, true)) {
$user = $this->userRepository->find($id);
if (!$user) {
throw $this->createNotFoundException(self::NOT_FOUND);
}
$status = $request->get('status');
if ($status === 'deactivate') {
$user->setIsActive(false);
$this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, $user);
if ($this->userService->isUserConnected($user->getUserIdentifier())) {
$this->userService->revokeUserTokens($user->getUserIdentifier());
}
$user->setModifiedAt(new \DateTimeImmutable('now'));
$this->entityManager->persist($user);
$this->entityManager->flush();
$this->logger->notice("User deactivated " . $user->getUserIdentifier());
$this->actionService->createAction("Deactivate user", $actingUser, null, $user->getUserIdentifier());
return new JsonResponse(['status' => 'deactivated'], Response::HTTP_OK);
}
if ($status === 'activate') {
$user->setIsActive(true);
$user->setModifiedAt(new \DateTimeImmutable('now'));
$this->logger->notice("User activated " . $user->getUserIdentifier());
$this->actionService->createAction("Activate user", $actingUser, null, $user->getUserIdentifier());
return new JsonResponse(['status' => 'activated'], Response::HTTP_OK);
}
}
}catch (\Exception $e){
$this->logger->error($e->getMessage());
}
throw $this->createNotFoundException(self::NOT_FOUND);
}
#[Route('/organization/activateStatus/{id}', name: 'activate_organization', methods: ['GET', 'POST'])]
public function activateStatusOrganization(int $id, Request $request): JsonResponse{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$ip = $request->getClientIp();
$status = $request->get('status');
try {
if ($this->userService->hasAccessTo($actingUser, true)) {
$orgId = $request->get('organizationId');
$org = $this->organizationRepository->find($orgId);
if (!$org) {
throw $this->createNotFoundException(self::NOT_FOUND);
}
$user = $this->userRepository->find($id);
if (!$user) {
throw $this->createNotFoundException(self::NOT_FOUND);
}
$uo = $this->uoRepository->findOneBy(['users' => $user,
'organization' => $org]);
if (!$uo) {
throw $this->createNotFoundException(self::NOT_FOUND);
}
$status = $request->get('status');
if ($status === 'deactivate') {
$uo->setIsActive(false);
$this->userOrganizationAppService->deactivateAllUserOrganizationsAppLinks($uo);
$this->entityManager->persist($uo);
$this->entityManager->flush();
$data = ['user' => $user,
'organization' => $org];
$this->organizationsService->notifyOrganizationAdmins($data, "USER_DEACTIVATED");
$this->logger->notice("User Organizaton deactivated " . $user->getUserIdentifier());
$this->actionService->createAction("Deactivate user in organization", $actingUser, $org, $org->getName() . " for user " . $user->getUserIdentifier());
return new JsonResponse(['status' => 'deactivated'], Response::HTTP_OK);
}
if($status === "activate"){
$uo->setIsActive(true);
$this->entityManager->persist($uo);
$this->entityManager->flush();
$this->actionService->createAction("Activate user in organization", $actingUser, $org, $org->getName() . " for user " . $user->getUserIdentifier());
$data = ['user' => $user,
'organization' => $org];
$this->organizationsService->notifyOrganizationAdmins($data, "USER_ACTIVATED");
return new JsonResponse(['status' => 'activated'], Response::HTTP_OK);
}
// Access control
if (!$this->userService->hasAccessTo($actingUser, true)) {
$this->securityLogger->warning('Access denied on user status change', [
'target_user_id' => $id,
'acting_user_id' => $actingUser?->getId(),
'acting_identifier' => $actingUser?->getUserIdentifier(),
'requested_status' => $status,
'ip' => $ip,
]);
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
}
}catch (\Exception $exception){
$this->logger->error($exception->getMessage());
// Load target user
$user = $this->userRepository->find($id);
if (!$user) {
$this->securityLogger->warning('User not found for status change', [
'target_user_id' => $id,
'acting_user_id' => $actingUser->getId(),
'requested_status' => $status,
'ip' => $ip,
]);
throw $this->createNotFoundException(self::NOT_FOUND);
}
// Deactivate
if ($status === 'deactivate') {
$user->setIsActive(false);
$this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, $user);
if ($this->userService->isUserConnected($user->getUserIdentifier())) {
$this->userService->revokeUserTokens($user->getUserIdentifier());
$this->securityLogger->info('User tokens revoked due to deactivation', [
'target_user_id' => $user->getId(),
'target_identifier' => $user->getUserIdentifier(),
'acting_user_id' => $actingUser->getId(),
'ip' => $ip,
]);
}
$user->setModifiedAt(new \DateTimeImmutable('now'));
$this->entityManager->flush();
$this->userManagementLogger->notice('User deactivated', [
'target_user_id' => $user->getId(),
'target_identifier' => $user->getUserIdentifier(),
'acting_user_id' => $actingUser->getId(),
'ip' => $ip,
]);
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
$this->loggerService->logSuperAdmin(
$user->getId(),
null,
$actingUser->getId(),
$ip,
'Super admin deactivated user'
);
}
$this->actionService->createAction('Deactivate user', $actingUser, null, $user->getUserIdentifier());
return new JsonResponse(['status' => 'deactivated'], Response::HTTP_OK);
}
// Activate
if ($status === 'activate') {
$user->setIsActive(true);
$user->setModifiedAt(new \DateTimeImmutable('now'));
$this->entityManager->flush();
$this->userManagementLogger->notice('User activated', [
'target_user_id' => $user->getId(),
'target_identifier' => $user->getUserIdentifier(),
'acting_user_id' => $actingUser->getId(),
'ip' => $ip,
]);
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
$this->loggerService->logSuperAdmin(
$user->getId(),
null,
$actingUser->getId(),
$ip,
'Super admin activated user'
);
}
$this->actionService->createAction('Activate user', $actingUser, null, $user->getUserIdentifier());
return new JsonResponse(['status' => 'activated'], Response::HTTP_OK);
}
// Invalid status
$this->loggerService->warning('Invalid status passed to activeStatus', [
'target_user_id' => $user->getId(),
'acting_user_id' => $actingUser->getId(),
'requested_status' => $status,
'ip' => $ip,
]);
return new JsonResponse(['error' => 'Invalid status'], Response::HTTP_BAD_REQUEST);
} catch (\Throwable $e) {
// Application-level error logging → error.log (via error channel)
$this->errorLogger->error('Error in activeStatus', [
'exception_message' => $e->getMessage(),
'exception_class' => get_class($e),
'target_user_id' => $id,
'acting_user_id' => $actingUser?->getId(),
'requested_status' => $status,
'ip' => $ip,
]);
// Preserve 403/404 semantics, 500 for everything else
if ($e instanceof NotFoundHttpException || $e instanceof AccessDeniedException) {
throw $e;
}
return new JsonResponse(['error' => 'An error occurred'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
throw $this->createNotFoundException(self::NOT_FOUND);
}
//TODO : MONOLOG + remove picture from bucket

View File

@ -97,7 +97,7 @@ readonly class LoggerService
]);
}
public function logSuperAdmin(int $userId, ?int $orgId, int $actingUserId, ?string $ip, string $message): void
public function logSuperAdmin(int $userId, ?int $orgId = null, int $actingUserId, ?string $ip, string $message): void
{
$this->adminActionsLogger->notice($message, [
'target_user_id' => $userId,