Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions server/src/main/java/invite/api/APITokenController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<List<APIToken>> apiTokensByInstitution(@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /tokens for user %s", user.getEduPersonPrincipalName()));
Expand All @@ -61,6 +65,7 @@ public ResponseEntity<List<APIToken>> 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<Map<String, String>> generateToken(@Parameter(hidden = true) User user,
@Parameter(hidden = true) HttpServletRequest request) {
Expand All @@ -72,6 +77,7 @@ public ResponseEntity<Map<String, String>> 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<APIToken> create(@Validated @RequestBody APIToken apiTokenRequest,
@Parameter(hidden = true) User user,
@Parameter(hidden = true) HttpServletRequest request) {
Expand Down Expand Up @@ -100,6 +106,12 @@ public ResponseEntity<APIToken> 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<Void> 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()));

Expand Down
14 changes: 14 additions & 0 deletions server/src/main/java/invite/api/InvitationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -237,6 +238,12 @@ public ResponseEntity<InvitationResponse> 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<Void> deleteInvitation(@PathVariable("id") Long id,
@Parameter(hidden = true) User user) {
LOG.debug(String.format("/deleteInvitation/%s by user %s", id, user.getEduPersonPrincipalName()));
Expand All @@ -256,6 +263,7 @@ public ResponseEntity<Void> deleteInvitation(@PathVariable("id") Long id,
}

@PutMapping("/{id}")
@Operation(summary = "Resend an invitation", description = "Resend an existing invitation by ID to the invitee")
public ResponseEntity<Map<String, Integer>> resendInvitation(@PathVariable("id") Long id,
@Parameter(hidden = true) User user) {
LOG.debug(String.format("ResendInvitation with id %s by user %s ", id, user.getEduPersonPrincipalName()));
Expand All @@ -265,6 +273,7 @@ public ResponseEntity<Map<String, Integer>> 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<Invitation> getInvitation(@RequestParam("hash") String hash) {
LOG.debug(String.format("getInvitation with hash %s", hash));
Expand All @@ -277,6 +286,7 @@ public ResponseEntity<Invitation> 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<List<Invitation>> all(@Parameter(hidden = true) User user) {
LOG.debug("GET /all invitations");
Expand All @@ -286,6 +296,7 @@ public ResponseEntity<List<Invitation>> 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<Map<String, Object>> accept(@Validated @RequestBody AcceptInvitation acceptInvitation,
Authentication authentication,
HttpServletRequest servletRequest,
Expand Down Expand Up @@ -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<List<Invitation>> byRole(@PathVariable("roleId") Long roleId, @Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /roles/%s by user %s", roleId, user.getEduPersonPrincipalName()));

Expand All @@ -488,6 +500,7 @@ public ResponseEntity<List<Invitation>> 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<Page<Map<String, Object>>> search(@Parameter(hidden = true) User user,
@RequestParam(value = "roleId", required = false) Long roleId,
Expand Down Expand Up @@ -572,6 +585,7 @@ public ResponseEntity<Page<Map<String, Object>>> 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<List<Invitation>> mine(@Parameter(hidden = true) User user) {
LOG.debug("GET /mine invitations");
Expand Down
10 changes: 10 additions & 0 deletions server/src/main/java/invite/api/ManageController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Map<String, Object>> providerById(@PathVariable("type") EntityType type,
@PathVariable("id") String id,
@Parameter(hidden = true) User user) {
Expand All @@ -81,6 +83,7 @@ public ResponseEntity<Map<String, Object>> providerById(@PathVariable("type") En
}

@GetMapping("/eduid-identity-provider")
@Operation(summary = "Get eduID identity provider", description = "Retrieve eduID identity provider metadata from Manage")
public ResponseEntity<Map<String, Object>> eduIDIdentityProvider(@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /manage/eduIDIdentityProvider type: %s", user.getEduPersonPrincipalName()));
UserPermissions.assertAuthority(user, Authority.INVITER);
Expand All @@ -90,6 +93,7 @@ public ResponseEntity<Map<String, Object>> 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<Map<String, String>> requestedAuthnContextValues() {
LOG.debug("GET /manage/requestedAuthnContextValues");
Map<String, String> acrMap = config.getAcrRequirements().stream()
Expand All @@ -98,6 +102,7 @@ public ResponseEntity<Map<String, String>> 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<List<Map<String, Object>>> providers(@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /manage/providers for user %s", user.getEduPersonPrincipalName()));
UserPermissions.assertAuthority(user, Authority.SUPER_USER);
Expand All @@ -106,6 +111,7 @@ public ResponseEntity<List<Map<String, Object>>> 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<List<Map<String, Object>>> 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);
Expand All @@ -117,6 +123,7 @@ public ResponseEntity<List<Map<String, Object>>> 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<Map<String, Object>> 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()));
Expand All @@ -131,6 +138,7 @@ public ResponseEntity<Map<String, Object>> 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<List<Map<String, Object>>> allApplications(@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /manage/all-applications for user %s", user.getEduPersonPrincipalName()));
Expand All @@ -156,6 +164,7 @@ private List<Map<String, Object>> getProviders(List<Application> 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<Map<String, List<Map<String, Object>>>> applications(@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /manage/applications for user %s", user.getEduPersonPrincipalName()));
Expand Down Expand Up @@ -206,6 +215,7 @@ private List<Map<String, Object>> sanitizeProvisionings(List<Map<String, Object>
}

@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<Boolean> provisionings(@PathVariable("id") String id,
@Parameter(hidden = true) User user) {
LOG.debug(String.format("GET /manage/provisionings for user %s", user.getEduPersonPrincipalName()));
Expand Down
14 changes: 14 additions & 0 deletions server/src/main/java/invite/api/RoleController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Page<Role>> rolesByApplication(@Parameter(hidden = true) User user,
@RequestParam(value = "force", required = false, defaultValue = "true") boolean force,
Expand Down Expand Up @@ -162,6 +166,7 @@ public ResponseEntity<Page<Role>> 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> role(@PathVariable("id") Long id, @Parameter(hidden = true) User user) {
LOG.debug(String.format("/role/%s for user %s", id, user.getEduPersonPrincipalName()));
Expand All @@ -175,6 +180,7 @@ public ResponseEntity<Role> 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<List<Role>> rolesPerApplicationId(@PathVariable("manageId") String manageId, @Parameter(hidden = true) User user) {
LOG.debug(String.format("/rolesPerApplicationId for user %s", user.getEduPersonPrincipalName()));
Expand Down Expand Up @@ -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<Role> newRole(@Validated @RequestBody RoleRequest roleRequest,
@Parameter(hidden = true) User user) {
LOG.debug(String.format("POST /roles/ for user %s", user.getEduPersonPrincipalName()));
Expand All @@ -236,6 +243,7 @@ public ResponseEntity<Role> 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,
Expand All @@ -253,6 +261,12 @@ public ResponseEntity<Role> 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<Void> deleteRole(@PathVariable("id") Long id,
@Parameter(hidden = true) User user) {
Role role = roleRepository.findById(id).orElseThrow(() -> new NotFoundException("Role not found"));
Expand Down
Loading
Loading