From 35d25bbc9d261e7b5585d0fd1d398dff3ab4a176 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 13 Jan 2023 17:38:06 +0300 Subject: Fix OpenAPI generation * Use HandlerMethodArgumentResolver to pass visitor * Hide visitor from OpenAPI definitions * Drop unused AsciiDoc template --- src/docs/index.adoc | 3 -- src/main/java/com/juick/config/OpenAPIConfig.java | 29 +++++++++++ src/main/java/com/juick/config/SecurityConfig.java | 1 + src/main/java/com/juick/config/WebConfig.java | 15 +++++- .../java/com/juick/www/SiteAttributesHandler.java | 15 ------ .../com/juick/www/VisitorArgumentResolver.java | 59 ++++++++++++++++++++++ src/main/java/com/juick/www/ad/SapeService.java | 3 +- src/main/java/com/juick/www/api/Index.java | 2 +- src/main/java/com/juick/www/api/Mastodon.java | 11 ++-- src/main/java/com/juick/www/api/Messages.java | 13 ++--- src/main/java/com/juick/www/api/Notifications.java | 13 ++--- src/main/java/com/juick/www/api/PM.java | 7 +-- src/main/java/com/juick/www/api/Post.java | 13 ++--- src/main/java/com/juick/www/api/Service.java | 7 +-- src/main/java/com/juick/www/api/Tags.java | 3 +- src/main/java/com/juick/www/api/Users.java | 17 ++++--- .../java/com/juick/www/api/activity/Profile.java | 7 +-- src/main/java/com/juick/www/controllers/Help.java | 3 +- .../java/com/juick/www/controllers/Settings.java | 7 +-- .../java/com/juick/www/controllers/SignUp.java | 5 +- src/main/java/com/juick/www/controllers/Site.java | 27 +++++----- .../com/juick/www/controllers/SocialLogin.java | 2 +- src/main/java/com/juick/www/rss/Feeds.java | 6 ++- 23 files changed, 184 insertions(+), 84 deletions(-) delete mode 100644 src/docs/index.adoc create mode 100644 src/main/java/com/juick/config/OpenAPIConfig.java create mode 100644 src/main/java/com/juick/www/VisitorArgumentResolver.java diff --git a/src/docs/index.adoc b/src/docs/index.adoc deleted file mode 100644 index 4d492510..00000000 --- a/src/docs/index.adoc +++ /dev/null @@ -1,3 +0,0 @@ -include::{src}/overview.adoc[] -include::{src}/paths.adoc[] -include::{src}/definitions.adoc[] \ No newline at end of file diff --git a/src/main/java/com/juick/config/OpenAPIConfig.java b/src/main/java/com/juick/config/OpenAPIConfig.java new file mode 100644 index 00000000..860565b3 --- /dev/null +++ b/src/main/java/com/juick/config/OpenAPIConfig.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2008-2023, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.juick.config; + +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import org.springframework.context.annotation.Configuration; + +@Configuration +@SecurityScheme(name = "basicAuth", + type = SecuritySchemeType.HTTP, + scheme = "basic") +public class OpenAPIConfig { +} diff --git a/src/main/java/com/juick/config/SecurityConfig.java b/src/main/java/com/juick/config/SecurityConfig.java index d8faff7b..cb448cf3 100644 --- a/src/main/java/com/juick/config/SecurityConfig.java +++ b/src/main/java/com/juick/config/SecurityConfig.java @@ -189,6 +189,7 @@ public class SecurityConfig { .authorizeHttpRequests(requests -> requests .requestMatchers(HttpMethod.OPTIONS).permitAll() .requestMatchers("/api/", "/api/messages", "/api/avatar", + "/v3/api-docs", "/api/swagger-ui/**", "/api/messages/discussions", "/api/users", "/api/thread", "/api/tags", diff --git a/src/main/java/com/juick/config/WebConfig.java b/src/main/java/com/juick/config/WebConfig.java index d736b863..136faea9 100644 --- a/src/main/java/com/juick/config/WebConfig.java +++ b/src/main/java/com/juick/config/WebConfig.java @@ -24,14 +24,18 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; +import com.juick.service.UserService; +import com.juick.www.VisitorArgumentResolver; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.format.FormatterRegistry; import org.springframework.http.CacheControl; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.VersionResourceResolver; @@ -45,6 +49,8 @@ public class WebConfig implements WebMvcConfigurer { private String baseDir; @Inject private List> converters; + @Inject + private UserService userService; @Override public void addFormatters(FormatterRegistry registry) { @@ -52,7 +58,14 @@ public class WebConfig implements WebMvcConfigurer { registry.addConverter(converter); } } - + @Bean + HandlerMethodArgumentResolver visitorArgumentResolver() { + return new VisitorArgumentResolver(userService); + } + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(visitorArgumentResolver()); + } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { try { diff --git a/src/main/java/com/juick/www/SiteAttributesHandler.java b/src/main/java/com/juick/www/SiteAttributesHandler.java index 4ead9d1e..0e1ca1db 100644 --- a/src/main/java/com/juick/www/SiteAttributesHandler.java +++ b/src/main/java/com/juick/www/SiteAttributesHandler.java @@ -36,8 +36,6 @@ import javax.inject.Inject; @ControllerAdvice public class SiteAttributesHandler { - @Inject - private UserService userService; @ModelAttribute public void setVaryResponseHeader(HttpServletResponse response) { response.setHeader("Vary", "Accept-Language"); @@ -46,17 +44,4 @@ public class SiteAttributesHandler { public void setReturnPathAttribute(Model model) { model.addAttribute("retpath", ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString()); } - @ModelAttribute - public User visitor(Model model, @AuthenticationPrincipal Object principal) { - if (principal != null) { - if (principal instanceof JuickUser) { - return ((JuickUser) principal).getUser(); - } - if (principal instanceof Jwt) { - var uname = (String) ((Jwt) principal).getClaims().get("sub"); - return userService.getUserByName(uname); - } - } - return AnonymousUser.INSTANCE; - } } diff --git a/src/main/java/com/juick/www/VisitorArgumentResolver.java b/src/main/java/com/juick/www/VisitorArgumentResolver.java new file mode 100644 index 00000000..a092581a --- /dev/null +++ b/src/main/java/com/juick/www/VisitorArgumentResolver.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2023, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.juick.www; + +import com.juick.model.AnonymousUser; +import com.juick.model.User; +import com.juick.service.UserService; +import com.juick.service.security.entities.JuickUser; +import org.springframework.core.MethodParameter; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.inject.Inject; + +public class VisitorArgumentResolver implements HandlerMethodArgumentResolver { + private final UserService userService; + public VisitorArgumentResolver(UserService userService) { + this.userService = userService; + } + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().equals(User.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + if (principal != null) { + if (principal instanceof JuickUser) { + return ((JuickUser) principal).getUser(); + } + if (principal instanceof Jwt) { + var uname = (String) ((Jwt) principal).getClaims().get("sub"); + return userService.getUserByName(uname); + } + } + return AnonymousUser.INSTANCE; + } +} diff --git a/src/main/java/com/juick/www/ad/SapeService.java b/src/main/java/com/juick/www/ad/SapeService.java index 7b398806..97ab882b 100644 --- a/src/main/java/com/juick/www/ad/SapeService.java +++ b/src/main/java/com/juick/www/ad/SapeService.java @@ -19,6 +19,7 @@ package com.juick.www.ad; import com.juick.model.User; import com.juick.www.controllers.Site; +import io.swagger.v3.oas.annotations.Parameter; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.ui.ModelMap; @@ -46,7 +47,7 @@ public class SapeService { @ModelAttribute public void addSapeLinks( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, @RequestParam(required = false, defaultValue = "0") int before, @RequestParam(name = "show", required = false) String paramShow, diff --git a/src/main/java/com/juick/www/api/Index.java b/src/main/java/com/juick/www/api/Index.java index 46aa65b5..921ebca4 100644 --- a/src/main/java/com/juick/www/api/Index.java +++ b/src/main/java/com/juick/www/api/Index.java @@ -45,7 +45,7 @@ public class Index { @Hidden @RequestMapping(value = { "/api/", "/ws/" }, method = RequestMethod.GET) public ResponseEntity description() { - URI redirectUri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/swagger-ui.html").build().toUri(); + URI redirectUri = ServletUriComponentsBuilder.fromCurrentRequestUri().replacePath("/api/swagger-ui/index.html").build().toUri(); return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).location(redirectUri).build(); } diff --git a/src/main/java/com/juick/www/api/Mastodon.java b/src/main/java/com/juick/www/api/Mastodon.java index 5982209e..c595bb19 100644 --- a/src/main/java/com/juick/www/api/Mastodon.java +++ b/src/main/java/com/juick/www/api/Mastodon.java @@ -33,6 +33,7 @@ import com.juick.util.HttpBadRequestException; import com.juick.util.MessageUtils; import com.juick.www.WebApp; import com.juick.www.api.activity.helpers.ProfileUriBuilder; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.validation.Valid; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; @@ -166,7 +167,7 @@ public class Mastodon { } @GetMapping("/api/v1/accounts/verify_credentials") - public CredentialAccount account(@ModelAttribute User visitor) { + public CredentialAccount account(@Parameter(hidden = true) User visitor) { return toAccount(visitor); } @@ -220,7 +221,7 @@ public class Mastodon { } @GetMapping("/api/v1/accounts/relationships") - public List relationships(@ModelAttribute User visitor, @RequestParam(value = "id[]") String[] ids) { + public List relationships(@Parameter(hidden = true) User visitor, @RequestParam(value = "id[]") String[] ids) { return Stream.of(ids).map( id -> findRelationships(String.valueOf(visitor.getUid()), id) ).collect(Collectors.toList()); @@ -283,7 +284,7 @@ public class Mastodon { } @GetMapping("/api/v1/conversations") - public List conversations(@ModelAttribute User visitor) { + public List conversations(@Parameter(hidden = true) User visitor) { return chatService.getLastChats(visitor).stream().map( this::toConversation ).collect(Collectors.toList()); @@ -313,7 +314,7 @@ public class Mastodon { } @GetMapping("/api/v1/timelines/{timeline}") - public List publicTimeline(@ModelAttribute User visitor, + public List publicTimeline(@Parameter(hidden = true) User visitor, @PathVariable String timeline, @RequestParam(value = "max_id", required = false) String maxId, @RequestParam(value = "only_media", required = false, defaultValue = "false") Boolean media) { @@ -349,7 +350,7 @@ public class Mastodon { } @GetMapping("/api/v1/statuses/{mid}-{rid}/context") - public Context thread(@ModelAttribute User visitor, @PathVariable int mid, @PathVariable int rid) { + public Context thread(@Parameter(hidden = true) User visitor, @PathVariable int mid, @PathVariable int rid) { var thread = messagesService.getReplies(visitor, mid).stream() .filter(m -> m.getRid() > rid) .peek(msg -> msg.getUser().setAvatar(webApp.getAvatarUrl(msg.getUser()))) diff --git a/src/main/java/com/juick/www/api/Messages.java b/src/main/java/com/juick/www/api/Messages.java index e23356a4..fb10d7a7 100644 --- a/src/main/java/com/juick/www/api/Messages.java +++ b/src/main/java/com/juick/www/api/Messages.java @@ -30,6 +30,7 @@ import com.juick.service.MessagesService; import com.juick.service.TagService; import com.juick.service.UserService; import com.juick.service.component.SystemEvent; +import io.swagger.v3.oas.annotations.Parameter; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; @@ -68,7 +69,7 @@ public class Messages { // TODO: serialize image urls @GetMapping({"/api/home"}) - public List getHome(@ModelAttribute User visitor, + public List getHome(@Parameter(hidden = true) User visitor, @RequestParam(defaultValue = "0") int before_mid) { int vuid = visitor.getUid(); List mids = messagesService.getMyFeed(vuid, before_mid, true); @@ -78,7 +79,7 @@ public class Messages { } @GetMapping("/api/messages") - public List getMessages(@ModelAttribute User visitor, + public List getMessages(@Parameter(hidden = true) User visitor, @RequestParam(required = false) String uname, @RequestParam(name = "before_mid", defaultValue = "0") Integer before, @RequestParam(required = false, defaultValue = "0") Integer daysback, @@ -136,7 +137,7 @@ public class Messages { } @DeleteMapping("/api/messages") - public CommandResult deleteMessage(@ModelAttribute User visitor, @RequestParam int mid, + public CommandResult deleteMessage(@Parameter(hidden = true) User visitor, @RequestParam int mid, @RequestParam(required = false, defaultValue = "0") int rid) { if (rid > 0) { if (messagesService.deleteReply(visitor.getUid(), mid, rid)) { @@ -150,7 +151,7 @@ public class Messages { } @GetMapping("/api/messages/discussions") - public List getDiscussions(@ModelAttribute User visitor, + public List getDiscussions(@Parameter(hidden = true) User visitor, @RequestParam(required = false, defaultValue = "0") Long to) { List msgs = messagesService.getMessages(visitor, messagesService.getDiscussions(visitor.getUid(), to)); msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); @@ -158,7 +159,7 @@ public class Messages { } @GetMapping("/api/thread") - public List getThread(@ModelAttribute User visitor, @RequestParam(defaultValue = "0") int mid, + public List getThread(@Parameter(hidden = true) User visitor, @RequestParam(defaultValue = "0") int mid, @RequestParam(defaultValue = "true") boolean showReplies) { Optional message = messagesService.getMessage(mid); if (message.isPresent()) { @@ -188,7 +189,7 @@ public class Messages { } @GetMapping(value = "/api/thread/mark_read/{mid}-{rid}.gif", produces = MediaType.IMAGE_GIF_VALUE) - public byte[] markThreadRead(@ModelAttribute User visitor, @PathVariable int mid, @PathVariable int rid) + public byte[] markThreadRead(@Parameter(hidden = true) User visitor, @PathVariable int mid, @PathVariable int rid) throws IOException { if (!visitor.isAnonymous()) { messagesService.setLastReadComment(visitor, mid, rid); diff --git a/src/main/java/com/juick/www/api/Notifications.java b/src/main/java/com/juick/www/api/Notifications.java index 32ba3dc1..e5e85eb7 100644 --- a/src/main/java/com/juick/www/api/Notifications.java +++ b/src/main/java/com/juick/www/api/Notifications.java @@ -22,6 +22,7 @@ import com.juick.service.*; import com.juick.util.HttpBadRequestException; import com.juick.util.HttpForbiddenException; import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Parameter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; @@ -71,7 +72,7 @@ public class Notifications { @Hidden @RequestMapping(value = "/api/notifications", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List doGet( - @ModelAttribute(binding = false) User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(required = false, defaultValue = "0") int uid, @RequestParam(required = false, defaultValue = "0") int mid, @RequestParam(required = false, defaultValue = "0") int rid) { @@ -110,7 +111,7 @@ public class Notifications { @Hidden @RequestMapping(value = "/api/notifications", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE) public Status doDelete( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestBody List list) { if (!visitor.equals(serviceUser)) { throw new HttpForbiddenException(); @@ -129,7 +130,7 @@ public class Notifications { @Hidden @RequestMapping(value = "/api/notifications/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public Status doDeleteTokens( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestBody List list) { if (!visitor.equals(serviceUser)) { throw new HttpForbiddenException(); @@ -149,7 +150,7 @@ public class Notifications { @Hidden @RequestMapping(value = "/api/notifications", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE) public Status doPut( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestBody List list) { list.forEach(t -> { switch (t.type()) { @@ -165,7 +166,7 @@ public class Notifications { @Deprecated @RequestMapping(value = "/api/android/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Status doAndroidRegister( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(name = "regid") String regId) { pushQueriesService.addGCMToken(visitor.getUid(), regId); return Status.OK; @@ -174,7 +175,7 @@ public class Notifications { @Deprecated @RequestMapping(value = "/api/winphone/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Status doWinphoneRegister( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(name = "url") String regId) { pushQueriesService.addMPNSToken(visitor.getUid(), regId); return Status.OK; diff --git a/src/main/java/com/juick/www/api/PM.java b/src/main/java/com/juick/www/api/PM.java index c4acd4b3..5f0988c1 100644 --- a/src/main/java/com/juick/www/api/PM.java +++ b/src/main/java/com/juick/www/api/PM.java @@ -29,6 +29,7 @@ import com.juick.www.WebApp; import com.juick.service.ChatService; import com.juick.service.UserService; import com.juick.service.component.SystemEvent; +import io.swagger.v3.oas.annotations.Parameter; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @@ -53,7 +54,7 @@ public class PM { @RequestMapping(value = "/api/pm", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List doGetPM( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(required = false) String uname) { int uid = 0; if (uname != null && uname.matches("^[a-zA-Z0-9\\-]{2,16}$")) { @@ -71,7 +72,7 @@ public class PM { @RequestMapping(value = "/api/pm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public Message doPostPM( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam String uname, @RequestParam String body) { User userTo = AnonymousUser.INSTANCE; @@ -103,7 +104,7 @@ public class PM { } @RequestMapping(value = "/api/groups_pms", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public PrivateChats doGetGroupsPMs( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(defaultValue = "5") int cnt) { // TODO: ignore cnt param for now but make sure paging param will not be cnt diff --git a/src/main/java/com/juick/www/api/Post.java b/src/main/java/com/juick/www/api/Post.java index 2dba6e07..97311c21 100644 --- a/src/main/java/com/juick/www/api/Post.java +++ b/src/main/java/com/juick/www/api/Post.java @@ -25,6 +25,7 @@ import java.util.Optional; import javax.inject.Inject; import com.juick.www.api.activity.helpers.ProfileUriBuilder; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.validation.constraints.NotNull; import com.juick.CommandsManager; @@ -74,7 +75,7 @@ public class Post { @RequestMapping(value = "/api/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(value = HttpStatus.OK) public CommandResult doPostMessage( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, @RequestParam(required = false) String img, @RequestParam(required = false) MultipartFile attach) throws Exception { @@ -105,7 +106,7 @@ public class Post { @RequestMapping(value = "/api/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public CommandResult doPostComment( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(defaultValue = "0") int mid, @RequestParam(defaultValue = "0") int rid, @RequestParam(required = false, defaultValue = StringUtils.EMPTY) final String body, @@ -157,7 +158,7 @@ public class Post { @PostMapping("/api/like") @ResponseStatus(value = HttpStatus.OK) - public Status doPostRecommendation(@ModelAttribute User visitor, @RequestParam Integer mid) throws Exception { + public Status doPostRecommendation(@Parameter(hidden = true) User visitor, @RequestParam Integer mid) throws Exception { Optional message = messagesService.getMessage(mid); if (message.isEmpty()) { throw new HttpNotFoundException(); @@ -173,7 +174,7 @@ public class Post { @PostMapping("/api/subscribe") @ResponseStatus(value = HttpStatus.OK) - public Status doPostSubscribe(@ModelAttribute User visitor, + public Status doPostSubscribe(@Parameter(hidden = true) User visitor, @RequestParam Integer mid) throws Exception { Optional message = messagesService.getMessage(mid); if (message.isEmpty()) { @@ -197,7 +198,7 @@ public class Post { @PostMapping("/api/react") @ResponseStatus(value = HttpStatus.OK) public Status doPostReact( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam Integer mid, @RequestParam @NotNull int reactionId, @RequestParam(required = false, defaultValue = "1") int count) { @@ -219,7 +220,7 @@ public class Post { } @PostMapping("/api/update") - public CommandResult updateMessage(@ModelAttribute User visitor, + public CommandResult updateMessage(@Parameter(hidden = true) User visitor, @RequestParam Integer mid, @RequestParam(required = false, defaultValue = "0") Integer rid, @RequestParam String body) { diff --git a/src/main/java/com/juick/www/api/Service.java b/src/main/java/com/juick/www/api/Service.java index f4599a56..1e3dcdc8 100644 --- a/src/main/java/com/juick/www/api/Service.java +++ b/src/main/java/com/juick/www/api/Service.java @@ -31,6 +31,7 @@ import com.juick.service.StorageService; import com.juick.service.UserService; import com.juick.service.component.AccountVerificationEvent; import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.mail.Session; import jakarta.mail.internet.AddressException; import jakarta.mail.internet.InternetAddress; @@ -88,7 +89,7 @@ public class Service { @Hidden @PostMapping("/api/mail") @ResponseStatus(value = HttpStatus.OK) - public void processMail(@ModelAttribute User current, InputStream data) throws Exception { + public void processMail(@Parameter(hidden = true) User current, InputStream data) throws Exception { if (current.equals(serviceUser)) { MimeMessage msg = new MimeMessage(session, data); String[] returnPaths = msg.getHeader("Return-Path"); @@ -203,7 +204,7 @@ public class Service { @Hidden @PostMapping("/api/mail/unsubscribe") @ResponseStatus(value = HttpStatus.OK) - public void processMailUnsubscribe(@ModelAttribute User current, InputStream data) throws Exception { + public void processMailUnsubscribe(@Parameter(hidden = true) User current, InputStream data) throws Exception { if (current.equals(serviceUser)) { MimeMessage msg = new MimeMessage(session, data); String from = msg.getFrom() == null || msg.getFrom().length > 1 @@ -227,7 +228,7 @@ public class Service { } @GetMapping("/api/events") - public SseEmitter handle(@ModelAttribute User visitor) { + public SseEmitter handle(@Parameter(hidden = true) User visitor) { logger.info("{} connected", visitor.getName()); if (!visitor.isAnonymous()) { userService.updateLastSeen(visitor); diff --git a/src/main/java/com/juick/www/api/Tags.java b/src/main/java/com/juick/www/api/Tags.java index 2b6405ac..5bb25af6 100644 --- a/src/main/java/com/juick/www/api/Tags.java +++ b/src/main/java/com/juick/www/api/Tags.java @@ -20,6 +20,7 @@ package com.juick.www.api; import com.juick.model.User; import com.juick.model.TagStats; import com.juick.service.TagService; +import io.swagger.v3.oas.annotations.Parameter; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @@ -36,7 +37,7 @@ public class Tags { @RequestMapping(value = "/api/tags", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List tags( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(required = false, defaultValue = "0") int user_id ) { if (user_id > 0) { diff --git a/src/main/java/com/juick/www/api/Users.java b/src/main/java/com/juick/www/api/Users.java index 124632d0..afca7ee3 100644 --- a/src/main/java/com/juick/www/api/Users.java +++ b/src/main/java/com/juick/www/api/Users.java @@ -42,6 +42,7 @@ import com.juick.util.HttpUtils; import com.juick.util.WebUtils; import com.juick.www.WebApp; +import io.swagger.v3.oas.annotations.Parameter; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; @@ -74,7 +75,7 @@ public class Users { @RequestMapping(value = "/api/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List doGetUsers( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(value = "uname", required = false) List unames) { List users = new ArrayList<>(); @@ -96,7 +97,7 @@ public class Users { } @GetMapping("/api/me") - public SecureUser getMe(@ModelAttribute User visitor) { + public SecureUser getMe(@Parameter(hidden = true) User visitor) { SecureUser me = new SecureUser(); me.setUid(visitor.getUid()); me.setName(visitor.getName()); @@ -115,7 +116,7 @@ public class Users { return (SecureUser)userService.getUserInfo(me); } @PostMapping("/api/me") - public void updateMe(@ModelAttribute User visitor, + public void updateMe(@Parameter(hidden = true) User visitor, @RequestParam(required = false) String password, @RequestParam(value = "jid-del", required = false) String jidForDeletion, @RequestParam(value = "email-add", required = false) String newEmail, @@ -159,12 +160,12 @@ public class Users { } } @PostMapping("/api/me/subscribe") - public void subscribeMe(@ModelAttribute User visitor, String email) { + public void subscribeMe(@Parameter(hidden = true) User visitor, String email) { // TODO: check status emailService.setNotificationsEmail(visitor.getUid(), email); } @PostMapping("/api/me/upload") - public void updateInfo(@ModelAttribute User visitor, + public void updateInfo(@Parameter(hidden = true) User visitor, @RequestParam MultipartFile avatar) throws IOException { String avatarTmpPath = HttpUtils.receiveMultiPartFile(avatar, storageService.getTemporaryDirectory()).getHost(); if (StringUtils.isNotEmpty(avatarTmpPath)) { @@ -175,7 +176,7 @@ public class Users { @RequestMapping(value = "/api/users/read", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List doGetUserRead( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam String uname) { int uid = 0; if (uname == null) { @@ -199,7 +200,7 @@ public class Users { @RequestMapping(value = "/api/users/readers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List doGetUserReaders( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam String uname) { int uid = 0; if (uname == null) { @@ -222,7 +223,7 @@ public class Users { } @GetMapping("/api/info/{uname}") - public User getUserInfo(@ModelAttribute User visitor, @PathVariable String uname) { + public User getUserInfo(@Parameter(hidden = true) User visitor, @PathVariable String uname) { User user = userService.getUserByName(uname); if (!user.isBanned()) { user.setRead(doGetUserRead(visitor, uname)); diff --git a/src/main/java/com/juick/www/api/activity/Profile.java b/src/main/java/com/juick/www/api/activity/Profile.java index bf4bda25..19a28a39 100644 --- a/src/main/java/com/juick/www/api/activity/Profile.java +++ b/src/main/java/com/juick/www/api/activity/Profile.java @@ -52,6 +52,7 @@ import com.juick.service.activities.FollowEvent; import com.juick.service.activities.UndoAnnounceEvent; import com.juick.service.activities.UndoFollowEvent; import com.overzealous.remark.Remark; +import io.swagger.v3.oas.annotations.Parameter; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -133,8 +134,8 @@ public class Profile { @GetMapping(value = "/u/{userName}/blog", produces = { Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE, MediaType.APPLICATION_JSON_VALUE }) - public OrderedCollectionPage getOutboxPage(@ModelAttribute User visitor, @PathVariable String userName, - @RequestParam(required = false, defaultValue = "0") int before) { + public OrderedCollectionPage getOutboxPage(@Parameter(hidden = true) User visitor, @PathVariable String userName, + @RequestParam(required = false, defaultValue = "0") int before) { User user = userService.getUserByName(userName); if (!user.isAnonymous() && !user.isBanned()) { UriComponentsBuilder uri = UriComponentsBuilder.fromUriString(baseUri); @@ -278,7 +279,7 @@ public class Profile { @CacheEvict(cacheNames = "profiles", key = "{ #visitor.uri }") @PostMapping(value = "/api/inbox", consumes = { Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE, MediaType.APPLICATION_JSON_VALUE }) - public ResponseEntity processInbox(@ModelAttribute User visitor, InputStream inboxData) + public ResponseEntity processInbox(@Parameter(hidden = true) User visitor, InputStream inboxData) throws Exception { String inbox = IOUtils.toString(inboxData, StandardCharsets.UTF_8); Activity activity = jsonMapper.readValue(inbox, Activity.class); diff --git a/src/main/java/com/juick/www/controllers/Help.java b/src/main/java/com/juick/www/controllers/Help.java index 32d96a53..ec60d7df 100644 --- a/src/main/java/com/juick/www/controllers/Help.java +++ b/src/main/java/com/juick/www/controllers/Help.java @@ -21,6 +21,7 @@ import com.juick.model.User; import com.juick.util.HttpNotFoundException; import com.juick.service.HelpService; import com.juick.www.WebApp; +import io.swagger.v3.oas.annotations.Parameter; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.springframework.stereotype.Controller; @@ -49,7 +50,7 @@ public class Help { @GetMapping({"/help/", "/help", "/help/{langOrPage}", "/help/{lang}/{page}"}) public String showHelp( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, Locale locale, @PathVariable(required = false, name = "lang") String lang, @PathVariable(required = false, name = "page") String page, diff --git a/src/main/java/com/juick/www/controllers/Settings.java b/src/main/java/com/juick/www/controllers/Settings.java index f2cd4aa9..bc6b6614 100644 --- a/src/main/java/com/juick/www/controllers/Settings.java +++ b/src/main/java/com/juick/www/controllers/Settings.java @@ -38,6 +38,7 @@ import com.juick.util.HttpBadRequestException; import com.juick.util.HttpUtils; import com.juick.www.WebApp; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.mail.Message; import jakarta.mail.MessagingException; import jakarta.mail.Session; @@ -88,7 +89,7 @@ public class Settings { @GetMapping("/settings") protected String doGet( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, Locale locale, @RequestParam(required = false, defaultValue = "main") String page, @RequestParam(required = false) String code, ModelMap model) { @@ -125,7 +126,7 @@ public class Settings { @PostMapping("/settings") protected String doPost( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, HttpServletRequest request, HttpServletResponse response, @RequestParam(required = false) MultipartFile newAvatar, ModelMap model) @@ -271,7 +272,7 @@ public class Settings { } @PostMapping("/settings/unsubscribe") public String unsubscribeOneClick( - @ModelAttribute User user, + User user, @RequestParam(name = "List-Unsubscribe") String unsubscribe, ModelMap model) { if (!user.isAnonymous()) { diff --git a/src/main/java/com/juick/www/controllers/SignUp.java b/src/main/java/com/juick/www/controllers/SignUp.java index b746c09b..87182ebd 100644 --- a/src/main/java/com/juick/www/controllers/SignUp.java +++ b/src/main/java/com/juick/www/controllers/SignUp.java @@ -24,6 +24,7 @@ import com.juick.www.WebApp; import com.juick.service.EmailService; import com.juick.service.UserService; import com.juick.service.security.entities.JuickUser; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.RememberMeAuthenticationToken; @@ -58,7 +59,7 @@ public class SignUp { @GetMapping("/signup") protected String doGet( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam String type, @RequestParam String hash, ModelMap model) { if (hash.length() > 36 || !type.matches("^[a-zA-Z0-9\\-]+$") || !hash.matches("^[a-zA-Z0-9\\-]+$")) { @@ -99,7 +100,7 @@ public class SignUp { protected String doPost( HttpServletRequest request, HttpServletResponse response, - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam String type, @RequestParam String hash, @RequestParam String action, diff --git a/src/main/java/com/juick/www/controllers/Site.java b/src/main/java/com/juick/www/controllers/Site.java index 217bb798..f4f8f744 100644 --- a/src/main/java/com/juick/www/controllers/Site.java +++ b/src/main/java/com/juick/www/controllers/Site.java @@ -26,6 +26,7 @@ import com.juick.util.WebUtils; import com.juick.www.WebApp; import com.juick.www.api.activity.model.Context; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; @@ -79,7 +80,7 @@ public class Site { @Value("${telegram_botname:Juick_bot}") private String tgBot; - private void fillUserModel(ModelMap model, User user, User visitor) { + private void fillUserModel(ModelMap model, User user, @Parameter(hidden = true) User visitor) { user.setAvatar(webApp.getAvatarWebPath(user)); model.addAttribute("user", user); model.addAttribute("isSubscribed", userService.isSubscribed(visitor.getUid(), user.getUid())); @@ -98,7 +99,7 @@ public class Site { } @GetMapping("/login") - public String getloginForm(@ModelAttribute User visitor, + public String getloginForm(@Parameter(hidden = true) User visitor, @RequestParam(name = "retpath", required = false, defaultValue = "/") String retPath, HttpSession session, ModelMap model) { @@ -126,7 +127,7 @@ public class Site { } @GetMapping("/") - protected String doGet(@ModelAttribute User visitor, Locale locale, @RequestParam(required = false) String tag, + protected String doGet(@Parameter(hidden = true) User visitor, Locale locale, @RequestParam(required = false) String tag, @RequestParam(name = "show", required = false) String paramShow, @RequestParam(name = "search", required = false) String paramSearch, @RequestParam(name = "before", required = false, defaultValue = "0") Integer paramBefore, @@ -218,7 +219,7 @@ public class Site { } @GetMapping(path = "/{uname}/", headers = "Connection!=Upgrade") - protected String doGetBlog(@ModelAttribute User visitor, @RequestParam(required = false, name = "show") String paramShow, + protected String doGetBlog(@Parameter(hidden = true) User visitor, @RequestParam(required = false, name = "show") String paramShow, @RequestParam(required = false, name = "tag") String paramTagStr, @RequestParam(required = false, name = "search") String paramSearch, @RequestParam(required = false, name = "page", defaultValue = "0") Integer page, @PathVariable String uname, @@ -325,7 +326,7 @@ public class Site { } @GetMapping("/{uname}/tags") - protected String doGetTags(@ModelAttribute User visitor, @PathVariable String uname, ModelMap model) { + protected String doGetTags(@Parameter(hidden = true) User visitor, @PathVariable String uname, ModelMap model) { User user = userService.getUserByName(uname); if (visitor.isBanned()) { throw new HttpNotFoundException(); @@ -345,7 +346,7 @@ public class Site { } @GetMapping("/{uname}/friends") - protected String doGetFriends(@ModelAttribute User visitor, @PathVariable String uname, ModelMap model) { + protected String doGetFriends(@Parameter(hidden = true) User visitor, @PathVariable String uname, ModelMap model) { User user = userService.getUserByName(uname); if (visitor.isBanned()) { throw new HttpNotFoundException(); @@ -361,7 +362,7 @@ public class Site { } @GetMapping("/{uname}/readers") - protected String doGetReaders(@ModelAttribute User visitor, @PathVariable String uname, ModelMap model) { + protected String doGetReaders(@Parameter(hidden = true) User visitor, @PathVariable String uname, ModelMap model) { User user = userService.getUserByName(uname); visitor.setAvatar(webApp.getAvatarWebPath(visitor)); model.addAttribute("title", "Читатели " + user.getName()); @@ -374,7 +375,7 @@ public class Site { } @GetMapping("/{uname}/bl") - protected String doGetBL(@ModelAttribute User visitor, @PathVariable String uname, ModelMap model) { + protected String doGetBL(@Parameter(hidden = true) User visitor, @PathVariable String uname, ModelMap model) { User user = userService.getUserByName(uname); if (visitor.getUid() != user.getUid()) { throw new HttpForbiddenException(); @@ -390,7 +391,7 @@ public class Site { } @GetMapping("/tag/{tagName}") - protected String tagAction(@ModelAttribute User visitor, HttpServletRequest request, @PathVariable String tagName, + protected String tagAction(@Parameter(hidden = true) User visitor, HttpServletRequest request, @PathVariable String tagName, @RequestParam(required = false, defaultValue = "0") int before, ModelMap model) { visitor.setAvatar(webApp.getAvatarWebPath(visitor)); String paramTagStr = StringEscapeUtils.unescapeHtml4(tagName); @@ -453,7 +454,7 @@ public class Site { } @GetMapping("/pm/inbox") - protected String doGetInbox(@ModelAttribute User visitor, ModelMap model) { + protected String doGetInbox(@Parameter(hidden = true) User visitor, ModelMap model) { visitor.setAvatar(webApp.getAvatarWebPath(visitor)); String title = "PM: Inbox"; List msgs = chatService.getInbox(visitor.getUid()); @@ -467,7 +468,7 @@ public class Site { } @GetMapping("/pm/sent") - protected String doGetSent(@ModelAttribute User visitor, @RequestParam(required = false) String uname, ModelMap model) { + protected String doGetSent(@Parameter(hidden = true) User visitor, @RequestParam(required = false) String uname, ModelMap model) { visitor.setAvatar(webApp.getAvatarWebPath(visitor)); String title = "PM: Sent"; List msgs = chatService.getOutbox(visitor.getUid()); @@ -492,7 +493,7 @@ public class Site { } @GetMapping(value = "/{uname}/{mid}", produces = { MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE }) - protected String threadAction(@ModelAttribute User visitor, ModelMap model, @PathVariable String uname, + protected String threadAction(@Parameter(hidden = true) User visitor, ModelMap model, @PathVariable String uname, @PathVariable int mid, @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie) { if (!messagesService.canViewThread(mid, visitor.getUid())) { @@ -585,7 +586,7 @@ public class Site { } @GetMapping("/post") - protected String postAction(@ModelAttribute User visitor, @RequestParam(required = false) String body, ModelMap model) { + protected String postAction(@Parameter(hidden = true) User visitor, @RequestParam(required = false) String body, ModelMap model) { fillUserModel(model, visitor, visitor); visitor.setAvatar(webApp.getAvatarWebPath(visitor)); model.addAttribute("title", "Написать"); diff --git a/src/main/java/com/juick/www/controllers/SocialLogin.java b/src/main/java/com/juick/www/controllers/SocialLogin.java index 4e26ab99..b43b65c6 100644 --- a/src/main/java/com/juick/www/controllers/SocialLogin.java +++ b/src/main/java/com/juick/www/controllers/SocialLogin.java @@ -193,7 +193,7 @@ public class SocialLogin { } @GetMapping("/_twitter") - protected void doTwitterLogin(@ModelAttribute com.juick.model.User user, HttpServletRequest request, + protected void doTwitterLogin(com.juick.model.User user, HttpServletRequest request, HttpServletResponse response) throws IOException, ExecutionException, InterruptedException { String hash = StringUtils.EMPTY, request_token = StringUtils.EMPTY, request_token_secret = StringUtils.EMPTY; String verifier = request.getParameter("oauth_verifier"); diff --git a/src/main/java/com/juick/www/rss/Feeds.java b/src/main/java/com/juick/www/rss/Feeds.java index 41b006a6..4e64bc5a 100644 --- a/src/main/java/com/juick/www/rss/Feeds.java +++ b/src/main/java/com/juick/www/rss/Feeds.java @@ -22,6 +22,7 @@ import com.juick.util.HttpNotFoundException; import com.juick.service.MessagesService; import com.juick.service.UserService; +import io.swagger.v3.oas.annotations.Parameter; import org.springframework.core.convert.ConversionFailedException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -49,7 +50,7 @@ public class Feeds { } @GetMapping("/rss/{userName}/{feedType}") - public ModelAndView getBlog(@ModelAttribute User visitor, @PathVariable String userName, @PathVariable FeedType feedType) { + public ModelAndView getBlog(@Parameter(hidden = true) User visitor, @PathVariable String userName, @PathVariable FeedType feedType) { User user = userService.getUserByName(userName); if (!user.isAnonymous() && !user.isBanned()) { List mids = feedType == FeedType.blog ? messagesService.getUserBlog(user.getUid(), 0, 0) : messagesService.getUserBlogWithRecommendations(user, visitor, 0, 0); @@ -65,11 +66,12 @@ public class Feeds { @GetMapping("/rss/") public ModelAndView getLast( - @ModelAttribute User visitor, + @Parameter(hidden = true) User visitor, @RequestParam(value = "hours", required = false, defaultValue = "0") Integer hours) { List mids = messagesService.getLastMessages(hours); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("messagesView"); + modelAndView.addObject("user", visitor); modelAndView.addObject("messages", messagesService.getMessages(visitor, mids)); return modelAndView; } -- cgit v1.2.3