From ae5870f1fa9bbf045f1881664bb8a3a098fd2610 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 11 Dec 2018 16:14:14 +0300 Subject: avatar upload api --- src/main/java/com/juick/server/www/controllers/Settings.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/server/www/controllers/Settings.java b/src/main/java/com/juick/server/www/controllers/Settings.java index 57984aef..fc84b410 100644 --- a/src/main/java/com/juick/server/www/controllers/Settings.java +++ b/src/main/java/com/juick/server/www/controllers/Settings.java @@ -60,8 +60,6 @@ import java.util.stream.IntStream; public class Settings { private static final Logger logger = LoggerFactory.getLogger(Settings.class); - @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String imgDir; @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") private String tmpDir; @Inject -- cgit v1.2.3 From 1dc570a8aaaa8657eb4faa7283e30a5fde93d321 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 12 Dec 2018 09:19:53 +0300 Subject: Vary: Accept-Language --- src/main/java/com/juick/server/www/VaryHandler.java | 14 ++++++++++++++ src/test/java/com/juick/server/tests/ServerTests.java | 12 ++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/main/java/com/juick/server/www/VaryHandler.java (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/server/www/VaryHandler.java b/src/main/java/com/juick/server/www/VaryHandler.java new file mode 100644 index 00000000..5a1b86a6 --- /dev/null +++ b/src/main/java/com/juick/server/www/VaryHandler.java @@ -0,0 +1,14 @@ +package com.juick.server.www; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; + +import javax.servlet.http.HttpServletResponse; + +@ControllerAdvice +public class VaryHandler { + @ModelAttribute + public void setVaryResponseHeader(HttpServletResponse response) { + response.setHeader("Vary", "Accept-Language"); + } +} diff --git a/src/test/java/com/juick/server/tests/ServerTests.java b/src/test/java/com/juick/server/tests/ServerTests.java index b732cb98..b914aed0 100644 --- a/src/test/java/com/juick/server/tests/ServerTests.java +++ b/src/test/java/com/juick/server/tests/ServerTests.java @@ -1877,4 +1877,16 @@ public class ServerTests { String newHash = DigestUtils.md5DigestAsHex(newAvatarData); assertThat(webApp.getAvatarUrl(userService.getUserByName(freefdName)), is(String.format("http://localhost:8080/i/a/%d-%s.png", freefd.getUid(), newHash))); } + @Test + public void varyMvcResponse() throws Exception { + mockMvc.perform(get("/")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + mockMvc.perform(get("/rss/ugnich/blog")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + mockMvc.perform(get("/api/messages")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + } } -- cgit v1.2.3 From 9d493ac966db2e016f73efcdcfb65dfb10bf8114 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 12 Dec 2018 15:12:27 +0300 Subject: UserInfo -> User --- src/main/java/com/juick/User.java | 27 ++++++++++ src/main/java/com/juick/model/UserInfo.java | 60 ---------------------- src/main/java/com/juick/server/XMPPConnection.java | 4 +- src/main/java/com/juick/server/api/Users.java | 14 +---- .../juick/server/configuration/SecurityConfig.java | 2 +- .../server/www/controllers/AnythingFilter.java | 2 +- .../com/juick/server/www/controllers/Settings.java | 12 ++--- src/main/java/com/juick/service/UserService.java | 5 +- .../java/com/juick/service/UserServiceImpl.java | 37 ++++++------- .../java/com/juick/server/tests/ServerTests.java | 20 ++++++-- 10 files changed, 74 insertions(+), 109 deletions(-) delete mode 100644 src/main/java/com/juick/model/UserInfo.java (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/User.java b/src/main/java/com/juick/User.java index 7221e416..78d47139 100644 --- a/src/main/java/com/juick/User.java +++ b/src/main/java/com/juick/User.java @@ -53,6 +53,9 @@ public class User { private URI uri; private Instant seen; private boolean verified; + private String country; + private String url; + private String description; public User() { tokens = new ArrayList<>(); @@ -232,4 +235,28 @@ public class User { public void setVerified(boolean verified) { this.verified = verified; } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } } diff --git a/src/main/java/com/juick/model/UserInfo.java b/src/main/java/com/juick/model/UserInfo.java deleted file mode 100644 index ca5d75e0..00000000 --- a/src/main/java/com/juick/model/UserInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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.model; - -/** - * Created by vt on 03/09/16. - */ -public class UserInfo { - private String fullName; - private String country; - private String url; - private String description; - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } -} diff --git a/src/main/java/com/juick/server/XMPPConnection.java b/src/main/java/com/juick/server/XMPPConnection.java index f77b2354..dfbe92d5 100644 --- a/src/main/java/com/juick/server/XMPPConnection.java +++ b/src/main/java/com/juick/server/XMPPConnection.java @@ -22,7 +22,6 @@ import com.juick.formatters.PlainTextFormatter; import com.juick.server.www.WebApp; import com.juick.service.component.*; import com.juick.model.CommandResult; -import com.juick.model.UserInfo; import com.juick.server.xmpp.iq.MessageQuery; import com.juick.server.xmpp.s2s.BasicXmppSession; import com.juick.server.xmpp.s2s.StanzaListener; @@ -35,7 +34,6 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; import rocks.xmpp.addr.Jid; import rocks.xmpp.core.XmppException; import rocks.xmpp.core.session.XmppSession; @@ -164,7 +162,7 @@ public class XMPPConnection implements StanzaListener, NotificationListener { } User user = userService.getUserByName(iq.getTo().getLocal()); if (!user.isAnonymous()) { - UserInfo info = userService.getUserInfo(user); + User info = userService.getUserInfo(user); VCard userVCard = new VCard(); userVCard.setFormattedName(info.getFullName()); userVCard.setNickname(user.getName()); diff --git a/src/main/java/com/juick/server/api/Users.java b/src/main/java/com/juick/server/api/Users.java index 0e0fee85..5c6efe0c 100644 --- a/src/main/java/com/juick/server/api/Users.java +++ b/src/main/java/com/juick/server/api/Users.java @@ -19,7 +19,6 @@ package com.juick.server.api; import com.juick.User; import com.juick.model.ApplicationStatus; -import com.juick.model.UserInfo; import com.juick.server.util.*; import com.juick.server.www.WebApp; import com.juick.service.*; @@ -96,7 +95,7 @@ public class Users { me.setRead(userService.getUserFriends(visitor.getUid())); me.setReaders(userService.getUserReaders(visitor.getUid())); me.setAvatar(webApp.getAvatarUrl(visitor)); - return me; + return (SecureUser)userService.getUserInfo(me); } @PostMapping("/api/me/upload") public void updateInfo(@RequestParam MultipartFile avatar) throws IOException { @@ -111,9 +110,6 @@ public class Users { public List doGetUserRead( @RequestParam String uname) { User visitor = UserUtils.getCurrentUser(); - if (visitor.isAnonymous()) { - throw new HttpForbiddenException(); - } int uid = 0; if (uname == null) { uid = visitor.getUid(); @@ -138,9 +134,6 @@ public class Users { public List doGetUserReaders( @RequestParam String uname) { User visitor = UserUtils.getCurrentUser(); - if (visitor.isAnonymous()) { - throw new HttpForbiddenException(); - } int uid = 0; if (uname == null) { uid = visitor.getUid(); @@ -162,7 +155,7 @@ public class Users { } @GetMapping("/api/info/{uname}") - public UserInfo getUserInfo(@PathVariable String uname) { + public User getUserInfo(@PathVariable String uname) { User user = userService.getUserByName(uname); if (!user.isBanned()) { user.setRead(doGetUserRead(uname)); @@ -177,9 +170,6 @@ public class Users { public String getHash() { return getAuthHash(); } - public UserInfo getUserInfo() { - return userService.getUserInfo(this); - } public List getJIDs() { return userService.getAllJIDs(this); } diff --git a/src/main/java/com/juick/server/configuration/SecurityConfig.java b/src/main/java/com/juick/server/configuration/SecurityConfig.java index f53cc531..16b61172 100644 --- a/src/main/java/com/juick/server/configuration/SecurityConfig.java +++ b/src/main/java/com/juick/server/configuration/SecurityConfig.java @@ -98,7 +98,7 @@ public class SecurityConfig { .authorizeRequests() .antMatchers(HttpMethod.OPTIONS).permitAll() .antMatchers("/api/", "/api/messages", "/api/messages/discussions", "/api/users", "/api/thread", "/api/tags", "/api/tlgmbtwbhk", "/api/fbwbhk", - "/api/skypebotendpoint", "/api/_fblogin", "/api/_vklogin", "/api/_tglogin", "/api/_google", "/api/signup", "/api/inbox", "/api/u/**", "/.well-known/webfinger", "/.well-known/x-nodeinfo2", "/rss/**", "/api/events").permitAll() + "/api/skypebotendpoint", "/api/_fblogin", "/api/_vklogin", "/api/_tglogin", "/api/_google", "/api/signup", "/api/inbox", "/api/u/**", "/.well-known/webfinger", "/.well-known/x-nodeinfo2", "/rss/**", "/api/events", "/api/info/**").permitAll() .anyRequest().hasRole("USER") .and() .anonymous().principal(JuickUser.ANONYMOUS_USER).authorities(JuickUser.ANONYMOUS_AUTHORITY) diff --git a/src/main/java/com/juick/server/www/controllers/AnythingFilter.java b/src/main/java/com/juick/server/www/controllers/AnythingFilter.java index cdbeafc0..57b298eb 100644 --- a/src/main/java/com/juick/server/www/controllers/AnythingFilter.java +++ b/src/main/java/com/juick/server/www/controllers/AnythingFilter.java @@ -60,7 +60,7 @@ public class AnythingFilter extends OncePerRequestFilter { } else { com.juick.User user = userService.getUserByName(anything); if (!user.isAnonymous()) { - ((HttpServletResponse) servletResponse).sendRedirect("/" + user.getName() + "/?before=" + before); + servletResponse.sendRedirect("/" + user.getName() + "/?before=" + before); } else { filterChain.doFilter(servletRequest, servletResponse); } diff --git a/src/main/java/com/juick/server/www/controllers/Settings.java b/src/main/java/com/juick/server/www/controllers/Settings.java index fc84b410..d5a21d09 100644 --- a/src/main/java/com/juick/server/www/controllers/Settings.java +++ b/src/main/java/com/juick/server/www/controllers/Settings.java @@ -18,7 +18,6 @@ package com.juick.server.www.controllers; import com.juick.User; import com.juick.model.NotifyOpts; -import com.juick.model.UserInfo; import com.juick.server.util.HttpBadRequestException; import com.juick.server.util.HttpUtils; import com.juick.server.util.UserUtils; @@ -156,16 +155,15 @@ public class Settings { } break; case "about": - UserInfo info = new UserInfo(); - info.setFullName(request.getParameter("fullname")); - info.setCountry(request.getParameter("country")); - info.setUrl(request.getParameter("url")); - info.setDescription(request.getParameter("descr")); + visitor.setFullName(request.getParameter("fullname")); + visitor.setCountry(request.getParameter("country")); + visitor.setUrl(request.getParameter("url")); + visitor.setDescription(request.getParameter("descr")); String avatarTmpPath = HttpUtils.receiveMultiPartFile(avatar, tmpDir).getHost(); if (StringUtils.isNotEmpty(avatarTmpPath)) { imagesService.saveAvatar(avatarTmpPath, visitor.getUid()); } - if (userService.updateUserInfo(visitor, info)) { + if (userService.updateUserInfo(visitor)) { result = String.format("

Your info is updated.

Back to blog.

", visitor.getName()); } break; diff --git a/src/main/java/com/juick/service/UserService.java b/src/main/java/com/juick/service/UserService.java index 832f978a..3a51dffb 100644 --- a/src/main/java/com/juick/service/UserService.java +++ b/src/main/java/com/juick/service/UserService.java @@ -20,7 +20,6 @@ package com.juick.service; import com.juick.Message; import com.juick.User; import com.juick.model.Auth; -import com.juick.model.UserInfo; import javax.annotation.Nonnull; import java.time.Instant; @@ -75,9 +74,9 @@ public interface UserService { int setUserOptionInt(int uid, String option, int value); - UserInfo getUserInfo(User user); + User getUserInfo(User user); - boolean updateUserInfo(User user, UserInfo info); + boolean updateUserInfo(User info); boolean getCanMedia(int uid); diff --git a/src/main/java/com/juick/service/UserServiceImpl.java b/src/main/java/com/juick/service/UserServiceImpl.java index 93904139..95a13f65 100644 --- a/src/main/java/com/juick/service/UserServiceImpl.java +++ b/src/main/java/com/juick/service/UserServiceImpl.java @@ -21,7 +21,6 @@ import com.juick.Message; import com.juick.User; import com.juick.model.AnonymousUser; import com.juick.model.Auth; -import com.juick.model.UserInfo; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; @@ -375,29 +374,31 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { @Transactional(readOnly = true) @Override - public UserInfo getUserInfo(final User user) { - List list = getJdbcTemplate().query( - "SELECT fullname, country, url, descr FROM usersinfo WHERE user_id = ?", - ((rs, rowNum) -> { - UserInfo info = new UserInfo(); - info.setFullName(rs.getString(1)); - info.setCountry(rs.getString(2)); - info.setUrl(rs.getString(3)); - info.setDescription(rs.getString(4)); - return info; - }), - user.getUid()); - - return list.isEmpty() ? new UserInfo() : list.get(0); + public User getUserInfo(final User user) { + try { + getJdbcTemplate().queryForObject( + "SELECT fullname, country, url, descr FROM usersinfo WHERE user_id = ?", + ((rs, rowNum) -> { + user.setFullName(rs.getString(1)); + user.setCountry(rs.getString(2)); + user.setUrl(rs.getString(3)); + user.setDescription(rs.getString(4)); + return user; + }), + user.getUid()); + } catch (EmptyResultDataAccessException e) { + return user; + } + return user; } @Transactional @Override - public boolean updateUserInfo(final User user, final UserInfo info) { + public boolean updateUserInfo(final User info) { try { return getJdbcTemplate().update( "INSERT INTO usersinfo(user_id, fullname, country, url, descr) VALUES (?, ?, ?, ?, ?)", - user.getUid(), + info.getUid(), info.getFullName(), info.getCountry(), info.getUrl(), @@ -408,7 +409,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { info.getCountry(), info.getUrl(), info.getDescription(), - user.getUid()) > 0; + info.getUid()) > 0; } } diff --git a/src/test/java/com/juick/server/tests/ServerTests.java b/src/test/java/com/juick/server/tests/ServerTests.java index 01aa298b..d1cdac8b 100644 --- a/src/test/java/com/juick/server/tests/ServerTests.java +++ b/src/test/java/com/juick/server/tests/ServerTests.java @@ -27,10 +27,7 @@ import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.jayway.jsonpath.JsonPath; import com.juick.*; -import com.juick.model.AnonymousUser; -import com.juick.model.CommandResult; -import com.juick.model.PrivateChats; -import com.juick.model.TagStats; +import com.juick.model.*; import com.juick.server.*; import com.juick.server.api.activity.model.Context; import com.juick.server.api.activity.model.activities.Create; @@ -1896,4 +1893,19 @@ public class ServerTests { .andExpect(status().isOk()) .andExpect(header().string("Vary", "Accept-Language")); } + @Test + public void apiInfo() throws Exception { + userService.createUser("tst", "tst"); + MvcResult result = mockMvc.perform(get("/api/info/tst")) + .andExpect(status().isOk()) + .andReturn(); + User tst = jsonMapper.readValue(result.getResponse().getContentAsString(), User.class); + assertThat(tst.getReaders(), is(nullValue())); + commandsManager.processCommand(ugnich, "S @tst", emptyUri); + result = mockMvc.perform(get("/api/info/tst")) + .andExpect(status().isOk()) + .andReturn(); + tst = jsonMapper.readValue(result.getResponse().getContentAsString(), User.class); + assertThat(tst.getReaders().size(), is(1)); + } } -- cgit v1.2.3 From 020b4bd111d02fd5273291c85024402ae6c46ab6 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 9 Jan 2019 20:11:15 +0300 Subject: Facebook API update --- src/main/java/com/juick/model/facebook/User.java | 70 ---------------------- .../java/com/juick/server/api/ApiSocialLogin.java | 19 +++--- .../juick/server/www/controllers/SocialLogin.java | 19 +++--- .../java/com/juick/service/CrosspostService.java | 4 +- .../com/juick/service/CrosspostServiceImpl.java | 12 ++-- 5 files changed, 24 insertions(+), 100 deletions(-) (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/model/facebook/User.java b/src/main/java/com/juick/model/facebook/User.java index 80838de6..a9288fe4 100644 --- a/src/main/java/com/juick/model/facebook/User.java +++ b/src/main/java/com/juick/model/facebook/User.java @@ -27,98 +27,28 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class User { private String id; private String name; - private String link; - private boolean verified; private String firstName; private String lastName; - private String gender; - private String locale; - private String timezone; - private String updatedTime; private String email; public String getId() { return id; } - public void setId(String id) { - this.id = id; - } - public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - - public String getLink() { - return link; - } - - public void setLink(String link) { - this.link = link; - } - - public boolean getVerified() { - return verified; - } - - public void setVerified(boolean verified) { - this.verified = verified; - } - @JsonProperty("first_name") public String getFirstName() { return firstName; } - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getGender() { - return gender; - } - - public void setGender(String gender) { - this.gender = gender; - } @JsonProperty("last_name") public String getLastName() { return lastName; } - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getLocale() { - return locale; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public String getTimezone() { - return timezone; - } - - public void setTimezone(String timezone) { - this.timezone = timezone; - } - - @JsonProperty("updated_time") - public String getUpdatedTime() { - return updatedTime; - } - - public void setUpdatedTime(String updatedTime) { - this.updatedTime = updatedTime; - } - public String getEmail() { return email; } diff --git a/src/main/java/com/juick/server/api/ApiSocialLogin.java b/src/main/java/com/juick/server/api/ApiSocialLogin.java index 72cda0af..75fd6d11 100644 --- a/src/main/java/com/juick/server/api/ApiSocialLogin.java +++ b/src/main/java/com/juick/server/api/ApiSocialLogin.java @@ -148,7 +148,7 @@ public class ApiSocialLogin { .state(state) .build(FacebookApi.instance()); OAuth2AccessToken token = facebookService.getAccessToken(code); - final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v2.10/me?fields=id,name,link,verified,email"); + final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v3.2/me?fields=id,name,email"); facebookService.signRequest(token, meRequest); String graph = facebookService.execute(meRequest).getBody(); if (StringUtils.isBlank(graph)) { @@ -157,36 +157,33 @@ public class ApiSocialLogin { } User fb = jsonMapper.readValue(graph, User.class); long fbID = NumberUtils.toLong(fb.getId(), 0); - if (fbID == 0 || StringUtils.isBlank(fb.getName()) || StringUtils.isBlank(fb.getLink())) { - logger.error("Missing required fields, id: {}, name: {}, link: {}", fbID, fb.getName(), fb.getLink()); + if (fbID == 0 || StringUtils.isBlank(fb.getName())) { + logger.error("Missing required fields, id: {}, name: {}", fbID, fb.getName()); throw new HttpBadRequestException(); } int uid = crosspostService.getUIDbyFBID(fbID); if (uid > 0) { - if (!crosspostService.updateFacebookUser(fbID, token.getAccessToken(), fb.getName(), fb.getLink())) { + if (!crosspostService.updateFacebookUser(fbID, token.getAccessToken(), fb.getName())) { logger.error("error updating facebook user, id: {}, token: {}", fbID, token.getAccessToken()); throw new HttpBadRequestException(); } UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(redirectUrl); uriComponentsBuilder.queryParam("hash", userService.getHashByUID(uid)); return "redirect:" + uriComponentsBuilder.build().toUriString(); - } else if (fb.getVerified()) { - if (!crosspostService.createFacebookUser(fbID, state, token.getAccessToken(), fb.getName(), fb.getLink())) { + } else { + if (!crosspostService.createFacebookUser(fbID, state, token.getAccessToken(), fb.getName())) { if (StringUtils.isNotEmpty(fb.getEmail())) { - logger.info("found {} for facebook user {}", fb.getEmail(), fb.getLink()); + logger.info("found {} for facebook user {}", fb.getEmail()); Integer userId = crosspostService.getUIDbyFBID(fbID); if (!emailService.getEmails(userId, false).contains(fb.getEmail())) { emailService.addEmail(userId, fb.getEmail()); } } - logger.info("email not found for facebook user {}", fb.getLink()); + logger.info("email not found for facebook user {}", fb.getName()); throw new HttpBadRequestException(); } return "redirect:/signup?type=fb&hash=" + state; - } else { - logger.error("Facebook account is not verified, id: {}", fbID); - throw new HttpBadRequestException(); } }/* @GetMapping("/_twitter") diff --git a/src/main/java/com/juick/server/www/controllers/SocialLogin.java b/src/main/java/com/juick/server/www/controllers/SocialLogin.java index bc631a1a..b071b6ca 100644 --- a/src/main/java/com/juick/server/www/controllers/SocialLogin.java +++ b/src/main/java/com/juick/server/www/controllers/SocialLogin.java @@ -142,7 +142,7 @@ public class SocialLogin { .state(state) .build(FacebookApi.instance()); OAuth2AccessToken token = facebookService.getAccessToken(code); - final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v2.10/me?fields=id,name,link,verified,email"); + final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v3.2/me?fields=id,name,link,verified,email"); facebookService.signRequest(token, meRequest); String graph = facebookService.execute(meRequest).getBody(); if (StringUtils.isBlank(graph)) { @@ -151,14 +151,14 @@ public class SocialLogin { } User fb = jsonMapper.readValue(graph, User.class); long fbID = NumberUtils.toLong(fb.getId(), 0); - if (fbID == 0 || StringUtils.isBlank(fb.getName()) || StringUtils.isBlank(fb.getLink())) { - logger.error("Missing required fields, id: {}, name: {}, link: {}", fbID, fb.getName(), fb.getLink()); + if (fbID == 0 || StringUtils.isBlank(fb.getName())) { + logger.error("Missing required fields, id: {}, name: {}", fbID, fb.getName()); throw new HttpBadRequestException(); } int uid = crosspostService.getUIDbyFBID(fbID); if (uid > 0) { - if (!crosspostService.updateFacebookUser(fbID, token.getAccessToken(), fb.getName(), fb.getLink())) { + if (!crosspostService.updateFacebookUser(fbID, token.getAccessToken(), fb.getName())) { logger.error("error updating facebook user, id: {}, token: {}", fbID, token.getAccessToken()); throw new HttpBadRequestException(); } @@ -166,22 +166,19 @@ public class SocialLogin { c.setMaxAge(50 * 24 * 60 * 60); response.addCookie(c); return "redirect:" + redirectUrl; - } else if (fb.getVerified()) { - if (!crosspostService.createFacebookUser(fbID, state, token.getAccessToken(), fb.getName(), fb.getLink())) { + } else { + if (!crosspostService.createFacebookUser(fbID, state, token.getAccessToken(), fb.getName())) { if (StringUtils.isNotEmpty(fb.getEmail())) { - logger.info("found {} for facebook user {}", fb.getEmail(), fb.getLink()); + logger.info("found {} for facebook user {}", fb.getEmail()); Integer userId = crosspostService.getUIDbyFBID(fbID); if (!emailService.getEmails(userId, false).contains(fb.getEmail())) { emailService.addEmail(userId, fb.getEmail()); } } - logger.info("email not found for facebook user {}", fb.getLink()); + logger.info("email not found for facebook user {}", fb.getName()); throw new HttpBadRequestException(); } return "redirect:/signup?type=fb&hash=" + state; - } else { - logger.error("Facebook account is not verified, id: {}", fbID); - throw new HttpBadRequestException(); } } @GetMapping("/_twitter") diff --git a/src/main/java/com/juick/service/CrosspostService.java b/src/main/java/com/juick/service/CrosspostService.java index 99911250..28b9e8ab 100644 --- a/src/main/java/com/juick/service/CrosspostService.java +++ b/src/main/java/com/juick/service/CrosspostService.java @@ -60,9 +60,9 @@ public interface CrosspostService { int getUIDbyFBID(long fbID); - boolean createFacebookUser(long fbID, String loginhash, String token, String fbName, String fbLink); + boolean createFacebookUser(long fbID, String loginhash, String token, String fbName); - boolean updateFacebookUser(long fbID, String token, String fbName, String fbLink); + boolean updateFacebookUser(long fbID, String token, String fbName); int getUIDbyVKID(long vkID); diff --git a/src/main/java/com/juick/service/CrosspostServiceImpl.java b/src/main/java/com/juick/service/CrosspostServiceImpl.java index d190faba..0eeb8c78 100644 --- a/src/main/java/com/juick/service/CrosspostServiceImpl.java +++ b/src/main/java/com/juick/service/CrosspostServiceImpl.java @@ -180,16 +180,16 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe @Transactional @Override - public boolean createFacebookUser(long fbID, String loginhash, String token, String fbName, String fbLink) { - return getJdbcTemplate().update("UPDATE facebook SET fb_id=?, access_token=?, fb_name=?, fb_link=? WHERE loginhash=?", - fbID, token, fbName, fbLink, loginhash) > 0; + public boolean createFacebookUser(long fbID, String loginhash, String token, String fbName) { + return getJdbcTemplate().update("UPDATE facebook SET fb_id=?, access_token=?, fb_name=? WHERE loginhash=?", + fbID, token, fbName, loginhash) > 0; } @Transactional @Override - public boolean updateFacebookUser(long fbID, String token, String fbName, String fbLink) { - return getJdbcTemplate().update("UPDATE facebook SET access_token=?,fb_name=?,fb_link=? WHERE fb_id=?", - token, fbName, fbLink, fbID) > 0; + public boolean updateFacebookUser(long fbID, String token, String fbName) { + return getJdbcTemplate().update("UPDATE facebook SET access_token=?,fb_name=? WHERE fb_id=?", + token, fbName, fbID) > 0; } @Transactional(readOnly = true) -- cgit v1.2.3 From 1eed5a8f1053f87b10cb3410e477792075d7f3e4 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 19 Feb 2019 10:23:07 +0300 Subject: refactor social login flow --- .../java/com/juick/server/api/ApiSocialLogin.java | 51 ++++++++-------------- .../juick/server/www/controllers/SocialLogin.java | 51 ++++++++-------------- 2 files changed, 38 insertions(+), 64 deletions(-) (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/server/api/ApiSocialLogin.java b/src/main/java/com/juick/server/api/ApiSocialLogin.java index 75fd6d11..be306fe9 100644 --- a/src/main/java/com/juick/server/api/ApiSocialLogin.java +++ b/src/main/java/com/juick/server/api/ApiSocialLogin.java @@ -82,6 +82,7 @@ public class ApiSocialLogin { @Inject private ObjectMapper jsonMapper; private ServiceBuilder facebookBuilder, twitterBuilder, vkBuilder; + private OAuth20Service facebookAuthService, vkAuthService; @Value("${twitter_consumer_key:appid}") private String twitterConsumerKey; @@ -117,6 +118,16 @@ public class ApiSocialLogin { verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) .setAudience(Collections.singletonList(googleClientId)) .build(); + facebookAuthService = facebookBuilder + .apiSecret(FACEBOOK_SECRET) + .callback(FACEBOOK_REDIRECT) + .scope("email") + .build(FacebookApi.instance()); + vkAuthService = vkBuilder + .apiSecret(VK_SECRET) + .scope("friends,wall,offline") + .callback(VK_REDIRECT) + .build(VkontakteApi.instance()); } @GetMapping("/api/_fblogin") @@ -125,13 +136,7 @@ public class ApiSocialLogin { if (StringUtils.isBlank(code)) { String fbstate = UUID.randomUUID().toString(); crosspostService.addFacebookState(fbstate, state); - OAuth20Service facebookAuthService = facebookBuilder - .apiSecret(FACEBOOK_SECRET) - .callback(FACEBOOK_REDIRECT) - .scope("email") - .state(fbstate) - .build(FacebookApi.instance()); - return "redirect:" + facebookAuthService.getAuthorizationUrl(); + return "redirect:" + facebookAuthService.getAuthorizationUrl(fbstate); } String redirectUrl = crosspostService.verifyFacebookState(state); @@ -140,17 +145,10 @@ public class ApiSocialLogin { logger.error("state is missing"); throw new HttpBadRequestException(); } - OAuth20Service facebookService = facebookBuilder - .apiKey(FACEBOOK_APPID) - .apiSecret(FACEBOOK_SECRET) - .callback(FACEBOOK_REDIRECT) - .scope("email") - .state(state) - .build(FacebookApi.instance()); - OAuth2AccessToken token = facebookService.getAccessToken(code); + OAuth2AccessToken token = facebookAuthService.getAccessToken(code); final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v3.2/me?fields=id,name,email"); - facebookService.signRequest(token, meRequest); - String graph = facebookService.execute(meRequest).getBody(); + facebookAuthService.signRequest(token, meRequest); + String graph = facebookAuthService.execute(meRequest).getBody(); if (StringUtils.isBlank(graph)) { logger.error("FACEBOOK GRAPH ERROR"); throw new HttpBadRequestException(); @@ -241,13 +239,7 @@ public class ApiSocialLogin { if (StringUtils.isBlank(code)) { String vkstate = UUID.randomUUID().toString(); crosspostService.addVKState(vkstate, state); - OAuth20Service vkAuthService = vkBuilder - .apiSecret(VK_SECRET) - .scope("friends,wall,offline") - .state(vkstate) - .callback(VK_REDIRECT) - .build(VkontakteApi.instance()); - return "redirect:" + vkAuthService.getAuthorizationUrl(); + return "redirect:" + vkAuthService.getAuthorizationUrl(vkstate); } String redirectUrl = crosspostService.verifyVKState(state); @@ -255,16 +247,11 @@ public class ApiSocialLogin { logger.error("state is missing"); throw new HttpBadRequestException(); } - - OAuth20Service vkService = vkBuilder - .apiKey(VK_APPID) - .apiSecret(VK_SECRET) - .build(VkontakteApi.instance()); - OAuth2AccessToken token = vkService.getAccessToken(code); + OAuth2AccessToken token = vkAuthService.getAccessToken(code); OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://api.vk.com/method/users.get?fields=screen_name&v=5.73"); - vkService.signRequest(token, meRequest); - String graph = vkService.execute(meRequest).getBody(); + vkAuthService.signRequest(token, meRequest); + String graph = vkAuthService.execute(meRequest).getBody(); com.juick.model.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); String vkName = jsonUser.getFirstName() + " " + jsonUser.getLastName(); diff --git a/src/main/java/com/juick/server/www/controllers/SocialLogin.java b/src/main/java/com/juick/server/www/controllers/SocialLogin.java index b071b6ca..59b1ec0b 100644 --- a/src/main/java/com/juick/server/www/controllers/SocialLogin.java +++ b/src/main/java/com/juick/server/www/controllers/SocialLogin.java @@ -79,6 +79,7 @@ public class SocialLogin { @Inject private ObjectMapper jsonMapper; private ServiceBuilder facebookBuilder, twitterBuilder, vkBuilder; + private OAuth20Service facebookAuthService, vkAuthService; @Value("${twitter_consumer_key:appid}") private String twitterConsumerKey; @@ -107,6 +108,16 @@ public class SocialLogin { vkBuilder = new ServiceBuilder(VK_APPID); UriComponentsBuilder facebookRedirectBuilder = UriComponentsBuilder.fromUriString(baseUri); facebookRedirectUri = facebookRedirectBuilder.replacePath("/_fblogin").build().toUriString(); + facebookAuthService = facebookBuilder + .apiSecret(FACEBOOK_SECRET) + .callback(facebookRedirectUri) + .scope("email") + .build(FacebookApi.instance()); + vkAuthService = vkBuilder + .apiSecret(VK_SECRET) + .scope("friends,wall,offline") + .callback(VK_REDIRECT) + .build(VkontakteApi.instance()); } @GetMapping("/_fblogin") @@ -120,13 +131,7 @@ public class SocialLogin { state = Utils.getPreviousPageByRequest(request).orElse("https://juick.com/"); } crosspostService.addFacebookState(fbstate, state); - OAuth20Service facebookAuthService = facebookBuilder - .apiSecret(FACEBOOK_SECRET) - .callback(facebookRedirectUri) - .scope("email") - .state(fbstate) - .build(FacebookApi.instance()); - return "redirect:" + facebookAuthService.getAuthorizationUrl(); + return "redirect:" + facebookAuthService.getAuthorizationUrl(fbstate); } String redirectUrl = crosspostService.verifyFacebookState(state); @@ -134,17 +139,10 @@ public class SocialLogin { logger.error("state is missing"); throw new HttpBadRequestException(); } - OAuth20Service facebookService = facebookBuilder - .apiKey(FACEBOOK_APPID) - .apiSecret(FACEBOOK_SECRET) - .callback(facebookRedirectUri) - .scope("email") - .state(state) - .build(FacebookApi.instance()); - OAuth2AccessToken token = facebookService.getAccessToken(code); + OAuth2AccessToken token = facebookAuthService.getAccessToken(code); final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v3.2/me?fields=id,name,link,verified,email"); - facebookService.signRequest(token, meRequest); - String graph = facebookService.execute(meRequest).getBody(); + facebookAuthService.signRequest(token, meRequest); + String graph = facebookAuthService.execute(meRequest).getBody(); if (StringUtils.isBlank(graph)) { logger.error("FACEBOOK GRAPH ERROR"); throw new HttpBadRequestException(); @@ -240,13 +238,7 @@ public class SocialLogin { vkstate = UUID.randomUUID().toString(); Cookie c = new Cookie("vkstate", vkstate); response.addCookie(c); - OAuth20Service vkAuthService = vkBuilder - .apiSecret(VK_SECRET) - .scope("friends,wall,offline") - .state(vkstate) - .callback(VK_REDIRECT) - .build(VkontakteApi.instance()); - return "redirect:" + vkAuthService.getAuthorizationUrl(); + return "redirect:" + vkAuthService.getAuthorizationUrl(vkstate); } if (StringUtils.isBlank(vkstate) || !vkstate.equals(state)) { @@ -256,16 +248,11 @@ public class SocialLogin { c.setMaxAge(0); response.addCookie(c); } - - OAuth20Service vkService = vkBuilder - .apiKey(VK_APPID) - .apiSecret(VK_SECRET) - .build(VkontakteApi.instance()); - OAuth2AccessToken token = vkService.getAccessToken(code); + OAuth2AccessToken token = vkAuthService.getAccessToken(code); OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://api.vk.com/method/users.get?fields=screen_name&v=5.73"); - vkService.signRequest(token, meRequest); - String graph = vkService.execute(meRequest).getBody(); + vkAuthService.signRequest(token, meRequest); + String graph = vkAuthService.execute(meRequest).getBody(); com.juick.model.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); String vkName = jsonUser.getFirstName() + " " + jsonUser.getLastName(); -- cgit v1.2.3 From fb6d7f3b9d34032ec7ed32295b13dd556088989f Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 15 Mar 2019 14:11:47 +0300 Subject: Allow parameters in sape links --- .../juick/server/www/controllers/MessagesWWW.java | 40 ++++++++++------------ src/main/java/ru/sape/Sape.java | 4 ++- src/main/java/ru/sape/SapePageLinks.java | 15 ++++---- 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/server/www/controllers/MessagesWWW.java b/src/main/java/com/juick/server/www/controllers/MessagesWWW.java index 1c69db32..6de8d51d 100644 --- a/src/main/java/com/juick/server/www/controllers/MessagesWWW.java +++ b/src/main/java/com/juick/server/www/controllers/MessagesWWW.java @@ -43,7 +43,9 @@ import ru.sape.Sape; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import java.io.IOException; +import java.net.URI; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -182,10 +184,9 @@ public class MessagesWWW { } model.addAttribute("nextpage", nextpage); } - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape.isPresent() && visitor.isAnonymous() && queryString == null) { + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequest().build(); + URI requestURI = builder.toUri(); + if (sape.isPresent() && visitor.isAnonymous()) { String links = sape.get().getPageLinks(requestURI, sapeCookie).render(); model.addAttribute("links", links); } @@ -295,17 +296,16 @@ public class MessagesWWW { nextpage += "&show=" + paramShow; } if (paramSearch != null) { - nextpage += "&search=" + URLEncoder.encode(paramSearch, CharEncoding.UTF_8); + nextpage += "&search=" + URLEncoder.encode(paramSearch, StandardCharsets.UTF_8); } if (paramTag != null) { - nextpage += "&tag=" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8); + nextpage += "&tag=" + URLEncoder.encode(paramTag.getName(), StandardCharsets.UTF_8); } model.addAttribute("nextpage", nextpage); } - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape.isPresent() && visitor.isAnonymous() && queryString == null) { + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequest().build(); + URI requestURI = builder.toUri(); + if (sape.isPresent() && visitor.isAnonymous()) { String links = sape.get().getPageLinks(requestURI, sapeCookie).render(); model.addAttribute("links", links); } @@ -313,7 +313,7 @@ public class MessagesWWW { } @GetMapping("/{uname}/tags") - protected String doGetTags(@PathVariable String uname, ModelMap model) throws IOException { + protected String doGetTags(@PathVariable String uname, ModelMap model) { com.juick.User user = userService.getUserByName(uname); com.juick.User visitor = UserUtils.getCurrentUser(); if (visitor.isBanned()) { @@ -332,7 +332,7 @@ public class MessagesWWW { } @GetMapping("/{uname}/friends") - protected String doGetFriends(@PathVariable String uname, ModelMap model) throws IOException { + protected String doGetFriends(@PathVariable String uname, ModelMap model) { com.juick.User user = userService.getUserByName(uname); com.juick.User visitor = UserUtils.getCurrentUser(); if (visitor.isBanned()) { @@ -444,13 +444,12 @@ public class MessagesWWW { model.addAttribute("isSubscribed", tagService.isSubscribed(visitor, paramTag)); model.addAttribute("isInBL", tagService.isInBL(visitor, paramTag)); if (mids.size() >= 20) { - String nextpage = "/tag/" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8) + "?before=" + mids.get(mids.size() - 1); + String nextpage = "/tag/" + URLEncoder.encode(paramTag.getName(), StandardCharsets.UTF_8) + "?before=" + mids.get(mids.size() - 1); model.addAttribute("nextpage", nextpage); } - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape.isPresent() && visitor.isAnonymous() && queryString == null) { + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequest().build(); + URI requestURI = builder.toUri(); + if (sape.isPresent() && visitor.isAnonymous()) { String links = sape.get().getPageLinks(requestURI, sapeCookie).render(); model.addAttribute("links", links); } @@ -591,10 +590,9 @@ public class MessagesWWW { } model.addAttribute("replies", replies); model.addAttribute("showAdv", visitor.isAnonymous()); - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape.isPresent() && visitor.isAnonymous() && queryString == null) { + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequest().build(); + URI requestURI = builder.toUri(); + if (sape.isPresent() && visitor.isAnonymous()) { String links = sape.get().getPageLinks(requestURI, sapeCookie).render(); model.addAttribute("links", links); } diff --git a/src/main/java/ru/sape/Sape.java b/src/main/java/ru/sape/Sape.java index 38577c45..a94bcc62 100644 --- a/src/main/java/ru/sape/Sape.java +++ b/src/main/java/ru/sape/Sape.java @@ -3,6 +3,8 @@ */ package ru.sape; +import java.net.URI; + public class Sape { private final String sapeUser; @@ -17,7 +19,7 @@ public class Sape { } public boolean debug = false; - public SapePageLinks getPageLinks(String requestUri, String cookie) { + public SapePageLinks getPageLinks(URI requestUri, String cookie) { return new SapePageLinks(sapePageLinkConnection, sapeUser, requestUri, cookie, debug); } } diff --git a/src/main/java/ru/sape/SapePageLinks.java b/src/main/java/ru/sape/SapePageLinks.java index e89b4e71..77715aea 100644 --- a/src/main/java/ru/sape/SapePageLinks.java +++ b/src/main/java/ru/sape/SapePageLinks.java @@ -1,17 +1,18 @@ package ru.sape; +import org.apache.commons.lang3.StringUtils; + +import java.net.URI; import java.util.*; public class SapePageLinks { private boolean showCode; - public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie) { - this(sapeConnection, sapeUser, requestUri, sapeCookie, false); - } - @SuppressWarnings("unchecked") - public SapePageLinks(SapeConnection sapeConnection, String sapeUser, String requestUri, String sapeCookie, boolean showCode) { + public SapePageLinks(SapeConnection sapeConnection, String sapeUser, URI request, String sapeCookie, boolean showCode) { + String req = StringUtils.isNotEmpty(request.getQuery()) ? request.getPath() + "?" + request.getQuery() + : request.getPath(); if (sapeUser.equals(sapeCookie)) { showCode = true; } @@ -22,8 +23,8 @@ public class SapePageLinks { linkDelimiter = (String) data.get("__sape_delimiter__"); } - if (data.containsKey(requestUri)) { - pageLinks = new ArrayList<>(((Map) data.get(requestUri)).values()); + if (data.containsKey(req)) { + pageLinks = new ArrayList<>(((Map) data.get(req)).values()); } if (data.containsKey("__sape_new_url__")) { -- cgit v1.2.3 From a49105285d0d7719d7f222a507af2d5ac5b4bdb1 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 15 Mar 2019 17:17:10 +0300 Subject: Correctly set webfinger content-type --- src/main/java/com/juick/server/api/webfinger/Resource.java | 2 +- src/main/java/com/juick/server/www/controllers/MessagesWWW.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/com/juick/server/www') diff --git a/src/main/java/com/juick/server/api/webfinger/Resource.java b/src/main/java/com/juick/server/api/webfinger/Resource.java index 71a0ca31..4e0447f7 100644 --- a/src/main/java/com/juick/server/api/webfinger/Resource.java +++ b/src/main/java/com/juick/server/api/webfinger/Resource.java @@ -26,7 +26,7 @@ public class Resource { @Value("${ap_base_uri:http://localhost:8080/}") private String baseUri; - @GetMapping("/.well-known/webfinger") + @GetMapping(value = "/.well-known/webfinger", produces = "application/jrd+json;charset=utf-8") public Account getWebResource(@RequestParam String resource) { if (resource.startsWith("acct:")) { Jid account = Jid.of(resource.substring(5)); diff --git a/src/main/java/com/juick/server/www/controllers/MessagesWWW.java b/src/main/java/com/juick/server/www/controllers/MessagesWWW.java index 6de8d51d..4410f591 100644 --- a/src/main/java/com/juick/server/www/controllers/MessagesWWW.java +++ b/src/main/java/com/juick/server/www/controllers/MessagesWWW.java @@ -99,7 +99,7 @@ public class MessagesWWW { @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, ModelMap model) throws IOException { if (tag != null) { - return "redirect:/tag/" + URLEncoder.encode(tag, CharEncoding.UTF_8); + return "redirect:/tag/" + URLEncoder.encode(tag, StandardCharsets.UTF_8); } com.juick.User visitor = UserUtils.getCurrentUser(); -- cgit v1.2.3