From 1e040dcbebc29eb7731c98c60d507b4db8ac10c7 Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 06:55:57 +0000 Subject: [PATCH 01/13] Clean up date time formatter --- src/main/java/com/imjustdoom/pluginsite/util/DateUtil.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/imjustdoom/pluginsite/util/DateUtil.java b/src/main/java/com/imjustdoom/pluginsite/util/DateUtil.java index 90b06e1..30be21b 100644 --- a/src/main/java/com/imjustdoom/pluginsite/util/DateUtil.java +++ b/src/main/java/com/imjustdoom/pluginsite/util/DateUtil.java @@ -3,10 +3,9 @@ import java.time.format.DateTimeFormatter; public class DateUtil { - - public static DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ssa"); + private static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ssa"); public static DateTimeFormatter getDateFormatter() { - return format; + return FORMAT; } } From da2a32804124b0eecf62dc3847219752c458f8a1 Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 08:38:14 +0000 Subject: [PATCH 02/13] Update AccountController & AdminController, error handler --- .../pluginsite/PluginSiteApplication.java | 2 + .../config/exception/RestErrorCode.java | 41 ++++++ .../config/exception/RestException.java | 20 +++ .../RestExceptionResponseHandler.java | 25 ++++ .../controller/AccountController.java | 119 ------------------ .../controller/AdminController.java | 83 ------------ .../controller/ErrorController.java | 22 ---- .../controller/ExternalUrlController.java | 28 ----- .../pluginsite/controller/HomeController.java | 53 -------- .../controller/OtherController.java | 34 ----- .../controller/rest/AccountController.java | 51 ++++++++ .../controller/rest/AdminController.java | 50 ++++++++ .../{ => account}/CreateAccountRequest.java | 4 +- .../dtos/in/account/UpdateAccountRequest.java | 11 ++ .../dtos/out/account/AccountDto.java | 14 +++ .../dtos/out/account/SelfAccountDto.java | 16 +++ .../repositories/ReportRepository.java | 6 +- .../service/rest/AccountService.java | 65 ++++++++++ .../pluginsite/service/rest/AdminService.java | 28 +++++ 19 files changed, 327 insertions(+), 345 deletions(-) create mode 100644 src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/config/exception/RestException.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/ErrorController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/ExternalUrlController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/HomeController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/OtherController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java rename src/main/java/com/imjustdoom/pluginsite/dtos/in/{ => account}/CreateAccountRequest.java (65%) create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/in/account/UpdateAccountRequest.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java diff --git a/src/main/java/com/imjustdoom/pluginsite/PluginSiteApplication.java b/src/main/java/com/imjustdoom/pluginsite/PluginSiteApplication.java index 69a4116..f66b3e2 100644 --- a/src/main/java/com/imjustdoom/pluginsite/PluginSiteApplication.java +++ b/src/main/java/com/imjustdoom/pluginsite/PluginSiteApplication.java @@ -3,8 +3,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.data.web.config.EnableSpringDataWebSupport; @SpringBootApplication +@EnableSpringDataWebSupport @ConfigurationPropertiesScan public class PluginSiteApplication { diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java new file mode 100644 index 0000000..1c7c669 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -0,0 +1,41 @@ +package com.imjustdoom.pluginsite.config.exception; + + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.http.HttpStatus; + +public enum RestErrorCode { + INVALID_USERNAME(HttpStatus.BAD_REQUEST, "auth", 1), + INVALID_EMAIL(HttpStatus.BAD_REQUEST, "auth", 2), + USERNAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 3), + EMAIL_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 4), + + ACCOUNT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 100), + REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), + WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), + FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), + PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4) + + private final HttpStatus httpStatus; + private final String module; + private final int errorCode; + + RestErrorCode(HttpStatus httpStatus, String module, int errorCode) { + this.httpStatus = httpStatus; + this.module = module; + this.errorCode = errorCode; + } + + @JsonIgnore + public HttpStatus getHttpStatus() { + return this.httpStatus; + } + + public String getModule() { + return this.module; + } + + public int getErrorCode() { + return this.errorCode; + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestException.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestException.java new file mode 100644 index 0000000..ad1a745 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestException.java @@ -0,0 +1,20 @@ +package com.imjustdoom.pluginsite.config.exception; + +import lombok.Getter; +import org.springframework.lang.Nullable; + +@Getter +public class RestException extends Exception { + private final RestErrorCode errorCode; + private final @Nullable String message; + + public RestException(RestErrorCode errorCode, String message, Object... params) { + this.errorCode = errorCode; + this.message = String.format(message, params); + } + + public RestException(RestErrorCode errorCode) { + this.errorCode = errorCode; + this.message = null; + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java new file mode 100644 index 0000000..1a2ae70 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java @@ -0,0 +1,25 @@ +package com.imjustdoom.pluginsite.config.exception; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@RestControllerAdvice +@RequiredArgsConstructor +public class RestExceptionResponseHandler extends ResponseEntityExceptionHandler { + + private final ObjectMapper mapper; + + @ExceptionHandler(RestException.class) + public void handle(HttpServletResponse response, RestException exception) throws IOException { + if (!response.isCommitted()) + this.mapper.writeValue(response.getWriter(), exception); + } + + // Could add an error ticketing system for unknown errors (5xx) thrown +} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java b/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java deleted file mode 100644 index 8e5f67a..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.config.custom.SiteConfig; -import com.imjustdoom.pluginsite.dtos.in.CreateAccountRequest; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.util.ImageUtil; -import com.imjustdoom.pluginsite.util.ValidationHelper; -import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.bcrypt.BCrypt; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.view.RedirectView; - -import java.util.Optional; - -@Controller -@RequiredArgsConstructor -public class AccountController { - - private final PasswordEncoder passwordEncoder; - private final AccountRepository accountRepository; - private final SiteConfig siteConfig; - - @GetMapping("/signup") - public String signup(Model model, @RequestParam(name = "error", required = false) String error, Account account) { - model.addAttribute("createAccount", new CreateAccountRequest()); - model.addAttribute("account", account); - model.addAttribute("error", error); - return "account/signup"; - } - - @GetMapping("/logout") - public RedirectView logout() { - return new RedirectView("/"); - } - - @PostMapping("/signup") - public String signupSubmit(@ModelAttribute CreateAccountRequest accountRequest) { - if (!ValidationHelper.isUsernameValid(accountRequest.getUsername())) return "redirect:/signup?error=invalidcharacter"; - - String emailAddress = accountRequest.getEmail(); - - if (!ValidationHelper.isEmailValid(emailAddress)) return "redirect:/signup?error=invalidemail"; - - if (accountRepository.existsByUsernameEqualsIgnoreCase(accountRequest.getUsername())) - return "redirect:/signup?error=usernametaken"; - - if (accountRepository.existsByEmailEqualsIgnoreCase(emailAddress)) return "redirect:/signup?error=emailtaken"; - - Account account = new Account(accountRequest.getUsername(), emailAddress, passwordEncoder.encode(accountRequest.getPassword())); - accountRepository.save(account); - - return "redirect:/profile/" + account.getId(); - } - - @GetMapping("/login") - public String login(Model model, @RequestParam(name = "error", required = false) String error, Account account) { - model.addAttribute("error", error); - model.addAttribute("createAccount", new CreateAccountRequest()); - model.addAttribute("account", account); - return "account/login"; - } - - @PostMapping("/login") - public String loginSubmit(@ModelAttribute CreateAccountRequest accountRequest) { - - if (accountRepository.existsByUsernameEqualsIgnoreCaseOrEmailEqualsIgnoreCase(accountRequest.getUsername(), "")) { // todo change - Optional account = accountRepository.findByUsernameEqualsIgnoreCase(accountRequest.getUsername()); - if (BCrypt.checkpw(accountRequest.getPassword(), account.get().getPassword())) { - - return "redirect:/profile/" + account.get().getId(); - } - return "redirect:/login?error=incorrectpassword"; - } - - return "redirect:/login?error=notfound"; - } - - @GetMapping("/account/details") - public String accountDetails(Model model, Account account, @RequestParam(name = "error", required = false) String error) { - model.addAttribute("account", account); - model.addAttribute("url", this.siteConfig.getDomain()); - model.addAttribute("error", error); - return "account/details"; - } - - @PostMapping("/account/details") - public String postAccountDetails(Account account, @RequestParam String username, @RequestParam String email, - @RequestParam String password, @RequestParam("logo") MultipartFile file) { - if (!ValidationHelper.isUsernameValid(username)) return "redirect:/account/details?error=invalidcharacter"; - if (!ValidationHelper.isEmailValid(email)) return "redirect:/account/details?error=invalidemail"; - - if (!file.isEmpty()) { - if (!file.getContentType().contains("image")) { - return "redirect:/account/details?error=logotype"; - } - - if (file.getSize() > 1024000) { - return "redirect:/account/details?error=filesize"; - } - - accountRepository.updateProfilePictureById(account.getId(), ImageUtil.handleImage(file)); - } - - if (accountRepository.existsByUsernameEqualsIgnoreCase(username)) - return "redirect:/account/details?error=usernametaken"; - - if (accountRepository.existsByEmailEqualsIgnoreCase(email)) return "redirect:/account/details?error=emailtaken"; - - accountRepository.setUsernameById(account.getId(), username); - accountRepository.setEmailById(account.getId(), email); - accountRepository.setPasswordById(account.getId(), passwordEncoder.encode(password)); - return "redirect:/profile/" + account.getId(); - } -} \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java b/src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java deleted file mode 100644 index 19b72b2..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Report; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.ReportRepository; -import com.imjustdoom.pluginsite.util.UrlUtil; -import lombok.AllArgsConstructor; -import org.commonmark.node.Node; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.Optional; - -@Controller -@AllArgsConstructor -public class AdminController { - private final AccountRepository accountRepository; - private final ReportRepository reportRepository; - - private final UrlUtil urlUtil; - - @GetMapping("/admin") - public String admin(Model model, Account account) { - model.addAttribute("account", account); - return "admin/admin"; - } - - @GetMapping("/admin/reports") - public String reports(Model model, Account account) { - model.addAttribute("account", account); - model.addAttribute("reports", reportRepository.findAll()); - return "admin/reports"; - } - - @GetMapping("/admin/report/{id}") - public String report(Model model, Account account, @PathVariable("id") int id) { - - Report report = reportRepository.findById(id).get(); - String description = urlUtil.encode(report.getReport()); - - description.replaceAll("script", "error style=\"display:none;\""); - Parser parser = Parser.builder().build(); - Node document = parser.parse(description); - HtmlRenderer renderer = HtmlRenderer.builder().build(); - String html = renderer.render(document); - - report.setReport(html); - - model.addAttribute("account", account); - model.addAttribute("report", report); - return "admin/report"; - } - - @PostMapping("/admin/report/{id}") - public String report(@PathVariable("id") int id, @RequestParam String action) { - reportRepository.updateActionTakenById(id, action); - return "redirect:/admin/reports"; - } - - @GetMapping("/admin/roles") - public String roles(Model model, Account account) { - model.addAttribute("account", account); - return "admin/account/roles"; - } - - @PostMapping("/admin/roles") - public void setRole(@RequestParam String username, @RequestParam String role, Account account, Model model) { - model.addAttribute("account", account); - - Optional optionalAccount = accountRepository.findByUsernameEqualsIgnoreCase(username); - if (optionalAccount.isEmpty()) return; - role = role.toUpperCase(); - optionalAccount.get().setRole("ROLE_" + role); - accountRepository.setRoleById(optionalAccount.get().getId(), "ROLE_" + role); - } -} \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ErrorController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ErrorController.java deleted file mode 100644 index 37a82a4..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ErrorController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.servlet.NoHandlerFoundException; - -@ControllerAdvice -public class ErrorController { - /* idk what an Exception error is */ -// @ExceptionHandler(Exception.class) -// public String handleException() { -// return "error/error"; -// } - - @ExceptionHandler(NoHandlerFoundException.class) - public String handle404(Model model, Account account) { - model.addAttribute("account", account); - return "error/404"; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ExternalUrlController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ExternalUrlController.java deleted file mode 100644 index 008c05b..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ExternalUrlController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -@Controller -public class ExternalUrlController { - @GetMapping("/redirect") - public String redirect(Model model, HttpServletResponse response, @RequestParam(name = "url", required = false, value = "") String url, Account account) { - // do you know how to remove the url from the parameters? - - url.replaceAll("%2F", "/"); - - Cookie cookie = new Cookie("url", url); - - response.addCookie(cookie); - - model.addAttribute("account", account); - - return "redirect/redirect"; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/HomeController.java b/src/main/java/com/imjustdoom/pluginsite/controller/HomeController.java deleted file mode 100644 index d1cb0bb..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/HomeController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Blog; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.BlogRepository; -import lombok.AllArgsConstructor; -import org.commonmark.node.Node; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; - -@Controller -@AllArgsConstructor -public class HomeController { - - private final BlogRepository blogRepository; - private final AccountRepository accountRepository; - - @GetMapping("/") - public String home(Model model, Account account) { - for (Blog blog : blogRepository.findAll()) { - int authorId = blog.getAuthorId(); - Account author = accountRepository.findById(authorId).get(); - blog.setAuthorName(author.getUsername()); - - LocalDateTime date = blog.getCreatedDate(); - String dateString = date.getDayOfMonth() + "/" + date.getMonthValue() + "/" + date.getYear() + ", " + date.getHour() + ":" + date.getMinute(); - blog.setDateString(dateString); - - String md_body = blog.getPost(); - md_body = md_body.replaceAll("script", "error style=\"display:none;\""); - Parser parser = Parser.builder().build(); - - Node document = parser.parse(md_body); - HtmlRenderer renderer = HtmlRenderer.builder().build(); - blog.setPost(renderer.render(document)); - } - - model.addAttribute("account", account); - - List blogs = blogRepository.findAll(); - Collections.reverse(blogs); - model.addAttribute("blogs", blogs); - return "home"; - } -} \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/OtherController.java b/src/main/java/com/imjustdoom/pluginsite/controller/OtherController.java deleted file mode 100644 index e0e0c2e..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/OtherController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class OtherController { - - @GetMapping("/privacy") - public String privacy(Account account, Model model) { - model.addAttribute("account", account); - return "terms/privacy"; - } - - @GetMapping("/terms") - public String terms(Account account, Model model) { - model.addAttribute("account", account); - return "terms/terms"; - } - - @GetMapping("/contact") - public String contact(Account account, Model model) { - model.addAttribute("account", account); - return "terms/contact"; - } - - @GetMapping("/team") - public String team(Account account, Model model) { - model.addAttribute("account", account); - return "team"; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java new file mode 100644 index 0000000..1d78568 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java @@ -0,0 +1,51 @@ +package com.imjustdoom.pluginsite.controller.rest; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; +import com.imjustdoom.pluginsite.dtos.in.account.UpdateAccountRequest; +import com.imjustdoom.pluginsite.dtos.out.account.AccountDto; +import com.imjustdoom.pluginsite.dtos.out.account.SelfAccountDto; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.service.rest.AccountService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/account") +@RequiredArgsConstructor +public class AccountController { + private final AccountService accountService; + + @PostMapping("/register") + public String signupSubmit(@RequestBody CreateAccountRequest accountRequest) throws RestException { + Account account = this.accountService.register(accountRequest); + + return ""; // todo return a registration DTO of some sort, probably with a session token + } + + // todo login with JWT + + @GetMapping("/account/details") + public SelfAccountDto getSelfAccountDetails(Account account) { + return SelfAccountDto.fromAccount(account); + } + + @GetMapping("/account/{id}/details") + public AccountDto getAccountDetails(@PathVariable int id) throws RestException { + return AccountDto.fromAccount(this.accountService.getAccount(id)); + } + + @PatchMapping("/account/details") + public SelfAccountDto updateAccountDetails(Account account, @RequestBody UpdateAccountRequest request, + @RequestParam("profilePicture") MultipartFile file) throws RestException { + return SelfAccountDto.fromAccount(this.accountService.updateAccountDetails(account, request, file)); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java new file mode 100644 index 0000000..1cee881 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java @@ -0,0 +1,50 @@ +package com.imjustdoom.pluginsite.controller.rest; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.model.Report; +import com.imjustdoom.pluginsite.service.rest.AdminService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/admin") +@RequiredArgsConstructor +public class AdminController { + private final AdminService adminService; + + @GetMapping("/report") + public Page listReports(Pageable pageable) throws RestException { + if (pageable.getPageSize() > 50) throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size too large (%s > %s)", pageable.getPageSize(), 50); + return this.adminService.getReportPage(pageable); + } + + @GetMapping("/report/{id}") + public Report getReport(@PathVariable int id) throws RestException { + return this.adminService.getReport(id); + } + + @PatchMapping("/report/{id}") + public Report updateActionTaken(@PathVariable int id, @RequestParam String actionTaken) { + return this.adminService.updateActionTaken(id, actionTaken); + } + + // todo didnt add roles since this system should be reworked. The code below is the old code. +// @PostMapping("/admin/roles") +// public void setRole(@RequestParam String username, @RequestParam String role, Account account, Model model) { +// model.addAttribute("account", account); +// +// Optional optionalAccount = accountRepository.findByUsernameEqualsIgnoreCase(username); +// if (optionalAccount.isEmpty()) return; +// role = role.toUpperCase(); +// optionalAccount.get().setRole("ROLE_" + role); +// accountRepository.setRoleById(optionalAccount.get().getId(), "ROLE_" + role); +// } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateAccountRequest.java b/src/main/java/com/imjustdoom/pluginsite/dtos/in/account/CreateAccountRequest.java similarity index 65% rename from src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateAccountRequest.java rename to src/main/java/com/imjustdoom/pluginsite/dtos/in/account/CreateAccountRequest.java index f8e8a01..148ea91 100644 --- a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateAccountRequest.java +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/in/account/CreateAccountRequest.java @@ -1,12 +1,10 @@ -package com.imjustdoom.pluginsite.dtos.in; +package com.imjustdoom.pluginsite.dtos.in.account; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter -@NoArgsConstructor public class CreateAccountRequest { private String username; diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/in/account/UpdateAccountRequest.java b/src/main/java/com/imjustdoom/pluginsite/dtos/in/account/UpdateAccountRequest.java new file mode 100644 index 0000000..3099ca2 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/in/account/UpdateAccountRequest.java @@ -0,0 +1,11 @@ +package com.imjustdoom.pluginsite.dtos.in.account; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UpdateAccountRequest { + private String username; + private String email; +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java new file mode 100644 index 0000000..4b6df82 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java @@ -0,0 +1,14 @@ +package com.imjustdoom.pluginsite.dtos.out.account; + +import com.imjustdoom.pluginsite.model.Account; + +import java.time.LocalDateTime; + +public record AccountDto(int id, String username, + byte[] profilePicture, LocalDateTime joined) { + + public static AccountDto fromAccount(Account account) { + return new AccountDto(account.getId(), account.getUsername(), + account.getProfile_picture(), account.getJoined()); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java new file mode 100644 index 0000000..e2087ba --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java @@ -0,0 +1,16 @@ +package com.imjustdoom.pluginsite.dtos.out.account; + +import com.imjustdoom.pluginsite.model.Account; + +import java.time.LocalDateTime; + +public record SelfAccountDto(int id, String username, + String email, byte[] profilePicture, + LocalDateTime joined) { + + public static SelfAccountDto fromAccount(Account account) { + return new SelfAccountDto(account.getId(), account.getUsername(), + account.getEmail(), account.getProfile_picture(), + account.getJoined()); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/ReportRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/ReportRepository.java index c6baccc..3e432f8 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/ReportRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/ReportRepository.java @@ -1,18 +1,18 @@ package com.imjustdoom.pluginsite.repositories; import com.imjustdoom.pluginsite.model.Report; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; import javax.transaction.Transactional; @Repository -public interface ReportRepository extends JpaRepository { +public interface ReportRepository extends PagingAndSortingRepository { @Modifying @Transactional @Query("UPDATE Report report SET report.actionTaken = ?2 WHERE report.id = ?1") - void updateActionTakenById(int id, String actionTaken); + Report updateActionTakenById(int id, String actionTaken); } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java new file mode 100644 index 0000000..513fdfe --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java @@ -0,0 +1,65 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; +import com.imjustdoom.pluginsite.dtos.in.account.UpdateAccountRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.repositories.AccountRepository; +import com.imjustdoom.pluginsite.util.ImageUtil; +import com.imjustdoom.pluginsite.util.ValidationHelper; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +@RequiredArgsConstructor +public class AccountService { + private final AccountRepository accountRepository; + private final BCryptPasswordEncoder passwordEncoder; + + public Account register(CreateAccountRequest request) throws RestException { + String username = request.getUsername(); + if (!ValidationHelper.isUsernameValid(username)) throw new RestException(RestErrorCode.INVALID_USERNAME); + + String email = request.getEmail(); + if (!ValidationHelper.isEmailValid(email)) throw new RestException(RestErrorCode.INVALID_EMAIL); + + if (this.accountRepository.existsByUsernameEqualsIgnoreCase(username)) throw new RestException(RestErrorCode.USERNAME_NOT_AVAILABLE); + if (this.accountRepository.existsByEmailEqualsIgnoreCase(email)) throw new RestException(RestErrorCode.EMAIL_NOT_AVAILABLE); + + Account account = new Account(username, email, this.passwordEncoder.encode(request.getPassword())); + this.accountRepository.save(account); + + return account; + } + + public Account getAccount(int id) throws RestException { + return this.accountRepository.findById(id).orElseThrow(() -> new RestException(RestErrorCode.ACCOUNT_NOT_FOUND)); + } + + // todo will there be concurrency issues with performing this all in one update? + public Account updateAccountDetails(Account account, UpdateAccountRequest request, MultipartFile file) throws RestException { + if (file != null) { + if (!file.getContentType().contains("image")) throw new RestException(RestErrorCode.WRONG_FILE_TYPE); + if (file.getSize() > 1024000) throw new RestException(RestErrorCode.FILE_TOO_LARGE); + + account.setProfile_picture(ImageUtil.handleImage(file)); + } + if (request.getEmail() != null) { + String email = request.getEmail(); + if (!ValidationHelper.isEmailValid(email)) throw new RestException(RestErrorCode.INVALID_EMAIL); + if (this.accountRepository.existsByEmailEqualsIgnoreCase(email)) throw new RestException(RestErrorCode.EMAIL_NOT_AVAILABLE); + account.setEmail(email); + } + if (request.getUsername() != null) { + String username = request.getUsername(); + if (!ValidationHelper.isUsernameValid(username)) throw new RestException(RestErrorCode.INVALID_USERNAME); + if (this.accountRepository.existsByUsernameEqualsIgnoreCase(username)) throw new RestException(RestErrorCode.USERNAME_NOT_AVAILABLE); + account.setUsername(username); + } + this.accountRepository.save(account); + return account; + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java new file mode 100644 index 0000000..d8a2e3c --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java @@ -0,0 +1,28 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.model.Report; +import com.imjustdoom.pluginsite.repositories.ReportRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AdminService { + private final ReportRepository reportRepository; + + public Page getReportPage(Pageable pageable) { + return this.reportRepository.findAll(pageable); + } + + public Report getReport(int id) throws RestException { + return this.reportRepository.findById(id).orElseThrow(() -> new RestException(RestErrorCode.REPORT_NOT_FOUND)); + } + + public Report updateActionTaken(int id, String actionTaken) { + return this.reportRepository.updateActionTakenById(id, actionTaken); + } +} From 9c5d9ef8825d6aae49f470b1f626a2d73e18c1ca Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 09:13:08 +0000 Subject: [PATCH 03/13] Move ReportController to rest, reorganise AdminService --- .../pluginsite/controller/FileController.java | 1 - .../controller/MessagesController.java | 1 - .../controller/ProfileController.java | 1 - .../controller/ReportController.java | 36 ------------------- .../controller/ResourcesController.java | 21 ++++++++--- .../controller/rest/AdminController.java | 14 ++++---- .../controller/rest/ReportController.java | 23 ++++++++++++ .../pluginsite/service/rest/AdminService.java | 17 --------- .../service/rest/ReportService.java | 35 ++++++++++++++++++ 9 files changed, 82 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java index e9591db..84e2274 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java @@ -20,7 +20,6 @@ import java.nio.file.Paths; import java.util.Optional; -@Controller @AllArgsConstructor public class FileController { diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java index c8734c6..c333920 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java @@ -30,7 +30,6 @@ import java.util.List; import java.util.Optional; -@Controller @AllArgsConstructor public class MessagesController { diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java index 377bf1a..673fbda 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Optional; -@Controller @AllArgsConstructor public class ProfileController { diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java deleted file mode 100644 index 12332e9..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.dtos.in.CreateReportRequest; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Report; -import com.imjustdoom.pluginsite.repositories.ReportRepository; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; - -@Controller -@AllArgsConstructor -public class ReportController { - - private final ReportRepository reportRepository; - - @GetMapping("/report") - public String report(Account account, Model model, @RequestParam(name = "status", required = false) String status) { - model.addAttribute("report", new CreateReportRequest()); - model.addAttribute("account", account); - model.addAttribute("status", status); - return "report"; - } - - @PostMapping("/report") - public String sendReport(Account account, @ModelAttribute CreateReportRequest reportRequest) { - Report report = new Report(account, reportRequest.getReportingObject(), reportRequest.getReportingId(), - reportRequest.getReport(), reportRequest.getReason()); - reportRepository.save(report); - return "redirect:/report?status=success"; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java index 2548334..4f769d3 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java @@ -12,7 +12,11 @@ import com.imjustdoom.pluginsite.repositories.UpdateRepository; import com.imjustdoom.pluginsite.service.LogoService; import com.imjustdoom.pluginsite.service.ResourceService; -import com.imjustdoom.pluginsite.util.*; +import com.imjustdoom.pluginsite.util.DateUtil; +import com.imjustdoom.pluginsite.util.FileUtil; +import com.imjustdoom.pluginsite.util.ImageUtil; +import com.imjustdoom.pluginsite.util.RequestUtil; +import com.imjustdoom.pluginsite.util.UrlUtil; import lombok.AllArgsConstructor; import me.xdrop.fuzzywuzzy.FuzzySearch; import org.commonmark.node.Node; @@ -23,9 +27,14 @@ import org.springframework.data.domain.Sort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @@ -36,9 +45,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; -@Controller @AllArgsConstructor @RequestMapping("/resources") public class ResourcesController { diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java index 1cee881..71b9d24 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java @@ -3,10 +3,12 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.model.Report; -import com.imjustdoom.pluginsite.service.rest.AdminService; +import com.imjustdoom.pluginsite.service.rest.ReportService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -18,22 +20,22 @@ @RequestMapping("/admin") @RequiredArgsConstructor public class AdminController { - private final AdminService adminService; + private final ReportService reportService; @GetMapping("/report") - public Page listReports(Pageable pageable) throws RestException { + public Page listReports(@PageableDefault(sort = "reportedDate", direction = Sort.Direction.DESC) Pageable pageable) throws RestException { if (pageable.getPageSize() > 50) throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size too large (%s > %s)", pageable.getPageSize(), 50); - return this.adminService.getReportPage(pageable); + return this.reportService.getReportPage(pageable); } @GetMapping("/report/{id}") public Report getReport(@PathVariable int id) throws RestException { - return this.adminService.getReport(id); + return this.reportService.getReport(id); } @PatchMapping("/report/{id}") public Report updateActionTaken(@PathVariable int id, @RequestParam String actionTaken) { - return this.adminService.updateActionTaken(id, actionTaken); + return this.reportService.updateActionTaken(id, actionTaken); } // todo didnt add roles since this system should be reworked. The code below is the old code. diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java new file mode 100644 index 0000000..827a183 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java @@ -0,0 +1,23 @@ +package com.imjustdoom.pluginsite.controller.rest; + +import com.imjustdoom.pluginsite.dtos.in.CreateReportRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.service.rest.ReportService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/report") +@RequiredArgsConstructor +public class ReportController { + private final ReportService reportService; + + // todo should a DTO be returned instead of the raw Report here? + @PostMapping + public void createReport(Account account, @RequestBody CreateReportRequest request) { + this.reportService.createReport(account, request); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java index d8a2e3c..28edafc 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java @@ -1,28 +1,11 @@ package com.imjustdoom.pluginsite.service.rest; -import com.imjustdoom.pluginsite.config.exception.RestErrorCode; -import com.imjustdoom.pluginsite.config.exception.RestException; -import com.imjustdoom.pluginsite.model.Report; import com.imjustdoom.pluginsite.repositories.ReportRepository; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class AdminService { private final ReportRepository reportRepository; - - public Page getReportPage(Pageable pageable) { - return this.reportRepository.findAll(pageable); - } - - public Report getReport(int id) throws RestException { - return this.reportRepository.findById(id).orElseThrow(() -> new RestException(RestErrorCode.REPORT_NOT_FOUND)); - } - - public Report updateActionTaken(int id, String actionTaken) { - return this.reportRepository.updateActionTakenById(id, actionTaken); - } } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java new file mode 100644 index 0000000..4bfd869 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java @@ -0,0 +1,35 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.CreateReportRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Report; +import com.imjustdoom.pluginsite.repositories.ReportRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReportService { + private final ReportRepository reportRepository; + + public void createReport(Account reporter, CreateReportRequest request) { + Report report = new Report(reporter, request.getReportingObject(), request.getReportingId(), request.getReport(), request.getReason()); + this.reportRepository.save(report); + } + + public Page getReportPage(Pageable pageable) { + return this.reportRepository.findAll(pageable); + } + + public Report getReport(int id) throws RestException { + return this.reportRepository.findById(id).orElseThrow(() -> new RestException(RestErrorCode.REPORT_NOT_FOUND)); + } + + public Report updateActionTaken(int id, String actionTaken) { + return this.reportRepository.updateActionTakenById(id, actionTaken); + } +} From bec6857ecc926232af66b04eac7d1145e913fc88 Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 09:33:36 +0000 Subject: [PATCH 04/13] Redo profile controller --- .../controller/ProfileController.java | 7 ++++-- .../controller/rest/ProfileController.java | 22 ++++++++++++++++++ .../pluginsite/dtos/out/ProfileDto.java | 8 +++++++ .../repositories/UpdateRepository.java | 3 +++ .../service/rest/ProfileService.java | 23 +++++++++++++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/out/ProfileDto.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java index 673fbda..25f5ee0 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java @@ -11,7 +11,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -29,7 +28,11 @@ public class ProfileController { private final UpdateRepository updateRepository; @GetMapping("/profile/{id}") - public String profile(Account account, @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, @RequestParam(name = "page", required = false, defaultValue = "1") String page, @RequestParam(name = "field", required = false, defaultValue = "") String field, @PathVariable("id") int id, Model model) { + public String profile(Account account, + @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, + @RequestParam(name = "page", required = false, defaultValue = "1") String page, + @RequestParam(name = "field", required = false, defaultValue = "") String field, + @PathVariable("id") int id, Model model) { model.addAttribute("account", account); model.addAttribute("page", Integer.parseInt(page)); diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java new file mode 100644 index 0000000..78e7ade --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java @@ -0,0 +1,22 @@ +package com.imjustdoom.pluginsite.controller.rest; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.out.ProfileDto; +import com.imjustdoom.pluginsite.service.rest.ProfileService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/profile") +@RequiredArgsConstructor +public class ProfileController { + private final ProfileService profileService; + + @GetMapping("/{id}") + public ProfileDto getProfile(@PathVariable int id) throws RestException { + return this.profileService.getProfileDto(id); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/ProfileDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/ProfileDto.java new file mode 100644 index 0000000..fed62a7 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/ProfileDto.java @@ -0,0 +1,8 @@ +package com.imjustdoom.pluginsite.dtos.out; + +import com.imjustdoom.pluginsite.dtos.out.account.AccountDto; + +public record ProfileDto(int id, int totalDownloads, + AccountDto accountDto) { + +} diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index adf759d..0bcf9f9 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -35,6 +35,9 @@ public interface UpdateRepository extends JpaRepository { @Query("SELECT SUM(updates.downloads) FROM Update updates WHERE updates.resource.id = ?1") Integer getTotalDownloads(int id); + @Query("SELECT SUM(update.downloads) FROM Update update WHERE update.resource.author.id = ?1") + Integer getTotalAccountDownloads(int userId); + @Modifying @Transactional @Query("UPDATE Update updates SET updates.name = ?2, updates.description = ?3, updates.version = ?4 WHERE updates.id = ?1") diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java new file mode 100644 index 0000000..6bd2c40 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java @@ -0,0 +1,23 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.out.ProfileDto; +import com.imjustdoom.pluginsite.dtos.out.account.AccountDto; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.repositories.UpdateRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ProfileService { + private final UpdateRepository updateRepository; + private final AccountService accountService; + + public ProfileDto getProfileDto(int userId) throws RestException { + Account account = this.accountService.getAccount(userId); + int totalDownloads = this.updateRepository.getTotalAccountDownloads(userId); + + return new ProfileDto(account.getId(), totalDownloads, AccountDto.fromAccount(account)); + } +} From 57cfb22a3f4bd158874c2d049c14f8fa7930c5ed Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 09:33:44 +0000 Subject: [PATCH 05/13] Delete ProfileController.java --- .../controller/ProfileController.java | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java deleted file mode 100644 index 25f5ee0..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.util.DateUtil; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -@AllArgsConstructor -public class ProfileController { - - private final ResourceRepository resourceRepository; - private final AccountRepository accountRepository; - private final UpdateRepository updateRepository; - - @GetMapping("/profile/{id}") - public String profile(Account account, - @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, - @RequestParam(name = "page", required = false, defaultValue = "1") String page, - @RequestParam(name = "field", required = false, defaultValue = "") String field, - @PathVariable("id") int id, Model model) { - model.addAttribute("account", account); - model.addAttribute("page", Integer.parseInt(page)); - - Optional optionalAccount = accountRepository.findById(id); - - if (optionalAccount.isEmpty()) return "error/404"; - - Account profile = accountRepository.getById(id); - - int totalDownloads = 0; - for (Resource resource : profile.getResources()) { - totalDownloads += updateRepository.getTotalDownloads(resource.getId()) == null ? 0 : updateRepository.getTotalDownloads(resource.getId()); - } - - model.addAttribute("totalDownloads", totalDownloads); - model.addAttribute("user", profile); - model.addAttribute("joined", profile.getJoined().format(DateUtil.getDateFormatter())); - - switch (field.toLowerCase()) { - case "resources": - if (Integer.parseInt(page) < 1) return "redirect:/profile/1?page=1"; - - Sort sort1 = Sort.by(sort).ascending(); - Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort1); - List resources = resourceRepository.findAllByAuthorId(id, pageable); - - List data = new ArrayList<>(); - int total = resources.size() / 25; - int remainder = resources.size() % 25; - if (remainder > 1) total++; - - for (Resource resource : resources) { - Integer downloads = updateRepository.getTotalDownloads(resource.getId()); - data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); - } - - model.addAttribute("total", total); - model.addAttribute("files", data); - return "profile/resources"; - default: - return "profile/profile"; - } - } -} \ No newline at end of file From e17f9c18c2b7fb4444529cae5b8e7c2096b5c9df Mon Sep 17 00:00:00 2001 From: Zak Date: Fri, 11 Feb 2022 18:24:29 +0000 Subject: [PATCH 06/13] Begin resource work, fix `update` keywork being used --- pom.xml | 30 ++++++++++++++++- .../config/exception/RestErrorCode.java | 2 +- .../controller/ResourcesController.java | 6 +++- .../controller/rest/ResourceController.java | 33 +++++++++++++++++++ .../repositories/ResourceRepository.java | 17 +++++++++- .../repositories/UpdateRepository.java | 3 +- .../service/rest/AccountService.java | 4 +-- .../service/rest/ResourceService.java | 26 +++++++++++++++ 8 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java diff --git a/pom.xml b/pom.xml index 3dab06f..cd412c4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.6 + 2.6.3 com.imjustdoom @@ -39,6 +39,18 @@ spring-boot-starter-data-jpa + + com.querydsl + querydsl-apt + 5.0.0 + + + + com.querydsl + querydsl-jpa + 5.0.0 + + org.springframework.boot spring-boot-starter-web @@ -154,6 +166,22 @@ 17 + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + + process + + + target/generated-sources/java + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java index 1c7c669..6d403a1 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -14,7 +14,7 @@ public enum RestErrorCode { REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), - PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4) + PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4); private final HttpStatus httpStatus; private final String module; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java index 4f769d3..488453a 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java @@ -63,7 +63,11 @@ public class ResourcesController { private final UrlUtil urlUtil; @GetMapping - public String resources(Account account, @RequestParam(name = "category", required = false, defaultValue = "all") String category, @RequestParam(name = "search", required = false) String search, @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, @RequestParam(name = "page", required = false, defaultValue = "1") String page, Model model) { + public String resources(Account account, @RequestParam(name = "category", required = false, defaultValue = "all") String category, + @RequestParam(name = "search", required = false) String search, + @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, + @RequestParam(name = "page", required = false, defaultValue = "1") String page, + Model model) { // TODO: clean up more and make it easier to read if (Integer.parseInt(page) < 1) return "redirect:/resources?page=1"; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java new file mode 100644 index 0000000..4e9c5e8 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java @@ -0,0 +1,33 @@ +package com.imjustdoom.pluginsite.controller.rest; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; +import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.service.rest.ResourceService; +import com.querydsl.core.types.Predicate; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.querydsl.binding.QuerydslPredicate; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/resource") +@RequiredArgsConstructor +public class ResourceController { + private final ResourceService resourceService; + + @GetMapping + public Page searchResources(@PageableDefault(size = 25, sort = "updated", direction = Sort.Direction.DESC) Pageable pageable, + @QuerydslPredicate(root = Resource.class) Predicate predicate) throws RestException { + if (pageable.getPageSize() > 50) + throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size is too large (%s > %s)", pageable.getPageSize(), 50); + return this.resourceService.searchResources(pageable, predicate); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java index a448534..fd39f56 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java @@ -1,11 +1,15 @@ package com.imjustdoom.pluginsite.repositories; +import com.imjustdoom.pluginsite.model.QResource; import com.imjustdoom.pluginsite.model.Resource; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; +import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.stereotype.Repository; import javax.transaction.Transactional; @@ -13,7 +17,18 @@ import java.util.Optional; @Repository -public interface ResourceRepository extends JpaRepository { +public interface ResourceRepository extends JpaRepository, QuerydslPredicateExecutor, QuerydslBinderCustomizer { + + @Override + default void customize(QuerydslBindings bindings, QResource root) { + bindings.including( + root.name, + root.category, + root.author.username, + root.author.id + ); + bindings.excludeUnlistedProperties(true); + } boolean existsByNameEqualsIgnoreCase(String name); diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index 0bcf9f9..b0b4365 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -8,7 +8,6 @@ import org.springframework.stereotype.Repository; import javax.transaction.Transactional; -import java.util.Collection; import java.util.List; @Repository @@ -35,7 +34,7 @@ public interface UpdateRepository extends JpaRepository { @Query("SELECT SUM(updates.downloads) FROM Update updates WHERE updates.resource.id = ?1") Integer getTotalDownloads(int id); - @Query("SELECT SUM(update.downloads) FROM Update update WHERE update.resource.author.id = ?1") + @Query("SELECT SUM(updates.downloads) FROM Update updates WHERE updates.resource.author.id = ?1") Integer getTotalAccountDownloads(int userId); @Modifying diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java index 513fdfe..1b8df8c 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java @@ -9,7 +9,7 @@ import com.imjustdoom.pluginsite.util.ImageUtil; import com.imjustdoom.pluginsite.util.ValidationHelper; import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -17,7 +17,7 @@ @RequiredArgsConstructor public class AccountService { private final AccountRepository accountRepository; - private final BCryptPasswordEncoder passwordEncoder; + private final PasswordEncoder passwordEncoder; public Account register(CreateAccountRequest request) throws RestException { String username = request.getUsername(); diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java new file mode 100644 index 0000000..6f25038 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java @@ -0,0 +1,26 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; +import com.imjustdoom.pluginsite.repositories.ResourceRepository; +import com.imjustdoom.pluginsite.repositories.UpdateRepository; +import com.querydsl.core.types.Predicate; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ResourceService { + private final ResourceRepository resourceRepository; + private final UpdateRepository updateRepository; + + public Page searchResources(Pageable pageable, Predicate query) throws RestException { + return this.resourceRepository.findAll(query, pageable) + .map(resource -> { + int totalDownloads = this.updateRepository.getTotalDownloads(resource.getId()); + return SimpleResourceDto.create(resource, totalDownloads); + }); + } +} From 499a172229aa554925f8a053079bf6ffbfa2fbf9 Mon Sep 17 00:00:00 2001 From: Zak Date: Sat, 12 Feb 2022 01:00:07 +0000 Subject: [PATCH 07/13] Continue moving ResourceController --- .../config/exception/RestErrorCode.java | 6 +- .../RestExceptionResponseHandler.java | 4 +- .../pluginsite/controller/FileController.java | 31 +-- .../controller/ResourcesController.java | 234 ------------------ .../controller/rest/ResourceController.java | 18 +- .../imjustdoom/pluginsite/model/Account.java | 6 +- .../imjustdoom/pluginsite/model/Resource.java | 1 + .../repositories/UpdateRepository.java | 5 +- .../service/impl/ResourceServiceImpl.java | 6 +- .../service/rest/ProfileService.java | 2 +- .../service/rest/ResourceService.java | 23 +- 11 files changed, 61 insertions(+), 275 deletions(-) diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java index 6d403a1..142ded0 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -14,7 +14,11 @@ public enum RestErrorCode { REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), - PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4); + PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4), + REQUIRED_ARGUMENTS_MISSING(HttpStatus.BAD_REQUEST, "data", 5), + + TOO_MANY_RESOURCE_UPDATES(HttpStatus.TOO_MANY_REQUESTS, "resource", 1), + RESOURCE_NAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "resource", 2); private final HttpStatus httpStatus; private final String module; diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java index 1a2ae70..ae6a226 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestExceptionResponseHandler.java @@ -17,8 +17,10 @@ public class RestExceptionResponseHandler extends ResponseEntityExceptionHandler @ExceptionHandler(RestException.class) public void handle(HttpServletResponse response, RestException exception) throws IOException { - if (!response.isCommitted()) + if (!response.isCommitted()) { + response.setStatus(exception.getErrorCode().getHttpStatus().value()); this.mapper.writeValue(response.getWriter(), exception); + } } // Could add an error ticketing system for unknown errors (5xx) thrown diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java index 84e2274..1e50a2b 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java @@ -9,8 +9,9 @@ import lombok.AllArgsConstructor; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; -import org.springframework.http.*; -import org.springframework.stereotype.Controller; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.ResponseBody; @@ -28,32 +29,6 @@ public class FileController { private final UpdateRepository updateRepository; private final ResourceRepository resourceRepository; - @GetMapping("/logo/{id}") - @ResponseBody - public HttpEntity serveLogo(@PathVariable("id") int id) { - - byte[] image = logoService.serverLogo(id); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.IMAGE_JPEG); - headers.setContentLength(image.length); - - return new HttpEntity<>(image, headers); - } - - @GetMapping("/profile-picture/{id}") - @ResponseBody - public HttpEntity serveProfilePicture(@PathVariable("id") int id) { - - byte[] image = profilePictureService.serverProfilePicture(id); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.IMAGE_JPEG); - headers.setContentLength(image.length); - - return new HttpEntity<>(image, headers); - } - @GetMapping("/files/{id}/download/{fileId}") @ResponseBody public ResponseEntity serveFile(Account account, @PathVariable("fileId") int fileId) throws MalformedURLException { diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java index 488453a..08dbba4 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java @@ -3,7 +3,6 @@ import com.imjustdoom.pluginsite.config.custom.SiteConfig; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; -import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; import com.imjustdoom.pluginsite.model.Update; @@ -12,19 +11,11 @@ import com.imjustdoom.pluginsite.repositories.UpdateRepository; import com.imjustdoom.pluginsite.service.LogoService; import com.imjustdoom.pluginsite.service.ResourceService; -import com.imjustdoom.pluginsite.util.DateUtil; import com.imjustdoom.pluginsite.util.FileUtil; import com.imjustdoom.pluginsite.util.ImageUtil; import com.imjustdoom.pluginsite.util.RequestUtil; import com.imjustdoom.pluginsite.util.UrlUtil; import lombok.AllArgsConstructor; -import me.xdrop.fuzzywuzzy.FuzzySearch; -import org.commonmark.node.Node; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.ui.Model; @@ -33,25 +24,21 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Optional; @AllArgsConstructor -@RequestMapping("/resources") public class ResourcesController { private final LogoService logoService; private final ResourceService resourceService; @@ -62,156 +49,6 @@ public class ResourcesController { private final SiteConfig siteConfig; private final UrlUtil urlUtil; - @GetMapping - public String resources(Account account, @RequestParam(name = "category", required = false, defaultValue = "all") String category, - @RequestParam(name = "search", required = false) String search, - @RequestParam(name = "sort", required = false, defaultValue = "updated") String sort, - @RequestParam(name = "page", required = false, defaultValue = "1") String page, - Model model) { - - // TODO: clean up more and make it easier to read - if (Integer.parseInt(page) < 1) return "redirect:/resources?page=1"; - - List data; - - int resources, total, remainder; - - if (search != null && !search.equals("")) { - - data = resourceService.searchResources(search, sort, page); - resources = FuzzySearch.extractSorted(search, resourceRepository.findAllByStatusEqualsIgnoreCase("public"), Resource::getName).size(); - total = resources / 25; - remainder = resources % 25; - if (remainder > 1) total++; - - model.addAttribute("results", resources); - } else if (!category.equalsIgnoreCase("all")) { - Sort sort1 = Sort.by(sort).descending(); - if (sort.equalsIgnoreCase("name")) sort1 = sort1.ascending(); - Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort1); - - resources = resourceRepository.findAllByCategoryEqualsAndStatusEquals(category, "public", pageable).size(); - total = resources / 25; - remainder = resources % 25; - if (remainder > 1) total++; - - data = resourceService.getResourcesWithCategory(sort, page, category); - } else { - - resources = resourceRepository.findAll().size(); - total = resources / 25; - remainder = resources % 25; - if (remainder > 1) total++; - - data = resourceService.getResources(sort, page); - } - - model.addAttribute("total", total); - model.addAttribute("files", data); - model.addAttribute("account", account); - model.addAttribute("page", Integer.parseInt(page)); - - return "resource/resources"; - } - - @GetMapping("/{id_s}") - public String resource(Account account, @RequestParam(name = "software", required = false, defaultValue = "all") String softwareParam, @RequestParam(name = "sort", required = false, defaultValue = "uploaded") String sort, @PathVariable("id_s") String id_s, @RequestParam(name = "field", required = false, defaultValue = "") String field, Model model) throws MalformedURLException { - int id; - try { - id = Integer.parseInt(id_s); - } catch (NumberFormatException e) { - return "error/404"; - } - - Optional optionalResource = resourceRepository.findById(id); - - if (optionalResource.isEmpty()) return "error/404"; - - Resource resource = resourceRepository.getById(id); - - if (!resource.getStatus().equalsIgnoreCase("public") && !account.getRole().equalsIgnoreCase("role_admin")) { - model.addAttribute("account", account); - return "error/resourceDeleted"; - } - - String description = urlUtil.encode(resource.getDescription()); - - description.replaceAll("script", "error style=\"display:none;\""); - Parser parser = Parser.builder().build(); - Node document = parser.parse(description); - HtmlRenderer renderer = HtmlRenderer.builder().build(); - String html = renderer.render(document); - - resource.setDescription(html); - - List updates = updateRepository.findAllByResourceIdAndStatusEquals(id, "public", Sort.by("uploaded").descending()); - - model.addAttribute("download", updates.size() > 0 ? updates.get(0).getDownload() : null); - model.addAttribute("account", account); - model.addAttribute("resource", resource); - model.addAttribute("editUrl", "/resources/%s/edit".formatted(id)); - model.addAttribute("uploadUrl", "/resources/%s/upload/".formatted(id)); - - Integer totalDownloads = updateRepository.getTotalDownloads(resource.getId()); - model.addAttribute("totalDownloads", totalDownloads == null ? 0 : totalDownloads); - model.addAttribute("created", resource.getCreated().format(DateUtil.getDateFormatter())); - model.addAttribute("updated", resource.getUpdated().format(DateUtil.getDateFormatter())); - - switch (field.toLowerCase()) { - case "updates": - Sort sort1 = Sort.by(sort).descending(); - if (sort.equalsIgnoreCase("name")) sort1 = sort1.ascending(); - - // TODO: improve getting the versions and software. 100% not the best way to do this - List data; - if (!softwareParam.equals("all")) { - data = updateRepository.findAllByResourceIdAndStatusEqualsAndSoftware(id, "public", softwareParam, sort1); - //data = new ArrayList<>(); - } else { - data = updateRepository.findAllByResourceIdAndStatusEquals(id, "public", sort1); - } - List> versions = new ArrayList<>(); - List versionLists = new ArrayList<>(); - List softwareLists = new ArrayList<>(); - for (Update update : data) { - List versionList = new ArrayList<>(); - - versionList.add(update.getVersions().get(0)); - boolean first = true; - StringBuilder versionString = new StringBuilder(); - String splitter = ""; - for (String v : update.getVersions()) { - if (first) { - first = false; - continue; - } - versionString.append(splitter); - splitter = ", "; - versionString.append(v); - } - versionLists.add(versionString.toString()); - versions.add(versionList); - - StringBuilder softwareString = new StringBuilder(); - splitter = ""; - for (String v : update.getSoftware()) { - softwareString.append(splitter); - splitter = ", "; - softwareString.append(v); - } - softwareLists.add(softwareString.toString()); - } - - model.addAttribute("versions", versions); - model.addAttribute("versionLists", versionLists); - model.addAttribute("softwareLists", softwareLists); - model.addAttribute("updates", data); - return "resource/updates"; - default: - return "resource/resource"; - } - } - @GetMapping("/{id}/edit/update/{fileId}") public String editResourceUpdate(@RequestParam(name = "error", required = false) String error, @PathVariable("id") int id, @PathVariable("fileId") int fileId, Model model, Account account) { @@ -246,26 +83,6 @@ public String editUpdateSubmit(@ModelAttribute Update update, @PathVariable("id" return "redirect:/resources/%s".formatted(id); } - @GetMapping("/{id}/edit") - public String editResource(@RequestParam(name = "error", required = false) String error, @PathVariable("id") int id, - Model model, Account account, @ModelAttribute(name = "resource") CreateResourceRequest resourceModel) { - model.addAttribute("error", error); - model.addAttribute("maxUploadSize", this.siteConfig.getMaxUploadSize().toBytes()); - - Optional optionalResource = resourceRepository.findById(id); - Resource resource = optionalResource.get(); - - if (optionalResource.isEmpty()) return "error/404"; - - model.addAttribute("id", id); - model.addAttribute("authorid", resource.getAuthor().getId()); - model.addAttribute("resource", resourceModel.getName() == null ? resource : resourceModel); - model.addAttribute("url", "/resources/" + id + "/edit"); - model.addAttribute("account", account); - - return "resource/edit"; - } - @PostMapping("/{id}/edit") public String editSubmit(@RequestParam("logo") MultipartFile file, RedirectAttributes redirectAttributes, @ModelAttribute CreateResourceRequest resource, @PathVariable("id") int id) { @@ -294,44 +111,6 @@ public String editSubmit(@RequestParam("logo") MultipartFile file, RedirectAttri return "redirect:/resources/%s".formatted(id); } - //TODO: Do sanity checks - @PostMapping("/create") - public String createSubmit(@ModelAttribute CreateResourceRequest resourceRequest, Account account, RedirectAttributes redirectAttributes) { - return resourceService.postCreateResource(resourceRequest, account, siteConfig, redirectAttributes); - } - - @GetMapping("/create") - public String create(Model model, Account account, @RequestParam(name = "error", required = false) String error, @ModelAttribute(name = "resourceRequest") CreateResourceRequest resourceRequest) { - model.addAttribute("error", error); - model.addAttribute("limit", this.siteConfig.getMaxCreationsPerHour()); - model.addAttribute("account", account); - model.addAttribute("resource", resourceRequest.getName() == null ? new CreateResourceRequest() : resourceRequest); - model.addAttribute("url", this.siteConfig.getDomain() + "/resources"); - return "resource/create"; - } - - @GetMapping("/{id}/upload") - public String uploadFile(@RequestParam(name = "error", required = false) String error, @PathVariable("id") int id, Model model, Account account, @ModelAttribute(name = "updateRequest") CreateUpdateRequest updateRequest) { - - // TODO: make the checkboxing also save - - Optional optionalResource = resourceRepository.findById(id); - Resource resource = optionalResource.get(); - - if (optionalResource.isEmpty()) return "error/404"; - - model.addAttribute("resource", resource); - model.addAttribute("update", updateRequest.getName() == null ? new CreateUpdateRequest() : updateRequest); - model.addAttribute("url", this.siteConfig.getDomain() + "/resources/%s/upload/".formatted(id)); - model.addAttribute("mainUrl", this.siteConfig.getDomain() + "/resources/%s".formatted(id)); - model.addAttribute("error", error); - model.addAttribute("maxUploadSize", this.siteConfig.getMaxUploadSize().toBytes()); - model.addAttribute("account", account); - model.addAttribute("limit", this.siteConfig.getMaxUpdatesPerHour()); - - return "resource/upload"; - } - @PostMapping("/{id}/upload") public String uploadFilePost(Account account, @RequestParam(name = "softwareCheckbox") List softwareBoxes, @RequestParam(name = "versionCheckbox") List versionBoxes, @@ -385,19 +164,6 @@ public String uploadFilePost(Account account, @RequestParam(name = "softwareChec return "redirect:/resources/%s".formatted(id); } - @GetMapping("/{id}/delete") - public String delete(Account account, Model model, @PathVariable("id") int id) { - model.addAttribute("account", account); - model.addAttribute("resource", resourceRepository.findById(id).get()); - return "resource/delete"; - } - - @PostMapping("/{id}/delete") - public String delete(@PathVariable("id") int id) { - resourceRepository.updateStatusById(id, "removed"); - return "redirect:/"; - } - @PostMapping("/{id}/update/{update}/status") public ResponseEntity> changeStatus(Account account, @PathVariable("id") int id, @PathVariable("update") int updateId, diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java index 4e9c5e8..86b4401 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java @@ -2,8 +2,11 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; +import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.service.rest.ResourceService; import com.querydsl.core.types.Predicate; import lombok.RequiredArgsConstructor; @@ -12,9 +15,10 @@ import org.springframework.data.domain.Sort; import org.springframework.data.querydsl.binding.QuerydslPredicate; import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -22,6 +26,7 @@ @RequiredArgsConstructor public class ResourceController { private final ResourceService resourceService; + private final ResourceRepository resourceRepository; @GetMapping public Page searchResources(@PageableDefault(size = 25, sort = "updated", direction = Sort.Direction.DESC) Pageable pageable, @@ -30,4 +35,15 @@ public Page searchResources(@PageableDefault(size = 25, sort throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size is too large (%s > %s)", pageable.getPageSize(), 50); return this.resourceService.searchResources(pageable, predicate); } + + @PostMapping + public void createResource(Account account, CreateResourceRequest resourceRequest) throws RestException { + this.resourceService.createResource(account, resourceRequest); + } + + // todo properly delete + @DeleteMapping("/{id}") + public void deleteResource(Account account, int id) { + this.resourceRepository.updateStatusById(id, "removed"); + } } diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Account.java b/src/main/java/com/imjustdoom/pluginsite/model/Account.java index ff67d84..96a8bc4 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Account.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Account.java @@ -30,10 +30,10 @@ public Account(String username, String email, String password) { private int id; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "author") - private List resources; + private List resources = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "reporter") - private List reports; + private List reports = new ArrayList<>(); @Column(nullable = false, unique = true) private String username; @@ -59,7 +59,7 @@ public Account(String username, String email, String password) { private byte[] profile_picture; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "author") - private List messages; + private List messages = new ArrayList<>(); public Account() { diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Resource.java b/src/main/java/com/imjustdoom/pluginsite/model/Resource.java index 1dfcf2a..d2488e9 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Resource.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Resource.java @@ -49,6 +49,7 @@ public Resource(String name, String description, String blurb, String donation, @Column(nullable = false) private LocalDateTime updated; + // todo if we are making these option, they should also be nullable?? @Column(nullable = false) private String donation; diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index b0b4365..4a1d871 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -9,6 +9,7 @@ import javax.transaction.Transactional; import java.util.List; +import java.util.Optional; @Repository public interface UpdateRepository extends JpaRepository { @@ -32,10 +33,10 @@ public interface UpdateRepository extends JpaRepository { void addDownload(int id); @Query("SELECT SUM(updates.downloads) FROM Update updates WHERE updates.resource.id = ?1") - Integer getTotalDownloads(int id); + Optional getTotalDownloads(int id); @Query("SELECT SUM(updates.downloads) FROM Update updates WHERE updates.resource.author.id = ?1") - Integer getTotalAccountDownloads(int userId); + Optional getTotalAccountDownloads(int userId); @Modifying @Transactional diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java index d1ab48a..6330c90 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java @@ -71,7 +71,7 @@ public List searchResources(String search, String sortBy, Str Optional optionalResource = resourceRepository.findByNameEqualsIgnoreCase(extractedResult.getString()); Resource resource = optionalResource.get(); - Integer downloads = updateRepository.getTotalDownloads(resource.getId()); + Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); } @@ -87,7 +87,7 @@ public List getResourcesWithCategory(String sortBy, String pa Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort); for (Resource resource : resourceRepository.findAllByCategoryEqualsAndStatusEquals(category, "public", pageable)) { - Integer downloads = updateRepository.getTotalDownloads(resource.getId()); + Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); } @@ -102,7 +102,7 @@ public List getResources(String sortBy, String page) { Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort); for (Resource resource : resourceRepository.findAllByStatusEqualsIgnoreCase("public", pageable)) { - Integer downloads = updateRepository.getTotalDownloads(resource.getId()); + Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java index 6bd2c40..962a0a4 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java @@ -16,7 +16,7 @@ public class ProfileService { public ProfileDto getProfileDto(int userId) throws RestException { Account account = this.accountService.getAccount(userId); - int totalDownloads = this.updateRepository.getTotalAccountDownloads(userId); + int totalDownloads = this.updateRepository.getTotalAccountDownloads(userId).orElse(0); return new ProfileDto(account.getId(), totalDownloads, AccountDto.fromAccount(account)); } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java index 6f25038..8dd10fa 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java @@ -1,7 +1,12 @@ package com.imjustdoom.pluginsite.service.rest; +import com.imjustdoom.pluginsite.config.custom.SiteConfig; +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Resource; import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.repositories.UpdateRepository; import com.querydsl.core.types.Predicate; @@ -15,12 +20,28 @@ public class ResourceService { private final ResourceRepository resourceRepository; private final UpdateRepository updateRepository; + private final SiteConfig siteConfig; public Page searchResources(Pageable pageable, Predicate query) throws RestException { return this.resourceRepository.findAll(query, pageable) .map(resource -> { - int totalDownloads = this.updateRepository.getTotalDownloads(resource.getId()); + int totalDownloads = this.updateRepository.getTotalDownloads(resource.getId()).orElse(0); return SimpleResourceDto.create(resource, totalDownloads); }); } + + //TODO: More sanity checks + public Resource createResource(Account account, CreateResourceRequest request) throws RestException { + if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); + if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); + if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING); + + Resource resource = new Resource(request.getName(), request.getDescription(), + request.getBlurb(), request.getDonation(), request.getSource(), + "", account, request.getSupport(), request.getCategory()); + + this.resourceRepository.save(resource); + + return this.resourceRepository.save(resource); + } } From 29e9845c60d649fd954863b212b9439d285c28bb Mon Sep 17 00:00:00 2001 From: Zak Date: Sat, 12 Feb 2022 01:48:01 +0000 Subject: [PATCH 08/13] Move update methods and clean up editing --- .../java/com/imjustdoom/pluginsite/Test.java | 28 ++++++ .../config/exception/RestErrorCode.java | 5 + .../controller/ResourcesController.java | 95 ------------------- .../controller/rest/ResourceController.java | 32 ++++++- .../resource/EditResourceUpdateRequest.java | 12 +++ .../repositories/UpdateRepository.java | 2 +- .../service/rest/ResourceService.java | 78 ++++++++++++++- 7 files changed, 147 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/imjustdoom/pluginsite/Test.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/in/resource/EditResourceUpdateRequest.java diff --git a/src/main/java/com/imjustdoom/pluginsite/Test.java b/src/main/java/com/imjustdoom/pluginsite/Test.java new file mode 100644 index 0000000..4f21863 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/Test.java @@ -0,0 +1,28 @@ +package com.imjustdoom.pluginsite; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.repositories.AccountRepository; +import com.imjustdoom.pluginsite.repositories.ResourceRepository; +import com.imjustdoom.pluginsite.service.rest.AccountService; +import org.springframework.stereotype.Component; + +@Component +public class Test { + + public Test(AccountService accountService, AccountRepository accountRepository, ResourceRepository resourceRepository) throws RestException { + if (accountRepository.existsByUsernameEqualsIgnoreCase("test")) + return; + CreateAccountRequest createAccountRequest = new CreateAccountRequest(); + createAccountRequest.setEmail("test@test.com"); + createAccountRequest.setUsername("test"); + createAccountRequest.setPassword("test"); + Account account = accountService.register(createAccountRequest); + + Resource resource = new Resource("test", "test", "", "", "", "test", account, "", "none"); + resourceRepository.save(resource); + accountRepository.save(account); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java index 142ded0..ada4827 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -10,8 +10,13 @@ public enum RestErrorCode { USERNAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 3), EMAIL_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 4), + INVALID_ACCESS(HttpStatus.UNAUTHORIZED, "auth", 100), + ACCOUNT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 100), REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), + RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 102), + RESOURCE_UPDATE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 103), + WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4), diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java index 08dbba4..8c2aa44 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java @@ -1,10 +1,8 @@ package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.config.custom.SiteConfig; -import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; import com.imjustdoom.pluginsite.model.Update; import com.imjustdoom.pluginsite.repositories.AccountRepository; import com.imjustdoom.pluginsite.repositories.ResourceRepository; @@ -12,18 +10,11 @@ import com.imjustdoom.pluginsite.service.LogoService; import com.imjustdoom.pluginsite.service.ResourceService; import com.imjustdoom.pluginsite.util.FileUtil; -import com.imjustdoom.pluginsite.util.ImageUtil; -import com.imjustdoom.pluginsite.util.RequestUtil; import com.imjustdoom.pluginsite.util.UrlUtil; import lombok.AllArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @@ -34,9 +25,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.HashMap; import java.util.List; -import java.util.Optional; @AllArgsConstructor public class ResourcesController { @@ -49,68 +38,6 @@ public class ResourcesController { private final SiteConfig siteConfig; private final UrlUtil urlUtil; - @GetMapping("/{id}/edit/update/{fileId}") - public String editResourceUpdate(@RequestParam(name = "error", required = false) String error, @PathVariable("id") int id, @PathVariable("fileId") int fileId, Model model, Account account) { - - Optional optionalResource = resourceRepository.findById(id); - if (optionalResource.isEmpty()) return "error/404"; - - Optional optionalUpdate = updateRepository.findById(fileId); - if (optionalUpdate.isEmpty()) return "error/404"; - Update update = optionalUpdate.get(); - - model.addAttribute("error", error); - model.addAttribute("update", update); - model.addAttribute("url", this.siteConfig.getDomain() + "/resources/" + id); - model.addAttribute("account", account); - model.addAttribute("resourceid", id); - - return "resource/editUpdate"; - } - - @PostMapping("/{id}/edit/update/{fileId}") - public String editUpdateSubmit(@ModelAttribute Update update, @PathVariable("id") int id, @PathVariable("fileId") int fileId) { - - if (update.getName().equalsIgnoreCase("") - || update.getVersion().equalsIgnoreCase("") - || update.getDescription().equalsIgnoreCase("")) - return "redirect:/resources/%s/edit/update/%s?error=invalidinput".formatted(id, fileId); - - //update.getId() doesnt actually return the id of the update for some reason - // figure out why in the future - updateRepository.setInfo(fileId, update.getName(), update.getDescription(), update.getVersion()); - - return "redirect:/resources/%s".formatted(id); - } - - @PostMapping("/{id}/edit") - public String editSubmit(@RequestParam("logo") MultipartFile file, RedirectAttributes redirectAttributes, - @ModelAttribute CreateResourceRequest resource, @PathVariable("id") int id) { - - redirectAttributes.addFlashAttribute("resource", resource); - if (resourceRepository.existsByNameEqualsIgnoreCaseAndIdEqualsNot(id, resource.getName())) - return "redirect:/resources/%s/edit?error=nametaken".formatted(id); - - if (resource.getName().equalsIgnoreCase("") - || resource.getBlurb().equalsIgnoreCase("") - || resource.getDescription().equalsIgnoreCase("")) - return "redirect:/resources/%s/edit?error=invalidinput".formatted(id); - - if (!file.isEmpty()) { - if (file.getSize() > 1024000) { - return "redirect:/resources/%s/edit?error=filesize".formatted(id); - } - - resourceRepository.updateLogoById(id, ImageUtil.handleImage(file)); - } - // todo handle errors from ImageUtil - - resourceRepository.setInfo(id, resource.getName(), resource.getBlurb(), resource.getDescription(), - resource.getDonation(), resource.getSource(), resource.getSupport(), resource.getCategory()); - - return "redirect:/resources/%s".formatted(id); - } - @PostMapping("/{id}/upload") public String uploadFilePost(Account account, @RequestParam(name = "softwareCheckbox") List softwareBoxes, @RequestParam(name = "versionCheckbox") List versionBoxes, @@ -163,26 +90,4 @@ public String uploadFilePost(Account account, @RequestParam(name = "softwareChec return "redirect:/resources/%s".formatted(id); } - - @PostMapping("/{id}/update/{update}/status") - public ResponseEntity> changeStatus(Account account, @PathVariable("id") int id, - @PathVariable("update") int updateId, - @RequestBody String request) { - - HashMap response = new HashMap<>(); - - Optional optionalResource = resourceRepository.findById(id); - Resource resource = optionalResource.get(); - - if (account.getId() != resource.getAuthor().getId()) { - return new ResponseEntity<>(response, HttpStatus.FORBIDDEN); - } - - HashMap params = RequestUtil.getParams(request); - String status = params.get("status"); - - updateRepository.updateStatusById(updateId, status); - - return new ResponseEntity<>(response, HttpStatus.OK); - } } \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java index 86b4401..044b071 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java @@ -3,9 +3,11 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; +import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.model.Update; import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.service.rest.ResourceService; import com.querydsl.core.types.Predicate; @@ -17,9 +19,14 @@ import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/resource") @@ -37,13 +44,28 @@ public Page searchResources(@PageableDefault(size = 25, sort } @PostMapping - public void createResource(Account account, CreateResourceRequest resourceRequest) throws RestException { - this.resourceService.createResource(account, resourceRequest); + public void createResource(Account account, CreateResourceRequest request) throws RestException { + this.resourceService.createResource(account, request); + } + + @PostMapping("/{resourceId}/edit") + public void updateResourceInfo(Account account, @PathVariable int resourceId, @RequestParam(value = "file", required = false) MultipartFile file, CreateResourceRequest request) throws RestException { + this.resourceService.updateResource(account, resourceId, file, request); } // todo properly delete - @DeleteMapping("/{id}") - public void deleteResource(Account account, int id) { - this.resourceRepository.updateStatusById(id, "removed"); + @DeleteMapping("/{resourceId}") + public void deleteResource(@PathVariable int resourceId) { + this.resourceRepository.updateStatusById(resourceId, "removed"); + } + + @PatchMapping("/{resourceId}/update/{updateId}/status") + public Update changeUpdateStatus(Account account, @PathVariable int resourceId, @PathVariable int updateId, @RequestParam String status) throws RestException { + return this.resourceService.changeUpdateStatus(account, resourceId, updateId, status); + } + + @PatchMapping("/{resourceId}/edit/update/{updateId}") + public Update editResourceUpdate(Account account, @PathVariable int resourceId, @PathVariable int updateId, @RequestBody EditResourceUpdateRequest request) throws RestException { + return this.resourceService.editResourceUpdate(account, resourceId, updateId, request); } } diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/in/resource/EditResourceUpdateRequest.java b/src/main/java/com/imjustdoom/pluginsite/dtos/in/resource/EditResourceUpdateRequest.java new file mode 100644 index 0000000..2601b31 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/in/resource/EditResourceUpdateRequest.java @@ -0,0 +1,12 @@ +package com.imjustdoom.pluginsite.dtos.in.resource; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EditResourceUpdateRequest { + private String name; + private String version; + private String description; +} diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index 4a1d871..51b927a 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -49,5 +49,5 @@ public interface UpdateRepository extends JpaRepository { @Modifying @Transactional @Query("UPDATE Update updates SET updates.status = ?2 WHERE updates.id = ?1") - void updateStatusById(int id, String status); + Optional updateStatusById(int id, String status); } \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java index 8dd10fa..c18fc76 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java @@ -4,16 +4,20 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; +import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.model.Update; import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.repositories.UpdateRepository; +import com.imjustdoom.pluginsite.util.ImageUtil; import com.querydsl.core.types.Predicate; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; @Service @RequiredArgsConstructor @@ -32,16 +36,82 @@ public Page searchResources(Pageable pageable, Predicate quer //TODO: More sanity checks public Resource createResource(Account account, CreateResourceRequest request) throws RestException { - if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); - if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); - if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING); + if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) + throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); + if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) + throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); + if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) + throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING); Resource resource = new Resource(request.getName(), request.getDescription(), request.getBlurb(), request.getDonation(), request.getSource(), "", account, request.getSupport(), request.getCategory()); - this.resourceRepository.save(resource); + return this.resourceRepository.save(resource); + } + + // TODO: More sanity checks + // todo: also this is horrible, can we just use querydsl? + public Resource updateResource(Account account, int resourceId, MultipartFile file, CreateResourceRequest request) throws RestException { + Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + + String name = request.getName(); + if (name != null && !name.isEmpty()) + resource.setName(name); + + String description = request.getDescription(); + if (description != null && !description.isEmpty()) + resource.setDescription(description); + + String blurb = request.getBlurb(); + if (blurb != null && !blurb.isEmpty()) + resource.setBlurb(blurb); + + String category = request.getCategory(); + if (category != null && !category.isEmpty()) + resource.setCategory(category); + + String donation = request.getDonation(); + if (donation != null && !donation.isEmpty()) + resource.setDonation(donation); + + String support = request.getSupport(); + if (support != null && !support.isEmpty()) + resource.setSupport(support); + + String source = request.getSource(); + if (source != null && !source.isEmpty()) + resource.setSource(source); + + if (file != null && !file.isEmpty()) + resource.setLogo(ImageUtil.handleImage(file)); return this.resourceRepository.save(resource); } + + public Update changeUpdateStatus(Account account, int resourceId, int updateId, String status) throws RestException { + Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + if (resource.getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + return this.updateRepository.updateStatusById(updateId, status).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); + } + + public Update editResourceUpdate(Account account, int resourceId, int updateId, EditResourceUpdateRequest request) throws RestException { + Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + if (resource.getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); + + String name = request.getName(); + if (name != null && !name.isEmpty()) + update.setName(name); + + String version = request.getVersion(); + if (version != null && !version.isEmpty()) + update.setVersion(version); + + String description = request.getDescription(); + if (description != null && !description.isEmpty()) + update.setDescription(description); + + return this.updateRepository.save(update); + } } From 4e80e96815b460a99907c62547f129a2b8286035 Mon Sep 17 00:00:00 2001 From: Zak Date: Sun, 13 Feb 2022 21:07:31 +0000 Subject: [PATCH 09/13] ResourceUpdate implemented --- .../java/com/imjustdoom/pluginsite/Test.java | 2 +- .../config/exception/RestErrorCode.java | 6 +- .../pluginsite/controller/FileController.java | 11 +- .../controller/ResourcesController.java | 93 --------------- .../controller/rest/ResourceController.java | 14 --- .../rest/ResourceUpdateController.java | 62 ++++++++++ .../dtos/in/CreateUpdateRequest.java | 7 ++ .../imjustdoom/pluginsite/model/Resource.java | 8 +- .../imjustdoom/pluginsite/model/Update.java | 18 ++- .../repositories/ResourceRepository.java | 5 - .../repositories/UpdateRepository.java | 5 - .../service/impl/ResourceServiceImpl.java | 111 ------------------ .../service/impl/UpdateServiceImpl.java | 29 ----- .../service/rest/ResourceService.java | 32 +---- .../service/rest/ResourceUpdateService.java | 101 ++++++++++++++++ 15 files changed, 191 insertions(+), 313 deletions(-) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/impl/UpdateServiceImpl.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java diff --git a/src/main/java/com/imjustdoom/pluginsite/Test.java b/src/main/java/com/imjustdoom/pluginsite/Test.java index 4f21863..55e53f9 100644 --- a/src/main/java/com/imjustdoom/pluginsite/Test.java +++ b/src/main/java/com/imjustdoom/pluginsite/Test.java @@ -21,7 +21,7 @@ public Test(AccountService accountService, AccountRepository accountRepository, createAccountRequest.setPassword("test"); Account account = accountService.register(createAccountRequest); - Resource resource = new Resource("test", "test", "", "", "", "test", account, "", "none"); + Resource resource = new Resource("test", "test", "", "", "", account, "", "none"); resourceRepository.save(resource); accountRepository.save(account); } diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java index ada4827..6ff0a36 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -16,14 +16,16 @@ public enum RestErrorCode { REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 102), RESOURCE_UPDATE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 103), + DOWNLOAD_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 104), WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), PAGE_SIZE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 4), REQUIRED_ARGUMENTS_MISSING(HttpStatus.BAD_REQUEST, "data", 5), - TOO_MANY_RESOURCE_UPDATES(HttpStatus.TOO_MANY_REQUESTS, "resource", 1), - RESOURCE_NAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "resource", 2); + TOO_MANY_RESOURCE_CREATIONS(HttpStatus.TOO_MANY_REQUESTS, "resource", 1), + TOO_MANY_RESOURCE_UPDATES(HttpStatus.TOO_MANY_REQUESTS, "resource", 2), + RESOURCE_NAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "resource", 3); private final HttpStatus httpStatus; private final String module; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java index 1e50a2b..3c4e468 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java @@ -10,7 +10,6 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -46,11 +45,11 @@ public ResponseEntity serveFile(Account account, @PathVariable("fileId") int fil updateRepository.addDownload(fileId); - if(!update.getExternal().equalsIgnoreCase("")) { - HttpHeaders headers = new HttpHeaders(); - headers.add("Location", update.getExternal()); - return new ResponseEntity(headers, HttpStatus.FOUND); - } +// if(!update.getExternal().equalsIgnoreCase("")) { +// HttpHeaders headers = new HttpHeaders(); +// headers.add("Location", update.getExternal()); +// return new ResponseEntity(headers, HttpStatus.FOUND); +// } return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file); diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java deleted file mode 100644 index 8c2aa44..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourcesController.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.config.custom.SiteConfig; -import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Update; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.service.LogoService; -import com.imjustdoom.pluginsite.service.ResourceService; -import com.imjustdoom.pluginsite.util.FileUtil; -import com.imjustdoom.pluginsite.util.UrlUtil; -import lombok.AllArgsConstructor; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.List; - -@AllArgsConstructor -public class ResourcesController { - private final LogoService logoService; - private final ResourceService resourceService; - private final ResourceRepository resourceRepository; - private final AccountRepository accountRepository; - private final UpdateRepository updateRepository; - - private final SiteConfig siteConfig; - private final UrlUtil urlUtil; - - @PostMapping("/{id}/upload") - public String uploadFilePost(Account account, @RequestParam(name = "softwareCheckbox") List softwareBoxes, - @RequestParam(name = "versionCheckbox") List versionBoxes, - @PathVariable("id") int id, @RequestParam("file") MultipartFile file, - @ModelAttribute CreateUpdateRequest updateRequest, RedirectAttributes redirectAttributes) - throws IOException { - - redirectAttributes.addFlashAttribute("updateRequest", updateRequest); - if (updateRepository.getUpdatesCreateLastHour(account.getId()) > this.siteConfig.getMaxUpdatesPerHour()) { - return "redirect:/resources/%s/upload?error=uploadlimit".formatted(id); - } - - if ((file.isEmpty() || file.getSize() > this.siteConfig.getMaxUploadSize().toBytes()) && updateRequest.getExternalLink().equals("")) { - return "redirect:/resources/%s/upload?error=filesize".formatted(id); - } - if ((!file.getOriginalFilename().endsWith(".jar") && !file.getOriginalFilename().endsWith(".zip")) && updateRequest.getExternalLink().equals("")) { - return "redirect:/resources/%s/upload?error=filetype".formatted(id); - } - - if (updateRequest.getName().equalsIgnoreCase("") - || updateRequest.getVersion().equalsIgnoreCase("") - || updateRequest.getDescription().equalsIgnoreCase("")) - return "redirect:/resources/%s/upload?error=invalidinput"; - - Update update = new Update(updateRequest.getDescription(), file.getOriginalFilename(), - updateRequest.getVersion(), "", updateRequest.getName(), versionBoxes, softwareBoxes, - resourceRepository.findById(id).get(), updateRequest.getExternalLink()); - updateRepository.save(update); - - if (updateRequest.getExternalLink() == null || updateRequest.getExternalLink().equals("")) { - if (!FileUtil.doesFileExist("./resources/plugins/" + update.getId())) { - try { - Files.createDirectory(Paths.get("./resources/plugins/" + update.getId())); - } catch (IOException e) { - e.printStackTrace(); - } - } - - Path destinationFile = Path.of("./resources/plugins/" + update.getId() + "/" + file.getOriginalFilename()).normalize().toAbsolutePath(); - - try (InputStream inputStream = file.getInputStream()) { - Files.copy(inputStream, destinationFile, - StandardCopyOption.REPLACE_EXISTING); - } - } - - String download = "%s/files/%s/download/%s".formatted(this.siteConfig.getDomain(), update.getResource().getId(), update.getId()); - resourceRepository.setDownload(id, download); - updateRepository.setDownload(update.getId(), download); - - return "redirect:/resources/%s".formatted(id); - } -} \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java index 044b071..17caa2f 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java @@ -3,11 +3,9 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; -import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.model.Update; import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.service.rest.ResourceService; import com.querydsl.core.types.Predicate; @@ -19,10 +17,8 @@ import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -58,14 +54,4 @@ public void updateResourceInfo(Account account, @PathVariable int resourceId, @R public void deleteResource(@PathVariable int resourceId) { this.resourceRepository.updateStatusById(resourceId, "removed"); } - - @PatchMapping("/{resourceId}/update/{updateId}/status") - public Update changeUpdateStatus(Account account, @PathVariable int resourceId, @PathVariable int updateId, @RequestParam String status) throws RestException { - return this.resourceService.changeUpdateStatus(account, resourceId, updateId, status); - } - - @PatchMapping("/{resourceId}/edit/update/{updateId}") - public Update editResourceUpdate(Account account, @PathVariable int resourceId, @PathVariable int updateId, @RequestBody EditResourceUpdateRequest request) throws RestException { - return this.resourceService.editResourceUpdate(account, resourceId, updateId, request); - } } diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java new file mode 100644 index 0000000..5202aaa --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java @@ -0,0 +1,62 @@ +package com.imjustdoom.pluginsite.controller.rest; + + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; +import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Update; +import com.imjustdoom.pluginsite.service.rest.ResourceUpdateService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ContentDisposition; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.util.List; + +@RestController +@RequestMapping("/resource/update") +@RequiredArgsConstructor +public class ResourceUpdateController { + private final ResourceUpdateService resourceUpdateService; + + @PatchMapping("/{updateId}/status") + public Update changeStatus(Account account, @PathVariable int updateId, @RequestParam String status) throws RestException { + return this.resourceUpdateService.changeStatus(account, updateId, status); + } + + @PatchMapping("/{updateId}") + public Update editUpdate(Account account, @PathVariable int updateId, @RequestBody EditResourceUpdateRequest request) throws RestException { + return this.resourceUpdateService.editUpdate(account, updateId, request); + } + + @PostMapping("/") + public void createUpdate(Account account, @RequestParam List softwareCheckbox, + @RequestParam List versionCheckbox, + @RequestParam int resourceId, @RequestParam MultipartFile file, + @RequestBody CreateUpdateRequest updateRequest) throws RestException { + this.resourceUpdateService.createUpdate(account, softwareCheckbox, versionCheckbox, resourceId, file, updateRequest); // todo should the variables like softwareCheckbox be inside the create request? + } + + @GetMapping(value = "/{updateId}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public ResponseEntity getFile(@PathVariable int updateId) throws RestException { + ResourceUpdateService.FileReturn fileReturn = this.resourceUpdateService.getDownload(updateId); + return ResponseEntity.ok() + .headers(httpHeaders -> httpHeaders.setContentDisposition( + ContentDisposition.attachment() + .filename(fileReturn.realName()) + .build() + )) + .body(fileReturn.file()); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java b/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java index f8368b5..6980d4d 100644 --- a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java @@ -13,4 +13,11 @@ public class CreateUpdateRequest { private String version; private String externalLink; private String description; + + public boolean isMissingRequirements() { + return this.name == null || this.name.isEmpty() + || this.version == null || this.version.isEmpty() + || this.externalLink == null || this.externalLink.isEmpty() + || this.description == null || this.description.isEmpty(); + } } \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Resource.java b/src/main/java/com/imjustdoom/pluginsite/model/Resource.java index d2488e9..5ae163b 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Resource.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Resource.java @@ -14,14 +14,13 @@ @NoArgsConstructor public class Resource { - public Resource(String name, String description, String blurb, String donation, String source, String download, + public Resource(String name, String description, String blurb, String donation, String source, Account author, String support, String category) { this.name = name; this.description = description; this.blurb = blurb; this.donation = donation; this.source = source; - this.download = download; this.author = author; this.support = support; this.created = LocalDateTime.now(); @@ -49,16 +48,13 @@ public Resource(String name, String description, String blurb, String donation, @Column(nullable = false) private LocalDateTime updated; - // todo if we are making these option, they should also be nullable?? + // todo if we are making these optional, they should also be nullable?? @Column(nullable = false) private String donation; @Column(nullable = false) private String source; - @Column(nullable = false) - private String download; - @ManyToOne(fetch = FetchType.LAZY) private Account author; diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Update.java b/src/main/java/com/imjustdoom/pluginsite/model/Update.java index 89a836a..4f37e91 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Update.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Update.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; +import org.springframework.lang.Nullable; import javax.persistence.*; import java.time.LocalDateTime; @@ -14,18 +15,17 @@ public class Update { public Update(String description, String filename, String version, String download, String name, - List versions, List software, Resource resource, String external) { + List versions, List software, Resource resource) { this.downloads = 0; this.description = description; this.filename = filename; this.version = version; - this.download = download; + this.downloadLink = download; this.name = name; this.uploaded = LocalDateTime.now(); this.versions = versions; this.software = software; this.resource = resource; - this.external = external; this.status = "public"; } @@ -33,6 +33,9 @@ public Update(String description, String filename, String version, String downlo @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; + @ManyToOne(fetch = FetchType.LAZY) + private Resource resource; + @Column(nullable = false) private String description; @@ -45,8 +48,7 @@ public Update(String description, String filename, String version, String downlo @ElementCollection private List software; - @Column(nullable = false) - private String download; + private @Nullable String downloadLink; @Column(nullable = false) private String name; @@ -60,12 +62,6 @@ public Update(String description, String filename, String version, String downlo @Column(nullable = false) private int downloads; - @Column(nullable = false) - private String external; - - @ManyToOne(fetch = FetchType.LAZY) - private Resource resource; - @Column(nullable = false) private String status; diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java index fd39f56..850aff1 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/ResourceRepository.java @@ -41,11 +41,6 @@ default void customize(QuerydslBindings bindings, QResource root) { List findAllByStatusEqualsIgnoreCase(String status); - @Modifying - @Transactional - @Query("UPDATE Resource resource SET resource.download = ?2 WHERE resource.id = ?1") - void setDownload(int id, String download); - @Modifying @Transactional @Query("UPDATE Resource resource SET resource.name = ?2, resource.blurb = ?3, resource.description = ?4, " + diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index 51b927a..3ffb217 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -22,11 +22,6 @@ public interface UpdateRepository extends JpaRepository { @Query("SELECT updates FROM Update updates WHERE ?3 in(updates.software)") List findAllByResourceIdAndStatusEqualsAndSoftware(int resourceId, String status, String software, Sort sort); - @Modifying - @Transactional - @Query("UPDATE Update updates SET updates.download = ?2 WHERE updates.id = ?1") - void setDownload(int id, String download); - @Modifying @Transactional @Query("UPDATE Update updates SET updates.downloads = updates.downloads + 1 WHERE updates.id = ?1") diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java deleted file mode 100644 index 6330c90..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/ResourceServiceImpl.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.imjustdoom.pluginsite.service.impl; - -import com.imjustdoom.pluginsite.config.custom.SiteConfig; -import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; -import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.service.ResourceService; -import lombok.AllArgsConstructor; -import me.xdrop.fuzzywuzzy.FuzzySearch; -import me.xdrop.fuzzywuzzy.model.BoundExtractedResult; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -@Service -@AllArgsConstructor -public class ResourceServiceImpl implements ResourceService { - - private final UpdateRepository updateRepository; - private final ResourceRepository resourceRepository; - - @Override - public String postCreateResource(CreateResourceRequest resourceRequest, Account account, SiteConfig siteConfig, - RedirectAttributes redirectAttributes) { - - redirectAttributes.addFlashAttribute("resourceRequest", resourceRequest); - if (resourceRepository.getResourcesCreateLastHour(account.getId()) > siteConfig.getMaxCreationsPerHour()) - return "redirect:/resources/create?error=createlimit"; - - if (resourceRepository.existsByNameEqualsIgnoreCase(resourceRequest.getName())) - return "redirect:/resources/create?error=nametaken"; - - if (resourceRequest.getName().equalsIgnoreCase("") - || resourceRequest.getBlurb().equalsIgnoreCase("") - || resourceRequest.getDescription().equalsIgnoreCase("")) - return "redirect:/resources/create?error=invalidinput"; - - Resource resource = new Resource(resourceRequest.getName(), resourceRequest.getDescription(), - resourceRequest.getBlurb(), resourceRequest.getDonation(), resourceRequest.getSource(), - "", account, resourceRequest.getSupport(), resourceRequest.getCategory()); - - resourceRepository.save(resource); - - return "redirect:/resources/%s".formatted(resource.getId()); - } - - @Override - public List searchResources(String search, String sortBy, String page) { - List> searchResults; - List data = new ArrayList<>(); - - Sort sort = Sort.by(sortBy).descending(); - if(sortBy.equalsIgnoreCase("name")) sort = sort.ascending(); - Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort); - - searchResults = FuzzySearch.extractSorted(search, resourceRepository.findAllByStatusEqualsIgnoreCase("public", pageable), Resource::getName); - - for (BoundExtractedResult extractedResult : searchResults) { - if (extractedResult.getScore() < 40) continue; - - //TODO: use getReferent - Optional optionalResource = resourceRepository.findByNameEqualsIgnoreCase(extractedResult.getString()); - Resource resource = optionalResource.get(); - - Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); - data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); - - } - - return data; - } - - @Override - public List getResourcesWithCategory(String sortBy, String page, String category) { - List data = new ArrayList<>(); - Sort sort = Sort.by(sortBy).descending(); - if(sortBy.equalsIgnoreCase("name")) sort = sort.ascending(); - Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort); - - for (Resource resource : resourceRepository.findAllByCategoryEqualsAndStatusEquals(category, "public", pageable)) { - Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); - data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); - } - - return data; - } - - @Override - public List getResources(String sortBy, String page) { - List data = new ArrayList<>(); - Sort sort = Sort.by(sortBy).descending(); - if(sortBy.equalsIgnoreCase("name")) sort = sort.ascending(); - Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, 25, sort); - - for (Resource resource : resourceRepository.findAllByStatusEqualsIgnoreCase("public", pageable)) { - Integer downloads = updateRepository.getTotalDownloads(resource.getId()).get(); - data.add(SimpleResourceDto.create(resource, downloads == null ? 0 : downloads)); - } - - return data; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/UpdateServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/UpdateServiceImpl.java deleted file mode 100644 index 525ce49..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/UpdateServiceImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.imjustdoom.pluginsite.service.impl; - -import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.model.Update; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.service.UpdateService; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; - -@Service -@AllArgsConstructor -public class UpdateServiceImpl implements UpdateService { - - private final UpdateRepository updateRepository; - - @Override - public Update createUpdate(CreateUpdateRequest updateRequest, Account account) { - Update resource = new Update(updateRequest.getDescription(), "", "", "", "", - new ArrayList<>(), new ArrayList<>(), new Resource(), updateRequest.getExternalLink()); - - updateRepository.save(resource); - - return resource; - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java index c18fc76..c010a73 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java @@ -4,11 +4,9 @@ import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; -import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.model.Update; import com.imjustdoom.pluginsite.repositories.ResourceRepository; import com.imjustdoom.pluginsite.repositories.UpdateRepository; import com.imjustdoom.pluginsite.util.ImageUtil; @@ -37,7 +35,7 @@ public Page searchResources(Pageable pageable, Predicate quer //TODO: More sanity checks public Resource createResource(Account account, CreateResourceRequest request) throws RestException { if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) - throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); + throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_CREATIONS); if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) @@ -45,7 +43,7 @@ public Resource createResource(Account account, CreateResourceRequest request) t Resource resource = new Resource(request.getName(), request.getDescription(), request.getBlurb(), request.getDonation(), request.getSource(), - "", account, request.getSupport(), request.getCategory()); + account, request.getSupport(), request.getCategory()); return this.resourceRepository.save(resource); } @@ -88,30 +86,4 @@ public Resource updateResource(Account account, int resourceId, MultipartFile fi return this.resourceRepository.save(resource); } - - public Update changeUpdateStatus(Account account, int resourceId, int updateId, String status) throws RestException { - Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); - if (resource.getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); - return this.updateRepository.updateStatusById(updateId, status).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); - } - - public Update editResourceUpdate(Account account, int resourceId, int updateId, EditResourceUpdateRequest request) throws RestException { - Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); - if (resource.getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); - Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); - - String name = request.getName(); - if (name != null && !name.isEmpty()) - update.setName(name); - - String version = request.getVersion(); - if (version != null && !version.isEmpty()) - update.setVersion(version); - - String description = request.getDescription(); - if (description != null && !description.isEmpty()) - update.setDescription(description); - - return this.updateRepository.save(update); - } } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java new file mode 100644 index 0000000..293f46d --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java @@ -0,0 +1,101 @@ +package com.imjustdoom.pluginsite.service.rest; + +import com.imjustdoom.pluginsite.config.custom.SiteConfig; +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; +import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.model.Update; +import com.imjustdoom.pluginsite.repositories.ResourceRepository; +import com.imjustdoom.pluginsite.repositories.UpdateRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ResourceUpdateService { + private static final Path BASE_PATH = Path.of("./resources/plugins/"); + + private final UpdateRepository updateRepository; + private final ResourceRepository resourceRepository; + private final SiteConfig siteConfig; + + @PostConstruct + public void setup() { + if (Files.notExists(BASE_PATH)) + BASE_PATH.toFile().mkdirs(); + } + + public Update changeStatus(Account account, int updateId, String status) throws RestException { + Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); + if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + update.setStatus(status); + return this.updateRepository.save(update); + } + + public Update editUpdate(Account account, int updateId, EditResourceUpdateRequest request) throws RestException { + Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); + if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + + String name = request.getName(); + if (name != null && !name.isEmpty()) + update.setName(name); + + String version = request.getVersion(); + if (version != null && !version.isEmpty()) + update.setVersion(version); + + String description = request.getDescription(); + if (description != null && !description.isEmpty()) + update.setDescription(description); + + return this.updateRepository.save(update); + } + + public void createUpdate(Account account, List softwareCheckbox, List versionCheckbox, int resourceId, + MultipartFile file, CreateUpdateRequest request) throws RestException { + + if (this.updateRepository.getUpdatesCreateLastHour(account.getId()) > this.siteConfig.getMaxUpdatesPerHour()) throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); + + if ((file.isEmpty() || file.getSize() > this.siteConfig.getMaxUploadSize().toBytes()) && (request.getExternalLink() == null || request.getExternalLink().isEmpty())) throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING, "Missing File"); + if ((!file.getOriginalFilename().endsWith(".jar") && !file.getOriginalFilename().endsWith(".zip")) && request.getExternalLink().equals("")) throw new RestException(RestErrorCode.WRONG_FILE_TYPE); + if (request.isMissingRequirements()) throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING, "Missing name, version or description."); + + Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + Update update; + if (file.isEmpty()) { + update = new Update(request.getDescription(), null, request.getVersion(), request.getExternalLink(), request.getName(), versionCheckbox, softwareCheckbox, resource); + } else { + update = new Update(request.getDescription(), file.getOriginalFilename(), request.getVersion(), null, request.getName(), versionCheckbox, softwareCheckbox, resource); + Path resourcePath = BASE_PATH.resolve(update.getId() + ".jar"); + try (InputStream inputStream = file.getInputStream()) { + Files.copy(inputStream, resourcePath); + } catch (IOException e) { + e.printStackTrace(); + } + } + this.updateRepository.save(update); + } + + public FileReturn getDownload(int updateId) throws RestException { + Path path = BASE_PATH.resolve(updateId + ".jar"); + if (!Files.exists(path)) throw new RestException(RestErrorCode.DOWNLOAD_NOT_FOUND, "File not found"); + Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); + if (update.getDownloadLink() != null) throw new RestException(RestErrorCode.WRONG_FILE_TYPE, "File is provided via an external URL"); + + return new FileReturn(path.toFile(), update.getFilename()); + } + + public record FileReturn(File file, String realName) {} +} From e471b853463728878bdee92e2f9e97acecfc4f25 Mon Sep 17 00:00:00 2001 From: Zak Date: Mon, 14 Feb 2022 01:38:59 +0000 Subject: [PATCH 10/13] Finish new controllers and services --- .../java/com/imjustdoom/pluginsite/Test.java | 2 +- .../config/exception/RestErrorCode.java | 4 +- .../security/PasswordEncoderConfig.java | 15 ++ .../config/{ => security}/SecurityConfig.java | 13 +- .../{rest => }/AccountController.java | 20 +- .../{rest => }/AdminController.java | 4 +- .../pluginsite/controller/FileController.java | 57 ----- .../controller/MessageController.java | 22 ++ .../controller/MessageGroupController.java | 63 +++++ .../controller/MessagesController.java | 235 ------------------ .../{rest => }/ProfileController.java | 4 +- .../{rest => }/ReportController.java | 4 +- .../{rest => }/ResourceController.java | 7 +- .../{rest => }/ResourceUpdateController.java | 4 +- .../dtos/out/message/MessageDto.java | 11 + .../dtos/out/message/MessageGroupDto.java | 12 + .../imjustdoom/pluginsite/model/Message.java | 11 +- .../pluginsite/model/MessageGroup.java | 17 +- .../repositories/MessageGroupRepository.java | 13 +- .../repositories/MessageRepository.java | 6 +- .../service/{rest => }/AccountService.java | 12 +- .../service/{rest => }/AdminService.java | 2 +- .../pluginsite/service/LogoService.java | 14 -- .../pluginsite/service/MessageService.java | 115 +++++++++ .../service/ProfilePictureService.java | 14 -- .../service/{rest => }/ProfileService.java | 2 +- .../service/{rest => }/ReportService.java | 2 +- .../pluginsite/service/ResourceService.java | 83 ++++++- .../{rest => }/ResourceUpdateService.java | 6 +- .../pluginsite/service/UpdateService.java | 15 -- .../service/impl/AccountServiceImpl.java | 20 -- .../service/impl/LogoServiceImpl.java | 54 ---- .../impl/ProfilePictureServiceImpl.java | 54 ---- .../service/rest/ResourceService.java | 89 ------- 34 files changed, 399 insertions(+), 607 deletions(-) create mode 100644 src/main/java/com/imjustdoom/pluginsite/config/security/PasswordEncoderConfig.java rename src/main/java/com/imjustdoom/pluginsite/config/{ => security}/SecurityConfig.java (84%) rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/AccountController.java (69%) rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/AdminController.java (95%) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/FileController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/MessageController.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/MessageGroupController.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/ProfileController.java (86%) rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/ReportController.java (87%) rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/ResourceController.java (89%) rename src/main/java/com/imjustdoom/pluginsite/controller/{rest => }/ResourceUpdateController.java (96%) create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageDto.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageGroupDto.java rename src/main/java/com/imjustdoom/pluginsite/service/{rest => }/AccountService.java (85%) rename src/main/java/com/imjustdoom/pluginsite/service/{rest => }/AdminService.java (84%) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/LogoService.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/service/MessageService.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/ProfilePictureService.java rename src/main/java/com/imjustdoom/pluginsite/service/{rest => }/ProfileService.java (94%) rename src/main/java/com/imjustdoom/pluginsite/service/{rest => }/ReportService.java (96%) rename src/main/java/com/imjustdoom/pluginsite/service/{rest => }/ResourceUpdateService.java (96%) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/UpdateService.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/impl/AccountServiceImpl.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/impl/LogoServiceImpl.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/impl/ProfilePictureServiceImpl.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java diff --git a/src/main/java/com/imjustdoom/pluginsite/Test.java b/src/main/java/com/imjustdoom/pluginsite/Test.java index 55e53f9..2ed5b33 100644 --- a/src/main/java/com/imjustdoom/pluginsite/Test.java +++ b/src/main/java/com/imjustdoom/pluginsite/Test.java @@ -6,7 +6,7 @@ import com.imjustdoom.pluginsite.model.Resource; import com.imjustdoom.pluginsite.repositories.AccountRepository; import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.service.rest.AccountService; +import com.imjustdoom.pluginsite.service.AccountService; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java index 6ff0a36..bc57527 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/exception/RestErrorCode.java @@ -10,13 +10,15 @@ public enum RestErrorCode { USERNAME_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 3), EMAIL_NOT_AVAILABLE(HttpStatus.BAD_REQUEST, "auth", 4), - INVALID_ACCESS(HttpStatus.UNAUTHORIZED, "auth", 100), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "auth", 100), + FORBIDDEN(HttpStatus.FORBIDDEN, "auth", 101), ACCOUNT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 100), REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 101), RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 102), RESOURCE_UPDATE_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 103), DOWNLOAD_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 104), + MESSAGE_GROUP_NOT_FOUND(HttpStatus.NOT_FOUND, "data", 105), WRONG_FILE_TYPE(HttpStatus.BAD_REQUEST, "data", 2), FILE_TOO_LARGE(HttpStatus.BAD_REQUEST, "data", 3), diff --git a/src/main/java/com/imjustdoom/pluginsite/config/security/PasswordEncoderConfig.java b/src/main/java/com/imjustdoom/pluginsite/config/security/PasswordEncoderConfig.java new file mode 100644 index 0000000..f884831 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/config/security/PasswordEncoderConfig.java @@ -0,0 +1,15 @@ +package com.imjustdoom.pluginsite.config.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/SecurityConfig.java b/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java similarity index 84% rename from src/main/java/com/imjustdoom/pluginsite/config/SecurityConfig.java rename to src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java index 1626fde..aaeb881 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/SecurityConfig.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.config; +package com.imjustdoom.pluginsite.config.security; import lombok.AllArgsConstructor; import org.springframework.context.annotation.Bean; @@ -9,7 +9,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @@ -17,18 +16,14 @@ @AllArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Bean - public PasswordEncoder encoder() { - return new BCryptPasswordEncoder(); - } - private final UserDetailsService userDetailsService; + private final PasswordEncoder passwordEncoder; @Bean public DaoAuthenticationProvider authProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); - authProvider.setUserDetailsService(userDetailsService); - authProvider.setPasswordEncoder(encoder()); + authProvider.setUserDetailsService(this.userDetailsService); + authProvider.setPasswordEncoder(this.passwordEncoder); return authProvider; } diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java b/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java similarity index 69% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java index 1d78568..9f53638 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AccountController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java @@ -1,13 +1,19 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; import com.imjustdoom.pluginsite.dtos.in.account.UpdateAccountRequest; import com.imjustdoom.pluginsite.dtos.out.account.AccountDto; import com.imjustdoom.pluginsite.dtos.out.account.SelfAccountDto; +import com.imjustdoom.pluginsite.dtos.out.message.MessageGroupDto; import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.service.rest.AccountService; +import com.imjustdoom.pluginsite.service.AccountService; +import com.imjustdoom.pluginsite.service.MessageService; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,6 +29,7 @@ @RequiredArgsConstructor public class AccountController { private final AccountService accountService; + private final MessageService messageService; @PostMapping("/register") public String signupSubmit(@RequestBody CreateAccountRequest accountRequest) throws RestException { @@ -48,4 +55,13 @@ public SelfAccountDto updateAccountDetails(Account account, @RequestBody UpdateA @RequestParam("profilePicture") MultipartFile file) throws RestException { return SelfAccountDto.fromAccount(this.accountService.updateAccountDetails(account, request, file)); } + + @GetMapping("/groups") + public Page getMessageGroups(Account account, + @PageableDefault(size = 25) Pageable pageable) throws RestException { + if (pageable.getPageSize() > 50) throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size is too large (%s > %s)", pageable.getPageSize(), 50); + + return this.messageService.getGroups(account, pageable) + .map(MessageGroupDto::fromMessageGroup); + } } diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java b/src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java similarity index 95% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java index 71b9d24..c20a8e6 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/AdminController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/AdminController.java @@ -1,9 +1,9 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.model.Report; -import com.imjustdoom.pluginsite.service.rest.ReportService; +import com.imjustdoom.pluginsite.service.ReportService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java deleted file mode 100644 index 3c4e468..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/FileController.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Update; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.service.LogoService; -import com.imjustdoom.pluginsite.service.ProfilePictureService; -import lombok.AllArgsConstructor; -import org.springframework.core.io.Resource; -import org.springframework.core.io.UrlResource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.net.MalformedURLException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Optional; - -@AllArgsConstructor -public class FileController { - - private final LogoService logoService; - private final ProfilePictureService profilePictureService; - private final UpdateRepository updateRepository; - private final ResourceRepository resourceRepository; - - @GetMapping("/files/{id}/download/{fileId}") - @ResponseBody - public ResponseEntity serveFile(Account account, @PathVariable("fileId") int fileId) throws MalformedURLException { - - Optional optional = updateRepository.findById(fileId); - Update update = optional.get(); - - if(!update.getStatus().equalsIgnoreCase("public") - && account.getId() != update.getResource().getAuthor().getId()) { - return ResponseEntity.notFound().build(); - } - - Path path = Paths.get("resources/plugins/" + fileId + "/"); - Resource file = new UrlResource(path.resolve(update.getFilename()).toUri()); - - updateRepository.addDownload(fileId); - -// if(!update.getExternal().equalsIgnoreCase("")) { -// HttpHeaders headers = new HttpHeaders(); -// headers.add("Location", update.getExternal()); -// return new ResponseEntity(headers, HttpStatus.FOUND); -// } - - return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, - "attachment; filename=\"" + file.getFilename() + "\"").body(file); - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/MessageController.java b/src/main/java/com/imjustdoom/pluginsite/controller/MessageController.java new file mode 100644 index 0000000..05c835a --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/MessageController.java @@ -0,0 +1,22 @@ +package com.imjustdoom.pluginsite.controller; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.service.MessageService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/message") +@RequiredArgsConstructor +public class MessageController { + private final MessageService messageService; + + @PostMapping + public void sendMessage(Account account, @RequestParam int groupId, @RequestParam String content) throws RestException { + this.messageService.sendMessage(account, groupId, content); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/MessageGroupController.java b/src/main/java/com/imjustdoom/pluginsite/controller/MessageGroupController.java new file mode 100644 index 0000000..78058b6 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/controller/MessageGroupController.java @@ -0,0 +1,63 @@ +package com.imjustdoom.pluginsite.controller; + +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.dtos.out.message.MessageDto; +import com.imjustdoom.pluginsite.dtos.out.message.MessageGroupDto; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.service.MessageService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/message/group") +@RequiredArgsConstructor +public class MessageGroupController { + private final MessageService messageService; + + @PostMapping + public void createGroup(Account sender, @RequestParam int targetId) throws RestException { + this.messageService.createGroup(sender, targetId); + } + + @GetMapping("/{groupId}") + public MessageGroupDto getGroup(Account account, @PathVariable int groupId) throws RestException { + return MessageGroupDto.fromMessageGroup(this.messageService.getGroup(account, groupId)); + } + + @GetMapping("/{groupId}/messages") + public Page getMessages(Account account, @PathVariable int groupId, @PageableDefault(size = 25) Pageable pageable) throws RestException { + return this.messageService.getMessages(account, groupId, pageable) + .map(MessageDto::fromMessage); + } + + @DeleteMapping("/{groupId}") + public void deleteGroup(Account account, @PathVariable int groupId) throws RestException { + this.messageService.deleteGroup(account, groupId); + } + + @PostMapping("/{groupId}/addUser") + public void addUserToGroup(Account account, @PathVariable int groupId, @RequestParam int targetId) throws RestException { + this.messageService.addUserToGroup(account, groupId, targetId); + } + + @PostMapping("/{groupId}/leave") + public void leaveGroup(Account account, @PathVariable int groupId) throws RestException { + this.messageService.leaveGroup(account, groupId); + } + + @PatchMapping("/{groupId}/name") + public MessageGroupDto editGroupName(Account account, @PathVariable int groupId, @RequestParam String name) throws RestException { + return MessageGroupDto.fromMessageGroup(this.messageService.editGroupName(account, groupId, name)); + } + +} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java b/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java deleted file mode 100644 index c333920..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/controller/MessagesController.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.imjustdoom.pluginsite.controller; - -import com.google.gson.Gson; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Message; -import com.imjustdoom.pluginsite.model.MessageGroup; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.MessageGroupRepository; -import com.imjustdoom.pluginsite.repositories.MessageRepository; -import com.imjustdoom.pluginsite.util.RequestUtil; -import lombok.AllArgsConstructor; -import me.xdrop.fuzzywuzzy.FuzzySearch; -import me.xdrop.fuzzywuzzy.model.BoundExtractedResult; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; - -@AllArgsConstructor -public class MessagesController { - - private final MessageRepository messageRepository; - private final MessageGroupRepository messageGroupRepository; - private final AccountRepository accountRepository; - - private void sendSystemMessage(String message, int groupId){ -// Account systemAccount = new Account("System", "a@a.a", "a@a.a"); -// accountRepository.save(systemAccount); - Account systemAccount = accountRepository.findByUsernameEqualsIgnoreCase("System").get(); - MessageGroup messageGroup = messageGroupRepository.findById(groupId).get(); - Message systemMessage = new Message(message, systemAccount, messageGroup); - messageRepository.save(systemMessage); - } - - @GetMapping("/message") - public String message(Model model, Account account){ - if (account == null) { - return "redirect:/login"; - } - model.addAttribute("account", account); - return "message/message"; - } - - @GetMapping("/message/new/{id}") - public String newMessage(Model model, Account account, @PathVariable("id") int id){ - List users = new ArrayList<>(); - Optional adding = accountRepository.findById(id); - // TODO: add an error message - if(adding.isEmpty() || adding.get().getId() == account.getId()) return "redirect:/message"; - users.add(adding.get()); - users.add(account); - String name = "Generic Group #" + (int) (Math.random() * 100); - MessageGroup messageGroup = new MessageGroup(name, LocalDateTime.now(), users); - messageGroupRepository.save(messageGroup); - - return "redirect:/message"; - } - - @PostMapping(value = "/message/api/get_groups", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> getConversations(Account account){ - List messageGroups; - if(account == null) { - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } - messageGroups = account.getGroups(); - HashMap response = new HashMap<>(); - for (MessageGroup messageGroup : messageGroups) { - HashMap group = new HashMap<>(); - group.put("GroupId", String.valueOf(messageGroup.getId())); - group.put("GroupName", messageGroup.getName()); - group.put("GroupMembers", String.valueOf(messageGroup.getMembers().size())); - response.put("Group." + response.size(), new Gson().toJson(group)); - } - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "/message/api/get_group", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> getGroup(@RequestBody String request) { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - HashMap response = new HashMap<>(); - for (Account account : messageGroup.getMembers()) { - response.put("Username." + response.size(), account.getUsername()); - } - response.put("GroupName", messageGroup.getName()); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "/message/api/get_messages", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> getMessages(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - List messages = messageGroup.getMessages(); - HashMap response = new HashMap<>(); - for (Message message : messages) { - HashMap messageMap = new HashMap<>(); - messageMap.put("MessageId", String.valueOf(message.getId())); - if(message.getAuthor().getUsername().equalsIgnoreCase("System")) { - messageMap.put("MessageAuthor", "system"); - }else{ - messageMap.put("MessageAuthor", (message.getAuthor().getId() == account.getId()) ? "self" : "other"); - } - messageMap.put("MessageAuthorId", String.valueOf(message.getAuthor().getId())); - messageMap.put("MessageAuthorName", message.getAuthor().getUsername()); - messageMap.put("MessageContent", message.getContent()); - - response.put("Message." + response.size(), new Gson().toJson(messageMap)); - } - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping("/message/api/send_message") - public ResponseEntity> sendMessage(@RequestBody String request, Account account) { - // send message to that conversation - // return json - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - String content = params.get("content"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - Message message = new Message(content, account, messageGroup); - messageRepository.save(message); - HashMap response = new HashMap<>(); - response.put("MessageId", String.valueOf(message.getId())); - response.put("MessageAuthor", String.valueOf(message.getAuthor().getId())); - response.put("MessageContent", message.getContent()); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "/message/api/create_group", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> getGroups(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String userIds = params.get("userIds"); - String name = "Generic Group #" + (int) (Math.random() * 100); - String[] userIdsList = userIds.split("%2C"); - List users = new ArrayList(); - for (String userId : userIdsList) { - users.add(accountRepository.findById(Integer.parseInt(userId)).get()); - } - - users.add(account); - - MessageGroup messageGroup = new MessageGroup(name, LocalDateTime.now(), users); - messageGroupRepository.save(messageGroup); - - HashMap response = new HashMap<>(); - response.put("groupId", String.valueOf(messageGroup.getId())); - response.put("name", messageGroup.getName()); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "message/api/add_member", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> addMember(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - String userId = params.get("userId"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - Account user = accountRepository.findByUsernameEqualsIgnoreCase(userId).get(); - messageGroup.getMembers().add(user); - messageGroupRepository.save(messageGroup); - HashMap response = new HashMap<>(); - response.put("groupId", groupId); - sendSystemMessage("User " + user.getUsername() + " has been added to the group.", messageGroup.getId()); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "message/api/leave", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> leave(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - messageGroup.getMembers().remove(account); - messageGroupRepository.save(messageGroup); - HashMap response = new HashMap<>(); - response.put("groupId", groupId); - sendSystemMessage("User " + account.getUsername() + " has left the group.", messageGroup.getId()); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "message/api/delete_group", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> deleteGroup(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - messageGroupRepository.delete(messageGroup); - HashMap response = new HashMap<>(); - response.put("groupId", groupId); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "message/api/edit_group_name", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> editGroupName(@RequestBody String request, Account account) throws UnsupportedEncodingException { - HashMap params = RequestUtil.getParams(request); - String groupId = params.get("groupId"); - String name = params.get("name"); - name = URLDecoder.decode(name, StandardCharsets.UTF_8); - MessageGroup messageGroup = messageGroupRepository.findById(Integer.parseInt(groupId)).get(); - messageGroup.setName(name); - messageGroupRepository.save(messageGroup); - HashMap response = new HashMap<>(); - response.put("groupId", groupId); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - @PostMapping(value = "message/api/fuzzy_search/users", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity> searchUsers(@RequestBody String request, Account account) { - HashMap params = RequestUtil.getParams(request); - String searchTerm = params.get("searchTerm"); - - List> searchResults = FuzzySearch.extractSorted(searchTerm, accountRepository.findAll(), Account::getUsername); - - HashMap response = new HashMap<>(); - List usernames = new ArrayList<>(); - for(BoundExtractedResult result : searchResults) { - usernames.add(result.getString()); - } - response.put("usernames", String.join(",", usernames)); - return new ResponseEntity<>(response, HttpStatus.OK); - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java similarity index 86% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java index 78e7ade..a704eca 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ProfileController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ProfileController.java @@ -1,8 +1,8 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.out.ProfileDto; -import com.imjustdoom.pluginsite.service.rest.ProfileService; +import com.imjustdoom.pluginsite.service.ProfileService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java similarity index 87% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java index 827a183..9a27b43 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ReportController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java @@ -1,8 +1,8 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.dtos.in.CreateReportRequest; import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.service.rest.ReportService; +import com.imjustdoom.pluginsite.service.ReportService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceController.java similarity index 89% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/ResourceController.java index 17caa2f..fab06d0 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceController.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; @@ -7,7 +7,7 @@ import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Resource; import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.service.rest.ResourceService; +import com.imjustdoom.pluginsite.service.ResourceService; import com.querydsl.core.types.Predicate; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -34,8 +34,7 @@ public class ResourceController { @GetMapping public Page searchResources(@PageableDefault(size = 25, sort = "updated", direction = Sort.Direction.DESC) Pageable pageable, @QuerydslPredicate(root = Resource.class) Predicate predicate) throws RestException { - if (pageable.getPageSize() > 50) - throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size is too large (%s > %s)", pageable.getPageSize(), 50); + if (pageable.getPageSize() > 50) throw new RestException(RestErrorCode.PAGE_SIZE_TOO_LARGE, "Page size is too large (%s > %s)", pageable.getPageSize(), 50); return this.resourceService.searchResources(pageable, predicate); } diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java similarity index 96% rename from src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java rename to src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java index 5202aaa..50e7993 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/rest/ResourceUpdateController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.controller.rest; +package com.imjustdoom.pluginsite.controller; import com.imjustdoom.pluginsite.config.exception.RestException; @@ -6,7 +6,7 @@ import com.imjustdoom.pluginsite.dtos.in.resource.EditResourceUpdateRequest; import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.Update; -import com.imjustdoom.pluginsite.service.rest.ResourceUpdateService; +import com.imjustdoom.pluginsite.service.ResourceUpdateService; import lombok.RequiredArgsConstructor; import org.springframework.http.ContentDisposition; import org.springframework.http.MediaType; diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageDto.java new file mode 100644 index 0000000..01cdab9 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageDto.java @@ -0,0 +1,11 @@ +package com.imjustdoom.pluginsite.dtos.out.message; + +import com.imjustdoom.pluginsite.model.Message; + +public record MessageDto(int id, int authorId, + String content) { + + public static MessageDto fromMessage(Message message) { + return new MessageDto(message.getId(), message.getAuthor().getId(), message.getContent()); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageGroupDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageGroupDto.java new file mode 100644 index 0000000..2d7e9a8 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/message/MessageGroupDto.java @@ -0,0 +1,12 @@ +package com.imjustdoom.pluginsite.dtos.out.message; + +import com.imjustdoom.pluginsite.model.MessageGroup; + +import java.time.LocalDateTime; + +public record MessageGroupDto(int id, String name, LocalDateTime createdTime) { + + public static MessageGroupDto fromMessageGroup(MessageGroup group) { + return new MessageGroupDto(group.getId(), group.getName(), group.getCreatedTime()); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Message.java b/src/main/java/com/imjustdoom/pluginsite/model/Message.java index 08daee0..18a3883 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Message.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Message.java @@ -3,9 +3,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import javax.persistence.Id; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; @Setter @Getter @@ -13,7 +18,7 @@ @NoArgsConstructor public class Message { - public Message(String content, Account author, MessageGroup group){ + public Message(String content, Account author, MessageGroup group) { this.content = content; this.author = author; this.group = group; diff --git a/src/main/java/com/imjustdoom/pluginsite/model/MessageGroup.java b/src/main/java/com/imjustdoom/pluginsite/model/MessageGroup.java index 6a0838a..7a02d3c 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/MessageGroup.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/MessageGroup.java @@ -3,9 +3,16 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import javax.persistence.Id; -import javax.persistence.*; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; import java.time.LocalDateTime; import java.util.List; @@ -15,9 +22,9 @@ @NoArgsConstructor public class MessageGroup { - public MessageGroup(String name, LocalDateTime createdDate, List members){ + public MessageGroup(String name, LocalDateTime createdTime, List members) { this.name = name; - this.createdDate = createdDate; + this.createdTime = createdTime; this.members = members; System.out.println(members.toString()); } @@ -34,7 +41,7 @@ public MessageGroup(String name, LocalDateTime createdDate, List member private String name; @Column(nullable = false) - private LocalDateTime createdDate; + private LocalDateTime createdTime; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "group") private List messages; diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/MessageGroupRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/MessageGroupRepository.java index 0c1dc56..5f874d0 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/MessageGroupRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/MessageGroupRepository.java @@ -1,12 +1,13 @@ package com.imjustdoom.pluginsite.repositories; +import com.imjustdoom.pluginsite.model.Account; import com.imjustdoom.pluginsite.model.MessageGroup; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; -public interface MessageGroupRepository extends JpaRepository { +public interface MessageGroupRepository extends PagingAndSortingRepository { + + Page findAllByMembersContains(Account account, Pageable pageable); - // get all message groups that an account is in -// @Query("select mg from MessageGroup mg where mg.account.id = ?1") -// Iterable findAllByAccountId(int accountId); } diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/MessageRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/MessageRepository.java index 1e3cba6..7730c1e 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/MessageRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/MessageRepository.java @@ -1,8 +1,12 @@ package com.imjustdoom.pluginsite.repositories; import com.imjustdoom.pluginsite.model.Message; +import com.imjustdoom.pluginsite.model.MessageGroup; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; public interface MessageRepository extends JpaRepository { + + Page findByGroup(MessageGroup group, Pageable pageable); } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java b/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java similarity index 85% rename from src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java rename to src/main/java/com/imjustdoom/pluginsite/service/AccountService.java index 1b8df8c..dc30bf7 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/AccountService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.service.rest; +package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; @@ -9,16 +9,24 @@ import com.imjustdoom.pluginsite.util.ImageUtil; import com.imjustdoom.pluginsite.util.ValidationHelper; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @Service @RequiredArgsConstructor -public class AccountService { +public class AccountService implements UserDetailsService { private final AccountRepository accountRepository; private final PasswordEncoder passwordEncoder; + @Override + public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { + return accountRepository.findByUsernameEqualsIgnoreCase(s).orElseThrow(() -> new UsernameNotFoundException("User not found")); + } + public Account register(CreateAccountRequest request) throws RestException { String username = request.getUsername(); if (!ValidationHelper.isUsernameValid(username)) throw new RestException(RestErrorCode.INVALID_USERNAME); diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java b/src/main/java/com/imjustdoom/pluginsite/service/AdminService.java similarity index 84% rename from src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java rename to src/main/java/com/imjustdoom/pluginsite/service/AdminService.java index 28edafc..b296d77 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/AdminService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/AdminService.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.service.rest; +package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.repositories.ReportRepository; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/imjustdoom/pluginsite/service/LogoService.java b/src/main/java/com/imjustdoom/pluginsite/service/LogoService.java deleted file mode 100644 index 495e2a4..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/LogoService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.imjustdoom.pluginsite.service; - -import org.springframework.web.multipart.MultipartFile; - -public interface LogoService { - - void updateLogo(int id, MultipartFile logo); - - boolean logoExists(int id); - - byte[] serveDefaultLogo(); - - byte[] serverLogo(int id); -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java b/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java new file mode 100644 index 0000000..96dc603 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java @@ -0,0 +1,115 @@ +package com.imjustdoom.pluginsite.service; + +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; +import com.imjustdoom.pluginsite.model.Account; +import com.imjustdoom.pluginsite.model.Message; +import com.imjustdoom.pluginsite.model.MessageGroup; +import com.imjustdoom.pluginsite.repositories.AccountRepository; +import com.imjustdoom.pluginsite.repositories.MessageGroupRepository; +import com.imjustdoom.pluginsite.repositories.MessageRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class MessageService { + + private final MessageRepository messageRepository; + private final MessageGroupRepository messageGroupRepository; + private final AccountRepository accountRepository; + + private Account systemAccount; + + @PostConstruct + public void setup() { + this.systemAccount = this.accountRepository.findByUsernameEqualsIgnoreCase("system").orElseGet(() -> { + Account account = new Account("system", "system@example.com", UUID.randomUUID().toString()); + return this.accountRepository.save(account); + }); + } + + private void sendSystemMessage(int groupId, String message) throws RestException { + MessageGroup messageGroup = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + Message systemMessage = new Message(message, this.systemAccount, messageGroup); + this.messageRepository.save(systemMessage); + } + + public void sendMessage(Account sender, int groupId, String content) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(sender)) throw new RestException(RestErrorCode.FORBIDDEN); + + Message message = new Message(content, sender, group); + this.messageRepository.save(message); + } + + public void createGroup(Account sender, int targetId) throws RestException { + Account targetAccount = this.accountRepository.findById(targetId).orElseThrow(() -> new RestException(RestErrorCode.ACCOUNT_NOT_FOUND, "Target user not found")); + + List users = new ArrayList<>() {{ + add(sender); + add(targetAccount); + }}; + String name = "Generic Group #" + (int) (Math.random() * 100); + MessageGroup messageGroup = new MessageGroup(name, LocalDateTime.now(), users); + this.messageGroupRepository.save(messageGroup); + } + + public Page getGroups(Account account, Pageable pageable) { + return this.messageGroupRepository.findAllByMembersContains(account, pageable); + } + + public MessageGroup getGroup(Account account, int groupId) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(account)) throw new RestException(RestErrorCode.FORBIDDEN); + + return group; + } + + public void addUserToGroup(Account sender, int groupId, int targetId) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(sender)) throw new RestException(RestErrorCode.FORBIDDEN); + + Account target = this.accountRepository.findById(targetId).orElseThrow(() -> new RestException(RestErrorCode.ACCOUNT_NOT_FOUND, "Target user not found")); + group.getMembers().add(target); + this.messageGroupRepository.save(group); + } + + public void leaveGroup(Account sender, int groupId) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(sender)) throw new RestException(RestErrorCode.FORBIDDEN); + + group.getMembers().remove(sender); + this.messageGroupRepository.save(group); + } + + public void deleteGroup(Account sender, int groupId) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(sender)) throw new RestException(RestErrorCode.FORBIDDEN); + + this.messageGroupRepository.delete(group); + } + + public MessageGroup editGroupName(Account sender, int groupId, String newName) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(sender)) throw new RestException(RestErrorCode.FORBIDDEN); + + group.setName(newName); + return this.messageGroupRepository.save(group); + } + + public Page getMessages(Account account, int groupId, Pageable pageable) throws RestException { + MessageGroup group = this.messageGroupRepository.findById(groupId).orElseThrow(() -> new RestException(RestErrorCode.MESSAGE_GROUP_NOT_FOUND)); + if (!group.getMembers().contains(account)) throw new RestException(RestErrorCode.FORBIDDEN); + + return this.messageRepository.findByGroup(group, pageable); + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/ProfilePictureService.java b/src/main/java/com/imjustdoom/pluginsite/service/ProfilePictureService.java deleted file mode 100644 index 95c02ed..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/ProfilePictureService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.imjustdoom.pluginsite.service; - -import org.springframework.web.multipart.MultipartFile; - -public interface ProfilePictureService { - - void updateProfilePicture(int id, MultipartFile logo); - - boolean logoExists(int id); - - byte[] serveDefaultProfilePicture(); - - byte[] serverProfilePicture(int id); -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java b/src/main/java/com/imjustdoom/pluginsite/service/ProfileService.java similarity index 94% rename from src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java rename to src/main/java/com/imjustdoom/pluginsite/service/ProfileService.java index 962a0a4..fc47193 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ProfileService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ProfileService.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.service.rest; +package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.out.ProfileDto; diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java b/src/main/java/com/imjustdoom/pluginsite/service/ReportService.java similarity index 96% rename from src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java rename to src/main/java/com/imjustdoom/pluginsite/service/ReportService.java index 4bfd869..d6dfcf1 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ReportService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ReportService.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.service.rest; +package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; diff --git a/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java index e5b8b7c..1e6b1e4 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java @@ -1,20 +1,89 @@ package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.config.custom.SiteConfig; +import com.imjustdoom.pluginsite.config.exception.RestErrorCode; +import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; import com.imjustdoom.pluginsite.model.Account; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import com.imjustdoom.pluginsite.model.Resource; +import com.imjustdoom.pluginsite.repositories.ResourceRepository; +import com.imjustdoom.pluginsite.repositories.UpdateRepository; +import com.imjustdoom.pluginsite.util.ImageUtil; +import com.querydsl.core.types.Predicate; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; -import java.util.List; +@Service +@RequiredArgsConstructor +public class ResourceService { + private final ResourceRepository resourceRepository; + private final UpdateRepository updateRepository; + private final SiteConfig siteConfig; -public interface ResourceService { + public Page searchResources(Pageable pageable, Predicate query) throws RestException { + return this.resourceRepository.findAll(query, pageable) + .map(resource -> { + int totalDownloads = this.updateRepository.getTotalDownloads(resource.getId()).orElse(0); + return SimpleResourceDto.create(resource, totalDownloads); + }); + } - String postCreateResource(CreateResourceRequest resourceRequest, Account account, SiteConfig siteConfig, RedirectAttributes redirectAttributes); + //TODO: More sanity checks + public Resource createResource(Account account, CreateResourceRequest request) throws RestException { + if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) + throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_CREATIONS); + if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) + throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); + if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) + throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING); - List searchResources(String search, String sortBy, String page); + Resource resource = new Resource(request.getName(), request.getDescription(), + request.getBlurb(), request.getDonation(), request.getSource(), + account, request.getSupport(), request.getCategory()); - List getResourcesWithCategory(String sort, String page, String category); + return this.resourceRepository.save(resource); + } - List getResources(String sort, String page); + // TODO: More sanity checks + // todo: also this is horrible, can we just use querydsl? + public Resource updateResource(Account account, int resourceId, MultipartFile file, CreateResourceRequest request) throws RestException { + Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + + String name = request.getName(); + if (name != null && !name.isEmpty()) + resource.setName(name); + + String description = request.getDescription(); + if (description != null && !description.isEmpty()) + resource.setDescription(description); + + String blurb = request.getBlurb(); + if (blurb != null && !blurb.isEmpty()) + resource.setBlurb(blurb); + + String category = request.getCategory(); + if (category != null && !category.isEmpty()) + resource.setCategory(category); + + String donation = request.getDonation(); + if (donation != null && !donation.isEmpty()) + resource.setDonation(donation); + + String support = request.getSupport(); + if (support != null && !support.isEmpty()) + resource.setSupport(support); + + String source = request.getSource(); + if (source != null && !source.isEmpty()) + resource.setSource(source); + + if (file != null && !file.isEmpty()) + resource.setLogo(ImageUtil.handleImage(file)); + + return this.resourceRepository.save(resource); + } } diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java b/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java similarity index 96% rename from src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java rename to src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java index 293f46d..7385098 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceUpdateService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java @@ -1,4 +1,4 @@ -package com.imjustdoom.pluginsite.service.rest; +package com.imjustdoom.pluginsite.service; import com.imjustdoom.pluginsite.config.custom.SiteConfig; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; @@ -39,14 +39,14 @@ public void setup() { public Update changeStatus(Account account, int updateId, String status) throws RestException { Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); - if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.FORBIDDEN); update.setStatus(status); return this.updateRepository.save(update); } public Update editUpdate(Account account, int updateId, EditResourceUpdateRequest request) throws RestException { Update update = this.updateRepository.findById(updateId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_UPDATE_NOT_FOUND)); - if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.INVALID_ACCESS); + if (update.getResource().getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.FORBIDDEN); String name = request.getName(); if (name != null && !name.isEmpty()) diff --git a/src/main/java/com/imjustdoom/pluginsite/service/UpdateService.java b/src/main/java/com/imjustdoom/pluginsite/service/UpdateService.java deleted file mode 100644 index f5b9f0f..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/UpdateService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.imjustdoom.pluginsite.service; - -import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; -import com.imjustdoom.pluginsite.dtos.in.CreateUpdateRequest; -import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.model.Update; - -import java.util.List; - -public interface UpdateService { - - Update createUpdate(CreateUpdateRequest updateRequest, Account account); -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/AccountServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/AccountServiceImpl.java deleted file mode 100644 index d7502cc..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/AccountServiceImpl.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.imjustdoom.pluginsite.service.impl; - -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import lombok.AllArgsConstructor; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -public class AccountServiceImpl implements UserDetailsService { - - private final AccountRepository accountRepository; - - @Override - public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { - return accountRepository.findByUsernameEqualsIgnoreCase(s).orElseThrow(() -> new UsernameNotFoundException("User not found")); - } -} \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/LogoServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/LogoServiceImpl.java deleted file mode 100644 index 788084b..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/LogoServiceImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.imjustdoom.pluginsite.service.impl; - -import com.imjustdoom.pluginsite.PluginSiteApplication; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.service.LogoService; -import com.imjustdoom.pluginsite.util.ImageUtil; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.nio.file.Paths; - -@Service -@AllArgsConstructor -public class LogoServiceImpl implements LogoService { - - private final ResourceRepository resourceRepository; - - @Override - public void updateLogo(int id, MultipartFile logo) { - - byte[] image = ImageUtil.handleImage(logo); - - resourceRepository.updateLogoById(id, image); - - //if (image.getHeight() != image.getWidth()) - //return "redirect:/resources/%s/edit?error=logosize".formatted(id); - } - - @Override - public boolean logoExists(int id) { - return Paths.get("resources/logos/%s".formatted(id)).toFile().exists(); - } - - @Override - public byte[] serveDefaultLogo() { - try { - return PluginSiteApplication.class.getResourceAsStream("/pictures/default.png").readAllBytes(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public byte[] serverLogo(int id) { - byte[] image = resourceRepository.findResourceLogo(id); - if(image == null){ - return serveDefaultLogo(); - } - return resourceRepository.findResourceLogo(id); - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/impl/ProfilePictureServiceImpl.java b/src/main/java/com/imjustdoom/pluginsite/service/impl/ProfilePictureServiceImpl.java deleted file mode 100644 index 2c31280..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/impl/ProfilePictureServiceImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.imjustdoom.pluginsite.service.impl; - -import com.imjustdoom.pluginsite.PluginSiteApplication; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.service.ProfilePictureService; -import com.imjustdoom.pluginsite.util.ImageUtil; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.nio.file.Paths; - -@Service -@AllArgsConstructor -public class ProfilePictureServiceImpl implements ProfilePictureService { - - private final AccountRepository accountRepository; - - @Override - public void updateProfilePicture(int id, MultipartFile profilePicture) { - - byte[] image = ImageUtil.handleImage(profilePicture); - - accountRepository.updateProfilePictureById(id, image); - - //if (image.getHeight() != image.getWidth()) - //return "redirect:/resources/%s/edit?error=logosize".formatted(id); - } - - @Override - public boolean logoExists(int id) { - return Paths.get("resources/logos/%s".formatted(id)).toFile().exists(); - } - - @Override - public byte[] serveDefaultProfilePicture() { - try { - return PluginSiteApplication.class.getResourceAsStream("/pictures/default.png").readAllBytes(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public byte[] serverProfilePicture(int id) { - byte[] image = accountRepository.findAccountProfilePicture(id); - if(image == null){ - return serveDefaultProfilePicture(); - } - return accountRepository.findAccountProfilePicture(id); - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java deleted file mode 100644 index c010a73..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/service/rest/ResourceService.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.imjustdoom.pluginsite.service.rest; - -import com.imjustdoom.pluginsite.config.custom.SiteConfig; -import com.imjustdoom.pluginsite.config.exception.RestErrorCode; -import com.imjustdoom.pluginsite.config.exception.RestException; -import com.imjustdoom.pluginsite.dtos.in.CreateResourceRequest; -import com.imjustdoom.pluginsite.dtos.out.SimpleResourceDto; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.repositories.UpdateRepository; -import com.imjustdoom.pluginsite.util.ImageUtil; -import com.querydsl.core.types.Predicate; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -@Service -@RequiredArgsConstructor -public class ResourceService { - private final ResourceRepository resourceRepository; - private final UpdateRepository updateRepository; - private final SiteConfig siteConfig; - - public Page searchResources(Pageable pageable, Predicate query) throws RestException { - return this.resourceRepository.findAll(query, pageable) - .map(resource -> { - int totalDownloads = this.updateRepository.getTotalDownloads(resource.getId()).orElse(0); - return SimpleResourceDto.create(resource, totalDownloads); - }); - } - - //TODO: More sanity checks - public Resource createResource(Account account, CreateResourceRequest request) throws RestException { - if (this.resourceRepository.getResourcesCreateLastHour(account.getId()) > this.siteConfig.getMaxCreationsPerHour()) - throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_CREATIONS); - if (this.resourceRepository.existsByNameEqualsIgnoreCase(request.getName())) - throw new RestException(RestErrorCode.RESOURCE_NAME_NOT_AVAILABLE); - if (request.getName().isEmpty() || request.getBlurb().isEmpty() || request.getDescription().isEmpty()) - throw new RestException(RestErrorCode.REQUIRED_ARGUMENTS_MISSING); - - Resource resource = new Resource(request.getName(), request.getDescription(), - request.getBlurb(), request.getDonation(), request.getSource(), - account, request.getSupport(), request.getCategory()); - - return this.resourceRepository.save(resource); - } - - // TODO: More sanity checks - // todo: also this is horrible, can we just use querydsl? - public Resource updateResource(Account account, int resourceId, MultipartFile file, CreateResourceRequest request) throws RestException { - Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); - - String name = request.getName(); - if (name != null && !name.isEmpty()) - resource.setName(name); - - String description = request.getDescription(); - if (description != null && !description.isEmpty()) - resource.setDescription(description); - - String blurb = request.getBlurb(); - if (blurb != null && !blurb.isEmpty()) - resource.setBlurb(blurb); - - String category = request.getCategory(); - if (category != null && !category.isEmpty()) - resource.setCategory(category); - - String donation = request.getDonation(); - if (donation != null && !donation.isEmpty()) - resource.setDonation(donation); - - String support = request.getSupport(); - if (support != null && !support.isEmpty()) - resource.setSupport(support); - - String source = request.getSource(); - if (source != null && !source.isEmpty()) - resource.setSource(source); - - if (file != null && !file.isEmpty()) - resource.setLogo(ImageUtil.handleImage(file)); - - return this.resourceRepository.save(resource); - } -} From 2ffc028f8a7fc9644c1f14dca2a4dd7238ff96af Mon Sep 17 00:00:00 2001 From: Zak Date: Tue, 15 Feb 2022 03:34:03 +0000 Subject: [PATCH 11/13] Remove dependencies & clean up --- pom.xml | 22 ------------- .../java/com/imjustdoom/pluginsite/Test.java | 28 ---------------- .../security/AuthenticationProvider.java | 23 +++++++++++++ .../config/security/SecurityConfig.java | 33 ++++++------------- .../controller/AccountController.java | 16 ++++----- .../pluginsite/service/MessageService.java | 4 ++- .../pluginsite/util/StringUtil.java | 15 --------- 7 files changed, 44 insertions(+), 97 deletions(-) delete mode 100644 src/main/java/com/imjustdoom/pluginsite/Test.java create mode 100644 src/main/java/com/imjustdoom/pluginsite/config/security/AuthenticationProvider.java delete mode 100644 src/main/java/com/imjustdoom/pluginsite/util/StringUtil.java diff --git a/pom.xml b/pom.xml index cd412c4..5700481 100644 --- a/pom.xml +++ b/pom.xml @@ -29,11 +29,6 @@ spring-boot-starter-security - - org.thymeleaf.extras - thymeleaf-extras-springsecurity5 - - org.springframework.boot spring-boot-starter-data-jpa @@ -80,11 +75,6 @@ test - - org.springframework.boot - spring-boot-starter-thymeleaf - - org.springframework.boot spring-boot-configuration-processor @@ -116,12 +106,6 @@ provided - - org.commonmark - commonmark - 0.18.1 - - com.google.code.gson gson @@ -129,12 +113,6 @@ compile - - me.xdrop - fuzzywuzzy - 1.3.1 - - diff --git a/src/main/java/com/imjustdoom/pluginsite/Test.java b/src/main/java/com/imjustdoom/pluginsite/Test.java deleted file mode 100644 index 2ed5b33..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/Test.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.imjustdoom.pluginsite; - -import com.imjustdoom.pluginsite.config.exception.RestException; -import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; -import com.imjustdoom.pluginsite.model.Account; -import com.imjustdoom.pluginsite.model.Resource; -import com.imjustdoom.pluginsite.repositories.AccountRepository; -import com.imjustdoom.pluginsite.repositories.ResourceRepository; -import com.imjustdoom.pluginsite.service.AccountService; -import org.springframework.stereotype.Component; - -@Component -public class Test { - - public Test(AccountService accountService, AccountRepository accountRepository, ResourceRepository resourceRepository) throws RestException { - if (accountRepository.existsByUsernameEqualsIgnoreCase("test")) - return; - CreateAccountRequest createAccountRequest = new CreateAccountRequest(); - createAccountRequest.setEmail("test@test.com"); - createAccountRequest.setUsername("test"); - createAccountRequest.setPassword("test"); - Account account = accountService.register(createAccountRequest); - - Resource resource = new Resource("test", "test", "", "", "", account, "", "none"); - resourceRepository.save(resource); - accountRepository.save(account); - } -} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/security/AuthenticationProvider.java b/src/main/java/com/imjustdoom/pluginsite/config/security/AuthenticationProvider.java new file mode 100644 index 0000000..2855b85 --- /dev/null +++ b/src/main/java/com/imjustdoom/pluginsite/config/security/AuthenticationProvider.java @@ -0,0 +1,23 @@ +package com.imjustdoom.pluginsite.config.security; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@RequiredArgsConstructor +public class AuthenticationProvider { + private final UserDetailsService userDetailsService; + private final PasswordEncoder passwordEncoder; + + @Bean + public DaoAuthenticationProvider authProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(this.userDetailsService); + authProvider.setPasswordEncoder(this.passwordEncoder); + return authProvider; + } +} diff --git a/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java b/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java index aaeb881..ff26b3f 100644 --- a/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java +++ b/src/main/java/com/imjustdoom/pluginsite/config/security/SecurityConfig.java @@ -1,50 +1,37 @@ package com.imjustdoom.pluginsite.config.security; import lombok.AllArgsConstructor; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @AllArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { - - private final UserDetailsService userDetailsService; - private final PasswordEncoder passwordEncoder; - - @Bean - public DaoAuthenticationProvider authProvider() { - DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); - authProvider.setUserDetailsService(this.userDetailsService); - authProvider.setPasswordEncoder(this.passwordEncoder); - return authProvider; - } + private final DaoAuthenticationProvider authProvider; @Override protected void configure(AuthenticationManagerBuilder auth) { - auth.authenticationProvider(authProvider()); + auth.authenticationProvider(this.authProvider); } @Override public void configure(HttpSecurity http) throws Exception { http - .csrf().disable() + .csrf().disable() - .authorizeRequests() - .antMatchers("/admin", "/admin/roles").hasRole("ADMIN") - .antMatchers("/resources/create", "/account/details").authenticated() - .antMatchers("/signup", "/login").not().authenticated() + .authorizeRequests() + .antMatchers("/admin", "/admin/roles").hasRole("ADMIN") + .antMatchers("/resources/create", "/account/details").authenticated() + .antMatchers("/register", "/login").not().authenticated() - .anyRequest().permitAll() + .anyRequest().permitAll() - .and() - .formLogin().loginPage("/login"); + .and() + .formLogin().loginProcessingUrl("/login"); } } \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java b/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java index 9f53638..882e50b 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/AccountController.java @@ -40,22 +40,22 @@ public String signupSubmit(@RequestBody CreateAccountRequest accountRequest) thr // todo login with JWT - @GetMapping("/account/details") + @GetMapping("/details") public SelfAccountDto getSelfAccountDetails(Account account) { return SelfAccountDto.fromAccount(account); } - @GetMapping("/account/{id}/details") - public AccountDto getAccountDetails(@PathVariable int id) throws RestException { - return AccountDto.fromAccount(this.accountService.getAccount(id)); - } - - @PatchMapping("/account/details") + @PatchMapping("/details") public SelfAccountDto updateAccountDetails(Account account, @RequestBody UpdateAccountRequest request, - @RequestParam("profilePicture") MultipartFile file) throws RestException { + @RequestParam(value = "profilePicture", required = false) MultipartFile file) throws RestException { return SelfAccountDto.fromAccount(this.accountService.updateAccountDetails(account, request, file)); } + @GetMapping("/{id}/details") + public AccountDto getAccountDetails(@PathVariable int id) throws RestException { + return AccountDto.fromAccount(this.accountService.getAccount(id)); + } + @GetMapping("/groups") public Page getMessageGroups(Account account, @PageableDefault(size = 25) Pageable pageable) throws RestException { diff --git a/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java b/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java index 96dc603..50c5fc6 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/MessageService.java @@ -11,6 +11,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; @@ -26,13 +27,14 @@ public class MessageService { private final MessageRepository messageRepository; private final MessageGroupRepository messageGroupRepository; private final AccountRepository accountRepository; + private final PasswordEncoder passwordEncoder; private Account systemAccount; @PostConstruct public void setup() { this.systemAccount = this.accountRepository.findByUsernameEqualsIgnoreCase("system").orElseGet(() -> { - Account account = new Account("system", "system@example.com", UUID.randomUUID().toString()); + Account account = new Account("system", "system@example.com", this.passwordEncoder.encode(UUID.randomUUID().toString())); // todo in the future, let's just lock the account return this.accountRepository.save(account); }); } diff --git a/src/main/java/com/imjustdoom/pluginsite/util/StringUtil.java b/src/main/java/com/imjustdoom/pluginsite/util/StringUtil.java deleted file mode 100644 index 4462d8a..0000000 --- a/src/main/java/com/imjustdoom/pluginsite/util/StringUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.imjustdoom.pluginsite.util; - -import org.commonmark.node.Node; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; - -public class StringUtil { - - public static String markdownToHtml(String markdown) { - Parser parser = Parser.builder().build(); - Node document = parser.parse(markdown); - HtmlRenderer renderer = HtmlRenderer.builder().build(); - return renderer.render(document); - } -} From 08bab1d423507d88a8b568ff42453b9802188efd Mon Sep 17 00:00:00 2001 From: Zak Date: Tue, 15 Feb 2022 03:45:42 +0000 Subject: [PATCH 12/13] Rename profile_picture, verify file size --- .../pluginsite/dtos/out/account/AccountDto.java | 2 +- .../pluginsite/dtos/out/account/SelfAccountDto.java | 2 +- .../java/com/imjustdoom/pluginsite/model/Account.java | 9 ++++----- .../pluginsite/repositories/AccountRepository.java | 6 +++--- .../imjustdoom/pluginsite/service/AccountService.java | 9 ++++++--- .../imjustdoom/pluginsite/service/ResourceService.java | 7 ++++++- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java index 4b6df82..4fd2f86 100644 --- a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/AccountDto.java @@ -9,6 +9,6 @@ public record AccountDto(int id, String username, public static AccountDto fromAccount(Account account) { return new AccountDto(account.getId(), account.getUsername(), - account.getProfile_picture(), account.getJoined()); + account.getProfilePicture(), account.getJoined()); } } diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java index e2087ba..93725e2 100644 --- a/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/out/account/SelfAccountDto.java @@ -10,7 +10,7 @@ public record SelfAccountDto(int id, String username, public static SelfAccountDto fromAccount(Account account) { return new SelfAccountDto(account.getId(), account.getUsername(), - account.getEmail(), account.getProfile_picture(), + account.getEmail(), account.getProfilePicture(), account.getJoined()); } } diff --git a/src/main/java/com/imjustdoom/pluginsite/model/Account.java b/src/main/java/com/imjustdoom/pluginsite/model/Account.java index 96a8bc4..d0be555 100644 --- a/src/main/java/com/imjustdoom/pluginsite/model/Account.java +++ b/src/main/java/com/imjustdoom/pluginsite/model/Account.java @@ -1,6 +1,7 @@ package com.imjustdoom.pluginsite.model; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -15,6 +16,7 @@ @Setter @Getter @Entity +@NoArgsConstructor public class Account implements UserDetails { public Account(String username, String email, String password) { @@ -56,15 +58,12 @@ public Account(String username, String email, String password) { private List groups; @Lob - private byte[] profile_picture; + @Column(name = "profile_picture") + private byte[] profilePicture; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "author") private List messages = new ArrayList<>(); - public Account() { - - } - @Override public Collection getAuthorities() { List list = new ArrayList<>(); diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/AccountRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/AccountRepository.java index fa870ef..bc5143d 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/AccountRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/AccountRepository.java @@ -42,9 +42,9 @@ public interface AccountRepository extends JpaRepository { @Modifying @Transactional - @Query("UPDATE Account account SET account.profile_picture = ?2 WHERE account.id = ?1") - void updateProfilePictureById(int id, byte[] profile_picture); + @Query("UPDATE Account account SET account.profilePicture = ?2 WHERE account.id = ?1") + void updateProfilePictureById(int id, byte[] profilePicture); - @Query("SELECT profile_picture FROM Account WHERE id = ?1") + @Query("SELECT profilePicture FROM Account WHERE id = ?1") byte[] findAccountProfilePicture(int id); } \ No newline at end of file diff --git a/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java b/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java index dc30bf7..895c965 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/AccountService.java @@ -1,5 +1,6 @@ package com.imjustdoom.pluginsite.service; +import com.imjustdoom.pluginsite.config.custom.SiteConfig; import com.imjustdoom.pluginsite.config.exception.RestErrorCode; import com.imjustdoom.pluginsite.config.exception.RestException; import com.imjustdoom.pluginsite.dtos.in.account.CreateAccountRequest; @@ -22,6 +23,8 @@ public class AccountService implements UserDetailsService { private final AccountRepository accountRepository; private final PasswordEncoder passwordEncoder; + private final SiteConfig siteConfig; + @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { return accountRepository.findByUsernameEqualsIgnoreCase(s).orElseThrow(() -> new UsernameNotFoundException("User not found")); @@ -50,10 +53,10 @@ public Account getAccount(int id) throws RestException { // todo will there be concurrency issues with performing this all in one update? public Account updateAccountDetails(Account account, UpdateAccountRequest request, MultipartFile file) throws RestException { if (file != null) { - if (!file.getContentType().contains("image")) throw new RestException(RestErrorCode.WRONG_FILE_TYPE); - if (file.getSize() > 1024000) throw new RestException(RestErrorCode.FILE_TOO_LARGE); + if (file.getContentType() == null || !file.getContentType().contains("image")) throw new RestException(RestErrorCode.WRONG_FILE_TYPE); + if (file.getSize() > this.siteConfig.getMaxUploadSize().toBytes()) throw new RestException(RestErrorCode.FILE_TOO_LARGE); - account.setProfile_picture(ImageUtil.handleImage(file)); + account.setProfilePicture(ImageUtil.handleImage(file)); } if (request.getEmail() != null) { String email = request.getEmail(); diff --git a/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java b/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java index 1e6b1e4..5eed884 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ResourceService.java @@ -52,6 +52,7 @@ public Resource createResource(Account account, CreateResourceRequest request) t // todo: also this is horrible, can we just use querydsl? public Resource updateResource(Account account, int resourceId, MultipartFile file, CreateResourceRequest request) throws RestException { Resource resource = this.resourceRepository.findById(resourceId).orElseThrow(() -> new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); + if (resource.getAuthor().getId() != account.getId()) throw new RestException(RestErrorCode.FORBIDDEN); String name = request.getName(); if (name != null && !name.isEmpty()) @@ -81,8 +82,12 @@ public Resource updateResource(Account account, int resourceId, MultipartFile fi if (source != null && !source.isEmpty()) resource.setSource(source); - if (file != null && !file.isEmpty()) + if (file != null && !file.isEmpty()) { + if (file.getSize() > this.siteConfig.getMaxUploadSize().toBytes()) throw new RestException(RestErrorCode.FILE_TOO_LARGE); + if (file.getContentType() == null || !file.getContentType().contains("image")) throw new RestException(RestErrorCode.WRONG_FILE_TYPE); + resource.setLogo(ImageUtil.handleImage(file)); + } return this.resourceRepository.save(resource); } From 6b17ea0bc8bb621a079a7fea5213b80c012d8dc1 Mon Sep 17 00:00:00 2001 From: Zak Date: Tue, 15 Feb 2022 03:55:16 +0000 Subject: [PATCH 13/13] Resolve some todos --- .../pluginsite/controller/ReportController.java | 1 - .../pluginsite/controller/ResourceUpdateController.java | 9 +++------ .../pluginsite/dtos/in/CreateUpdateRequest.java | 4 ++++ .../pluginsite/repositories/UpdateRepository.java | 4 ---- .../pluginsite/service/ResourceUpdateService.java | 7 +++---- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java index 9a27b43..0e27017 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ReportController.java @@ -15,7 +15,6 @@ public class ReportController { private final ReportService reportService; - // todo should a DTO be returned instead of the raw Report here? @PostMapping public void createReport(Account account, @RequestBody CreateReportRequest request) { this.reportService.createReport(account, request); diff --git a/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java index 50e7993..385bfcd 100644 --- a/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java +++ b/src/main/java/com/imjustdoom/pluginsite/controller/ResourceUpdateController.java @@ -22,7 +22,6 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; -import java.util.List; @RestController @RequestMapping("/resource/update") @@ -41,11 +40,9 @@ public Update editUpdate(Account account, @PathVariable int updateId, @RequestBo } @PostMapping("/") - public void createUpdate(Account account, @RequestParam List softwareCheckbox, - @RequestParam List versionCheckbox, - @RequestParam int resourceId, @RequestParam MultipartFile file, - @RequestBody CreateUpdateRequest updateRequest) throws RestException { - this.resourceUpdateService.createUpdate(account, softwareCheckbox, versionCheckbox, resourceId, file, updateRequest); // todo should the variables like softwareCheckbox be inside the create request? + public void createUpdate(Account account, @RequestParam int resourceId, + @RequestParam MultipartFile file, @RequestBody CreateUpdateRequest updateRequest) throws RestException { + this.resourceUpdateService.createUpdate(account, resourceId, file, updateRequest); } @GetMapping(value = "/{updateId}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) diff --git a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java b/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java index 6980d4d..9d67e68 100644 --- a/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java +++ b/src/main/java/com/imjustdoom/pluginsite/dtos/in/CreateUpdateRequest.java @@ -4,6 +4,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + @Setter @Getter @NoArgsConstructor @@ -13,6 +15,8 @@ public class CreateUpdateRequest { private String version; private String externalLink; private String description; + private List versions; + private List software; public boolean isMissingRequirements() { return this.name == null || this.name.isEmpty() diff --git a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java index 3ffb217..0e7e7ce 100644 --- a/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java +++ b/src/main/java/com/imjustdoom/pluginsite/repositories/UpdateRepository.java @@ -18,10 +18,6 @@ public interface UpdateRepository extends JpaRepository { List findAllByResourceIdAndStatusEquals(int resourceId, String status, Sort sort); - // TODO: get this to actually work at some point - @Query("SELECT updates FROM Update updates WHERE ?3 in(updates.software)") - List findAllByResourceIdAndStatusEqualsAndSoftware(int resourceId, String status, String software, Sort sort); - @Modifying @Transactional @Query("UPDATE Update updates SET updates.downloads = updates.downloads + 1 WHERE updates.id = ?1") diff --git a/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java b/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java index 7385098..69846fb 100644 --- a/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java +++ b/src/main/java/com/imjustdoom/pluginsite/service/ResourceUpdateService.java @@ -20,7 +20,6 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; @Service @RequiredArgsConstructor @@ -63,7 +62,7 @@ public Update editUpdate(Account account, int updateId, EditResourceUpdateReques return this.updateRepository.save(update); } - public void createUpdate(Account account, List softwareCheckbox, List versionCheckbox, int resourceId, + public void createUpdate(Account account, int resourceId, MultipartFile file, CreateUpdateRequest request) throws RestException { if (this.updateRepository.getUpdatesCreateLastHour(account.getId()) > this.siteConfig.getMaxUpdatesPerHour()) throw new RestException(RestErrorCode.TOO_MANY_RESOURCE_UPDATES); @@ -75,9 +74,9 @@ public void createUpdate(Account account, List softwareCheckbox, List new RestException(RestErrorCode.RESOURCE_NOT_FOUND)); Update update; if (file.isEmpty()) { - update = new Update(request.getDescription(), null, request.getVersion(), request.getExternalLink(), request.getName(), versionCheckbox, softwareCheckbox, resource); + update = new Update(request.getDescription(), null, request.getVersion(), request.getExternalLink(), request.getName(), request.getVersions(), request.getSoftware(), resource); } else { - update = new Update(request.getDescription(), file.getOriginalFilename(), request.getVersion(), null, request.getName(), versionCheckbox, softwareCheckbox, resource); + update = new Update(request.getDescription(), file.getOriginalFilename(), request.getVersion(), null, request.getName(), request.getVersions(), request.getSoftware(), resource); Path resourcePath = BASE_PATH.resolve(update.getId() + ".jar"); try (InputStream inputStream = file.getInputStream()) { Files.copy(inputStream, resourcePath);