Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/context logger #602

Merged
merged 5 commits into from
Sep 3, 2024
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
14 changes: 14 additions & 0 deletions src/main/java/org/highmed/numportal/service/logger/ContextLog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.highmed.numportal.service.logger;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContextLog {

String type() default ""; // z.B. "UserManagement"

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.highmed.numportal.service.logger;

import net.logstash.logback.argument.StructuredArguments;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
@Component
public class ContextLogger {

private static final Logger logger = LoggerFactory.getLogger(ContextLogger.class);

@Before("@annotation(contextLog)")
public boolean logBefore(JoinPoint joinPoint, ContextLog contextLog) {

if (SecurityContextHolder.getContext().getAuthentication() == null) {
return false;
}
try {
String type = contextLog.type();
Jwt principal = (Jwt) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userId = principal.getSubject();
logger.info("Logging context",
StructuredArguments.keyValue("method", joinPoint.getSignature().toShortString()),
StructuredArguments.keyValue("type", type),
StructuredArguments.keyValue("userID", userId)
);
} catch (Exception e) {
logger.error("Cannot log context log {}", e);
}
return true;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.highmed.numportal.service.logger.ContextLog;
import org.highmed.numportal.web.config.Role;
import org.highmed.numportal.web.feign.KeycloakFeign;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -92,6 +93,7 @@ public ResponseEntity<Level> setLogLevel(@NotNull @PathVariable String logLevel)
return ResponseEntity.ok(numLogger.getLevel());
}

@ContextLog(type = "UserManagement")
@AuditLog(description = "Delete user")
@DeleteMapping("user/{userId}")
@PreAuthorize(Role.SUPER_ADMIN)
Expand All @@ -116,6 +118,7 @@ public ResponseEntity<Set<org.highmed.numportal.domain.model.admin.Role>> getRol
return ResponseEntity.ok(userService.getUserRoles(userId, principal.getSubject()));
}

@ContextLog(type = "UserManagement")
@AuditLog(description = "Update user's roles")
@PostMapping("user/{userId}/role")
@Operation(description = "Updates the users roles to the given set.")
Expand All @@ -128,6 +131,7 @@ public ResponseEntity<List<String>> updateRoles(@AuthenticationPrincipal @NotNul
return ResponseEntity.ok(updatedRoles);
}

@ContextLog(type = "UserManagement")
@AuditLog(description = "Update user's organization")
@PostMapping("user/{userId}/organization")
@Operation(description = "Sets the user's organization")
Expand All @@ -141,6 +145,7 @@ public ResponseEntity<String> setOrganization(
return ResponseEntity.ok(SUCCESS_REPLY);
}

@ContextLog(type = "UserManagement")
@AuditLog
@PostMapping("user/{userId}")
@Operation(description = "Creates user details")
Expand All @@ -151,6 +156,7 @@ public ResponseEntity<String> createUserOnFirstLogin(
return ResponseEntity.ok(SUCCESS_REPLY);
}

@ContextLog(type = "UserManagement")
@AuditLog(description = "Update user's name")
@PostMapping("user/{userId}/name")
@Operation(description = "Changes user name")
Expand All @@ -161,6 +167,7 @@ public ResponseEntity<String> changeUserName(
return ResponseEntity.ok(SUCCESS_REPLY);
}

@ContextLog(type = "UserManagement")
@AuditLog(description = "Approve user")
@PostMapping("user/{userId}/approve")
@Operation(description = "Adds the given organization to the user")
Expand All @@ -185,6 +192,8 @@ public ResponseEntity<Page<User>> searchUsersWithPagination(@AuthenticationPrinc
userService.searchUsers(principal.getSubject(), Roles.extractRoles(principal), criteria, pageable));
}


