diff options
author | 2019-03-16 23:56:27 +0300 | |
---|---|---|
committer | 2019-03-16 23:56:27 +0300 | |
commit | 06105f76dbfa3b65e63ed06f9c4d5107bd49ed88 (patch) | |
tree | 5702c01cec9688039d891f4a711878706101c1c5 /src/main/java/com/juick/service | |
parent | 3ea4cd1942fa4e763034da11c5fa429407b67829 (diff) | |
parent | a49105285d0d7719d7f222a507af2d5ac5b4bdb1 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src/main/java/com/juick/service')
10 files changed, 218 insertions, 121 deletions
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) diff --git a/src/main/java/com/juick/service/MessagesService.java b/src/main/java/com/juick/service/MessagesService.java index 4bcdba46..922170db 100644 --- a/src/main/java/com/juick/service/MessagesService.java +++ b/src/main/java/com/juick/service/MessagesService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017, Juick + * Copyright (C) 2008-2019, 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 @@ -29,7 +29,7 @@ import java.util.*; * Created by aalexeev on 11/13/16. */ public interface MessagesService { - int createMessage(int uid, String txt, String attachment, Collection<com.juick.Tag> tags); + int createMessage(int uid, String txt, String attachment, List<com.juick.Tag> tags); int createReply(int mid, int rid, User user, String txt, String attachment); @@ -68,7 +68,7 @@ public interface MessagesService { User getMessageAuthor(int mid); - List<String> getMessageRecommendations(int mid); + List<User> getMessageRecommendations(int mid); List<Integer> getAll(int visitorUid, int before); diff --git a/src/main/java/com/juick/service/MessagesServiceImpl.java b/src/main/java/com/juick/service/MessagesServiceImpl.java index 4e5dca81..7dbfe1dd 100644 --- a/src/main/java/com/juick/service/MessagesServiceImpl.java +++ b/src/main/java/com/juick/service/MessagesServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017, Juick + * Copyright (C) 2008-2019, 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 @@ -17,11 +17,14 @@ package com.juick.service; -import com.juick.*; +import com.juick.Message; +import com.juick.Reaction; +import com.juick.User; import com.juick.model.AnonymousUser; import com.juick.model.PrivacyOpts; import com.juick.model.ResponseReply; import com.juick.server.util.HttpNotFoundException; +import com.juick.server.www.WebApp; import com.juick.util.MessageUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -29,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @@ -37,12 +41,24 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Nonnull; import javax.inject.Inject; import java.net.URI; -import java.sql.*; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; import java.time.Instant; -import java.util.*; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; /** @@ -59,6 +75,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ private SearchService searchService; @Inject private ImagesService imagesService; + @Inject + private WebApp webApp; @Value("${photos_url:https://i.juick.com/}") private String baseImagesUrl; @@ -75,7 +93,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ user.setBanned(rs.getBoolean(6)); user.setUri(URI.create(Optional.ofNullable(rs.getString(22)).orElse(StringUtils.EMPTY))); msg.setUser(user); - msg.setTimestamp(rs.getTimestamp(7).toInstant()); + msg.setCreated(rs.getTimestamp(7).toInstant()); msg.ReadOnly = rs.getBoolean(8); msg.setPrivacy(rs.getInt(9)); msg.FriendsOnly = msg.getPrivacy() < 0; @@ -83,7 +101,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ msg.setAttachmentType(rs.getString(11)); msg.setLikes(rs.getInt(12)); msg.Hidden = rs.getBoolean(13); - String tagsStr = rs.getString(14); + String tagsStr = StringUtils.defaultString(rs.getString(14)); msg.setTags(MessageUtils.parseTags(tagsStr)); msg.setRepliesBy(rs.getString(15)); msg.setText(rs.getString(16)); @@ -96,6 +114,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ if (quoteUid == 0) { quoteUser.setName(AnonymousUser.INSTANCE.getName()); quoteUser.setUri(URI.create(Optional.ofNullable(rs.getString(23)).orElse(StringUtils.EMPTY))); + } else { + quoteUser.setAvatar(webApp.getAvatarUrl(quoteUser)); } msg.setTo(quoteUser); msg.setUpdatedAt(rs.getTimestamp(21).toInstant()); @@ -119,7 +139,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ */ @Transactional @Override - public int createMessage(final int uid, final String txt, final String attachment, final Collection<com.juick.Tag> tags) { + public int createMessage(final int uid, final String txt, final String attachment, final List<com.juick.Tag> tags) { SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("messages") .usingColumns("user_id", "attach", "ts") .usingGeneratedKeyColumns("message_id"); @@ -132,34 +152,25 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ } int mid = simpleJdbcInsert.executeAndReturnKey(insertMap).intValue(); if (mid > 0) { - String tagsNames = StringUtils.EMPTY; - if (CollectionUtils.isNotEmpty(tags)) { - StringBuilder tasNamesBuilder = new StringBuilder(); - List<Object[]> params = new ArrayList<>(tags.size()); - - boolean next = false; - - for (Tag tag : tags) { - if (next) { - tasNamesBuilder.append(" "); - } else - next = true; - - tasNamesBuilder.append(tag.getName()); - params.add(new Object[]{mid, tag.TID}); - } - tagsNames = tasNamesBuilder.toString(); - getJdbcTemplate().batchUpdate( "INSERT INTO messages_tags(message_id, tag_id) VALUES (?, ?)", - params, new int[]{Types.INTEGER, Types.INTEGER}); + new BatchPreparedStatementSetter() { + @Override + public void setValues(@Nonnull PreparedStatement ps, int i) throws SQLException { + ps.setInt(1, mid); + ps.setInt(2, tags.get(i).TID); + } + @Override + public int getBatchSize() { + return tags.size(); + } + }); } - getJdbcTemplate().update( - "INSERT INTO messages_txt(message_id, tags, txt, updated_at) VALUES (?, ?, ?, ?)", - new Object[]{mid, tagsNames, txt, Timestamp.from(now)}, - new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP}); + "INSERT INTO messages_txt(message_id, txt, updated_at) VALUES (?, ?, ?)", + new Object[]{mid, txt, Timestamp.from(now)}, + new int[]{Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP}); getJdbcTemplate().update("UPDATE users SET lastmessage=?, last_seen=? where id=?", Timestamp.from(now), Timestamp.from(now), uid); } @@ -365,16 +376,18 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "messages.ts," + "messages.readonly, messages.privacy, messages.replies," + "messages.attach, COUNT(DISTINCT favorites.user_id) as likes, messages.hidden," - + "txt.tags, txt.repliesby, txt.txt, '' as q, messages.updated as updated, 0 as to_uid, " + + "GROUP_CONCAT(tags.name SEPARATOR ' '), txt.repliesby, txt.txt, '' as q, messages.updated as updated, 0 as to_uid, " + "NULL as to_name, txt.updated_at, '' as user_uri, '' as to_uri, '' as reply_uri, 0 as html FROM messages " + "INNER JOIN users ON messages.user_id = users.id " + "INNER JOIN messages_txt AS txt " + "ON messages.message_id = txt.message_id " + "LEFT JOIN favorites " + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " + + "LEFT JOIN messages_tags ON messages_tags.message_id=txt.message_id " + + "LEFT JOIN tags ON tags.tag_id=messages_tags.tag_id " + "WHERE messages.message_id = ? " + "GROUP BY mid, rid, replyto, uid, nick, banned, messages.ts, readonly, " - + "privacy, replies, attach, tags, repliesby, q, updated_at, user_uri, to_uri, reply_uri, html", + + "privacy, replies, attach, repliesby, q, updated_at, user_uri, to_uri, reply_uri, html", new MessageMapper(), mid); if (!list.isEmpty()) { @@ -418,7 +431,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ URI.create(Optional.ofNullable(rs.getString(11)).orElse(StringUtils.EMPTY))); } msg.setReplyto(rs.getInt(3)); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); + msg.setCreated(rs.getTimestamp(4).toInstant()); msg.setAttachmentType(rs.getString(5)); msg.setText(rs.getString(6)); String quote = rs.getString(7); @@ -477,15 +490,21 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ @Transactional(readOnly = true) @Override - public List<String> getMessageRecommendations(final int mid) { - return getJdbcTemplate().queryForList( - "SELECT DISTINCT users.nick FROM favorites " + + public List<User> getMessageRecommendations(final int mid) { + return getJdbcTemplate().query( + "SELECT DISTINCT users.id, users.nick, favorites.user_uri FROM favorites " + "INNER JOIN users ON (favorites.message_id = ? AND favorites.user_id = users.id) " + "INNER JOIN messages m ON favorites.message_id=m.message_id WHERE favorites.like_id=1 " + "AND NOT EXISTS (SELECT 1 FROM bl_users WHERE " + "(user_id = favorites.user_id AND bl_user_id = m.user_id) " + "OR (user_id = m.user_id AND bl_user_id = favorites.user_id))", - String.class, mid); + (rs, rowNum) -> { + User user = new User(); + user.setUid(rs.getInt(1)); + user.setName(rs.getString(2)); + user.setUri(URI.create(rs.getString(3))); + return user; + }, mid); } @Transactional(readOnly = true) @@ -577,29 +596,25 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ .addValue("before", before); List<Integer> mids = getNamedParameterJdbcTemplate().queryForList( - "(SELECT message_id FROM messages " + - " INNER JOIN subscr_users ON (subscr_users.suser_id = :uid AND subscr_users.user_id = messages.user_id) " + - " WHERE " + - (before > 0 ? - " message_id < :before AND " : StringUtils.EMPTY) + - " (privacy >= 0 OR (privacy >= -2 AND privacy <= -1" + - " AND EXISTS (SELECT 1 FROM wl_users w WHERE w.wl_user_id = :uid and w.user_id = messages.user_id))) " + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + - "(SELECT tag_id FROM messages_tags WHERE message_id = messages.message_id) and :uid = bt.user_id))" + - " UNION " + - " (SELECT message_id FROM messages WHERE user_id=:uid " + - (before > 0 ? - " AND message_id < :before " : StringUtils.EMPTY) + + "SELECT message_id FROM messages WHERE " + + "(user_id=:uid OR " + + "(EXISTS (SELECT 1 FROM subscr_users WHERE subscr_users.suser_id = :uid " + + "AND subscr_users.user_id = messages.user_id) " + + "AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + + "(SELECT tag_id FROM messages_tags WHERE message_id = messages.message_id) AND :uid = bt.user_id) " + + "AND (privacy >= 0 OR (privacy >= -2 AND privacy <= -1 " + + "AND EXISTS (SELECT 1 FROM wl_users w WHERE w.wl_user_id = :uid and w.user_id = messages.user_id)))) " + (recommended ? - ") UNION " + - " (SELECT f.message_id as message_id FROM favorites f INNER JOIN messages ON " + - "f.message_id=messages.message_id WHERE " + - "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + - (before > 0 ? - " AND f.message_id < :before " : StringUtils.EMPTY) : StringUtils.EMPTY) + - " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid and b.bl_user_id = messages.user_id)" + - " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + - "(SELECT tag_id FROM messages_tags WHERE message_id = messages.message_id) and :uid = bt.user_id)) " + + "OR (EXISTS (SELECT 1 FROM favorites WHERE favorites.message_id=messages.message_id " + + "AND favorites.user_id IN (SELECT user_id FROM subscr_users WHERE suser_id=:uid)) " + + "AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN (SELECT tag_id FROM messages_tags " + + "WHERE message_id = messages.message_id) and :uid = bt.user_id) " + + "AND (privacy >= 0 OR (privacy >= -2 AND privacy <= -1 " + + "AND EXISTS (SELECT 1 FROM wl_users w " + + "WHERE w.wl_user_id = :uid and w.user_id = messages.user_id)))) " + + "AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid and b.bl_user_id = messages.user_id)" : StringUtils.EMPTY) + + ") " + + (before > 0 ? "AND message_id < :before " : StringUtils.EMPTY) + "ORDER BY message_id DESC LIMIT 20", sqlParameterSource, Integer.class); @@ -871,7 +886,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "messages.ts," + "messages.readonly,messages.privacy, messages.replies-COUNT(DISTINCT banned.reply_id) as replies," + "messages.attach,COUNT(DISTINCT favorites.user_id) AS likes,messages.hidden," - + "messages_txt.tags,messages_txt.repliesby, messages_txt.txt, '' as q, " + + "GROUP_CONCAT(tags.name SEPARATOR ' '), messages_txt.repliesby, messages_txt.txt, '' as q, " + "messages.updated, 0 as to_uid, NULL as to_name, messages_txt.updated_at, '' as m_user_uri, " + "'' as to_uri, '' as msg_reply_uri, 0 as html " + "FROM (messages INNER JOIN messages_txt " @@ -881,9 +896,11 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 " + "LEFT JOIN banned " + "ON messages.message_id = banned.message_id " + + "LEFT JOIN messages_tags ON messages_tags.message_id=messages_txt.message_id " + + "LEFT JOIN tags ON tags.tag_id=messages_tags.tag_id " + "WHERE messages.message_id IN (:ids) GROUP BY " + "messages.message_id, rid, replyto, messages.user_id, users.nick, usr_banned, messages.ts, " - + "messages.readonly, messages.privacy, messages.attach, messages.hidden, messages_txt.tags, " + + "messages.readonly, messages.privacy, messages.attach, messages.hidden, " + "messages_txt.repliesby, messages_txt.txt, q, messages.updated, to_uid, to_name, updated_at, " + "m_user_uri, msg_reply_uri, html", new MapSqlParameterSource("ids", mids) @@ -971,7 +988,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ "ORDER BY replies.reply_id ASC", new MapSqlParameterSource("mid", mid).addValue("uid", user.getUid()), new MessageMapper()); - if (replies.size() > 0) { + if (replies.size() > 0 && !user.isAnonymous()) { setRead(user, mid); } replies.forEach(i -> i.setEntities(MessageUtils.getEntities(i))); @@ -1143,7 +1160,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ @Override public boolean updateReplyUri(Message reply, URI replyUri) { - return jdbcTemplate.update("UPDATE replies SET reply_uri=?, html=1 WHERE message_id=? AND reply_id=?", + return jdbcTemplate.update("UPDATE replies SET reply_uri=?, html=0 WHERE message_id=? AND reply_id=?", replyUri.toASCIIString(), reply.getMid(), reply.getRid()) > 0; } diff --git a/src/main/java/com/juick/service/PMQueriesServiceImpl.java b/src/main/java/com/juick/service/PMQueriesServiceImpl.java index 712e4b0e..f1f98024 100644 --- a/src/main/java/com/juick/service/PMQueriesServiceImpl.java +++ b/src/main/java/com/juick/service/PMQueriesServiceImpl.java @@ -105,7 +105,7 @@ public class PMQueriesServiceImpl extends BaseJdbcService implements PMQueriesSe user.setName(rs.getString(4)); msg.setUser(user); msg.setText(rs.getString(2).trim()); - msg.setTimestamp(rs.getTimestamp(3).toInstant()); + msg.setCreated(rs.getTimestamp(3).toInstant()); return msg; }); } @@ -122,7 +122,7 @@ public class PMQueriesServiceImpl extends BaseJdbcService implements PMQueriesSe msg.getUser().setUid(rs.getInt(1)); msg.getUser().setName(rs.getString(2)); msg.setText(rs.getString(3).trim()); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); + msg.setCreated(rs.getTimestamp(4).toInstant()); return msg; }, uid); @@ -141,7 +141,7 @@ public class PMQueriesServiceImpl extends BaseJdbcService implements PMQueriesSe msg.getUser().setUid(rs.getInt(1)); msg.getUser().setName(rs.getString(2)); msg.setText(rs.getString(3).trim()); - msg.setTimestamp(rs.getTimestamp(4).toInstant()); + msg.setCreated(rs.getTimestamp(4).toInstant()); return msg; }, uid); diff --git a/src/main/java/com/juick/service/TagServiceImpl.java b/src/main/java/com/juick/service/TagServiceImpl.java index 42159d3b..95a1a309 100644 --- a/src/main/java/com/juick/service/TagServiceImpl.java +++ b/src/main/java/com/juick/service/TagServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017, Juick + * Copyright (C) 2008-2019, 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 @@ -20,10 +20,10 @@ package com.juick.service; import com.juick.Tag; import com.juick.User; import com.juick.model.TagStats; -import com.juick.util.StreamUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -31,6 +31,7 @@ import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Nonnull; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -199,21 +200,28 @@ public class TagServiceImpl extends BaseJdbcService implements TagService { "DELETE FROM messages_tags WHERE message_id = :mid AND tag_id in (:ids)", new MapSqlParameterSource().addValue("ids", idsForDelete).addValue("mid", mid)); - newTags.stream().filter(t -> !currentTags.contains(t)) - .forEach(t -> getJdbcTemplate().update("INSERT INTO messages_tags(message_id,tag_id) VALUES (?,?)", mid, t.TID)); - - List<Tag> result = getMessageTags(mid).stream() + List<Tag> addedTags = newTags.stream().filter(t -> !currentTags.contains(t)).collect(Collectors.toList()); + getJdbcTemplate().batchUpdate("INSERT INTO messages_tags(message_id,tag_id) VALUES (?,?)", new BatchPreparedStatementSetter() { + @Override + public void setValues(@Nonnull PreparedStatement ps, int i) throws SQLException { + ps.setInt(1, mid); + ps.setInt(2, addedTags.get(i).TID); + } + @Override + public int getBatchSize() { + return addedTags.size(); + } + }); + + return getMessageTags(mid).stream() .map(TagStats::getTag).collect(Collectors.toList()); - jdbcTemplate.update("UPDATE messages_txt SET tags=? WHERE message_id=?", result.stream() - .map(Tag::getName).collect(Collectors.joining(" ")), mid); - return result; } @Override public Pair<String, List<Tag>> fromString(final String txt) { String firstLine = txt.split("\\n", 2)[0]; - Supplier<Stream<String>> tagsStream = () -> StreamUtils.takeWhile(Arrays.stream(firstLine.split("\\ ")), - t -> !t.equals("*") && t.startsWith("*")); + Supplier<Stream<String>> tagsStream = () -> Arrays.stream(firstLine.split("\\ ")) + .takeWhile(t -> !t.equals("*") && t.startsWith("*")); int tagsLength = tagsStream.get().collect(Collectors.joining(" ")).length(); String body = txt.substring(tagsLength); List<Tag> tags = tagsStream.get().map(t -> getTag(t.substring(1), true)) 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..bcfb8dac 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; @@ -121,7 +120,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { return -1; } - int uid = holder.getKey().intValue(); + int uid = holder.getKeys().size() > 1 ? (int)holder.getKeys().get("id") : holder.getKey().intValue(); getJdbcTemplate().update("INSERT INTO useroptions(user_id) VALUES (?)", uid); getJdbcTemplate().update("INSERT INTO subscr_users(user_id, suser_id) VALUES (2, ?)", uid); @@ -133,7 +132,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { @Override public Optional<User> getUserByUID(final int uid) { List<User> list = getJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen, " + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen, " + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -148,7 +147,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public User getUserByName(final String username) { if (StringUtils.isNotBlank(username)) { List<User> list = getJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen, " + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen, " + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -167,7 +166,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public User getUserByEmail(String email) { if (StringUtils.isNotBlank(email)) { List<User> list = getJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen, " + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen, " + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -189,7 +188,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { if (StringUtils.isNotBlank(jid)) { List<User> list = getJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen," + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen," + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -211,7 +210,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { return Collections.emptyList(); return getNamedParameterJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen," + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen," + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -228,7 +227,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { return Collections.emptyList(); return getNamedParameterJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen," + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen," + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -288,7 +287,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public com.juick.User getUserByHash(final String hash) { if (StringUtils.isNotBlank(hash)) { List<User> list = getJdbcTemplate().query( - "SELECT logins.user_id, u.nick, u.passw, u.banned, u.last_seen," + + "SELECT DISTINCT logins.user_id, u.nick, u.passw, u.banned, u.last_seen," + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM logins INNER JOIN users u ON logins.user_id = u.id " + "LEFT JOIN facebook f ON f.user_id = u.id " + @@ -326,7 +325,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public int checkPassword(final String username, final String password) { if (StringUtils.isNotBlank(username)) { List<User> list = getJdbcTemplate().query( - "SELECT u.id, u.nick, u.passw, u.banned, u.last_seen," + + "SELECT DISTINCT u.id, u.nick, u.passw, u.banned, u.last_seen," + "COALESCE(f.fb_id, vk.vk_id, t.tg_id, e.user_id, 0) AS verified " + "FROM users u LEFT JOIN facebook f ON f.user_id = u.id " + "LEFT JOIN vk ON u.id = vk.user_id LEFT JOIN telegram t ON u.id = t.user_id " + @@ -375,29 +374,31 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { @Transactional(readOnly = true) @Override - public UserInfo getUserInfo(final User user) { - List<UserInfo> 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/main/java/com/juick/service/security/HTTPSignatureAuthenticationFilter.java b/src/main/java/com/juick/service/security/HTTPSignatureAuthenticationFilter.java new file mode 100644 index 00000000..44d97207 --- /dev/null +++ b/src/main/java/com/juick/service/security/HTTPSignatureAuthenticationFilter.java @@ -0,0 +1,71 @@ +package com.juick.service.security; + +import com.juick.User; +import com.juick.server.SignatureManager; +import com.juick.service.UserService; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.annotation.Nonnull; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + +public class HTTPSignatureAuthenticationFilter extends OncePerRequestFilter { + + private final SignatureManager signatureManager; + private final UserService userService; + + + public HTTPSignatureAuthenticationFilter( + final SignatureManager signatureManager, + final UserService userService) { + this.signatureManager = signatureManager; + this.userService = userService; + } + @Override + protected void doFilterInternal(@Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response, @Nonnull FilterChain filterChain) throws IOException, ServletException { + if (authenticationIsRequired()) { + Map<String, String> headers = Collections.list(request.getHeaderNames()) + .stream() + .collect(Collectors.toMap(String::toLowerCase, request::getHeader)); + if (StringUtils.isNotEmpty(headers.get("signature"))) { + User user = signatureManager.verifySignature(request.getMethod(), request.getRequestURI(), headers); + String userUri = user.getUri().toString(); + if (!user.isAnonymous() || userUri.length() > 0) { + if (userUri.length() == 0) { + User userWithPassword = userService.getUserByName(user.getName()); + userWithPassword.setAuthHash(userService.getHashByUID(userWithPassword.getUid())); + Authentication authentication = new UsernamePasswordAuthenticationToken(userWithPassword.getName(), userWithPassword.getCredentials()); + SecurityContextHolder.getContext().setAuthentication(authentication); + } else { + Authentication authentication = new AnonymousAuthenticationToken(userUri, user, Collections.singletonList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + } + + filterChain.doFilter(request, response); + } + + private boolean authenticationIsRequired() { + Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); + + return existingAuth == null || + !existingAuth.isAuthenticated() || + existingAuth instanceof AnonymousAuthenticationToken; + } +} diff --git a/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java b/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java index 9215d09a..2fd5a2a7 100644 --- a/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java +++ b/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java @@ -30,6 +30,7 @@ import org.springframework.util.Assert; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.WebUtils; +import javax.annotation.Nonnull; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.Cookie; @@ -59,9 +60,9 @@ public class HashParamAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal( - HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + @Nonnull HttpServletRequest request, + @Nonnull HttpServletResponse response, + @Nonnull FilterChain filterChain) throws ServletException, IOException { String hash = getHashFromRequest(request); |