mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-03-13 15:39:18 +08:00
improve SPeL support in various annotations
This commit is contained in:
parent
b4f4f426af
commit
03352e47cb
@ -161,7 +161,7 @@ public class LoginController extends HangarComponent {
|
||||
@RateLimit(overdraft = 5, refillTokens = 2, refillSeconds = 10)
|
||||
@ResponseStatus(HttpStatus.ACCEPTED)
|
||||
public void sync(@NotNull @RequestBody SsoSyncData body, @RequestHeader("X-Kratos-Hook-Api-Key") String apiKey) {
|
||||
if (!apiKey.equals("hookapikey-changeme")) {
|
||||
if (!apiKey.equals("hookapikey-changeme")) { // TODO change
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,10 @@ import io.papermc.hangar.security.annotations.visibility.VisibilityRequired;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequired.Type;
|
||||
import io.papermc.hangar.service.internal.projects.ChannelService;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectService;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -30,11 +34,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// @el(projectId: long)
|
||||
@Controller
|
||||
@RateLimit(path = "channel")
|
||||
@RequestMapping(value = "/api/internal/channels", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
|
@ -1,7 +1,13 @@
|
||||
package io.papermc.hangar.controller.internal;
|
||||
|
||||
import io.papermc.hangar.HangarComponent;
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.internal.job.PostDiscourseReplyJob;
|
||||
import io.papermc.hangar.security.annotations.LoggedIn;
|
||||
import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequired;
|
||||
import io.papermc.hangar.service.internal.JobService;
|
||||
import java.util.Map;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@ -10,16 +16,9 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.papermc.hangar.HangarComponent;
|
||||
import io.papermc.hangar.model.internal.job.PostDiscourseReplyJob;
|
||||
import io.papermc.hangar.security.annotations.LoggedIn;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequired;
|
||||
import io.papermc.hangar.service.internal.JobService;
|
||||
|
||||
import static io.papermc.hangar.security.annotations.visibility.VisibilityRequired.Type;
|
||||
|
||||
// @el(projectId: long)
|
||||
@LoggedIn
|
||||
@Controller
|
||||
@RateLimit(path = "discourse")
|
||||
@ -36,7 +35,7 @@ public class DiscourseController extends HangarComponent {
|
||||
@ResponseBody
|
||||
@RateLimit(overdraft = 5, refillTokens = 1, refillSeconds = 30)
|
||||
@VisibilityRequired(type = Type.PROJECT, args = "{#projectId}")
|
||||
public String createPost(@PathVariable("projectId") long projectId, @RequestBody Map<String, String> content) {
|
||||
public String createPost(@PathVariable long projectId, @RequestBody Map<String, String> content) {
|
||||
if (!config.discourse.isEnabled()) {
|
||||
throw new HangarApiException("Discourse is NOT enabled!");
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ public class HangarUserController extends HangarComponent {
|
||||
return ResponseEntity.ok(usersApiService.getUser(hangarAuthenticationToken.getName(), HangarUser.class));
|
||||
}
|
||||
|
||||
// @el(userName: String)
|
||||
@Unlocked
|
||||
@CurrentUser("#userName")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
|
@ -47,6 +47,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
// @el(orgName: String)
|
||||
@Controller
|
||||
@RateLimit(path = "organization")
|
||||
@RequestMapping("/api/internal/organizations")
|
||||
@ -83,20 +84,20 @@ public class OrganizationController extends HangarComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(value = "/org/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<HangarOrganization> getOrganization(@PathVariable String name) {
|
||||
return ResponseEntity.ok(organizationService.getHangarOrganization(name));
|
||||
@GetMapping(value = "/org/{orgName}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<HangarOrganization> getOrganization(@PathVariable String orgName) {
|
||||
return ResponseEntity.ok(organizationService.getHangarOrganization(orgName));
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@RateLimit(overdraft = 7, refillTokens = 2, refillSeconds = 10)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/members/add", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void addOrganizationMember(@PathVariable String name, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/members/add", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void addOrganizationMember(@PathVariable String orgName, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
if (organizationTable == null) {
|
||||
throw new HangarApiException("Org " + name + " doesn't exist");
|
||||
throw new HangarApiException("Org " + orgName + " doesn't exist");
|
||||
}
|
||||
inviteService.sendInvite(member, organizationTable);
|
||||
}
|
||||
@ -104,48 +105,48 @@ public class OrganizationController extends HangarComponent {
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@RateLimit(overdraft = 5, refillTokens = 2, refillSeconds = 10)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/members/edit", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void editOrganizationMember(@PathVariable String name, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/members/edit", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void editOrganizationMember(@PathVariable String orgName, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
memberService.editMember(member, organizationTable);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@RateLimit(overdraft = 7, refillTokens = 2, refillSeconds = 10)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/members/remove", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void removeOrganizationMember(@PathVariable String name, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.MANAGE_SUBJECT_MEMBERS, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/members/remove", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void removeOrganizationMember(@PathVariable String orgName, @Valid @RequestBody EditMembersForm.Member<OrganizationRole> member) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
memberService.removeMember(member, organizationTable);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_MEMBER, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/members/leave", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void leaveOrganization(@PathVariable String name) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_MEMBER, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/members/leave", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void leaveOrganization(@PathVariable String orgName) {
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
memberService.leave(organizationTable);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_OWNER, args = "{#name}")
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_OWNER, args = "{#orgName}")
|
||||
@RateLimit(overdraft = 5, refillTokens = 1, refillSeconds = 60)
|
||||
@PostMapping(path = "/org/{name}/transfer", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void transferOrganization(@PathVariable String name, @Valid @RequestBody StringContent nameContent) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PostMapping(path = "/org/{orgName}/transfer", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void transferOrganization(@PathVariable String orgName, @Valid @RequestBody StringContent nameContent) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
inviteService.sendTransferRequest(nameContent.getContent(), organizationTable);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_OWNER, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/canceltransfer", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void cancelOrganizationTransfer(@PathVariable String name) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.IS_SUBJECT_OWNER, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/canceltransfer", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void cancelOrganizationTransfer(@PathVariable String orgName) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
inviteService.cancelTransferRequest(organizationTable);
|
||||
}
|
||||
|
||||
@ -160,21 +161,21 @@ public class OrganizationController extends HangarComponent {
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@RateLimit(overdraft = 3, refillTokens = 1, refillSeconds = 60)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.DELETE_ORGANIZATION, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/delete", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void delete(@PathVariable String name, @RequestBody @Valid StringContent content) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.DELETE_ORGANIZATION, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/delete", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void delete(@PathVariable String orgName, @RequestBody @Valid StringContent content) {
|
||||
final OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
organizationFactory.deleteOrganization(organizationTable, content.getContent());
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@RateLimit(overdraft = 7, refillTokens = 1, refillSeconds = 20)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#name}")
|
||||
@PostMapping(path = "/org/{name}/settings/tagline", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void saveTagline(@PathVariable String name, @Valid @RequestBody StringContent content) {
|
||||
UserTable userTable = userService.getUserTable(name);
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(name);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#orgName}")
|
||||
@PostMapping(path = "/org/{orgName}/settings/tagline", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public void saveTagline(@PathVariable String orgName, @Valid @RequestBody StringContent content) {
|
||||
UserTable userTable = userService.getUserTable(orgName);
|
||||
OrganizationTable organizationTable = organizationService.getOrganizationTable(orgName);
|
||||
if (userTable == null || organizationTable == null) {
|
||||
throw new HangarApiException(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
@ -190,10 +191,10 @@ public class OrganizationController extends HangarComponent {
|
||||
@Unlocked
|
||||
@ResponseBody
|
||||
@RateLimit(overdraft = 5, refillTokens = 1, refillSeconds = 60)
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#name}")
|
||||
@PostMapping(value = "/org/{name}/settings/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public void changeAvatar(@PathVariable String name, @RequestParam MultipartFile avatar) throws IOException {
|
||||
authenticationService.changeAvatar(name, avatar);
|
||||
@PermissionRequired(type = PermissionType.ORGANIZATION, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#orgName}")
|
||||
@PostMapping(value = "/org/{orgName}/settings/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public void changeAvatar(@PathVariable String orgName, @RequestParam MultipartFile avatar) throws IOException {
|
||||
authenticationService.changeAvatar(orgName, avatar);
|
||||
}
|
||||
|
||||
@Anyone
|
||||
|
@ -47,6 +47,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
// @el(projectId: long, author: String, slug: String, versionString: String, platform: io.papermc.hangar.model.common.Platform)
|
||||
@Controller
|
||||
@Secured("ROLE_USER")
|
||||
@RateLimit(path = "version")
|
||||
@ -174,13 +175,13 @@ public class VersionController extends HangarComponent {
|
||||
|
||||
@ResponseBody
|
||||
@RateLimit(overdraft = 5, refillTokens = 1, refillSeconds = 20)
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}") // TODO is platform needed in the visibility check? it's not used in the VisibilityRequiredVoter
|
||||
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public Resource download(@PathVariable String author, @PathVariable String slug, @PathVariable String versionString, @PathVariable Platform platform, @RequestParam(required = false) String token) {
|
||||
return downloadService.getVersionFile(author, slug, versionString, platform, true, token);
|
||||
}
|
||||
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}") // TODO is platform needed in the visibility check? it's not used in the VisibilityRequiredVoter
|
||||
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/downloadCheck")
|
||||
public ResponseEntity<String> downloadCheck(@PathVariable String author, @PathVariable String slug, @PathVariable String versionString, @PathVariable Platform platform) {
|
||||
boolean requiresConfirmation = downloadService.requiresConfirmation(author, slug, versionString, platform);
|
||||
|
@ -10,16 +10,13 @@ import io.papermc.hangar.security.annotations.permission.PermissionRequired;
|
||||
import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectAdminService;
|
||||
import io.papermc.hangar.service.internal.versions.ReviewService;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RateLimit(path = "adminapproval")
|
||||
|
@ -12,6 +12,8 @@ import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
|
||||
import io.papermc.hangar.security.annotations.unlocked.Unlocked;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectAdminService;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectNoteService;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -24,9 +26,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
// @el(projectId: long)
|
||||
@LoggedIn
|
||||
@Controller
|
||||
@RateLimit(path = "projectadmin")
|
||||
|
@ -30,6 +30,9 @@ import io.papermc.hangar.service.internal.projects.ProjectService;
|
||||
import io.papermc.hangar.service.internal.uploads.ImageService;
|
||||
import io.papermc.hangar.service.internal.users.UserService;
|
||||
import io.papermc.hangar.service.internal.users.invites.ProjectInviteService;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -44,10 +47,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// @el(author: String, slug: String, projectId: long, project: io.papermc.hangar.model.db.projects.ProjectTable)
|
||||
@Controller
|
||||
@RateLimit(path = "project")
|
||||
@RequestMapping(path = "/api/internal/projects", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ -96,7 +97,7 @@ public class ProjectController extends HangarComponent {
|
||||
@PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<String> createProject(@RequestBody @Valid NewProjectForm newProject) {
|
||||
ProjectTable projectTable = projectFactory.createProject(newProject);
|
||||
// need to do this here, outside of the transactional
|
||||
// need to do this here, outside the transactional
|
||||
projectService.refreshHomeProjects();
|
||||
return ResponseEntity.ok(projectTable.getUrl());
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import io.papermc.hangar.service.ValidationService;
|
||||
import io.papermc.hangar.service.internal.MarkdownService;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectPageService;
|
||||
import io.papermc.hangar.util.BBCodeConverter;
|
||||
import java.util.Collection;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -32,9 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collection;
|
||||
|
||||
// @el(author: String, slug: String, projectId: long)
|
||||
@Anyone
|
||||
@Controller
|
||||
@RateLimit(path = "projectpage")
|
||||
|
@ -1,21 +1,21 @@
|
||||
package io.papermc.hangar.controller.validations;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.Payload;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.Payload;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = Validate.ValidateConstraintValidator.class)
|
||||
@ -23,6 +23,7 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Repeatable(Validate.List.class)
|
||||
public @interface Validate {
|
||||
@Language("SpEL")
|
||||
String SpEL() default "";
|
||||
String message() default "Invalid field";
|
||||
Class<?>[] groups() default {};
|
||||
|
@ -12,8 +12,12 @@ public class ProjectLicense {
|
||||
private static final HangarConfig config = StaticContextAccessor.getBean(HangarConfig.class);
|
||||
|
||||
private final String name;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String url;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.required(#root)")
|
||||
private final String type;
|
||||
|
||||
|
@ -2,33 +2,45 @@ package io.papermc.hangar.model.api.project;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import java.util.Collection;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ProjectSettings {
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String homepage;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String issues;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String source;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String support;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")
|
||||
private final String wiki;
|
||||
@Valid
|
||||
private final ProjectLicense license;
|
||||
@Valid
|
||||
private final ProjectDonationSettings donation;
|
||||
|
||||
// @el(root: Collection<String>)
|
||||
@NotNull
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.projects.maxKeywords)", message = "project.new.error.tooManyKeywords")
|
||||
private final Collection<String> keywords;
|
||||
private final boolean forumSync;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.projects.maxSponsorsLen)", message = "project.new.error.tooLongSponsors")
|
||||
private final String sponsors;
|
||||
|
||||
|
@ -2,10 +2,10 @@ package io.papermc.hangar.model.internal.api.requests;
|
||||
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.common.roles.OrganizationRole;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CreateOrganizationForm extends EditMembersForm<OrganizationRole> {
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.required(#root)", message = "organization.new.error.invalidName")
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.org.nameRegex)", message = "organization.new.error.invalidName")
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.org.maxNameLen)", message = "organization.new.error.invalidName")
|
||||
|
@ -5,11 +5,10 @@ import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.common.roles.Role;
|
||||
import io.papermc.hangar.model.db.roles.ExtendedRoleTable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class EditMembersForm<R extends Role<? extends ExtendedRoleTable<R, ?>>> {
|
||||
|
||||
@ -35,7 +34,9 @@ public class EditMembersForm<R extends Role<? extends ExtendedRoleTable<R, ?>>>
|
||||
|
||||
@NotBlank
|
||||
private final String name;
|
||||
@Validate(SpEL = "#root.isAssignable")
|
||||
|
||||
// @el(root: Role)
|
||||
@Validate(SpEL = "#root.assignable")
|
||||
private final R role;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -4,13 +4,13 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.common.ChannelFlag;
|
||||
import io.papermc.hangar.model.common.Color;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Set;
|
||||
|
||||
public class ChannelForm {
|
||||
|
||||
// @el(root: String)
|
||||
@NotBlank
|
||||
@Validate(SpEL = "@validations.regex(#root, @hangarConfig.channels.nameRegex)", message = "channel.modal.error.invalidName")
|
||||
@Validate(SpEL = "@validations.max(#root, @hangarConfig.channels.maxNameLen)", message = "channel.modal.error.tooLongName")
|
||||
|
@ -3,16 +3,19 @@ package io.papermc.hangar.model.internal.api.requests.projects;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.api.project.ProjectSettings;
|
||||
import io.papermc.hangar.model.common.projects.Category;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class NewProjectForm extends ProjectSettingsForm {
|
||||
|
||||
private final long ownerId;
|
||||
|
||||
// @el(root: String)
|
||||
@NotNull(message = "project.new.error.invalidName")
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.projects.maxNameLen)", message = "project.new.error.tooLongName")
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.projects.nameRegex)", message = "project.new.error.invalidName")
|
||||
private final String name;
|
||||
|
||||
// @el(root: String)
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.pages.maxLen)", message = "page.new.error.maxLength")
|
||||
private final String pageContent;
|
||||
|
||||
|
@ -2,11 +2,11 @@ package io.papermc.hangar.model.internal.api.requests.projects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
public class NewProjectPage {
|
||||
|
||||
// @el(root: String)
|
||||
@NotBlank
|
||||
@Validate(SpEL = "@validate.min(#root, @hangarConfig.pages.minNameLen)", message = "page.new.error.name.minLength")
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.pages.maxNameLen)", message = "page.new.error.name.maxLength")
|
||||
|
@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.api.project.ProjectSettings;
|
||||
import io.papermc.hangar.model.common.projects.Category;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ -14,6 +13,8 @@ public class ProjectSettingsForm {
|
||||
private final ProjectSettings settings;
|
||||
@NotNull(message = "project.new.error.noCategory")
|
||||
private final Category category;
|
||||
|
||||
// @el(root: String)
|
||||
@NotNull(message = "project.new.error.noDescription")
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.projects.maxDescLen)", message = "project.new.error.tooLongDesc")
|
||||
private final String description;
|
||||
|
@ -2,11 +2,11 @@ package io.papermc.hangar.model.internal.versions;
|
||||
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import java.util.List;
|
||||
import javax.validation.constraints.Size;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
// @el(root: String) // can't figure out how to apply this to just the one record component
|
||||
public record MultipartFileOrUrl(
|
||||
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms") List<Platform> platforms,
|
||||
@Nullable @Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl") String externalUrl) {
|
||||
|
@ -7,31 +7,35 @@ import io.papermc.hangar.model.api.project.version.PluginDependency;
|
||||
import io.papermc.hangar.model.common.ChannelFlag;
|
||||
import io.papermc.hangar.model.common.Color;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PendingVersion {
|
||||
|
||||
// @el(root: String)
|
||||
@NotBlank(message = "version.new.error.invalidVersionString")
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.projects.versionNameRegex)", message = "version.new.error.invalidVersionString")
|
||||
private final String versionString;
|
||||
private final Map<Platform, Set<@Valid PluginDependency>> pluginDependencies;
|
||||
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms")
|
||||
private final Map<Platform, @Size(min = 1, message = "version.edit.error.noPlatformVersions") SortedSet<@NotBlank(message = "version.new.error.invalidPlatformVersion") String>> platformDependencies;
|
||||
|
||||
// @el(root: String)
|
||||
@NotBlank(message = "version.new.error.noDescription")
|
||||
@Validate(SpEL = "@validate.max(#root, @hangarConfig.pages.maxLen)", message = "page.new.error.maxLength")
|
||||
private final String description;
|
||||
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms")
|
||||
private final List<@Valid PendingVersionFile> files;
|
||||
|
||||
// @el(root: String)
|
||||
@NotBlank(message = "version.new.error.channel.noName")
|
||||
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.channels.nameRegex)", message = "channel.modal.error.invalidName")
|
||||
private final String channelName;
|
||||
|
@ -3,11 +3,11 @@ package io.papermc.hangar.model.internal.versions;
|
||||
import io.papermc.hangar.controller.validations.Validate;
|
||||
import io.papermc.hangar.model.api.project.version.FileInfo;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import java.util.List;
|
||||
import javax.validation.constraints.Size;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
// @el(root: String) // can't figure out how to apply this to just the field
|
||||
public record PendingVersionFile(
|
||||
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms") List<Platform> platforms,
|
||||
@Nullable FileInfo fileInfo,
|
||||
|
@ -1,12 +1,12 @@
|
||||
package io.papermc.hangar.security.annotations.currentuser;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Requires that the user referenced in the method be the current user
|
||||
@ -21,6 +21,7 @@ public @interface CurrentUser {
|
||||
* interchangeable with {@link #userArgument()}
|
||||
* @return the SpEL string for the argument in a method
|
||||
*/
|
||||
@Language("SpEL")
|
||||
@AliasFor("userArgument")
|
||||
String value() default "";
|
||||
|
||||
@ -28,6 +29,7 @@ public @interface CurrentUser {
|
||||
* interchangeable with {@link #value()}
|
||||
* @return the SpEL string for the argument in a method
|
||||
*/
|
||||
@Language("SpEL")
|
||||
@AliasFor("value")
|
||||
String userArgument() default "";
|
||||
}
|
||||
|
@ -3,14 +3,14 @@ package io.papermc.hangar.security.annotations.permission;
|
||||
import io.papermc.hangar.model.common.NamedPermission;
|
||||
import io.papermc.hangar.model.common.PermissionType;
|
||||
import io.papermc.hangar.security.annotations.permission.PermissionRequired.List;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Mark a method or class to require permissions
|
||||
@ -45,6 +45,8 @@ public @interface PermissionRequired {
|
||||
* <br>
|
||||
* The length of the SpEL array <b>must</b> match the type;
|
||||
*/
|
||||
// @el(projectId: String)
|
||||
@Language("SpEL")
|
||||
String args() default "{}";
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
|
@ -6,6 +6,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Set;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
|
||||
/**
|
||||
* Visibility check for a project or version
|
||||
@ -24,6 +25,7 @@ public @interface VisibilityRequired {
|
||||
* Method arguments to resolve the project or version
|
||||
* @return method arguments as an SpEL array
|
||||
*/
|
||||
@Language("SpEL")
|
||||
String args();
|
||||
|
||||
enum Type {
|
||||
|
@ -1,19 +1,17 @@
|
||||
package io.papermc.hangar.security.annotations.visibility;
|
||||
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.security.annotations.HangarDecisionVoter;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequiredMetadataExtractor.VisibilityRequiredAttribute;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectService;
|
||||
import io.papermc.hangar.service.internal.versions.VersionService;
|
||||
import java.util.Arrays;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Component
|
||||
public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequiredAttribute> {
|
||||
|
||||
@ -47,7 +45,7 @@ public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequi
|
||||
if (arguments.length == 1 && versionService.getProjectVersionTable((long) arguments[0]) != null) {
|
||||
return ACCESS_GRANTED;
|
||||
} else {
|
||||
if (versionService.getProjectVersionTable((String) arguments[0], (String) arguments[1], (String) arguments[2]) != null) {
|
||||
if (versionService.getProjectVersionTable((String) arguments[0], (String) arguments[1], (String) arguments[2]) != null) { // TODO is platform needed here?
|
||||
return ACCESS_GRANTED;
|
||||
} else {
|
||||
return ACCESS_DENIED;
|
||||
|
Loading…
x
Reference in New Issue
Block a user