2020-01-11 18:28:48 +01:00
|
|
|
package envoy.server.processors;
|
2019-12-30 14:53:40 +01:00
|
|
|
|
2020-06-20 09:57:54 +02:00
|
|
|
import static envoy.data.User.UserStatus.ONLINE;
|
|
|
|
import static envoy.event.HandshakeRejection.*;
|
|
|
|
|
2020-01-06 13:58:28 +01:00
|
|
|
import java.io.IOException;
|
2020-06-20 09:57:54 +02:00
|
|
|
import java.time.LocalDateTime;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.HashSet;
|
2020-06-11 12:06:06 +02:00
|
|
|
import java.util.logging.Logger;
|
2020-01-06 13:58:28 +01:00
|
|
|
|
2020-02-07 23:37:33 +01:00
|
|
|
import javax.persistence.NoResultException;
|
|
|
|
|
2019-12-30 14:53:40 +01:00
|
|
|
import envoy.data.LoginCredentials;
|
2020-01-11 18:28:48 +01:00
|
|
|
import envoy.data.Message.MessageStatus;
|
2020-06-20 09:57:54 +02:00
|
|
|
import envoy.event.HandshakeRejection;
|
|
|
|
import envoy.event.MessageStatusChange;
|
|
|
|
import envoy.server.Startup;
|
2020-02-15 22:43:20 +01:00
|
|
|
import envoy.server.data.PersistenceManager;
|
2020-06-20 09:57:54 +02:00
|
|
|
import envoy.server.data.User;
|
2020-02-12 22:01:32 +01:00
|
|
|
import envoy.server.net.ConnectionManager;
|
2020-01-06 13:58:28 +01:00
|
|
|
import envoy.server.net.ObjectWriteProxy;
|
2020-06-11 12:06:06 +02:00
|
|
|
import envoy.util.EnvoyLog;
|
2019-12-30 14:53:40 +01:00
|
|
|
|
|
|
|
/**
|
2019-12-30 15:15:25 +01:00
|
|
|
* This {@link ObjectProcessor} handles {@link LoginCredentials}.<br>
|
|
|
|
* <br>
|
2019-12-30 14:53:40 +01:00
|
|
|
* Project: <strong>envoy-server-standalone</strong><br>
|
|
|
|
* File: <strong>LoginCredentialProcessor.java</strong><br>
|
|
|
|
* Created: <strong>30.12.2019</strong><br>
|
2019-12-30 15:15:25 +01:00
|
|
|
*
|
2019-12-30 14:53:40 +01:00
|
|
|
* @author Kai S. K. Engelbart
|
2020-01-18 23:50:41 +01:00
|
|
|
* @author Maximilian Käfer
|
2019-12-30 15:15:25 +01:00
|
|
|
* @since Envoy Server Standalone v0.1-alpha
|
2019-12-30 14:53:40 +01:00
|
|
|
*/
|
2020-06-20 09:57:54 +02:00
|
|
|
public final class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> {
|
2019-12-30 14:53:40 +01:00
|
|
|
|
2020-02-12 07:10:33 +01:00
|
|
|
private final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
|
|
|
private final ConnectionManager connectionManager = ConnectionManager.getInstance();
|
2019-12-30 15:15:25 +01:00
|
|
|
|
2020-06-11 12:06:06 +02:00
|
|
|
private static final Logger logger = EnvoyLog.getLogger(LoginCredentialProcessor.class);
|
2020-06-20 09:57:54 +02:00
|
|
|
// private static final Pattern versionPattern =
|
|
|
|
// Pattern.compile("v(?<major>\\d).(?<minor>\\d)(?:-(?<suffix>\\w+))?");
|
2020-06-11 12:06:06 +02:00
|
|
|
|
2019-12-30 14:53:40 +01:00
|
|
|
@Override
|
2020-06-20 09:57:54 +02:00
|
|
|
public void process(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
|
|
|
|
|
|
|
// Cache this write proxy for user-independant notifications
|
2020-02-02 13:34:28 +01:00
|
|
|
UserStatusChangeProcessor.setWriteProxy(writeProxy);
|
2020-01-06 13:58:28 +01:00
|
|
|
|
2020-06-20 09:57:54 +02:00
|
|
|
// TODO: Verify compatibility
|
|
|
|
if (Startup.MIN_CLIENT_VERSION.compareTo(credentials.getClientVersion()) <= 0
|
|
|
|
&& Startup.MAX_CLIENT_VERSION.compareTo(credentials.getClientVersion()) >= 0) {
|
|
|
|
// writeProxy.write(socketID, new HandshakeRejectionEvent("Wrong version"));
|
|
|
|
// return;
|
|
|
|
}
|
2020-01-18 23:50:41 +01:00
|
|
|
|
2020-06-20 09:57:54 +02:00
|
|
|
// Acquire a user object (or reject the handshake if that's impossible)
|
|
|
|
User user = null;
|
|
|
|
if (!credentials.isRegistration()) {
|
|
|
|
try {
|
|
|
|
user = persistenceManager.getUserByName(credentials.getIdentifier());
|
|
|
|
|
|
|
|
// Checking if user is already online
|
|
|
|
if (connectionManager.isOnline(user.getID())) {
|
|
|
|
logger.warning(user + " is already online!");
|
|
|
|
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Evaluating the correctness of the password hash
|
|
|
|
if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) {
|
|
|
|
logger.info(user + " has entered the wrong password.");
|
|
|
|
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (NoResultException e) {
|
|
|
|
logger.info("The requested user does not exist.");
|
|
|
|
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
// Checking that no user already has this identifier
|
|
|
|
PersistenceManager.getInstance().getUserByName(credentials.getIdentifier());
|
|
|
|
|
|
|
|
// This code only gets executed if this user already exists
|
|
|
|
logger.info("The requested user already exists.");
|
|
|
|
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
|
|
|
|
return;
|
|
|
|
} catch (NoResultException e) {
|
|
|
|
// Creation of a new user
|
|
|
|
user = new User();
|
|
|
|
user.setName(credentials.getIdentifier());
|
|
|
|
user.setLastSeen(LocalDateTime.now());
|
|
|
|
user.setStatus(ONLINE);
|
|
|
|
user.setPasswordHash(credentials.getPasswordHash());
|
|
|
|
user.setContacts(new HashSet<>());
|
|
|
|
persistenceManager.addContact(user);
|
|
|
|
logger.info("Registered new " + user);
|
|
|
|
}
|
2020-02-12 07:10:33 +01:00
|
|
|
}
|
2020-06-20 09:57:54 +02:00
|
|
|
|
|
|
|
logger.info(user + " successfully authenticated.");
|
|
|
|
|
2020-03-26 20:14:09 +01:00
|
|
|
connectionManager.registerUser(user.getID(), socketID);
|
2020-02-04 21:09:59 +01:00
|
|
|
|
2020-06-20 09:57:54 +02:00
|
|
|
// Change status and notify contacts about it
|
|
|
|
user.setStatus(ONLINE);
|
2020-02-05 21:32:53 +01:00
|
|
|
UserStatusChangeProcessor.updateUserStatus(user);
|
2020-01-25 18:41:44 +01:00
|
|
|
|
2020-06-20 09:57:54 +02:00
|
|
|
// Complete the handshake
|
2020-03-26 20:14:09 +01:00
|
|
|
writeProxy.write(socketID, user.toCommon());
|
2020-06-20 09:57:54 +02:00
|
|
|
|
|
|
|
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user);
|
|
|
|
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");
|
|
|
|
for (var msg : pendingMessages) {
|
|
|
|
final var msgCommon = msg.toCommon();
|
2020-04-02 20:41:05 +02:00
|
|
|
if (msg.getStatus() == MessageStatus.SENT) {
|
2020-06-20 09:57:54 +02:00
|
|
|
writeProxy.write(socketID, msgCommon);
|
|
|
|
msg.received();
|
|
|
|
if (connectionManager.isOnline(msg.getSender().getID()))
|
|
|
|
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()), new MessageStatusChange(msgCommon));
|
2020-04-02 20:41:05 +02:00
|
|
|
PersistenceManager.getInstance().updateMessage(msg);
|
2020-06-20 09:57:54 +02:00
|
|
|
} else writeProxy.write(socketID, new MessageStatusChange(msgCommon));
|
|
|
|
}
|
2019-12-30 14:53:40 +01:00
|
|
|
}
|
2020-01-25 18:41:44 +01:00
|
|
|
|
2020-02-12 07:10:33 +01:00
|
|
|
@Override
|
|
|
|
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
|
2019-12-30 14:53:40 +01:00
|
|
|
}
|