diff --git a/backend/core/src/main/java/org/opencdmp/query/lookup/LockLookup.java b/backend/core/src/main/java/org/opencdmp/query/lookup/LockLookup.java index f32381644..d8afe04fb 100644 --- a/backend/core/src/main/java/org/opencdmp/query/lookup/LockLookup.java +++ b/backend/core/src/main/java/org/opencdmp/query/lookup/LockLookup.java @@ -1,10 +1,9 @@ package org.opencdmp.query.lookup; - -import org.opencdmp.commons.enums.LockTargetType; -import org.opencdmp.query.LockQuery; import gr.cite.tools.data.query.Lookup; import gr.cite.tools.data.query.QueryFactory; +import org.opencdmp.commons.enums.LockTargetType; +import org.opencdmp.query.LockQuery; import java.util.List; import java.util.UUID; @@ -20,8 +19,8 @@ public class LockLookup extends Lookup { private List targetTypes; private List excludedIds; - private List userIds; + private List userIds; public String getLike() { return like; @@ -73,12 +72,18 @@ public class LockLookup extends Lookup { public LockQuery enrich(QueryFactory queryFactory) { LockQuery query = queryFactory.query(LockQuery.class); - if (this.like != null) query.like(this.like); - if (this.ids != null) query.ids(this.ids); - if (this.targetIds != null) query.targetIds(this.targetIds); - if (this.targetTypes != null) query.targetTypes(this.targetTypes); - if (this.excludedIds != null) query.excludedIds(this.excludedIds); - if (this.userIds != null) query.userIds(this.userIds); + if (this.like != null) + query.like(this.like); + if (this.ids != null) + query.ids(this.ids); + if (this.targetIds != null) + query.targetIds(this.targetIds); + if (this.targetTypes != null) + query.targetTypes(this.targetTypes); + if (this.excludedIds != null) + query.excludedIds(this.excludedIds); + if (this.userIds != null) + query.userIds(this.userIds); this.enrichCommon(query); diff --git a/backend/core/src/main/java/org/opencdmp/query/lookup/UserLookup.java b/backend/core/src/main/java/org/opencdmp/query/lookup/UserLookup.java index 14f9c8694..6cffccce9 100644 --- a/backend/core/src/main/java/org/opencdmp/query/lookup/UserLookup.java +++ b/backend/core/src/main/java/org/opencdmp/query/lookup/UserLookup.java @@ -1,9 +1,9 @@ package org.opencdmp.query.lookup; -import org.opencdmp.commons.enums.IsActive; -import org.opencdmp.query.UserQuery; import gr.cite.tools.data.query.Lookup; import gr.cite.tools.data.query.QueryFactory; +import org.opencdmp.commons.enums.IsActive; +import org.opencdmp.query.UserQuery; import java.util.List; import java.util.UUID; @@ -13,11 +13,15 @@ public class UserLookup extends Lookup { private String like; private List ids; + private List emails; private List excludedIds; + private List isActive; + private UserRoleLookup userRoleSubQuery; + private TenantUserLookup tenantUserSubQuery; public String getLike() { @@ -78,13 +82,20 @@ public class UserLookup extends Lookup { public UserQuery enrich(QueryFactory queryFactory) { UserQuery query = queryFactory.query(UserQuery.class); - if (this.like != null) query.like(this.like); - if (this.ids != null) query.ids(this.ids); - if (this.emails != null) query.emails(this.emails); - if (this.userRoleSubQuery != null) query.userRoleSubQuery(this.userRoleSubQuery.enrich(queryFactory)); - if (this.tenantUserSubQuery != null) query.tenantUserSubQuery(this.tenantUserSubQuery.enrich(queryFactory)); - if (this.excludedIds != null) query.excludedIds(this.excludedIds); - if (this.isActive != null) query.isActive(this.isActive); + if (this.like != null) + query.like(this.like); + if (this.ids != null) + query.ids(this.ids); + if (this.emails != null) + query.emails(this.emails); + if (this.userRoleSubQuery != null) + query.userRoleSubQuery(this.userRoleSubQuery.enrich(queryFactory)); + if (this.tenantUserSubQuery != null) + query.tenantUserSubQuery(this.tenantUserSubQuery.enrich(queryFactory)); + if (this.excludedIds != null) + query.excludedIds(this.excludedIds); + if (this.isActive != null) + query.isActive(this.isActive); this.enrichCommon(query); diff --git a/backend/web/src/main/java/org/opencdmp/controllers/LockController.java b/backend/web/src/main/java/org/opencdmp/controllers/LockController.java index 94935b276..ee78a1498 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/LockController.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/LockController.java @@ -12,6 +12,13 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidationFilterAnnotation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.transaction.Transactional; import org.opencdmp.audit.AuditableAction; import org.opencdmp.authorization.AffiliatedResource; @@ -19,6 +26,11 @@ import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.authorization.Permission; import org.opencdmp.authorization.authorizationcontentresolver.AuthorizationContentResolver; import org.opencdmp.commons.enums.LockTargetType; +import org.opencdmp.controllers.swagger.SwaggerHelpers; +import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader; +import org.opencdmp.controllers.swagger.annotation.Swagger400; +import org.opencdmp.controllers.swagger.annotation.Swagger404; +import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses; import org.opencdmp.data.LockEntity; import org.opencdmp.model.Lock; import org.opencdmp.model.LockStatus; @@ -26,6 +38,7 @@ import org.opencdmp.model.builder.LockBuilder; import org.opencdmp.model.censorship.LockCensor; import org.opencdmp.model.persist.LockPersist; import org.opencdmp.model.result.QueryResult; +import org.opencdmp.model.user.User; import org.opencdmp.query.LockQuery; import org.opencdmp.query.lookup.LockLookup; import org.opencdmp.service.lock.LockService; @@ -49,6 +62,8 @@ import java.util.UUID; @RestController @RequestMapping(path = "api/lock") +@Tag(name = "Locks", description = "Manage locked entities") +@SwaggerCommonErrorResponses public class LockController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockController.class)); @@ -66,7 +81,9 @@ public class LockController { private final MessageSource messageSource; private final AuthorizationService authService; + private final AuthorizationContentResolver authorizationContentResolver; + @Autowired public LockController(BuilderFactory builderFactory, AuditService auditService, @@ -81,10 +98,29 @@ public class LockController { this.queryFactory = queryFactory; this.messageSource = messageSource; this.authService = authService; - this.authorizationContentResolver = authorizationContentResolver; + this.authorizationContentResolver = authorizationContentResolver; } @PostMapping("query") + @OperationWithTenantHeader(summary = "Query all locked entities", description = SwaggerHelpers.Lock.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.Lock.endpoint_query_request_body, content = @Content( + examples = { + @ExampleObject( + name = "Pagination and projection", + description = "Simple paginated request using a property projection list and pagination info", + value = SwaggerHelpers.Lock.endpoint_query_request_body_example + ) + } + )), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + array = @ArraySchema( + schema = @Schema( + implementation = Lock.class + ) + ), + examples = @ExampleObject( + name = "First page", + description = "Example with the first page of paginated results", + value = SwaggerHelpers.Lock.endpoint_query_response_example + )))) public QueryResult query(@RequestBody LockLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { logger.debug("querying {}", Lock.class.getSimpleName()); @@ -101,7 +137,17 @@ public class LockController { } @GetMapping("{id}") - public Lock get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + @OperationWithTenantHeader(summary = "Fetch a specific lock by id", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Lock.class + )) + )) + @Swagger404 + public Lock get( + @Parameter(name = "id", description = "The id of a user to fetch", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("id", id).And("fields", fieldSet)); this.censorFactory.censor(LockCensor.class).censor(fieldSet, null); @@ -120,9 +166,20 @@ public class LockController { } @PostMapping("persist") + @OperationWithTenantHeader(summary = "Create a new or update an existing lock", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Lock.class + )) + )) + @Swagger400 + @Swagger404 @Transactional @ValidationFilterAnnotation(validator = LockPersist.LockPersistValidator.ValidatorName, argumentName = "model") - public Lock persist(@RequestBody LockPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + public Lock persist( + @RequestBody LockPersist model, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting" + Lock.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); this.censorFactory.censor(LockCensor.class).censor(fieldSet, null); @@ -137,7 +194,17 @@ public class LockController { } @GetMapping("target/{id}") - public Lock getWithTarget(@PathVariable("id") UUID targetId, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + @OperationWithTenantHeader(summary = "Fetch a specific lock by target id", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Lock.class + )) + )) + @Swagger404 + public Lock getWithTarget( + @Parameter(name = "id", description = "The target id of a lock to fetch", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID targetId, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("targetId", targetId).And("fields", fieldSet)); this.censorFactory.censor(LockCensor.class).censor(fieldSet, null); @@ -157,7 +224,16 @@ public class LockController { @Transactional @GetMapping("target/status/{id}") - public LockStatus getLocked(@PathVariable("id") UUID targetId, FieldSet fieldSet) throws Exception { + @OperationWithTenantHeader(summary = "Fetch a lock status by target id", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = LockStatus.class + )) + )) + public LockStatus getLocked( + @Parameter(name = "id", description = "The target id of a lock to fetch the status", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID targetId, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws Exception { logger.debug(new MapLogEntry("is locked" + Lock.class.getSimpleName()).And("targetId", targetId).And("fields", fieldSet)); this.authService.authorizeForce(Permission.BrowseLock); @@ -171,7 +247,16 @@ public class LockController { @Transactional @GetMapping("target/lock/{id}/{targetType}") - public boolean lock(@PathVariable("id") UUID targetId, @PathVariable("targetType") int targetType) throws Exception { + @OperationWithTenantHeader(summary = "Lock a target", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Boolean.class + )) + )) + public boolean lock( + @Parameter(name = "id", description = "The target id to be locked", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID targetId, + @Parameter(name = "targetType", description = "The target type to be locked", example = "0", required = true) @PathVariable("targetType") int targetType + ) throws Exception { AffiliatedResource affiliatedResourcePlan = this.authorizationContentResolver.planAffiliation(targetId); AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(targetId); AffiliatedResource affiliatedResourceDescriptionTemplate = this.authorizationContentResolver.descriptionTemplateAffiliation(targetId); @@ -187,7 +272,15 @@ public class LockController { @Transactional @GetMapping("target/touch/{id}") - public boolean touch(@PathVariable("id") UUID targetId) throws Exception { + @OperationWithTenantHeader(summary = "Touch a locked target", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Boolean.class + )) + )) + public boolean touch( + @Parameter(name = "id", description = "The target id to be touched", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID targetId + ) throws Exception { AffiliatedResource affiliatedResourcePlan = this.authorizationContentResolver.planAffiliation(targetId); AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(targetId); AffiliatedResource affiliatedResourceDescriptionTemplate = this.authorizationContentResolver.descriptionTemplateAffiliation(targetId); @@ -202,7 +295,15 @@ public class LockController { @Transactional @DeleteMapping("target/unlock/{id}") - public boolean unlock(@PathVariable("id") UUID targetId) throws Exception { + @OperationWithTenantHeader(summary = "Unlock a target", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Boolean.class + )) + )) + public boolean unlock( + @Parameter(name = "id", description = "The target id to be unlocked", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID targetId + ) throws Exception { AffiliatedResource affiliatedResourcePlan = this.authorizationContentResolver.planAffiliation(targetId); AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(targetId); AffiliatedResource affiliatedResourceDescriptionTemplate = this.authorizationContentResolver.descriptionTemplateAffiliation(targetId); @@ -216,8 +317,13 @@ public class LockController { } @DeleteMapping("{id}/{target}") + @OperationWithTenantHeader(summary = "Delete a lock by id and target", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public void delete(@PathVariable("id") UUID id, @PathVariable("target") UUID target) throws MyForbiddenException, InvalidApplicationException { + public void delete( + @Parameter(name = "id", description = "The id of the lock to be deleted", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id, + @Parameter(name = "target", description = "The target id of the lock", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("target") UUID target + ) throws MyForbiddenException, InvalidApplicationException { logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("id", id)); this.lockService.deleteAndSave(id, target); diff --git a/backend/web/src/main/java/org/opencdmp/controllers/PlanController.java b/backend/web/src/main/java/org/opencdmp/controllers/PlanController.java index 41a5d14e2..08404887f 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/PlanController.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/PlanController.java @@ -502,7 +502,7 @@ public class PlanController { public PreprocessingPlanModel preprocessing( @RequestParam("fileId") UUID fileId, @RequestParam("repositoryId") String repositoryId - ) throws InvalidAlgorithmParameterException, JAXBException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { + ) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { logger.debug(new MapLogEntry("preprocessing plan" + Plan.class.getSimpleName()).And("transformerId", repositoryId).And("fileId", fileId)); PreprocessingPlanModel model = this.planService.preprocessingPlan(fileId, repositoryId); diff --git a/backend/web/src/main/java/org/opencdmp/controllers/PrincipalController.java b/backend/web/src/main/java/org/opencdmp/controllers/PrincipalController.java index c687070d1..641f5bcfd 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/PrincipalController.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/PrincipalController.java @@ -6,7 +6,15 @@ import gr.cite.tools.auditing.AuditService; import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import org.opencdmp.audit.AuditableAction; +import org.opencdmp.controllers.swagger.SwaggerHelpers; +import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader; +import org.opencdmp.model.Lock; import org.opencdmp.model.Tenant; import org.opencdmp.models.Account; import org.opencdmp.models.AccountBuilder; @@ -23,6 +31,7 @@ import java.util.List; @RestController @RequestMapping("/api/principal/") +@Tag(name = "Principal", description = "Get user account information") public class PrincipalController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrincipalController.class)); private final AuditService auditService; @@ -43,7 +52,15 @@ public class PrincipalController { } @RequestMapping(path = "me", method = RequestMethod.GET ) - public Account me(FieldSet fieldSet) throws InvalidApplicationException { + @OperationWithTenantHeader(summary = "Fetch auth information of the logged in user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = Account.class + )) + )) + public Account me( + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws InvalidApplicationException { logger.debug("me"); if (fieldSet == null || fieldSet.isEmpty()) { @@ -80,7 +97,11 @@ public class PrincipalController { } @GetMapping("my-tenants") - public List myTenants(FieldSet fieldSet) { + @OperationWithTenantHeader(summary = "Fetch a list with the tenants the user belongs to", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + public List myTenants( + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) { logger.debug("my-tenants"); List models = this.tenantService.myTenants(fieldSet); diff --git a/backend/web/src/main/java/org/opencdmp/controllers/UserController.java b/backend/web/src/main/java/org/opencdmp/controllers/UserController.java index 51e8fc52f..0683fd296 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/UserController.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/UserController.java @@ -12,11 +12,24 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidationFilterAnnotation; +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.xml.bind.JAXBException; import org.opencdmp.audit.AuditableAction; import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.scope.user.UserScope; +import org.opencdmp.controllers.swagger.SwaggerHelpers; +import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader; +import org.opencdmp.controllers.swagger.annotation.Swagger400; +import org.opencdmp.controllers.swagger.annotation.Swagger404; +import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses; import org.opencdmp.data.UserEntity; import org.opencdmp.model.PlanAssociatedUser; import org.opencdmp.model.UserRole; @@ -26,6 +39,7 @@ import org.opencdmp.model.censorship.PlanAssociatedUserCensor; import org.opencdmp.model.censorship.UserCensor; import org.opencdmp.model.persist.*; import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist; +import org.opencdmp.model.plan.Plan; import org.opencdmp.model.result.QueryResult; import org.opencdmp.model.user.User; import org.opencdmp.query.UserQuery; @@ -51,6 +65,8 @@ import java.util.UUID; @RestController @RequestMapping(path = "api/user") +@Tag(name = "Users", description = "Manage users") +@SwaggerCommonErrorResponses public class UserController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserController.class)); @@ -91,6 +107,25 @@ public class UserController { } @PostMapping("query") + @OperationWithTenantHeader(summary = "Query all users", description = SwaggerHelpers.User.endpoint_query, requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(description = SwaggerHelpers.User.endpoint_query_request_body, content = @Content( + examples = { + @ExampleObject( + name = "Pagination and projection", + description = "Simple paginated request using a property projection list and pagination info", + value = SwaggerHelpers.User.endpoint_query_request_body_example + ) + } + )), responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + array = @ArraySchema( + schema = @Schema( + implementation = User.class + ) + ), + examples = @ExampleObject( + name = "First page", + description = "Example with the first page of paginated results", + value = SwaggerHelpers.User.endpoint_query_response_example + )))) public QueryResult query(@RequestBody UserLookup lookup) throws MyApplicationException, MyForbiddenException { logger.debug("querying {}", User.class.getSimpleName()); @@ -108,6 +143,7 @@ public class UserController { } @PostMapping("plan-associated/query") + @Hidden public QueryResult queryPlanAssociated(@RequestBody UserLookup lookup) throws MyApplicationException, MyForbiddenException { logger.debug("querying {}", User.class.getSimpleName()); @@ -125,7 +161,17 @@ public class UserController { } @GetMapping("{id}") - public User get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + @OperationWithTenantHeader(summary = "Fetch a specific user by id", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = User.class + )) + )) + @Swagger404 + public User get( + @Parameter(name = "id", description = "The id of a user to fetch", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("id", id).And("fields", fieldSet)); this.censorFactory.censor(UserCensor.class).censor(fieldSet, id); @@ -144,7 +190,17 @@ public class UserController { } @GetMapping("/by-email/{email}") - public User get(@PathVariable("email") String email, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + @OperationWithTenantHeader(summary = "Fetch a specific user by email", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = User.class + )) + )) + @Swagger404 + public User get( + @Parameter(name = "email", description = "The email of a user to fetch", example = "admin@cite.gr", required = true) @PathVariable("email") String email, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("email", email).And("fields", fieldSet)); this.censorFactory.censor(UserCensor.class).censor(fieldSet, null); @@ -163,6 +219,7 @@ public class UserController { } @GetMapping("/export/csv/{hasTenantAdminMode}") + @Hidden public ResponseEntity exportCsv(@PathVariable("hasTenantAdminMode") Boolean hasTenantAdminMode) throws MyApplicationException, MyForbiddenException, MyNotFoundException, IOException, InvalidApplicationException { logger.debug(new MapLogEntry("export" + User.class.getSimpleName()).And("hasTenantAdminMode", hasTenantAdminMode)); @@ -177,7 +234,16 @@ public class UserController { } @GetMapping("mine") - public User getMine(FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + @OperationWithTenantHeader(summary = "Fetch information for the logged in user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = User.class + )) + )) + @Swagger404 + public User getMine( + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("retrieving me" + User.class.getSimpleName()).And("fields", fieldSet)); this.censorFactory.censor(UserCensor.class).censor(fieldSet, this.userScope.getUserId()); @@ -195,8 +261,12 @@ public class UserController { } @GetMapping("mine/language/{language}") + @OperationWithTenantHeader(summary = "Update the language for the logged in user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public void updateLanguageMine(@PathVariable("language") String language) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public void updateLanguageMine( + @Parameter(name = "language", description = "The updated language", example = "en", required = true) @PathVariable("language") String language + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { logger.debug(new MapLogEntry("persisting" + User.class.getSimpleName()).And("language", language)); this.userTypeService.updateLanguageMine(language); @@ -206,8 +276,12 @@ public class UserController { } @GetMapping("mine/timezone/{timezone}") + @OperationWithTenantHeader(summary = "Update the timezone for the logged in user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public void updateTimezoneMine(@PathVariable("timezone") String timezone) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public void updateTimezoneMine( + @Parameter(name = "timezone", description = "The updated timezone", example = "Europe/Budapest", required = true) @PathVariable("timezone") String timezone + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { logger.debug(new MapLogEntry("persisting" + User.class.getSimpleName()).And("timezone", timezone)); this.userTypeService.updateTimezoneMine(timezone); @@ -217,8 +291,12 @@ public class UserController { } @GetMapping("mine/culture/{culture}") + @OperationWithTenantHeader(summary = "Update the culture for the logged in user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public void updateCultureMine(@PathVariable("culture") String culture) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public void updateCultureMine( + @Parameter(name = "culture", description = "The updated culture", example = "en-US", required = true) @PathVariable("culture") String culture + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { logger.debug(new MapLogEntry("persisting" + User.class.getSimpleName()).And("culture", culture)); this.userTypeService.updateCultureMine(culture); @@ -228,9 +306,20 @@ public class UserController { } @PostMapping("persist") + @OperationWithTenantHeader(summary = "Create a new or update an existing user", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = User.class + )) + )) + @Swagger400 + @Swagger404 @Transactional @ValidationFilterAnnotation(validator = UserPersist.UserPersistValidator.ValidatorName, argumentName = "model") - public User persist(@RequestBody UserPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { + public User persist( + @RequestBody UserPersist model, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { logger.debug(new MapLogEntry("persisting" + User.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); User persisted = this.userTypeService.persist(model, fieldSet); @@ -243,9 +332,20 @@ public class UserController { } @PostMapping("persist/roles") + @OperationWithTenantHeader(summary = "Update user roles", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( + schema = @Schema( + implementation = User.class + )) + )) + @Swagger400 + @Swagger404 @Transactional @ValidationFilterAnnotation(validator = UserRolePatchPersist.UserRolePatchPersistValidator.ValidatorName, argumentName = "model") - public User persistRoles(@RequestBody UserRolePatchPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { + public User persistRoles( + @RequestBody UserRolePatchPersist model, + @Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet + ) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { logger.debug(new MapLogEntry("persisting" + UserRole.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); User persisted = this.userTypeService.patchRoles(model, fieldSet); @@ -258,8 +358,13 @@ public class UserController { } @DeleteMapping("{id}") + @OperationWithTenantHeader(summary = "Delete a user by id", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + @Swagger404 @Transactional - public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { + public void delete( + @Parameter(name = "id", description = "The id of a user to delete", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id + ) throws MyForbiddenException, InvalidApplicationException { logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("id", id)); this.userTypeService.deleteAndSave(id); @@ -268,6 +373,10 @@ public class UserController { } @PostMapping("mine/merge-account-request") + @OperationWithTenantHeader(summary = "Merge user accounts", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + @Swagger400 + @Swagger404 @Transactional @ValidationFilterAnnotation(validator = UserMergeRequestPersist.UserMergeRequestPersistValidator.ValidatorName, argumentName = "model") public Boolean mergeAccount(@RequestBody UserMergeRequestPersist model) throws InvalidApplicationException, JAXBException { @@ -283,8 +392,12 @@ public class UserController { } @GetMapping("mine/confirm-merge-account/token/{token}") + @OperationWithTenantHeader(summary = "Confirm the merge of user accounts", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public Boolean confirmMergeAccount(@PathVariable("token") String token) throws InvalidApplicationException, IOException { + public Boolean confirmMergeAccount( + @Parameter(name = "token", description = "The token for the action", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("token") String token + ) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("confirm merge account to user").And("token", token)); this.userTypeService.confirmMergeAccount(token); @@ -297,7 +410,11 @@ public class UserController { } @GetMapping("mine/allow-merge-account/token/{token}") - public Boolean getUserTokenPermission(@PathVariable("token") String token) throws InvalidApplicationException, IOException { + @OperationWithTenantHeader(summary = "Allow the merge of user accounts", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + public Boolean getUserTokenPermission( + @Parameter(name = "token", description = "The token for the action", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("token") String token + ) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("allow merge account to user").And("token", token)); this.auditService.track(AuditableAction.User_AllowMergeAccount); @@ -306,6 +423,9 @@ public class UserController { } @PostMapping("mine/remove-credential-request") + @OperationWithTenantHeader(summary = "Remove user credentials", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + @Swagger400 @Transactional @ValidationFilterAnnotation(validator = RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.ValidatorName, argumentName = "model") public Boolean removeCredentialAccount(@RequestBody RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException { @@ -321,8 +441,12 @@ public class UserController { } @GetMapping("mine/confirm-remove-credential/token/{token}") + @OperationWithTenantHeader(summary = "Confirm the removal of user credentials", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) @Transactional - public Boolean confirmRemoveCredentialAccount(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException { + public Boolean confirmRemoveCredentialAccount( + @Parameter(name = "token", description = "The token for the action", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("token") String token + ) throws InvalidApplicationException, JAXBException { logger.debug(new MapLogEntry("confirm remove credential to user").And("token", token)); this.userTypeService.confirmRemoveCredential(token); @@ -335,6 +459,9 @@ public class UserController { } @PostMapping("invite-users-to-tenant") + @OperationWithTenantHeader(summary = "Invite users to a tenant", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + @Swagger400 @Transactional @ValidationFilterAnnotation(validator = UserTenantUsersInviteRequest.UserTenantUsersInviteRequestValidator.ValidatorName, argumentName = "model") public Boolean inviteUsersToTenant(@RequestBody UserTenantUsersInviteRequest users) throws InvalidApplicationException, JAXBException { @@ -350,8 +477,13 @@ public class UserController { } @GetMapping("confirm-invite-user-to-tenant/token/{token}") + @OperationWithTenantHeader(summary = "Confirm user tenant invitation", description = "", + responses = @ApiResponse(description = "OK", responseCode = "200")) + @Swagger400 @Transactional - public Boolean confirmInviteUserToTenant(@PathVariable("token") String token) throws InvalidApplicationException { + public Boolean confirmInviteUserToTenant( + @Parameter(name = "token", description = "The token for the action", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("token") String token + ) throws InvalidApplicationException { logger.debug(new MapLogEntry("confirm merge account to user").And("token", token)); this.userTypeService.confirmUserInviteToTenant(token); diff --git a/backend/web/src/main/java/org/opencdmp/controllers/swagger/SwaggerHelpers.java b/backend/web/src/main/java/org/opencdmp/controllers/swagger/SwaggerHelpers.java index f67d7bbcc..e3ba6bc6b 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/swagger/SwaggerHelpers.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/swagger/SwaggerHelpers.java @@ -1,8 +1,8 @@ package org.opencdmp.controllers.swagger; -public class SwaggerHelpers { +public final class SwaggerHelpers { - public static class Commons { + public static final class Commons { public static final String fieldset_description = """ @@ -10,7 +10,7 @@ public class SwaggerHelpers { """; } - public static class Errors { + public static final class Errors { public static final String message_400 = """ @@ -51,7 +51,7 @@ public class SwaggerHelpers { } - public static class Plan { + public static final class Plan { public static final String endpoint_query = """ @@ -905,7 +905,7 @@ public class SwaggerHelpers { """; } - public static class Description { + public static final class Description { public static final String endpoint_query = """ @@ -1760,7 +1760,7 @@ public class SwaggerHelpers { """; } - public static class DescriptionTemplate { + public static final class DescriptionTemplate { public static final String endpoint_query = """ @@ -2144,7 +2144,7 @@ public class SwaggerHelpers { """; } - public static class DescriptionTemplateType { + public static final class DescriptionTemplateType { public static final String endpoint_query = """ @@ -2307,7 +2307,7 @@ public class SwaggerHelpers { } - public static class PlanBlueprint { + public static final class PlanBlueprint { public static final String endpoint_query = """ @@ -2548,7 +2548,7 @@ public class SwaggerHelpers { } - public static class FileTransformer { + public static final class FileTransformer { public static final String endpoint_get_available_transformers = """ @@ -2569,7 +2569,7 @@ public class SwaggerHelpers { } - public static class EntityDoi { + public static final class EntityDoi { public static final String endpoint_query = """ @@ -2835,7 +2835,7 @@ public class SwaggerHelpers { } - public static class Deposit { + public static final class Deposit { public static final String endpoint_get_available_repos = """ @@ -2859,7 +2859,7 @@ public class SwaggerHelpers { } - public static class Tag { + public static final class Tag { public static final String endpoint_query = """ @@ -3086,7 +3086,7 @@ public class SwaggerHelpers { } - public static class Reference { + public static final class Reference { public static final String endpoint_query = """ @@ -3348,7 +3348,7 @@ public class SwaggerHelpers { } - public static class ReferenceType { + public static final class ReferenceType { public static final String endpoint_query = """ @@ -3579,4 +3579,672 @@ public class SwaggerHelpers { } + public static final class Lock { + + public static final String endpoint_query = + """ + This endpoint is used to fetch all the current entity locks.
+ It also allows to restrict the results using a query object passed in the request body.
+ """; + + public static final String endpoint_query_request_body = + """ + Let's explore the options this object gives us. + + ### General query parameters: + +
    +
  • page: + This is an object controlling the pagination of the results. It contains two properties. +
  • +
      +
    • offset: + How many records to omit. +
    • +
    • size: + How many records to include in each page. +
    • +
    +
+ + For example, if we want the third page, and our pages to contain 15 elements, we would pass the following object: + + ```JSON + { + "offset": 30, + "size": 15 + } + ``` + +
    +
  • order: + This is an object controlling the ordering of the results. + It contains a list of strings called items with the names of the properties to use. +
    If the name of the property is prefixed with a '-', the ordering direction is DESC. Otherwise, it is ASC. +
  • +
+ + For example, if we wanted to order based on the field 'createdAt' in descending order, we would pass the following object: + + ```JSON + { + "items": [ + "-createdAt" + ], + } + ``` + +
    +
  • metadata: + This is an object containing metadata for the request. There is only one available option. +
      +
    • countAll: + If this is set to true, the count property included in the response will account for all the records regardless the pagination, + with all the rest of filtering options applied of course. + Otherwise, if it is set to false or not present, only the returned results will be counted. +
      The first option is useful for the UI clients to calculate how many result pages are available. +
    • +
    +
  • +
  • project: + This is an object controlling the data projection of the results. + It contains a list of strings called fields with the names of the properties to project. +
    You can also include properties that are deeper in the object tree by prefixing them with dots. +
  • +
+ + ### Lock specific query parameters: + +
    +
  • like: + If there is a like parameter present in the query, only the locks locking the provided target id will be in the response. +
  • +
  • ids: + This is a list and contains the ids we want to include in the response.
    If empty, every record is included. +
  • +
  • excludedIds: + This is a list and contains the ids we want to exclude from the response.
    If empty, no record gets excluded. +
  • +
  • targetIds: + This is a list and contains the ids of the locked targets of the locks we want to include in the response.
    If empty, every record is included. +
  • +
  • userIds: + This is a list and contains the ids of the users of the locks we want to include in the response.
    If empty, every record is included. +
  • +
  • targetTypes: + This is a list and determines which records we want to include in the response, based on their target type. + The target type can be Plan, Description, PlanBlueprint or DescriptionTemplate. We add 0, 1, 2 or 3 to the list respectively. +
    If not present, every record is included. +
  • +
+ """; + + public static final String endpoint_query_request_body_example = + """ + { + "project":{ + "fields":[ + "id", + "target", + "targetType", + "lockedAt", + "lockedBy.name", + "touchedAt", + "hash", + "belongsToCurrentTenant" + ] + }, + "metadata":{ + "countAll":true + }, + "page":{ + "offset":0, + "size":10 + }, + "isActive":[ + 1 + ], + "order":{ + "items":[ + "-lockedAt" + ] + } + } + """; + + public static final String endpoint_query_response_example = + """ + { + "items":[ + { + "id":"d0423a02-abe8-4210-8ee3-504deb79d8c6", + "target":"39fabf73-546c-49a3-8789-6401f65d56b6", + "targetType":1, + "lockedBy":{ + "name":"admin admin" + }, + "lockedAt":"2024-06-28T08:47:03.784241Z", + "touchedAt":"2024-07-04T11:01:10.762955Z", + "hash":"1720090870", + "belongsToCurrentTenant":true + }, + { + "id":"74b2ae7e-0a28-4ebc-aec9-3f849ccb3e60", + "target":"37701076-e0ff-4e4f-95aa-9f3d6a23083a", + "targetType":2, + "lockedBy":{ + "name":"admin admin" + }, + "lockedAt":"2024-07-04T08:29:46.591493Z", + "touchedAt":"2024-07-04T08:33:13.451444Z", + "hash":"1720081993", + "belongsToCurrentTenant":true + }, + { + "id":"642d6756-bf62-4555-9ca5-bec50c5cdb85", + "target":"212342fe-ab6f-4604-b80e-ac23aca93c76", + "targetType":3, + "lockedBy":{ + "name":"admin admin" + }, + "lockedAt":"2024-07-02T11:36:17.926775Z", + "touchedAt":"2024-07-02T11:39:24.278433Z", + "hash":"1719920364", + "belongsToCurrentTenant":true + }, + { + "id":"4a7fd0b4-1b2e-4148-a5fc-152f73caa7e5", + "target":"0e58f8b7-a91e-432a-8de2-edf03679c313", + "targetType":1, + "lockedBy":{ + "name":"admin" + }, + "lockedAt":"2024-07-01T11:16:14.806474Z", + "touchedAt":"2024-07-01T11:23:21.922533Z", + "hash":"1719833001", + "belongsToCurrentTenant":true + } + ], + "count":4 + } + """; + + } + + public static final class User { + + public static final String endpoint_query = + """ + This endpoint is used to fetch all the available users.
+ It also allows to restrict the results using a query object passed in the request body.
+ """; + + public static final String endpoint_query_request_body = + """ + Let's explore the options this object gives us. + + ### General query parameters: + +
    +
  • page: + This is an object controlling the pagination of the results. It contains two properties. +
  • +
      +
    • offset: + How many records to omit. +
    • +
    • size: + How many records to include in each page. +
    • +
    +
+ + For example, if we want the third page, and our pages to contain 15 elements, we would pass the following object: + + ```JSON + { + "offset": 30, + "size": 15 + } + ``` + +
    +
  • order: + This is an object controlling the ordering of the results. + It contains a list of strings called items with the names of the properties to use. +
    If the name of the property is prefixed with a '-', the ordering direction is DESC. Otherwise, it is ASC. +
  • +
+ + For example, if we wanted to order based on the field 'createdAt' in descending order, we would pass the following object: + + ```JSON + { + "items": [ + "-createdAt" + ], + } + ``` + +
    +
  • metadata: + This is an object containing metadata for the request. There is only one available option. +
      +
    • countAll: + If this is set to true, the count property included in the response will account for all the records regardless the pagination, + with all the rest of filtering options applied of course. + Otherwise, if it is set to false or not present, only the returned results will be counted. +
      The first option is useful for the UI clients to calculate how many result pages are available. +
    • +
    +
  • +
  • project: + This is an object controlling the data projection of the results. + It contains a list of strings called fields with the names of the properties to project. +
    You can also include properties that are deeper in the object tree by prefixing them with dots. +
  • +
+ + ### User specific query parameters: + +
    +
  • like: + If there is a like parameter present in the query, only the users that include the contents of the parameter in their names will be in the response. +
  • +
  • ids: + This is a list and contains the ids we want to include in the response.
    If empty, every record is included. +
  • +
  • excludedIds: + This is a list and contains the ids we want to exclude from the response.
    If empty, no record gets excluded. +
  • +
  • isActive: + This is a list and determines which records we want to include in the response, based on if they are deleted or not. + This filter works like this. If we want to view only the active records we pass [1] and for only the deleted records we pass [0]. +
    If not present or if we pass [0,1], every record is included. +
  • +
  • emails: + This is a list and determines which records we want to include in the response, based on their emails. +
    If not present, every record is included. +
  • +
+ """; + + public static final String endpoint_query_request_body_example = + """ + { + "project":{ + "fields":[ + "id", + "name", + "contacts.id", + "contacts.type", + "contacts.value", + "globalRoles.id", + "globalRoles.role", + "tenantRoles.id", + "tenantRoles.role", + "additionalInfo.avatarUrl", + "updatedAt", + "createdAt", + "hash", + "isActive" + ] + }, + "metadata":{ + "countAll":true + }, + "page":{ + "offset":0, + "size":10 + }, + "isActive":[ + 1 + ], + "order":{ + "items":[ + "-createdAt" + ] + } + } + """; + + public static final String endpoint_query_response_example = + """ + { + "items":[ + { + "id":"fc97ad11-2c73-4fc4-835e-e1ca0cf7b918", + "name":"user5 user5", + "createdAt":"2024-07-03T09:59:05.005425Z", + "updatedAt":"2024-07-03T09:59:05.005425Z", + "isActive":1, + "hash":"1720000745", + "additionalInfo":{ + \s + }, + "contacts":[ + { + "id":"8b0972d2-e9d8-4c61-b69b-907ee452dade", + "value":"user5@user5.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ], + "globalRoles":[ + { + "id":"50b8e8e8-eb02-40cb-aa6f-a99eb0f48721", + "role":"User", + "user":{ + \s + } + } + ], + "tenantRoles":[ + { + "id":"cc0307e5-4421-4e46-b7a1-b1326e6e786b", + "role":"TenantUser", + "user":{ + \s + } + } + ] + }, + { + "id":"b494c989-60f1-4584-bc52-b56c40c66ade", + "name":"installationadmin installationadmin", + "createdAt":"2024-06-28T13:23:24.957340Z", + "updatedAt":"2024-06-28T13:23:24.957340Z", + "isActive":1, + "hash":"1719581004", + "additionalInfo":{ + \s + }, + "contacts":[ + { + "id":"cd281a02-f851-400f-ba7f-391e16884051", + "value":"installationadmin@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ], + "globalRoles":[ + { + "id":"1d4088c3-7d42-4227-93d9-ee46ead5f500", + "role":"InstallationAdmin", + "user":{ + \s + } + } + ], + "tenantRoles":[ + { + "id":"b606b428-f404-4232-81fa-a313fcbab25a", + "role":"TenantUser", + "user":{ + \s + } + } + ] + }, + { + "id":"5119e0a6-53ee-4cad-ae58-aa3c1fc79683", + "name":"user3 user3", + "createdAt":"2024-06-28T11:23:22.962858Z", + "updatedAt":"2024-06-28T11:23:22.962858Z", + "isActive":1, + "hash":"1719573802", + "additionalInfo":{ + \s + }, + "contacts":[ + { + "id":"18f1f3f2-77d6-4258-a7d0-1623d7282b82", + "value":"user3@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ], + "globalRoles":[ + { + "id":"116ec22c-3b3a-44ae-9de0-be31c8d621c2", + "role":"User", + "user":{ + \s + } + } + ], + "tenantRoles":[ + { + "id":"618b266b-ecdb-46cd-a5c5-686dc76bba12", + "role":"TenantUser", + "user":{ + \s + } + } + ] + }, + { + "id":"d1873841-3ae3-4a1c-8cfc-841327552313", + "name":"dmproot dmproot", + "createdAt":"2024-06-28T07:19:37.150149Z", + "updatedAt":"2024-06-28T07:19:37.150149Z", + "isActive":1, + "hash":"1719559177", + "additionalInfo":{ + \s + }, + "contacts":[ + { + "id":"20d108c6-8277-40d0-a2b8-e6d8c9c332f0", + "value":"dmproot@cite.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ], + "globalRoles":[ + { + "id":"209b7b67-5374-4b11-a1cf-ecfba6da5f16", + "role":"Admin", + "user":{ + \s + } + }, + { + "id":"5d7ee923-5456-456c-b46f-b53458b0e10a", + "role":"User", + "user":{ + \s + } + } + ], + "tenantRoles":[ + { + "id":"4a14b1fd-2e35-4817-89fa-9d8bf741aee7", + "role":"TenantUser", + "user":{ + \s + } + } + ] + }, + { + "id":"890667ae-7efd-49d9-8ab5-3d48b84a48d1", + "name":"admin admin", + "createdAt":"2024-06-28T07:07:18.589432Z", + "updatedAt":"2024-06-28T07:07:18.589432Z", + "isActive":1, + "hash":"1719558438", + "additionalInfo":{ + \s + }, + "contacts":[ + { + "id":"9739739b-b5d9-4e13-bc47-637b3760b340", + "value":"admin@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ], + "globalRoles":[ + { + "id":"718dd2d0-cbda-4b33-b8be-a25ec30a53f3", + "role":"User", + "user":{ + \s + } + }, + { + "id":"c2c4129e-dcec-448a-8e7c-e4dd7cbc3d9d", + "role":"Admin", + "user":{ + \s + } + } + ], + "tenantRoles":[ + { + "id":"6961542d-6ea7-4064-a0ad-20d82896b9de", + "role":"TenantAdmin", + "user":{ + \s + } + } + ] + }, + { + "id":"1f709343-353b-4787-a8e0-f71020b53f94", + "name":"user5847", + "createdAt":"2024-06-26T22:46:43Z", + "updatedAt":"2024-06-26T22:46:43Z", + "isActive":1, + "hash":"1719442003", + "additionalInfo":{ + "avatarUrl":"null" + }, + "contacts":[ + { + "id":"b8c17fa6-c8e1-49d8-9c7b-173dad43d995", + "value":"user5847@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ] + }, + { + "id":"ac633bd9-ac0b-4258-adc5-24246e1dacbc", + "name":"user5846", + "createdAt":"2024-06-26T22:08:44Z", + "updatedAt":"2024-06-26T22:08:44Z", + "isActive":1, + "hash":"1719439724", + "additionalInfo":{ + "avatarUrl":"null" + }, + "contacts":[ + { + "id":"0126a7d6-c2f3-4f2e-85cc-9c999d74fa85", + "value":"user5846@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ] + }, + { + "id":"2b4e633b-5451-46fb-a1ad-34c1f8fb8fe7", + "name":"user5844", + "createdAt":"2024-06-26T17:04:01Z", + "updatedAt":"2024-06-26T17:04:01Z", + "isActive":1, + "hash":"1719421441", + "additionalInfo":{ + "avatarUrl":"null" + }, + "contacts":[ + { + "id":"138b9b60-8bfb-4900-8f0f-32dd70c8841c", + "value":"user5844@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ] + }, + { + "id":"d9d0ae8b-8037-403e-a155-28d2387d6d7f", + "name":"user5842", + "createdAt":"2024-06-26T13:38:58Z", + "updatedAt":"2024-06-26T13:38:58Z", + "isActive":1, + "hash":"1719409138", + "additionalInfo":{ + "avatarUrl":"null" + }, + "contacts":[ + { + "id":"12bb3f67-941c-4731-8de0-b8d43ff6e17a", + "value":"user5842@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ] + }, + { + "id":"3748e22c-3760-4ada-88ef-8addd247fc76", + "name":"user5841", + "createdAt":"2024-06-26T13:19:52Z", + "updatedAt":"2024-06-26T13:22:19Z", + "isActive":1, + "hash":"1719408139", + "additionalInfo":{ + "avatarUrl":"null" + }, + "contacts":[ + { + "id":"d536278f-9714-43f8-846c-cb5c6bcf2f59", + "value":"user5841@dmp.gr", + "type":0, + "ordinal":0, + "user":{ + \s + } + } + ] + } + ], + "count":5821 + } + """; + + } + + public static final class Principal { + + } + } diff --git a/backend/web/src/main/resources/config/swagger.yml b/backend/web/src/main/resources/config/swagger.yml index 2d97790b1..445e518be 100644 --- a/backend/web/src/main/resources/config/swagger.yml +++ b/backend/web/src/main/resources/config/swagger.yml @@ -11,7 +11,7 @@ springdoc: displayName: Current packagesToScan: org.opencdmp.controllers packagesToExclude: org.opencdmp.controllers.publicapi - pathsToMatch: "/api/plan/**, /api/description/**, /api/description-template/**, /api/description-template-type/**, /api/plan-blueprint/**, /api/entity-doi/**, /api/deposit/**, /api/file-transformer/**, /api/tag/**, /api/reference/**, /api/reference-type/**" + pathsToMatch: "/api/plan/**, /api/description/**, /api/description-template/**, /api/description-template-type/**, /api/plan-blueprint/**, /api/entity-doi/**, /api/deposit/**, /api/file-transformer/**, /api/tag/**, /api/reference/**, /api/reference-type/**, /api/lock/**, /api/user/**, /api/principal/**" swaggerUi: enabled: true useRootPath: true