@ContextLog(type = "UserManagement")
@AuditLog(description = "Update user's active field")
@PostMapping("user/{userId}/status")
@Operation(description = "Updates user's status for active flag (enabled field in keycloak representation).")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.AllArgsConstructor;
import org.highmed.numportal.service.logger.ContextLog;
import org.highmed.numportal.web.config.Role;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -51,6 +52,7 @@ public ResponseEntity<AqlDto> getAqlById(
mapper.convertToDto(aqlService.getAqlById(id, principal.getSubject())));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Create AQL criteria")
@PostMapping()
@Operation(description = "Creates an aql; the logged in user is assigned as owner of the aql.")
Expand All @@ -62,6 +64,7 @@ public ResponseEntity<AqlDto> createAql(
return ResponseEntity.ok(mapper.convertToDto(aql));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Update AQL criteria")
@PutMapping(value = "/{id}")
@Operation(description = "Updates an aql; the logged in user is assigned as owner of the aql at creation time")
Expand All @@ -75,6 +78,7 @@ public ResponseEntity<AqlDto> updateAql(
return ResponseEntity.ok(mapper.convertToDto(aql));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Delete AQL criteria")
@DeleteMapping("/{id}")
@Operation(description = "Delete AQL criteria")
Expand Down Expand Up @@ -119,6 +123,7 @@ public ResponseEntity<Long> getAqlSize(@AuthenticationPrincipal @NotNull Jwt pri
return ResponseEntity.ok(aqlService.getAqlSize(aql, principal.getSubject()));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Create AQL category")
@PostMapping(value = "/category")
@Operation(description = "Creates a category. If there is an id in the DTO, it is ignored.")
Expand All @@ -130,6 +135,7 @@ public ResponseEntity<AqlCategoryDto> createCategory(@AuthenticationPrincipal @N
return ResponseEntity.ok(modelMapper.map(aqlCategory, AqlCategoryDto.class));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Update AQL category")
@PutMapping(value = "/category/{id}")
@Operation(description = "Updates a category. If present, the id in the DTO is ignored.")
Expand All @@ -145,6 +151,7 @@ public ResponseEntity<AqlCategoryDto> updateCategory(@AuthenticationPrincipal @N
return ResponseEntity.ok(modelMapper.map(aqlCategory, AqlCategoryDto.class));
}

@ContextLog(type = "KriterienManagement")
@AuditLog(description = "Delete AQL category")
@DeleteMapping(value = "/category/{id}")
@Operation(description = "Delete a category")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import org.highmed.numportal.service.logger.ContextLog;
import org.highmed.numportal.web.config.Role;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -37,6 +40,7 @@
@SecurityRequirement(name = "security_auth")
public class ContentController extends CustomizedExceptionHandler {

private static final Logger logger = LoggerFactory.getLogger(ContentController.class);
private final ContentService contentService;

@GetMapping("/navigation")
Expand Down Expand Up @@ -87,6 +91,7 @@ public ResponseEntity<List<ProjectInfoDto>> getLatestProjects(
return ResponseEntity.ok(contentService.getLatestProjects(roles));
}

@ContextLog(type = "ContentManagement")
@PostMapping("/navigation")
@Operation(description = "Retrieves a list of navigation items")
@PreAuthorize(Role.CONTENT_ADMIN)
Expand All @@ -100,6 +105,9 @@ public ResponseEntity<List<ProjectInfoDto>> getLatestProjects(
public ResponseEntity<String> setNavigationItems(
@Valid @NotNull @RequestBody @Size(max = 5) List<NavigationItemDto> navigationItemDtos) {
contentService.setNavigationItems(navigationItemDtos);
for(NavigationItemDto navigationItemDto : navigationItemDtos){
logger.info("Set navigation item: {}", navigationItemDto);
}
return ResponseEntity.ok("Success");
}

Expand All @@ -113,6 +121,7 @@ public ResponseEntity<String> getCards() {
return ResponseEntity.ok(contentService.getCards());
}

@ContextLog(type = "ContentManagement")
@PostMapping("/cards")
@Operation(description = "Retrieves a list of cards")
@PreAuthorize(Role.CONTENT_ADMIN)
Expand All @@ -126,6 +135,9 @@ public ResponseEntity<String> getCards() {
public ResponseEntity<String> setCards(
@Valid @NotNull @RequestBody @Size(max = 8) List<CardDto> cardDtos) {
contentService.setCards(cardDtos);
for(CardDto cardDto : cardDtos){
logger.info("Set card item: {}", cardDto);
}
return ResponseEntity.ok("Success");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.AllArgsConstructor;
import org.highmed.numportal.service.logger.ContextLog;
import org.highmed.numportal.web.config.Role;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -85,6 +86,7 @@ public ResponseEntity<Page<OrganizationDto>> getOrganizations(@AuthenticationPri
return ResponseEntity.ok(new PageImpl<>(content, pageable, organizationPage.getTotalElements()));
}

@ContextLog(type = "OrgaManagement")
@AuditLog(description = "Create organization")
@PostMapping()
@Operation(description = "Creates an organization")
Expand All @@ -96,22 +98,26 @@ public ResponseEntity<OrganizationDto> createOrganization(
mapper.convertToDto(organizationService.create(principal.getSubject(), organizationDto)));
}

@ContextLog(type = "OrgaManagement")
@AuditLog(description = "Update organization")
@PutMapping(value = "/{id}")
@Operation(description = "Updates an organization")
@PreAuthorize(Role.SUPER_ADMIN_OR_ORGANIZATION_ADMIN)
public ResponseEntity<OrganizationDto> updateOrganization(@AuthenticationPrincipal @NotNull Jwt principal,
@NotNull @PathVariable("id") Long organizationId,
@Valid @NotNull @RequestBody OrganizationDto organizationDto) {
return ResponseEntity.ok(
mapper.convertToDto(

OrganizationDto updatedOrganizationDto = mapper.convertToDto(
organizationService.update(
organizationId,
organizationDto,
Roles.extractRoles(principal),
principal.getSubject())));
organizationId,
organizationDto,
Roles.extractRoles(principal),
principal.getSubject()));

return ResponseEntity.ok(updatedOrganizationDto);
}

@ContextLog(type = "OrgaManagement")
@AuditLog(description = "Delete organization")
@Operation(description = "Delete the given organization if no users are assigned to this organization")
@DeleteMapping(value = "/{id}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import org.highmed.numportal.service.logger.ContextLog;
import org.highmed.numportal.web.config.Role;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -85,6 +86,7 @@ public ResponseEntity<ProjectDto> getProjectById(@AuthenticationPrincipal @NotNu
return ResponseEntity.ok(projectMapper.convertToDto(project.get()));
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Create project")
@PostMapping()
@Operation(
Expand All @@ -101,6 +103,7 @@ public ResponseEntity<ProjectDto> createProject(
return ResponseEntity.ok(projectMapper.convertToDto(project));
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Create project")
@PostMapping(path = "/new", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
@Operation(
Expand All @@ -118,6 +121,7 @@ public ResponseEntity<ProjectDto> createMultipartProject(
return ResponseEntity.ok(projectMapper.convertToDto(project));
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Update project")
@PutMapping(value = "/{id}")
@Operation(description =
Expand All @@ -135,6 +139,7 @@ public ResponseEntity<ProjectDto> updateProject(
return ResponseEntity.ok(projectMapper.convertToDto(project));
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Update project")
@PutMapping(value = "/new/{id}", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
@Operation(description =
Expand Down Expand Up @@ -234,6 +239,7 @@ public ResponseEntity<List<CommentDto>> getComments(
.collect(Collectors.toList()));
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Add comment")
@PostMapping("/{projectId}/comment")
@Operation(description = "Adds a comment to a particular project")
Expand All @@ -250,6 +256,7 @@ public ResponseEntity<CommentDto> addComment(
return ResponseEntity.ok(commentMapper.convertToDto(comment));
}

@ContextLog(type = "ProjektManagement")
@AuditLog
@PutMapping("/{projectId}/comment/{commentId}")
@Operation(description = "Updates a comment")
Expand All @@ -270,6 +277,7 @@ public ResponseEntity<CommentDto> updateComment(
return ResponseEntity.ok(commentMapper.convertToDto(comment));
}

@ContextLog(type = "ProjektManagement")
@AuditLog
@DeleteMapping("/{projectId}/comment/{commentId}")
@PreAuthorize(Role.STUDY_COORDINATOR_OR_RESEARCHER_OR_APPROVER)
Expand All @@ -280,6 +288,7 @@ public void deleteComment(
commentService.deleteComment(commentId, projectId, principal.getSubject());
}

@ContextLog(type = "ProjektManagement")
@AuditLog(description = "Delete project")
@DeleteMapping("/{id}")
@Operation(description = "Deletes a project")
Expand All @@ -289,6 +298,7 @@ public void deleteProject(@AuthenticationPrincipal @NotNull Jwt principal,
projectService.deleteProject(id, principal.getSubject(), Roles.extractRoles(principal));
}

@ContextLog(type = "ProjektManagement")
@AuditLog
@PostMapping("/{id}/archive")
@Operation(description = "Archive a project")
Expand All @@ -298,6 +308,7 @@ public void archiveProject(@AuthenticationPrincipal @NotNull Jwt principal,
projectService.archiveProject(id, principal.getSubject(), Roles.extractRoles(principal));
}

@ContextLog(type = "ProjektManagement")
@GetMapping(value = "/{id}/document", produces = MediaType.TEXT_PLAIN_VALUE)
@Operation(description = "Get the project info as a document")
@PreAuthorize(Role.STUDY_COORDINATOR_OR_APPROVER)
Expand Down
Loading