diff --git a/server/src/main/java/invite/api/APITokenController.java b/server/src/main/java/invite/api/APITokenController.java index bf641b71..288dd31c 100644 --- a/server/src/main/java/invite/api/APITokenController.java +++ b/server/src/main/java/invite/api/APITokenController.java @@ -8,7 +8,10 @@ import invite.model.User; import invite.repository.APITokenRepository; import invite.security.UserPermissions; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; @@ -50,6 +53,7 @@ public APITokenController(APITokenRepository apiTokenRepository) { } @GetMapping("") + @Operation(summary = "Get API tokens by institution", description = "Retrieve API tokens for the authenticated user or organization") @Transactional(readOnly = true) public ResponseEntity> apiTokensByInstitution(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /tokens for user %s", user.getEduPersonPrincipalName())); @@ -61,6 +65,7 @@ public ResponseEntity> apiTokensByInstitution(@Parameter(hidden = } @GetMapping("generate-token") + @Operation(summary = "Generate a new API token", description = "Generate a new unhashed API token and store it temporarily in the session") @Transactional(readOnly = true) public ResponseEntity> generateToken(@Parameter(hidden = true) User user, @Parameter(hidden = true) HttpServletRequest request) { @@ -72,6 +77,7 @@ public ResponseEntity> generateToken(@Parameter(hidden = tru } @PostMapping("") + @Operation(summary = "Create an API token", description = "Create and persist a new API token using the token generated in the current session") public ResponseEntity create(@Validated @RequestBody APIToken apiTokenRequest, @Parameter(hidden = true) User user, @Parameter(hidden = true) HttpServletRequest request) { @@ -100,6 +106,12 @@ public ResponseEntity create(@Validated @RequestBody APIToken apiToken } @DeleteMapping("/{id}") + @Operation(summary = "Delete an API token", description = "Delete an existing API token by ID") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "API token deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "API token not found") + }) public ResponseEntity deleteToken(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { LOG.debug(String.format("DELETE /tokens/deleteToken with id %s for user %s", id.toString(), user.getEduPersonPrincipalName())); diff --git a/server/src/main/java/invite/api/InvitationController.java b/server/src/main/java/invite/api/InvitationController.java index 8dbadb23..f55f4651 100644 --- a/server/src/main/java/invite/api/InvitationController.java +++ b/server/src/main/java/invite/api/InvitationController.java @@ -41,6 +41,7 @@ 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.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -237,6 +238,12 @@ public ResponseEntity newInvitation(@Validated @RequestBody } @DeleteMapping("/{id}") + @Operation(summary = "Delete an invitation", description = "Delete an existing invitation by ID") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "Invitation deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Invitation not found") + }) public ResponseEntity deleteInvitation(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { LOG.debug(String.format("/deleteInvitation/%s by user %s", id, user.getEduPersonPrincipalName())); @@ -256,6 +263,7 @@ public ResponseEntity deleteInvitation(@PathVariable("id") Long id, } @PutMapping("/{id}") + @Operation(summary = "Resend an invitation", description = "Resend an existing invitation by ID to the invitee") public ResponseEntity> resendInvitation(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { LOG.debug(String.format("ResendInvitation with id %s by user %s ", id, user.getEduPersonPrincipalName())); @@ -265,6 +273,7 @@ public ResponseEntity> resendInvitation(@PathVariable("id") } @GetMapping("public") + @Operation(summary = "Get invitation by hash", description = "Retrieve an open invitation using its secure hash token") @Transactional(readOnly = true) public ResponseEntity getInvitation(@RequestParam("hash") String hash) { LOG.debug(String.format("getInvitation with hash %s", hash)); @@ -277,6 +286,7 @@ public ResponseEntity getInvitation(@RequestParam("hash") String has } @GetMapping("all") + @Operation(summary = "Get all open invitations", description = "Retrieve all open invitations (super user only)") @Transactional(readOnly = true) public ResponseEntity> all(@Parameter(hidden = true) User user) { LOG.debug("GET /all invitations"); @@ -286,6 +296,7 @@ public ResponseEntity> all(@Parameter(hidden = true) User user) @PostMapping("accept") + @Operation(summary = "Accept an invitation", description = "Accept an invitation using invitation ID and hash token") public ResponseEntity> accept(@Validated @RequestBody AcceptInvitation acceptInvitation, Authentication authentication, HttpServletRequest servletRequest, @@ -476,6 +487,7 @@ private void saveOAuth2AuthenticationToken(Authentication authentication, } @GetMapping("roles/{roleId}") + @Operation(summary = "Get open invitations by Role", description = "Retrieve all open invitations for a specific role ID") public ResponseEntity> byRole(@PathVariable("roleId") Long roleId, @Parameter(hidden = true) User user) { LOG.debug(String.format("GET /roles/%s by user %s", roleId, user.getEduPersonPrincipalName())); @@ -488,6 +500,7 @@ public ResponseEntity> byRole(@PathVariable("roleId") Long role } @GetMapping("search") + @Operation(summary = "Search invitations", description = "Search and paginate invitations optionally filtered by role ID and search query") @Transactional(readOnly = true) public ResponseEntity>> search(@Parameter(hidden = true) User user, @RequestParam(value = "roleId", required = false) Long roleId, @@ -572,6 +585,7 @@ public ResponseEntity>> search(@Parameter(hidden = true } @GetMapping("/mine") + @Operation(summary = "Get my invitations", description = "Retrieve all open invitations created by the current authenticated user") @Transactional(readOnly = true) public ResponseEntity> mine(@Parameter(hidden = true) User user) { LOG.debug("GET /mine invitations"); diff --git a/server/src/main/java/invite/api/ManageController.java b/server/src/main/java/invite/api/ManageController.java index 06795f30..f4fc7a8a 100644 --- a/server/src/main/java/invite/api/ManageController.java +++ b/server/src/main/java/invite/api/ManageController.java @@ -12,6 +12,7 @@ import invite.repository.ApplicationRepository; import invite.repository.RoleRepository; import invite.security.UserPermissions; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.apache.commons.logging.Log; @@ -71,6 +72,7 @@ public ManageController(Manage manage, } @GetMapping("/provider/{type}/{id}") + @Operation(summary = "Get provider by type and ID", description = "Retrieve identity or service provider metadata by entity type and ID (super user only)") public ResponseEntity> providerById(@PathVariable("type") EntityType type, @PathVariable("id") String id, @Parameter(hidden = true) User user) { @@ -81,6 +83,7 @@ public ResponseEntity> providerById(@PathVariable("type") En } @GetMapping("/eduid-identity-provider") + @Operation(summary = "Get eduID identity provider", description = "Retrieve eduID identity provider metadata from Manage") public ResponseEntity> eduIDIdentityProvider(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/eduIDIdentityProvider type: %s", user.getEduPersonPrincipalName())); UserPermissions.assertAuthority(user, Authority.INVITER); @@ -90,6 +93,7 @@ public ResponseEntity> eduIDIdentityProvider(@Parameter(hidd } @GetMapping("/requested-authn-context-values") + @Operation(summary = "Get requested authn context values", description = "Retrieve map of configured ACR requirement keys and URLs") public ResponseEntity> requestedAuthnContextValues() { LOG.debug("GET /manage/requestedAuthnContextValues"); Map acrMap = config.getAcrRequirements().stream() @@ -98,6 +102,7 @@ public ResponseEntity> requestedAuthnContextValues() { } @GetMapping("/providers") + @Operation(summary = "Get all service providers and relying parties", description = "Retrieve SAML20 SP and OIDC10 RP providers from Manage (super user only)") public ResponseEntity>> providers(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/providers for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertAuthority(user, Authority.SUPER_USER); @@ -106,6 +111,7 @@ public ResponseEntity>> providers(@Parameter(hidden = t } @GetMapping("/identity-providers") + @Operation(summary = "Get identity providers", description = "Retrieve identity providers with institution GUID from Manage (super user only)") public ResponseEntity>> identityProviders(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/identity-providers for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertAuthority(user, Authority.SUPER_USER); @@ -117,6 +123,7 @@ public ResponseEntity>> identityProviders(@Parameter(hi } @GetMapping("/organization-guid-validation/{organizationGUID}") + @Operation(summary = "Validate organization GUID", description = "Retrieve identity provider matching the specified organization GUID (super user only)") public ResponseEntity> organizationGUIDValidation(@Parameter(hidden = true) User user, @PathVariable("organizationGUID") String organizationGUID) { LOG.debug(String.format("GET /manage/organization-guid-validation guid: %s for user %s", organizationGUID, user.getEduPersonPrincipalName())); @@ -131,6 +138,7 @@ public ResponseEntity> organizationGUIDValidation(@Parameter @GetMapping("/all-applications") + @Operation(summary = "Get all applications", description = "Retrieve provider metadata for all registered applications (super user only)") @Transactional(readOnly = true) public ResponseEntity>> allApplications(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/all-applications for user %s", user.getEduPersonPrincipalName())); @@ -156,6 +164,7 @@ private List> getProviders(List applications) { } @GetMapping("/applications") + @Operation(summary = "Get applications for current user", description = "Retrieve accessible applications and provisioning configurations for the authenticated user") @Transactional(readOnly = true) public ResponseEntity>>> applications(@Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/applications for user %s", user.getEduPersonPrincipalName())); @@ -206,6 +215,7 @@ private List> sanitizeProvisionings(List } @GetMapping("/provisionings/{id}") + @Operation(summary = "Check provisioning exists for ID", description = "Check if provisioning exists in Manage for the specified application manage ID") public ResponseEntity provisionings(@PathVariable("id") String id, @Parameter(hidden = true) User user) { LOG.debug(String.format("GET /manage/provisionings for user %s", user.getEduPersonPrincipalName())); diff --git a/server/src/main/java/invite/api/RoleController.java b/server/src/main/java/invite/api/RoleController.java index 46f43024..517d9540 100644 --- a/server/src/main/java/invite/api/RoleController.java +++ b/server/src/main/java/invite/api/RoleController.java @@ -23,7 +23,10 @@ import invite.repository.UserRepository; import invite.repository.UserRoleRepository; import invite.security.UserPermissions; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.Getter; import org.apache.commons.logging.Log; @@ -112,6 +115,7 @@ public RoleController(RoleRepository roleRepository, } @GetMapping("") + @Operation(summary = "Get roles by application", description = "Search and paginate roles accessible to the authenticated user") @Transactional(readOnly = true) public ResponseEntity> rolesByApplication(@Parameter(hidden = true) User user, @RequestParam(value = "force", required = false, defaultValue = "true") boolean force, @@ -162,6 +166,7 @@ public ResponseEntity> rolesByApplication(@Parameter(hidden = true) U } @GetMapping("{id}") + @Operation(summary = "Get role by ID", description = "Retrieve role details by its unique identifier") @Transactional(readOnly = true) public ResponseEntity role(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { LOG.debug(String.format("/role/%s for user %s", id, user.getEduPersonPrincipalName())); @@ -175,6 +180,7 @@ public ResponseEntity role(@PathVariable("id") Long id, @Parameter(hidden } @GetMapping("/application/{manageId}") + @Operation(summary = "Get roles by application manage ID", description = "Retrieve all roles associated with a specific application manage ID") @Transactional(readOnly = true) public ResponseEntity> rolesPerApplicationId(@PathVariable("manageId") String manageId, @Parameter(hidden = true) User user) { LOG.debug(String.format("/rolesPerApplicationId for user %s", user.getEduPersonPrincipalName())); @@ -215,6 +221,7 @@ private void assertRoleAccess(@PathVariable("manageId") String manageId, @Parame } @PostMapping("") + @Operation(summary = "Create a new role", description = "Create a new role with associated applications and permissions") public ResponseEntity newRole(@Validated @RequestBody RoleRequest roleRequest, @Parameter(hidden = true) User user) { LOG.debug(String.format("POST /roles/ for user %s", user.getEduPersonPrincipalName())); @@ -236,6 +243,7 @@ public ResponseEntity newRole(@Validated @RequestBody RoleRequest roleRequ } @PutMapping("") + @Operation(summary = "Update an existing role", description = "Update role name, description, and application usages") @Retryable( retryFor = {SQLTransactionRollbackException.class}, maxAttempts = 3, @@ -253,6 +261,12 @@ public ResponseEntity updateRole(@Validated @RequestBody Role role, } @DeleteMapping("/{id}") + @Operation(summary = "Delete a role", description = "Delete an existing role by ID and clean up associated group requests") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "Role deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "Role not found") + }) public ResponseEntity deleteRole(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { Role role = roleRepository.findById(id).orElseThrow(() -> new NotFoundException("Role not found")); diff --git a/server/src/main/java/invite/api/SystemController.java b/server/src/main/java/invite/api/SystemController.java index bf5cfabe..672bb43b 100644 --- a/server/src/main/java/invite/api/SystemController.java +++ b/server/src/main/java/invite/api/SystemController.java @@ -16,6 +16,7 @@ import invite.repository.UserRoleRepository; import invite.security.UserPermissions; import invite.seed.PerformanceSeed; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.apache.commons.logging.Log; @@ -73,6 +74,7 @@ public SystemController(ResourceCleaner resourceCleaner, } @GetMapping("/cron/cleanup") + @Operation(summary = "Trigger cron resource cleanup", description = "Clean up expired invitations and tokens (super user only)") public ResponseEntity> cronCleanup(@Parameter(hidden = true) User user) { LOG.debug(String.format("/cron/cleanup for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertSuperUser(user); @@ -81,6 +83,7 @@ public ResponseEntity> cronCleanup(@Parameter(hidden = true) } @GetMapping("/cron/expiry-notifications") + @Operation(summary = "Trigger cron role expiry notifications", description = "Send notifications for roles that are about to expire (super user only)") public ResponseEntity>> expiryNotifications(@Parameter(hidden = true) User user) { LOG.debug(String.format("/cron/expiry-notifications for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertSuperUser(user); @@ -88,6 +91,7 @@ public ResponseEntity>> expiryNotifications(@Parameter( } @GetMapping("/expiry-user-roles") + @Operation(summary = "Get expiring user roles", description = "Retrieve user roles that will expire within the next 30 days (super user only)") public ResponseEntity> expiryUserRoles(@Parameter(hidden = true) User user) { LOG.debug(String.format("/expiry-user-roles for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertSuperUser(user); @@ -98,6 +102,7 @@ public ResponseEntity> expiryUserRoles(@Parameter(hidden = true) } @GetMapping("/unknown-roles") + @Operation(summary = "Get unknown roles", description = "Retrieve roles with unknown Manage application metadata (super user only)") @Transactional(readOnly = true) public ResponseEntity> unknownRoles(@Parameter(hidden = true) User user) { LOG.debug(String.format("/unknown-roles for user %s", user.getEduPersonPrincipalName())); @@ -108,6 +113,7 @@ public ResponseEntity> unknownRoles(@Parameter(hidden = true) User us } @PutMapping("/performance-seed") + @Operation(summary = "Seed performance test data", description = "Generate seed roles and users for performance testing (super user only)") public ResponseEntity> performanceSeed(@Parameter(hidden = true) User user, @RequestParam(value = "numberOfRole", required = false, defaultValue = "500") int numberOfRole, @RequestParam(value = "numberOfUsers", required = false, defaultValue = "75000") int numberOfUsers) { @@ -121,6 +127,7 @@ public ResponseEntity> performanceSeed(@Parameter(hidden = t } @GetMapping("/landing-page-fix") + @Operation(summary = "Fix missing landing pages", description = "Update missing application landing pages from Manage provider metadata (super user only)") public ResponseEntity> landingPageFix(@Parameter(hidden = true) User user) { LOG.debug(String.format("landing-page-fix for user %s", user.getEduPersonPrincipalName())); UserPermissions.assertSuperUser(user); diff --git a/server/src/main/java/invite/api/UserController.java b/server/src/main/java/invite/api/UserController.java index 90c1d04c..40dab223 100644 --- a/server/src/main/java/invite/api/UserController.java +++ b/server/src/main/java/invite/api/UserController.java @@ -19,7 +19,10 @@ import invite.repository.RoleRepository; import invite.repository.UserRepository; import invite.security.UserPermissions; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; @@ -100,6 +103,7 @@ public UserController(Config config, } @GetMapping("config") + @Operation(summary = "Get user configuration", description = "Get configuration information and authentication status for the current user session") public ResponseEntity config(User user, @RequestParam(value = "guest", required = false, defaultValue = "false") boolean guest) { LOG.debug("GET /config"); @@ -114,6 +118,7 @@ public ResponseEntity config(User user, } @GetMapping("me") + @Operation(summary = "Get current authenticated user", description = "Retrieve user details and roles for the currently authenticated user") @Transactional(readOnly = true) public ResponseEntity me(@Parameter(hidden = true) User user) { LOG.debug(String.format("/me for user %s", user.getEduPersonPrincipalName())); @@ -126,6 +131,7 @@ public ResponseEntity me(@Parameter(hidden = true) User user) { } @GetMapping("institutionAdmins") + @Operation(summary = "Get institution admins", description = "Retrieve list of institution admins for the current user's organization") @Transactional(readOnly = true) public ResponseEntity>> institutionAdmins(@Parameter(hidden = true) User user, @RequestParam(value = "includeMe", required = false, defaultValue = "false") boolean includeMe) { @@ -139,6 +145,7 @@ public ResponseEntity>> institutionAdmins(@Parameter(hi } @GetMapping("applicationManagers") + @Operation(summary = "Get application managers", description = "Retrieve list of application managers for the current user's organization") @Transactional(readOnly = true) public ResponseEntity>> applicationManagers(@Parameter(hidden = true) User user) { LOG.debug(String.format("/applicationManagers for user %s", user.getEduPersonPrincipalName())); @@ -150,6 +157,7 @@ public ResponseEntity>> applicationManagers(@Parameter( } @GetMapping("other/{id}") + @Operation(summary = "Get user details by ID", description = "Retrieve details and roles for a specific user by their ID") @Transactional(readOnly = true) public ResponseEntity details(@PathVariable("id") Long id, @Parameter(hidden = true) User user) { LOG.debug(String.format("/other/%s for user %s", id, user.getEduPersonPrincipalName())); @@ -170,6 +178,7 @@ public ResponseEntity details(@PathVariable("id") Long id, @Parameter(hidd } @GetMapping("search") + @Operation(summary = "Search users", description = "Search and paginate all users (super user only)") @Transactional(readOnly = true) public ResponseEntity>> search(@Parameter(hidden = true) User user, @RequestParam(value = "force", required = false, defaultValue = "true") boolean force, @@ -201,6 +210,7 @@ public ResponseEntity>> search(@Parameter(hidden = true } @GetMapping("search-by-application") + @Operation(summary = "Search users by application", description = "Search and paginate users and their roles within the institution admin's organization") @Transactional(readOnly = true) public ResponseEntity> searchByApplication(@Parameter(hidden = true) User user, @RequestParam(value = "query", required = false, defaultValue = "") String query, @@ -234,12 +244,14 @@ public ResponseEntity> searchByApplication(@Parameter(hidden = t } @GetMapping("login") + @Operation(summary = "User login redirect", description = "Redirect user to client or welcome application login flow") public View login(@RequestParam(value = "app", required = false, defaultValue = "client") String app) { LOG.debug(String.format("/login for app: %s", app)); return new RedirectView(app.equals("client") ? config.getClientUrl() : config.getWelcomeUrl(), false); } @GetMapping("logout") + @Operation(summary = "User logout", description = "Clear authentication session and log out current user") public ResponseEntity> logout(HttpServletRequest request, @Parameter(hidden = true) Authentication authentication) { LOG.debug("/logout"); @@ -256,6 +268,7 @@ public ResponseEntity> logout(HttpServletRequest request, } @GetMapping("ms-accept-return/{manageId}/{userId}") + @Operation(summary = "Microsoft invitation accept return", description = "Handle callback redirect after Microsoft graph invitation acceptance") public View msAcceptReturn(@PathVariable("manageId") String manageId, @PathVariable("userId") Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("User not found")); @@ -277,6 +290,12 @@ public View msAcceptReturn(@PathVariable("manageId") String manageId, @PathVaria } @DeleteMapping("/{userId}") + @Operation(summary = "Delete a user", description = "Delete an existing user by ID (super user only)") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "User deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "User not found") + }) public ResponseEntity delete(@PathVariable("userId") Long userId, @Parameter(hidden = true) User user) { User other = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("User not found")); @@ -291,6 +310,7 @@ public ResponseEntity delete(@PathVariable("userId") Long userId, @Paramet } @PutMapping("/removeInstitutionAdmin/{userId}") + @Operation(summary = "Remove institution admin rights", description = "Remove institution admin status from an invited user") public ResponseEntity> removeInstitutionAdmin(@PathVariable("userId") Long userId, @Parameter(hidden = true) User user) { User other = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("User not found")); @@ -312,6 +332,7 @@ public ResponseEntity> removeInstitutionAdmin(@PathVariable } @PutMapping("/removeApplicationManager/{userId}") + @Operation(summary = "Remove application manager rights", description = "Clear application manager applications for a user") public ResponseEntity> removeApplicationManager(@PathVariable("userId") Long userId, @Parameter(hidden = true) User user) { User other = userRepository.findById(userId).orElseThrow(() -> new NotFoundException("User not found")); @@ -327,6 +348,7 @@ public ResponseEntity> removeApplicationManager(@PathVariab } @GetMapping("/institution-admins/{roleId}") + @Operation(summary = "Get institution admins by role", description = "Retrieve institution admins associated with a specific role") @Transactional(readOnly = true) public ResponseEntity> institutionAdminsbyRole(@PathVariable Long roleId, @Parameter(hidden = true) User user) { @@ -342,7 +364,8 @@ public ResponseEntity> institutionAdminsbyRole(@PathVariable Long rol return ResponseEntity.ok(users); } - @PostMapping("error") + @PostMapping("error") + @Operation(summary = "Log frontend error", description = "Log client-side error payload on the server") public ResponseEntity> error(@RequestBody Map payload, @Parameter(hidden = true) User user) throws JsonProcessingException, UnknownHostException { diff --git a/server/src/main/java/invite/api/UserRoleController.java b/server/src/main/java/invite/api/UserRoleController.java index 11dca503..a6d236bf 100644 --- a/server/src/main/java/invite/api/UserRoleController.java +++ b/server/src/main/java/invite/api/UserRoleController.java @@ -91,6 +91,7 @@ public UserRoleController(UserRoleRepository userRoleRepository, } @GetMapping("roles/{roleId}") + @Operation(summary = "Get UserRoles by Role", description = "Get all UserRoles for the specified Role") @Transactional(readOnly = true) public ResponseEntity> byRole(@PathVariable("roleId") Long roleId, @Parameter(hidden = true) User user) { @@ -101,6 +102,7 @@ public ResponseEntity> byRole(@PathVariable("roleId") Long roleId } @GetMapping("managers/{roleId}") + @Operation(summary = "Get managers by Role", description = "Get all managers for the specified Role") @Transactional(readOnly = true) public ResponseEntity> managersByRole(@PathVariable("roleId") Long roleId, @Parameter(hidden = true) User user) { @@ -115,6 +117,7 @@ public ResponseEntity> managersByRole(@PathVariable("roleId") Long } @GetMapping("/consequences/{roleId}") + @Operation(summary = "Get consequences of deleting a Role", description = "Get all UserRoles and user information that will be affected by deleting the specified Role") @Transactional(readOnly = true) public ResponseEntity>> consequencesDeleteRole(@PathVariable("roleId") Long roleId, @Parameter(hidden = true) User user) { @@ -133,6 +136,7 @@ public ResponseEntity>> consequencesDeleteRole(@PathVar } @GetMapping("/search/{roleId}/{guests}") + @Operation(summary = "Search UserRoles with pagination", description = "Search and paginate UserRoles for the specified Role, filtered by guest status and search query") @Transactional(readOnly = true) public ResponseEntity> searchPaginated(@PathVariable("roleId") Long roleId, @PathVariable("guests") boolean guests, @@ -222,6 +226,7 @@ public ResponseEntity userRoleProvisioning(@Validated @RequestBody UserRol } @PutMapping("") + @Operation(summary = "Update UserRole expiration date", description = "Update the expiration end date of an existing UserRole") public ResponseEntity> updateUserRoleExpirationDate(@Validated @RequestBody UpdateUserRole updateUserRole, @Parameter(hidden = true) User user) { LOG.debug(String.format("PUT user_roles for user %s", user.getEduPersonPrincipalName())); @@ -240,6 +245,12 @@ public ResponseEntity> updateUserRoleExpirationDate(@Valida } @DeleteMapping("/{id}/{isGuest}") + @Operation(summary = "Delete UserRole", description = "Delete an existing UserRole by ID, or update authority if guest role is included") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "Role deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), + @ApiResponse(responseCode = "404", description = "UserRole not found") + }) public ResponseEntity deleteUserRole(@PathVariable("id") Long id, @PathVariable("isGuest") Boolean isGuest, @Parameter(hidden = true) User user) { @@ -277,6 +288,7 @@ public ResponseEntity deleteUserRole(@PathVariable("id") Long id, description = "Lookup the User and Role by their remote provisioned SCIM identifiers and delete the UserRole") @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "UserRole deleted successfully"), + @ApiResponse(responseCode = "401", description = "Unauthorized"), @ApiResponse(responseCode = "404", description = "User or Role not found") }) public ResponseEntity deleteUserRoleByProvisionedScim(