feat: make permission controller use tables as param

This commit is contained in:
MiniDigger | Martin 2025-01-10 11:42:10 +01:00
parent e7c2ad9acd
commit 70def75193
2 changed files with 22 additions and 53 deletions

View File

@ -13,9 +13,6 @@ import io.papermc.hangar.model.db.projects.ProjectTable;
import io.papermc.hangar.security.annotations.Anyone;
import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
import io.papermc.hangar.service.PermissionService;
import io.papermc.hangar.service.internal.organizations.OrganizationService;
import io.papermc.hangar.service.internal.projects.ProjectService;
import io.papermc.hangar.util.StringUtils;
import java.util.Collection;
import java.util.Set;
import java.util.function.BiPredicate;
@ -31,71 +28,41 @@ import org.springframework.stereotype.Controller;
@RateLimit(path = "apipermissions", refillTokens = 100, greedy = true)
public class PermissionsController extends HangarComponent implements IPermissionsController {
private final OrganizationService organizationService;
private final ProjectService projectService;
private final PermissionService permissionService;
@Autowired
public PermissionsController(final OrganizationService organizationService, final ProjectService projectService, final PermissionService permissionService) {
this.organizationService = organizationService;
this.projectService = projectService;
public PermissionsController(final PermissionService permissionService) {
this.permissionService = permissionService;
}
@Override
public ResponseEntity<PermissionCheck> hasAllPermissions(final Set<NamedPermission> permissions, final String project, final String organization) {
public ResponseEntity<PermissionCheck> hasAllPermissions(final Set<NamedPermission> permissions, final ProjectTable project, final OrganizationTable organization) {
return this.has(permissions, project, organization, (namedPerms, perm) -> namedPerms.stream().allMatch(p -> perm.has(p.getPermission())));
}
@Override
public ResponseEntity<PermissionCheck> hasAny(final Set<NamedPermission> permissions, final String project, final String organization) {
public ResponseEntity<PermissionCheck> hasAny(final Set<NamedPermission> permissions, final ProjectTable project, final OrganizationTable organization) {
return this.has(permissions, project, organization, (namedPerms, perm) -> namedPerms.stream().anyMatch(p -> perm.has(p.getPermission())));
}
@Override
public ResponseEntity<UserPermissions> showPermissions(final String project, final String organization) {
public ResponseEntity<UserPermissions> showPermissions(final ProjectTable project, final OrganizationTable organization) {
final Pair<PermissionType, Permission> scopedPerms = this.getPermissionsInScope(project, organization);
return ResponseEntity.ok(new UserPermissions(scopedPerms.getLeft(), scopedPerms.getRight().toBinString(), scopedPerms.getRight().toNamed()));
}
private Pair<PermissionType, Permission> getPermissionsInScope(final String project, final String organization) {
private Pair<PermissionType, Permission> getPermissionsInScope(final ProjectTable project, final OrganizationTable organization) {
if (project != null && organization != null) {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "Specifying both project and organization is not allowed");
}
if (project != null) {
ProjectTable projectTable = null;
if (StringUtils.isLong(project)) {
projectTable = this.projectService.getProjectTable(Long.parseLong(project));
}
if (projectTable == null) {
projectTable = this.projectService.getProjectTable(project);
}
if (projectTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND, "Project not found");
}
final Permission perms = this.permissionService.getProjectPermissions(this.getHangarUserId(), projectTable.getId());
final Permission perms = this.permissionService.getProjectPermissions(this.getHangarUserId(), project.getId());
return new ImmutablePair<>(PermissionType.PROJECT, perms);
}
if (organization != null) {
OrganizationTable organizationTable = null;
if (StringUtils.isLong(organization)) {
organizationTable = this.organizationService.getOrganizationTable(Long.parseLong(organization));
}
if (organizationTable == null) {
organizationTable = this.organizationService.getOrganizationTable(organization);
}
if (organizationTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND, "Organization not found");
}
final Permission perms = this.permissionService.getOrganizationPermissions(this.getHangarUserId(), organizationTable.getId());
final Permission perms = this.permissionService.getOrganizationPermissions(this.getHangarUserId(), organization.getId());
return new ImmutablePair<>(PermissionType.ORGANIZATION, perms);
}
@ -104,7 +71,7 @@ public class PermissionsController extends HangarComponent implements IPermissio
return new ImmutablePair<>(PermissionType.GLOBAL, perms);
}
private ResponseEntity<PermissionCheck> has(final Collection<NamedPermission> perms, final String project, final String organization, final BiPredicate<Collection<NamedPermission>, Permission> check) {
private ResponseEntity<PermissionCheck> has(final Collection<NamedPermission> perms, final ProjectTable project, final OrganizationTable organization, final BiPredicate<Collection<NamedPermission>, Permission> check) {
final Pair<PermissionType, Permission> scopedPerms = this.getPermissionsInScope(project, organization);
return ResponseEntity.ok(new PermissionCheck(scopedPerms.getLeft(), check.test(perms, scopedPerms.getRight())));
}

View File

@ -3,6 +3,8 @@ package io.papermc.hangar.controller.api.v1.interfaces;
import io.papermc.hangar.model.api.permissions.PermissionCheck;
import io.papermc.hangar.model.api.permissions.UserPermissions;
import io.papermc.hangar.model.common.NamedPermission;
import io.papermc.hangar.model.db.OrganizationTable;
import io.papermc.hangar.model.db.projects.ProjectTable;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@ -37,8 +39,8 @@ public interface IPermissionsController {
@GetMapping(value = "/permissions/hasAll", params = "!slug")
ResponseEntity<PermissionCheck> hasAllPermissions(
@Parameter(description = "The permissions to check", required = true) @RequestParam @Size(max = 50) Set<NamedPermission> permissions,
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false) String project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false) String organization
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false, name = "project") ProjectTable project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false, name = "organization") OrganizationTable organization
);
@Operation(
@ -56,8 +58,8 @@ public interface IPermissionsController {
@GetMapping(value = "/permissions/hasAll", params = "slug")
default ResponseEntity<PermissionCheck> hasAllPermissionsLegacy(
@Parameter(description = "The permissions to check", required = true) @RequestParam final @Size(max = 50) Set<NamedPermission> permissions,
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false) final String slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `slug`") @RequestParam(required = false) final String organization
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false, name = "slug") final ProjectTable slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `slug`") @RequestParam(required = false, name = "organization") final OrganizationTable organization
) {
return this.hasAllPermissions(permissions, slug, organization);
}
@ -78,8 +80,8 @@ public interface IPermissionsController {
@GetMapping(value = "/permissions/hasAny", params = "!slug")
ResponseEntity<PermissionCheck> hasAny(
@Parameter(description = "The permissions to check", required = true) @RequestParam Set<NamedPermission> permissions,
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false) String project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false) String organization
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false, name = "project") ProjectTable project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false, name = "organization") OrganizationTable organization
);
@Operation(
@ -97,8 +99,8 @@ public interface IPermissionsController {
@GetMapping(value = "/permissions/hasAny", params = "slug")
default ResponseEntity<PermissionCheck> hasAnyLegacy(
@Parameter(description = "The permissions to check", required = true) @RequestParam final Set<NamedPermission> permissions,
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false) final String slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false) final String organization
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false, name = "slug") final ProjectTable slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false, name = "organization") final OrganizationTable organization
) {
return this.hasAny(permissions, slug, organization);
}
@ -117,8 +119,8 @@ public interface IPermissionsController {
})
@GetMapping(value = "/permissions", params = "!slug", produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<UserPermissions> showPermissions(
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false) String project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false) String organization
@Parameter(description = "The id or slug of the project to check permissions in. Must not be used together with `organization`") @RequestParam(required = false, name = "project") ProjectTable project,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false, name = "organization") OrganizationTable organization
);
@Operation(
@ -135,8 +137,8 @@ public interface IPermissionsController {
})
@GetMapping(value = "/permissions", params = "slug", produces = MediaType.APPLICATION_JSON_VALUE)
default ResponseEntity<UserPermissions> showPermissionsLegacy(
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false) final String slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`") @RequestParam(required = false) final String organization
@Deprecated @Parameter(description = "Deprecated alias for `project`") @RequestParam(required = false, name = "slug") final ProjectTable slug,
@Parameter(description = "The id or name of the organization to check permissions in. Must not be used together with `project`", name = "organization") @RequestParam(required = false) final OrganizationTable organization
) {
return this.showPermissions(slug, organization);
}