From 8e83a22012c2bee323eeeb3ae1384ac488741ebf Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 23 Oct 2018 17:48:25 +0300 Subject: Last seen --- juick-common/src/main/java/com/juick/User.java | 10 +++++++ .../main/java/com/juick/service/UserService.java | 3 ++ .../java/com/juick/server/CommandsManager.java | 3 ++ .../main/java/com/juick/server/XMPPConnection.java | 5 ++++ .../main/java/com/juick/server/api/Service.java | 8 ++++-- .../com/juick/service/MessagesServiceImpl.java | 4 +-- .../java/com/juick/service/UserServiceImpl.java | 33 ++++++++++++++++------ .../resources/db/migration/V1.16__last seen.sql | 2 ++ .../java/com/juick/server/tests/ServerTests.java | 11 ++++++-- 9 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 juick-server/src/main/resources/db/migration/V1.16__last seen.sql diff --git a/juick-common/src/main/java/com/juick/User.java b/juick-common/src/main/java/com/juick/User.java index 765b5abb..ca907987 100644 --- a/juick-common/src/main/java/com/juick/User.java +++ b/juick-common/src/main/java/com/juick/User.java @@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import java.net.URI; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -50,6 +51,7 @@ public class User { private List readers; private List unread; private URI uri; + private Instant seen; public User() { tokens = new ArrayList<>(); @@ -209,4 +211,12 @@ public class User { public void setUri(URI uri) { this.uri = uri; } + + public Instant getSeen() { + return seen; + } + + public void setSeen(Instant seen) { + this.seen = seen; + } } diff --git a/juick-common/src/main/java/com/juick/service/UserService.java b/juick-common/src/main/java/com/juick/service/UserService.java index d59f71ef..832f978a 100644 --- a/juick-common/src/main/java/com/juick/service/UserService.java +++ b/juick-common/src/main/java/com/juick/service/UserService.java @@ -23,6 +23,7 @@ import com.juick.model.Auth; import com.juick.model.UserInfo; import javax.annotation.Nonnull; +import java.time.Instant; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -131,4 +132,6 @@ public interface UserService { boolean unauthJID(int uid, String jid); List getActiveJIDs(); + + void updateLastSeen(User user); } diff --git a/juick-server/src/main/java/com/juick/server/CommandsManager.java b/juick-server/src/main/java/com/juick/server/CommandsManager.java index 597604c6..ade70dc9 100644 --- a/juick-server/src/main/java/com/juick/server/CommandsManager.java +++ b/juick-server/src/main/java/com/juick/server/CommandsManager.java @@ -77,6 +77,9 @@ public class CommandsManager { private ImagesService imagesService; public CommandResult processCommand(User user, String data, @Nonnull URI attachment) throws Exception { + if (!user.isAnonymous()) { + userService.updateLastSeen(user); + } String strippedData = StringUtils.stripStart(data, null); if (strippedData.startsWith("?OTR")) { return CommandResult.fromString("?OTR Error: we are not using OTR"); diff --git a/juick-server/src/main/java/com/juick/server/XMPPConnection.java b/juick-server/src/main/java/com/juick/server/XMPPConnection.java index d03251a3..9c0c09e1 100644 --- a/juick-server/src/main/java/com/juick/server/XMPPConnection.java +++ b/juick-server/src/main/java/com/juick/server/XMPPConnection.java @@ -497,6 +497,11 @@ public class XMPPConnection implements StanzaListener, NotificationListener { int uid_to = 0; if (!toJuick) { uid_to = userService.getUIDbyName(username); + } else { + User visitor = userService.getUserByJID(p.getFrom().asBareJid().toEscapedString()); + if (visitor != null) { + userService.updateLastSeen(visitor); + } } if (toJuick || uid_to > 0) { diff --git a/juick-server/src/main/java/com/juick/server/api/Service.java b/juick-server/src/main/java/com/juick/server/api/Service.java index 2938e9da..3cf3ac28 100644 --- a/juick-server/src/main/java/com/juick/server/api/Service.java +++ b/juick-server/src/main/java/com/juick/server/api/Service.java @@ -144,12 +144,16 @@ public class Service { } @GetMapping("/api/events") public SseEmitter handle() throws IOException { - logger.info("{} connected", UserUtils.getCurrentUser().getName()); + User visitor = UserUtils.getCurrentUser(); + logger.info("{} connected", visitor.getName()); + if (!visitor.isAnonymous()) { + userService.updateLastSeen(visitor); + } SseEmitter emitter = new SseEmitter(600000L); Message service = new Message(); service.setService(true); emitter.send(service); - serverManager.getSessions().add(new ServerManager.EventSession(UserUtils.getCurrentUser(), emitter)); + serverManager.getSessions().add(new ServerManager.EventSession(visitor, emitter)); emitter.onCompletion(() -> endSession(emitter)); emitter.onTimeout(() -> endSession(emitter)); diff --git a/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java index 65a4f116..0b7faf87 100644 --- a/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java @@ -160,7 +160,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ "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}); - getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", Timestamp.from(now), uid); + getJdbcTemplate().update("UPDATE users SET lastmessage=?, last_seen=? where id=?", Timestamp.from(now), Timestamp.from(now), uid); } return mid; @@ -189,7 +189,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ "UPDATE messages SET replies = replies + 1, updated=? WHERE message_id = ?", ts, mid); setLastReadComment(user, mid, ridnew); - getJdbcTemplate().update("UPDATE users SET lastmessage=? where id=?", ts, user.getUid()); + getJdbcTemplate().update("UPDATE users SET lastmessage=?, last_seen=? where id=?", ts, ts, user.getUid()); } return ridnew; } diff --git a/juick-server/src/main/java/com/juick/service/UserServiceImpl.java b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java index 0eae1ae3..fdc4f28c 100644 --- a/juick-server/src/main/java/com/juick/service/UserServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java @@ -39,7 +39,13 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.*; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; /** * Created by aalexeev on 11/13/16. @@ -56,6 +62,10 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { user.setName(rs.getString(2)); user.setCredentials(rs.getString(3)); user.setBanned(rs.getBoolean(4)); + Timestamp seen = rs.getTimestamp(5); + if (seen != null) { + user.setSeen(seen.toInstant()); + } return user; } } @@ -122,7 +132,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { @Override public Optional getUserByUID(final int uid) { List list = getJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE id = ?", new UserMapper(), uid); + "SELECT id, nick, passw, banned, last_seen FROM users WHERE id = ?", new UserMapper(), uid); return list.isEmpty() ? Optional.empty() : Optional.of(list.get(0)); } @@ -133,7 +143,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public User getUserByName(final String username) { if (StringUtils.isNotBlank(username)) { List list = getJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE nick = ?", new UserMapper(), username); + "SELECT id, nick, passw, banned, last_seen FROM users WHERE nick = ?", new UserMapper(), username); if (!list.isEmpty()) return list.get(0); @@ -147,7 +157,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public User getUserByEmail(String email) { if (StringUtils.isNotBlank(email)) { List list = getJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE id = (SELECT DISTINCT user_id FROM emails WHERE email = ?)", + "SELECT id, nick, passw, banned, last_seen FROM users WHERE id = (SELECT DISTINCT user_id FROM emails WHERE email = ?)", new UserMapper(), email); @@ -164,7 +174,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { if (StringUtils.isNotBlank(jid)) { List list = getJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE id = (SELECT user_id FROM jids WHERE jid = ?)", + "SELECT id, nick, passw, banned, last_seen FROM users WHERE id = (SELECT user_id FROM jids WHERE jid = ?)", new UserMapper(), jid); @@ -181,7 +191,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { return Collections.emptyList(); return getNamedParameterJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE nick IN (:unames)", + "SELECT id, nick, passw, banned, last_seen FROM users WHERE nick IN (:unames)", new MapSqlParameterSource("unames", unames), new UserMapper()); } @@ -193,7 +203,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { return Collections.emptyList(); return getNamedParameterJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE id IN (:ids)", + "SELECT id, nick, passw, banned, last_seen FROM users WHERE id IN (:ids)", new MapSqlParameterSource("ids", uids), new UserMapper()); } @@ -248,7 +258,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public com.juick.User getUserByHash(final String hash) { if (StringUtils.isNotBlank(hash)) { List list = getJdbcTemplate().query( - "SELECT logins.user_id, users.nick, users.passw, users.banned FROM logins " + + "SELECT logins.user_id, users.nick, users.passw, users.banned, last_seen FROM logins " + "INNER JOIN users ON logins.user_id = users.id WHERE logins.hash = ?", new UserMapper(), hash); @@ -281,7 +291,7 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public int checkPassword(final String username, final String password) { if (StringUtils.isNotBlank(username)) { List list = getJdbcTemplate().query( - "SELECT id, nick, passw, banned FROM users WHERE nick = ?", + "SELECT id, nick, passw, banned, last_seen FROM users WHERE nick = ?", new UserMapper(), username); @@ -650,4 +660,9 @@ public class UserServiceImpl extends BaseJdbcService implements UserService { public List getActiveJIDs() { return getJdbcTemplate().queryForList("SELECT jid FROM jids WHERE active=1 AND loginhash IS NULL", String.class); } + + @Override + public void updateLastSeen(User user) { + getJdbcTemplate().update("UPDATE users SET last_seen=now() WHERE id=?", user.getUid()); + } } diff --git a/juick-server/src/main/resources/db/migration/V1.16__last seen.sql b/juick-server/src/main/resources/db/migration/V1.16__last seen.sql new file mode 100644 index 00000000..52ca4e90 --- /dev/null +++ b/juick-server/src/main/resources/db/migration/V1.16__last seen.sql @@ -0,0 +1,2 @@ +ALTER TABLE users ADD COLUMN last_seen timestamp(6) NULL; +UPDATE users SET last_seen=lastmessage; \ No newline at end of file diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java index a6750644..58596850 100644 --- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java +++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java @@ -33,7 +33,6 @@ import com.juick.model.PrivateChats; import com.juick.model.TagStats; import com.juick.server.*; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.Key; import com.juick.server.api.activity.model.Note; import com.juick.server.api.activity.model.Person; import com.juick.server.api.activity.model.activities.Create; @@ -159,8 +158,6 @@ public class ServerTests { @Inject private ObjectMapper jsonMapper; @Inject - private WebApplicationContext wac; - @Inject private XMPPServer server; @Inject private CommandsManager commandsManager; @@ -1745,4 +1742,12 @@ public class ServerTests { PrivateChats chats = jsonMapper.readValue(result.getResponse().getContentAsString(), PrivateChats.class); assertThat(chats.getUsers().size(), is(1)); } + @Test + public void seenTests() { + Instant now = Instant.now(); + int newUserUid = userService.createUser("newuser", "assword"); + assertThat(userService.getUserByUID(newUserUid).get().getSeen(), is(nullValue())); + messagesService.createMessage(newUserUid, "YO", "", null); + assertThat(userService.getUserByUID(newUserUid).get().getSeen(), greaterThan(now)); + } } -- cgit v1.2.3