Move Envoy Server Standalone to server/ subdirectory
This commit is contained in:
189
server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java
Executable file
189
server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java
Executable file
@ -0,0 +1,189 @@
|
||||
package envoy.server.processors;
|
||||
|
||||
import static envoy.data.Message.MessageStatus.*;
|
||||
import static envoy.data.User.UserStatus.ONLINE;
|
||||
import static envoy.event.HandshakeRejection.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.event.GroupMessageStatusChange;
|
||||
import envoy.event.HandshakeRejection;
|
||||
import envoy.event.MessageStatusChange;
|
||||
import envoy.server.data.GroupMessage;
|
||||
import envoy.server.data.PersistenceManager;
|
||||
import envoy.server.data.User;
|
||||
import envoy.server.net.ConnectionManager;
|
||||
import envoy.server.net.ObjectWriteProxy;
|
||||
import envoy.server.util.PasswordUtil;
|
||||
import envoy.server.util.VersionUtil;
|
||||
import envoy.util.Bounds;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
/**
|
||||
* This {@link ObjectProcessor} handles {@link LoginCredentials}.<br>
|
||||
* <br>
|
||||
* Project: <strong>envoy-server-standalone</strong><br>
|
||||
* File: <strong>LoginCredentialProcessor.java</strong><br>
|
||||
* Created: <strong>30.12.2019</strong><br>
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Server Standalone v0.1-alpha
|
||||
*/
|
||||
public final class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> {
|
||||
|
||||
private final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
||||
private final ConnectionManager connectionManager = ConnectionManager.getInstance();
|
||||
|
||||
private static final Logger logger = EnvoyLog.getLogger(LoginCredentialProcessor.class);
|
||||
|
||||
@Override
|
||||
public void process(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) {
|
||||
|
||||
// Cache this write proxy for user-independant notifications
|
||||
UserStatusChangeProcessor.setWriteProxy(writeProxy);
|
||||
|
||||
if (!VersionUtil.verifyCompatibility(credentials.getClientVersion())) {
|
||||
logger.info("The client has the wrong version.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(WRONG_VERSION));
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 (!PasswordUtil.validate(credentials.getPassword(), 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 {
|
||||
// Validate user name
|
||||
if (!Bounds.isValidContactName(credentials.getIdentifier())) {
|
||||
logger.info("The requested user name is not valid.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
|
||||
return;
|
||||
}
|
||||
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(USERNAME_TAKEN));
|
||||
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(PasswordUtil.hash(credentials.getPassword()));
|
||||
user.setContacts(new HashSet<>());
|
||||
persistenceManager.addContact(user);
|
||||
logger.info("Registered new " + user);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(user + " successfully authenticated.");
|
||||
connectionManager.registerUser(user.getID(), socketID);
|
||||
|
||||
// Change status and notify contacts about it
|
||||
user.setStatus(ONLINE);
|
||||
UserStatusChangeProcessor.updateUserStatus(user);
|
||||
|
||||
// Complete the handshake
|
||||
writeProxy.write(socketID, user.toCommon());
|
||||
|
||||
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user);
|
||||
pendingMessages.removeIf(GroupMessage.class::isInstance);
|
||||
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");
|
||||
|
||||
for (var msg : pendingMessages) {
|
||||
final var msgCommon = msg.toCommon();
|
||||
if (msg.getStatus() == SENT) {
|
||||
|
||||
// Send the message
|
||||
writeProxy.write(socketID, msgCommon);
|
||||
msg.received();
|
||||
PersistenceManager.getInstance().updateMessage(msg);
|
||||
|
||||
// Notify the sender about the delivery
|
||||
if (connectionManager.isOnline(msg.getSender().getID())) {
|
||||
msgCommon.nextStatus();
|
||||
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()), new MessageStatusChange(msgCommon));
|
||||
}
|
||||
} else writeProxy.write(socketID, new MessageStatusChange(msgCommon));
|
||||
}
|
||||
|
||||
List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance().getPendingGroupMessages(user);
|
||||
logger.fine("Sending " + pendingGroupMessages.size() + " pending group messages to " + user + "...");
|
||||
|
||||
for (var gmsg : pendingGroupMessages) {
|
||||
final var gmsgCommon = gmsg.toCommon();
|
||||
|
||||
// Deliver the message to the user if he hasn't received it yet
|
||||
if (gmsg.getMemberMessageStatus().get(user.getID()) == SENT) {
|
||||
gmsg.getMemberMessageStatus().replace(user.getID(), RECEIVED);
|
||||
|
||||
gmsg.setLastStatusChangeDate(LocalDateTime.now());
|
||||
|
||||
writeProxy.write(socketID, gmsgCommon);
|
||||
|
||||
// Notify all online group members about the status change
|
||||
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
|
||||
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, LocalDateTime
|
||||
.now(),
|
||||
connectionManager.getUserIDBySocketID(socketID)));
|
||||
|
||||
if (Collections.min(gmsg.getMemberMessageStatus().values()) == RECEIVED) {
|
||||
gmsg.received();
|
||||
|
||||
// Notify online members about the status change
|
||||
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
|
||||
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), LocalDateTime.now()));
|
||||
}
|
||||
|
||||
PersistenceManager.getInstance().updateMessage(gmsg);
|
||||
} else {
|
||||
|
||||
// Sending group message status changes
|
||||
if (gmsg.getStatus() == SENT && gmsg.getLastStatusChangeDate().isAfter(gmsg.getCreationDate())
|
||||
|| gmsg.getStatus() == RECEIVED && gmsg.getLastStatusChangeDate().isAfter(gmsg.getReceivedDate())) {
|
||||
gmsg.getMemberMessageStatus().forEach((memberID, memberStatus) ->
|
||||
writeProxy.write(socketID, new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID)));
|
||||
}
|
||||
|
||||
// Deliver just a status change instead of the whole message
|
||||
if (gmsg.getStatus() == SENT && user.getLastSeen().isBefore(gmsg.getCreationDate())
|
||||
|| gmsg.getStatus() == RECEIVED && user.getLastSeen().isBefore(gmsg.getReceivedDate()))
|
||||
writeProxy.write(socketID, new MessageStatusChange(gmsgCommon));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
|
||||
}
|
Reference in New Issue
Block a user