Fix: Resolving Git Merge Conflicts #253
+28
-1
@@ -48,6 +48,9 @@ gradle-app.setting
|
|||||||
# JDT-specific (Eclipse Java Development Tools)
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
.classpath
|
.classpath
|
||||||
|
|
||||||
|
# Gradle properties
|
||||||
|
gradle.properties
|
||||||
|
|
||||||
## MacOS
|
## MacOS
|
||||||
# General
|
# General
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -122,4 +125,28 @@ $RECYCLE.BIN/
|
|||||||
|
|
||||||
## bin
|
## bin
|
||||||
bin/
|
bin/
|
||||||
gradle.properties
|
|
||||||
|
# LaTeX (TeX)
|
||||||
|
## Core latex/pdflatex auxiliary files:
|
||||||
|
*.aux
|
||||||
|
*.lof
|
||||||
|
*.log
|
||||||
|
*.lot
|
||||||
|
*.fls
|
||||||
|
*.out
|
||||||
|
*.toc
|
||||||
|
*.fmt
|
||||||
|
*.fot
|
||||||
|
*.cb
|
||||||
|
*.cb2
|
||||||
|
.*.lb
|
||||||
|
|
||||||
|
## Build tool auxiliary files:
|
||||||
|
*.fdb_latexmk
|
||||||
|
*.synctex
|
||||||
|
*.synctex(busy)
|
||||||
|
*.synctex.gz
|
||||||
|
*.synctex.gz(busy)
|
||||||
|
*.pdfsync
|
||||||
|
*.rubbercache
|
||||||
|
rubber.cache
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ package ch.unibas.dmi.dbis.cs108.casono.server;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameHandler;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameParser;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameParser;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginRequest;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutRequest;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingHandler;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingParser;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingParser;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingRequest;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingRequest;
|
||||||
@@ -91,5 +97,13 @@ public class ServerApp {
|
|||||||
commandRouter.register(
|
commandRouter.register(
|
||||||
CheckUsernameRequest.class,
|
CheckUsernameRequest.class,
|
||||||
new CheckUsernameHandler(responseDispatcher, userRegistry));
|
new CheckUsernameHandler(responseDispatcher, userRegistry));
|
||||||
|
|
||||||
|
parserDispatcher.register("LOGIN", new LoginParser());
|
||||||
|
commandRouter.register(
|
||||||
|
LoginRequest.class, new LoginHandler(responseDispatcher, userRegistry));
|
||||||
|
|
||||||
|
parserDispatcher.register("LOGOUT", new LogoutParser());
|
||||||
|
commandRouter.register(
|
||||||
|
LogoutRequest.class, new LogoutHandler(responseDispatcher, userRegistry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserFactory;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles {@link LoginRequest}s to create a user for a session, if the session has not assigned one
|
||||||
|
* already
|
||||||
|
*/
|
||||||
|
public class LoginHandler implements CommandHandler<LoginRequest> {
|
||||||
|
private final ResponseDispatcher responseDispatcher;
|
||||||
|
private final UserRegistry userRegistry;
|
||||||
|
private final UserFactory userFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handler for checking for existing user and creating a new one
|
||||||
|
*
|
||||||
|
* @param responseDispatcher the dispatcher used to send the response
|
||||||
|
* @param userRegistry the registry used to look up existing users and create the new one
|
||||||
|
*/
|
||||||
|
public LoginHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
|
||||||
|
this.responseDispatcher = responseDispatcher;
|
||||||
|
this.userRegistry = userRegistry;
|
||||||
|
this.userFactory = new UserFactory(userRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the login request
|
||||||
|
*
|
||||||
|
* <p>If no user is already assigned to the session, a new user is created and its name and
|
||||||
|
* {@link UserId} returned in the response. If the session has already a user assigned, a {@code
|
||||||
|
* ALREADY_LOGGED_IN} error is responded with.
|
||||||
|
*
|
||||||
|
* @param request the request to execute
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(LoginRequest request) {
|
||||||
|
Optional<User> existingUser = userRegistry.getBySessionId(request.getSessionId());
|
||||||
|
if (existingUser.isPresent()) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(),
|
||||||
|
"ALREADY_LOGGED_IN",
|
||||||
|
"This session is already associated with an active user."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userFactory.create(request.getUsername(), request.getSessionId());
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new LoginResponse(request.getContext(), user.getName(), user.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.RequestParameterAccessor;
|
||||||
|
|
||||||
|
/** Parses a primitive request into a {@link LoginRequest}. */
|
||||||
|
public class LoginParser implements CommandParser<LoginRequest> {
|
||||||
|
/**
|
||||||
|
* Extracts the required {@code USERNAME} parameter from the incoming request.
|
||||||
|
*
|
||||||
|
* @param primitiveRequest the request to parse
|
||||||
|
* @return {@link LoginRequest} containing the username
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LoginRequest parse(PrimitiveRequest primitiveRequest) {
|
||||||
|
RequestParameterAccessor accessor =
|
||||||
|
new RequestParameterAccessor(primitiveRequest.parameters());
|
||||||
|
return new LoginRequest(primitiveRequest.context(), accessor.require("USERNAME"));
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
|
||||||
|
/** Request implementation used to create server-side user instance based on provided username */
|
||||||
|
public class LoginRequest extends Request {
|
||||||
|
private final String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new LoginRequest with the given context and desired username
|
||||||
|
*
|
||||||
|
* @param context the {@link RequestContext} containing information for responding to the
|
||||||
|
* request
|
||||||
|
* @param username the desired username when creating the user
|
||||||
|
*/
|
||||||
|
public LoginRequest(RequestContext context, String username) {
|
||||||
|
super(context);
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the desired username requested for login
|
||||||
|
*
|
||||||
|
* @return the desired username
|
||||||
|
*/
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBodyBuilder;
|
||||||
|
|
||||||
|
/** Response containing the assigned username and id of said user */
|
||||||
|
public class LoginResponse extends SuccessResponse {
|
||||||
|
/**
|
||||||
|
* @param context the {@link RequestContext} associated with the request
|
||||||
|
* @param assignedUsername the assigned username to this user
|
||||||
|
* @param id of the created user
|
||||||
|
*/
|
||||||
|
public LoginResponse(RequestContext context, String assignedUsername, UserId id) {
|
||||||
|
super(
|
||||||
|
context,
|
||||||
|
new ResponseBodyBuilder()
|
||||||
|
.param("USERNAME", assignedUsername)
|
||||||
|
.param("ID", id.value())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
|
|
||||||
|
/** Handles {@link LogoutRequest} to logout connected user. */
|
||||||
|
public class LogoutHandler implements CommandHandler<LogoutRequest> {
|
||||||
|
private final ResponseDispatcher responseDispatcher;
|
||||||
|
private final UserRegistry userRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new logout handler to logout user.
|
||||||
|
*
|
||||||
|
* @param responseDispatcher dispatcher used to send the logout result back to the client
|
||||||
|
* @param userRegistry registry responsible for tracking connected user sessions
|
||||||
|
*/
|
||||||
|
public LogoutHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
|
||||||
|
this.responseDispatcher = responseDispatcher;
|
||||||
|
this.userRegistry = userRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the logout request for the given request.
|
||||||
|
*
|
||||||
|
* <p>The user is removed from the {@link UserRegistry}.
|
||||||
|
*
|
||||||
|
* @param request the request to execute
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(LogoutRequest request) {
|
||||||
|
boolean wasRemoved = userRegistry.removeBySessionId(request.getSessionId());
|
||||||
|
if (wasRemoved) {
|
||||||
|
responseDispatcher.dispatch(new OkResponse(request.getContext()));
|
||||||
|
} else {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(),
|
||||||
|
"NO_USER_ASSOCIATED",
|
||||||
|
"No user is associated with your session. Did you login before?"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||||
|
|
||||||
|
/** Parses a primitive request into a {@link LogoutRequest}. */
|
||||||
|
public class LogoutParser implements CommandParser<LogoutRequest> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a primitive request into a LogoutRequest.
|
||||||
|
*
|
||||||
|
* @param primitiveRequest the request to parse
|
||||||
|
* @return the created {@link LogoutRequest}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LogoutRequest parse(PrimitiveRequest primitiveRequest) {
|
||||||
|
return new LogoutRequest(primitiveRequest.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
|
||||||
|
/** Request implementation used to logout a currently logged in user */
|
||||||
|
public class LogoutRequest extends Request {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new LogoutRequest with the given context.
|
||||||
|
*
|
||||||
|
* @param context the {@link RequestContext} containing information for responding to the
|
||||||
|
* request
|
||||||
|
*/
|
||||||
|
public LogoutRequest(RequestContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,66 @@ public class UserRegistry {
|
|||||||
return Optional.of(user);
|
return Optional.of(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a user from the registry by user ID.
|
||||||
|
*
|
||||||
|
* @param userId the ID of the user to remove
|
||||||
|
* @return true if a user was removed, false if no user with that ID exists
|
||||||
|
*/
|
||||||
|
public synchronized boolean removeByUserId(UserId userId) {
|
||||||
|
User user = byId.get(userId);
|
||||||
|
if (user == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
byName.remove(user.getName());
|
||||||
|
user.getSessionId().ifPresent(bySessionId::remove);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a user from the registry by session ID.
|
||||||
|
*
|
||||||
|
* @param sessionId the session ID associated with the user to remove
|
||||||
|
* @return true if a user was removed, false if no user with that session exists
|
||||||
|
*/
|
||||||
|
public synchronized boolean removeBySessionId(SessionId sessionId) {
|
||||||
|
User user = bySessionId.get(sessionId);
|
||||||
|
if (user == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a user from the registry by username.
|
||||||
|
*
|
||||||
|
* @param username the username associated with the user to remove
|
||||||
|
* @return true if a user was removed, false if no user with that session exists
|
||||||
|
*/
|
||||||
|
public synchronized boolean removeByUsername(String username) {
|
||||||
|
User user = byName.get(username);
|
||||||
|
if (user == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a user from the internals of the registry.
|
||||||
|
*
|
||||||
|
* @param user the user to remove
|
||||||
|
*/
|
||||||
|
private synchronized void remove(User user) {
|
||||||
|
byId.remove(user.getId());
|
||||||
|
byName.remove(user.getName());
|
||||||
|
user.getSessionId().ifPresent(bySessionId::remove);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the user with the given ID, but only if they are still disconnected. This prevents
|
* Removes the user with the given ID, but only if they are still disconnected. This prevents
|
||||||
* removing a user who has reconnected between the cleanup job's check and its removal call.
|
* removing a user who has reconnected between the cleanup job's check and its removal call.
|
||||||
@@ -47,8 +107,7 @@ public class UserRegistry {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
byId.remove(user.getId());
|
remove(user);
|
||||||
byName.remove(user.getName());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user