diff --git a/README.md b/README.md
index 80bd162..a77c9b1 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ You probably want to customize your server a bit. To do so, first stop your serv
- `name` The name of the server.
- `description` A short description of what this server is for, or who it's run by.
- `port` The port on which the server accepts client connections.
+- `acceptAllNewClients` Whether to automatically accept any new client that registers to this server. Set to false by default, meaning an administrator needs to approve any pending registration before it is complete.
- `chatHistoryMaxCount` The maximum amount of chat messages that a client can request from the server at any given time. Decrease this to improve performance.
- `chatHistoryDefaultCount` The default number of chat messages that are provided to clients when they join a channel, if they don't explicitly request a certain amount. Decrease this to improve performance.
- `maxMessageLength` The maximum length of a message. Messages longer than this will be rejected.
@@ -46,11 +47,6 @@ You probably want to customize your server a bit. To do so, first stop your serv
## Server CLI
-As mentioned briefly, the server supports a basic command-line-interface with some commands. You can show which commands are available via the `help` command. The following is a list of some of the most useful commands and a description of their functionality:
-
-- `add-channel
+ * This core module defines the message protocol that clients must use to
+ * communicate with any server.
+ *
* The following query parameters are supported: + *
*count
- Fetch up to N messages. Minimum of 1, and
* a server-specific maximum count, usually no higher than 1000.* Responses to this request are sent via {@link ChatHistoryResponse}, where * the list of messages is always sorted by the timestamp. diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/ChatHistoryResponse.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/ChatHistoryResponse.java index 4743bfa..629d856 100644 --- a/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/ChatHistoryResponse.java +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/ChatHistoryResponse.java @@ -7,5 +7,7 @@ import java.util.UUID; /** * The response that a server sends to a {@link ChatHistoryRequest}. The list of * messages is ordered by timestamp, with the newest messages appearing first. + * @param channelId The id of the channel that the chat messages belong to. + * @param messages The list of messages that comprises the history. */ public record ChatHistoryResponse (UUID channelId, Chat[] messages) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/package-info.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/package-info.java new file mode 100644 index 0000000..da1115c --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/chat/package-info.java @@ -0,0 +1,5 @@ +/** + * Messages pertaining to chat messages and other auxiliary messages regarding + * the management of chat information. + */ +package nl.andrewl.concord_core.msg.types.chat; \ No newline at end of file diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientLogin.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientLogin.java new file mode 100644 index 0000000..6455aff --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientLogin.java @@ -0,0 +1,9 @@ +package nl.andrewl.concord_core.msg.types.client_setup; + +import nl.andrewl.concord_core.msg.Message; + +/** + * This message is sent by clients to log into a server that they have already + * registered with, but don't have a valid session token for. + */ +public record ClientLogin(String username, String password) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Registration.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientRegistration.java similarity index 60% rename from core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Registration.java rename to core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientRegistration.java index 4421dc5..a8a2f74 100644 --- a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Registration.java +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientRegistration.java @@ -6,4 +6,9 @@ import nl.andrewl.concord_core.msg.Message; * The data that new users should send to a server in order to register in that * server. */ -public record Registration (String username, String password) implements Message {} +public record ClientRegistration( + String name, + String description, + String username, + String password +) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientSessionResume.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientSessionResume.java new file mode 100644 index 0000000..ee9881e --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/ClientSessionResume.java @@ -0,0 +1,9 @@ +package nl.andrewl.concord_core.msg.types.client_setup; + +import nl.andrewl.concord_core.msg.Message; + +/** + * This message is sent by the client to log into a server using a session token + * instead of a username/password combination. + */ +public record ClientSessionResume(String sessionToken) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Identification.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Identification.java deleted file mode 100644 index ed2d237..0000000 --- a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/Identification.java +++ /dev/null @@ -1,11 +0,0 @@ -package nl.andrewl.concord_core.msg.types.client_setup; - -import nl.andrewl.concord_core.msg.Message; - -/** - * This message is sent from the client to a server, to provide identification - * information about the client to the server when the connection is started. - * - * @param nickname - */ -public record Identification(String nickname, String sessionToken) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/KeyData.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/KeyData.java index f46d18f..feca228 100644 --- a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/KeyData.java +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/KeyData.java @@ -5,5 +5,8 @@ import nl.andrewl.concord_core.msg.Message; /** * This message is sent as the first message from both the server and the client * to establish an end-to-end encryption via a key exchange. + * @param iv The initialization vector bytes. + * @param salt The salt bytes. + * @param publicKey The public key. */ public record KeyData (byte[] iv, byte[] salt, byte[] publicKey) implements Message {} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/RegistrationStatus.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/RegistrationStatus.java new file mode 100644 index 0000000..43b951d --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/RegistrationStatus.java @@ -0,0 +1,15 @@ +package nl.andrewl.concord_core.msg.types.client_setup; + +import nl.andrewl.concord_core.msg.Message; + +/** + * A response from the server which indicates the current status of the client's + * registration request. + */ +public record RegistrationStatus (Type type, String reason) implements Message { + public enum Type {PENDING, ACCEPTED, REJECTED} + + public static RegistrationStatus pending() { + return new RegistrationStatus(Type.PENDING, null); + } +} diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/package-info.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/package-info.java new file mode 100644 index 0000000..f23e1e6 --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/client_setup/package-info.java @@ -0,0 +1,4 @@ +/** + * Messages pertaining to the establishment of a connection with clients. + */ +package nl.andrewl.concord_core.msg.types.client_setup; \ No newline at end of file diff --git a/core/src/main/java/nl/andrewl/concord_core/msg/types/package-info.java b/core/src/main/java/nl/andrewl/concord_core/msg/types/package-info.java new file mode 100644 index 0000000..f060e4f --- /dev/null +++ b/core/src/main/java/nl/andrewl/concord_core/msg/types/package-info.java @@ -0,0 +1,10 @@ +/** + * Contains all the various message types which can be sent between the server + * and client. + *
+ * Note that not all message types defined here may be supported by the + * latest version of Concord. See {@link nl.andrewl.concord_core.msg.Serializer} + * for the definitive list. + *
+ */ +package nl.andrewl.concord_core.msg.types; \ No newline at end of file diff --git a/core/src/main/java/nl/andrewl/concord_core/util/ChainedDataOutputStream.java b/core/src/main/java/nl/andrewl/concord_core/util/ChainedDataOutputStream.java index 48e0687..38df084 100644 --- a/core/src/main/java/nl/andrewl/concord_core/util/ChainedDataOutputStream.java +++ b/core/src/main/java/nl/andrewl/concord_core/util/ChainedDataOutputStream.java @@ -63,13 +63,16 @@ public class ChainedDataOutputStream { public+ More content coming soon! +
+ + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8e65f56..16c95bd 100644 --- a/pom.xml +++ b/pom.xml @@ -16,9 +16,10 @@- * If the client provides a session token with their identification - * message, then we should load their data from our database, otherwise - * we assume this is a new client. - *
- * @param identification The client's identification data. - * @param clientThread The client manager thread. + * Handles an attempt by a new client to register as a user for this server. + * If the server is set to automatically accept all new clients, the new + * user is registered and the client is sent a {@link RegistrationStatus} + * with the {@link RegistrationStatus.Type#ACCEPTED} value, closely followed + * by a {@link ServerWelcome} message. Otherwise, the client is sent a + * {@link RegistrationStatus.Type#PENDING} response, which indicates that + * the client's registration is pending approval. The client can choose to + * remain connected and wait for approval, or disconnect and try logging in + * later. + * + * @param registration The client's registration information. + * @param clientThread The client thread. + * @throws InvalidIdentificationException If the user's registration info is + * not valid. */ - public void handleLogIn(Identification identification, ClientThread clientThread) { - ClientConnectionData data; - try { - data = identification.sessionToken() == null ? getNewClientData(identification) : getClientDataFromDb(identification); - } catch (InvalidIdentificationException e) { - clientThread.sendToClient(Error.warning(e.getMessage())); - return; + public void handleRegistration(ClientRegistration registration, ClientThread clientThread) throws InvalidIdentificationException { + Document userDoc = this.userCollection.find(Filters.eq("username", registration.username())).firstOrDefault(); + if (userDoc != null) throw new InvalidIdentificationException("Username is taken."); + if (this.server.getConfig().isAcceptAllNewClients()) { + var clientData = this.authService.registerNewClient(registration); + clientThread.sendToClient(new RegistrationStatus(RegistrationStatus.Type.ACCEPTED, null)); + this.initializeClientConnection(clientData, clientThread); + } else { + var clientId = this.authService.registerPendingClient(registration); + this.initializePendingClientConnection(clientId, registration.username(), clientThread); } + } - this.clients.put(data.id, clientThread); - clientThread.setClientId(data.id); - clientThread.setClientNickname(data.nickname); + /** + * Handles an attempt by a new client to login as an existing user to the + * server. If the user's credentials are valid, then the following can + * result: + *