diff --git a/src/Cryptie.Server/DatabaseUpdater.cs b/src/Cryptie.Server/DatabaseUpdater.cs
index 9515303..6ed5a8d 100644
--- a/src/Cryptie.Server/DatabaseUpdater.cs
+++ b/src/Cryptie.Server/DatabaseUpdater.cs
@@ -12,6 +12,10 @@ public DatabaseUpdater(IServiceProvider serviceProvider)
_serviceProvider = serviceProvider;
}
+ ///
+ /// Applies pending Entity Framework migrations on application startup.
+ ///
+ /// A task representing the asynchronous operation.
public async Task PerformDatabaseUpdate()
{
using var scope = _serviceProvider.CreateScope();
diff --git a/src/Cryptie.Server/DockerStarter.cs b/src/Cryptie.Server/DockerStarter.cs
index e658c74..8f01d79 100644
--- a/src/Cryptie.Server/DockerStarter.cs
+++ b/src/Cryptie.Server/DockerStarter.cs
@@ -5,6 +5,10 @@ namespace Cryptie.Server;
public class DockerStarter
{
+ ///
+ /// Starts a local PostgreSQL container if it is not running.
+ ///
+ /// A task representing the asynchronous startup process.
public async Task StartPostgresAsync()
{
var client = new DockerClientConfiguration().CreateClient();
diff --git a/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs b/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs
index e1abdfd..53d60c5 100644
--- a/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs
+++ b/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs
@@ -15,6 +15,15 @@ public class AuthenticationService(
IDatabaseService databaseService)
: ControllerBase, IAuthenticationService
{
+ ///
+ /// Handles the first phase of login by verifying provided credentials
+ /// and issuing a temporary TOTP token when successful.
+ ///
+ /// Login credentials.
+ ///
+ /// containing a TOTP token when
+ /// credentials are valid; otherwise an error result.
+ ///
public IActionResult LoginHandler(LoginRequestDto loginRequest)
{
var user = appDbContext.Users
@@ -40,6 +49,12 @@ public IActionResult LoginHandler(LoginRequestDto loginRequest)
return Ok(new LoginResponseDto { TotpToken = totpToken });
}
+ ///
+ /// Validates the provided TOTP code and issues a session token when
+ /// the code is correct.
+ ///
+ /// Request containing TOTP code and token.
+ /// Session token on success or an error result.
public IActionResult TotpHandler(TotpRequestDto totpRequest)
{
var now = DateTime.UtcNow;
@@ -72,6 +87,12 @@ public IActionResult TotpHandler(TotpRequestDto totpRequest)
});
}
+ ///
+ /// Registers a new user and returns the initial TOTP configuration
+ /// along with a TOTP token for verification.
+ ///
+ /// Information required to create the user.
+ /// Registration details including the TOTP secret.
public IActionResult RegisterHandler(RegisterRequestDto registerRequest)
{
if (databaseService.FindUserByLogin(registerRequest.Login) != null) return BadRequest();
diff --git a/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs b/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs
index a977c3d..3942fa9 100644
--- a/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs
+++ b/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs
@@ -7,6 +7,12 @@ public class DelayService : IDelayService
{
private const int TargetMilliseconds = 100;
+ ///
+ /// Executes the given action and ensures that the call takes at least a
+ /// predefined amount of time. Useful to mitigate timing attacks.
+ ///
+ /// Action returning an to execute.
+ /// Result of after the artificial delay.
public async Task FakeDelay(Func func)
{
var stopwatch = Stopwatch.StartNew();
diff --git a/src/Cryptie.Server/Features/Authentication/Services/LockoutService.cs b/src/Cryptie.Server/Features/Authentication/Services/LockoutService.cs
index dc72f65..beaf518 100644
--- a/src/Cryptie.Server/Features/Authentication/Services/LockoutService.cs
+++ b/src/Cryptie.Server/Features/Authentication/Services/LockoutService.cs
@@ -5,6 +5,13 @@ namespace Cryptie.Server.Features.Authentication.Services;
public class LockoutService(IAppDbContext appDbContext) : ILockoutService
{
+ ///
+ /// Determines whether a user or honeypot account should be locked out
+ /// based on failed login attempts.
+ ///
+ /// Real user instance if available.
+ /// Login of a honeypot account when no real user exists.
+ /// true if the account is locked out; otherwise false.
public bool IsUserLockedOut(User? user, string honeypotLogin = "")
{
var referenceLockTimestamp = DateTime.UtcNow.AddMinutes(-60);
@@ -28,28 +35,56 @@ public bool IsUserLockedOut(User? user, string honeypotLogin = "")
return true;
}
+ ///
+ /// Checks if the specified user has an active lockout entry.
+ ///
+ /// User entity to check.
+ /// Timestamp defining the lockout window.
+ /// true when the user has an active lock.
public bool IsUserAccountHasLock(User user, DateTime referenceLockTimestamp)
{
return appDbContext.UserAccountLocks.Any(l => l.User == user && l.Until > referenceLockTimestamp);
}
+ ///
+ /// Checks if the honeypot account has an active lockout entry.
+ ///
+ /// Honeypot login to check.
+ /// Timestamp defining the lockout window.
+ /// true when the account has an active lock.
public bool IsUserAccountHasLock(string user, DateTime referenceLockTimestamp)
{
return appDbContext.HoneypotAccountLocks.Any(l => l.Username == user && l.Until > referenceLockTimestamp);
}
+ ///
+ /// Evaluates if the user has exceeded the allowed login attempts.
+ ///
+ /// User entity to check.
+ /// Timestamp defining the attempts window.
+ /// true if there are too many attempts.
public bool IsUserAccountHasTooManyAttempts(User user, DateTime referenceAttemptTimestamp)
{
return appDbContext.UserLoginAttempts.Count(a => a.User == user && a.Timestamp > referenceAttemptTimestamp) <
2;
}
+ ///
+ /// Evaluates if the honeypot account has exceeded the allowed login attempts.
+ ///
+ /// Honeypot login to check.
+ /// Timestamp defining the attempts window.
+ /// true if there are too many attempts.
public bool IsUserAccountHasTooManyAttempts(string user, DateTime referenceAttemptTimestamp)
{
return appDbContext.HoneypotLoginAttempts.Count(a =>
a.Username == user && a.Timestamp > referenceAttemptTimestamp) < 2;
}
+ ///
+ /// Creates a lockout entry for the specified user.
+ ///
+ /// User entity to lock.
public void LockUserAccount(User user)
{
appDbContext.UserAccountLocks.Add(new UserAccountLock
@@ -62,6 +97,10 @@ public void LockUserAccount(User user)
appDbContext.SaveChanges();
}
+ ///
+ /// Creates a lockout entry for the specified honeypot login.
+ ///
+ /// Honeypot login to lock.
public void LockUserAccount(string user)
{
appDbContext.HoneypotAccountLocks.Add(new HoneypotAccountLock
diff --git a/src/Cryptie.Server/Features/GroupManagement/Services/GroupManagementService.cs b/src/Cryptie.Server/Features/GroupManagement/Services/GroupManagementService.cs
index 6686cc1..a76feac 100644
--- a/src/Cryptie.Server/Features/GroupManagement/Services/GroupManagementService.cs
+++ b/src/Cryptie.Server/Features/GroupManagement/Services/GroupManagementService.cs
@@ -9,6 +9,11 @@ public class GroupManagementService(
IDatabaseService databaseService
) : ControllerBase, IGroupManagementService
{
+ ///
+ /// Determines privacy status for a collection of groups.
+ ///
+ /// List of group identifiers.
+ /// Dictionary with group ids and their privacy status.
public IActionResult IsGroupsPrivate(IsGroupsPrivateRequestDto isGroupsPrivateRequest)
{
var result = new Dictionary();
@@ -22,6 +27,12 @@ public IActionResult IsGroupsPrivate(IsGroupsPrivateRequestDto isGroupsPrivateRe
return Ok(new IsGroupsPrivateResponseDto { GroupStatuses = result });
}
+ ///
+ /// Returns display names for all groups the user is a member of.
+ /// Private groups are represented by the other member's display name.
+ ///
+ /// Request containing user session token.
+ /// Mapping of group ids to their display names.
public IActionResult GetGroupsNames([FromBody] GetGroupsNamesRequestDto getGroupsNamesRequest)
{
var user = databaseService.GetUserFromToken(getGroupsNamesRequest.SessionToken);
diff --git a/src/Cryptie.Server/Features/KeysManagement/Services/KeysManagementService.cs b/src/Cryptie.Server/Features/KeysManagement/Services/KeysManagementService.cs
index 7cf98ec..283661b 100644
--- a/src/Cryptie.Server/Features/KeysManagement/Services/KeysManagementService.cs
+++ b/src/Cryptie.Server/Features/KeysManagement/Services/KeysManagementService.cs
@@ -6,6 +6,11 @@ namespace Cryptie.Server.Features.KeysManagement.Services;
public class KeysManagementService(IDatabaseService databaseService) : ControllerBase, IKeysManagementService
{
+ ///
+ /// Retrieves public key of specified user.
+ ///
+ /// Request containing the user identifier.
+ /// DTO with the public key string.
public IActionResult getUserKey([FromBody] GetUserKeyRequestDto getUserKeyRequest)
{
var key = databaseService.GetUserPublicKey(getUserKeyRequest.UserId);
@@ -15,6 +20,11 @@ public IActionResult getUserKey([FromBody] GetUserKeyRequestDto getUserKeyReques
});
}
+ ///
+ /// Retrieves AES keys for all groups the current user belongs to.
+ ///
+ /// Request containing the session token.
+ /// Dictionary mapping group ids to their AES keys.
public IActionResult getGroupsKey([FromBody] GetGroupsKeyRequestDto getGroupsKeyRequest)
{
var user = databaseService.GetUserFromToken(getGroupsKeyRequest.SessionToken);
diff --git a/src/Cryptie.Server/Features/Messages/Hubs/MessageHub.cs b/src/Cryptie.Server/Features/Messages/Hubs/MessageHub.cs
index 8f18975..4349a38 100644
--- a/src/Cryptie.Server/Features/Messages/Hubs/MessageHub.cs
+++ b/src/Cryptie.Server/Features/Messages/Hubs/MessageHub.cs
@@ -7,11 +7,20 @@ public class MessageHub : Hub, IMessageHub
{
private static readonly ConcurrentDictionary Users = new();
+ ///
+ /// Broadcasts a plain text message to all connected clients.
+ ///
+ /// Message to broadcast.
public async Task SendMessage(string message)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
+ ///
+ /// Adds the current connection to a SignalR group and notifies other members.
+ ///
+ /// Identifier of the joining user.
+ /// Group identifier.
public async Task JoinGroup(Guid user, Guid group)
{
Users.TryAdd(Context.ConnectionId, user);
@@ -19,6 +28,12 @@ public async Task JoinGroup(Guid user, Guid group)
await Clients.Group(group.ToString()).SendAsync("UserJoinedGroup", user, group);
}
+ ///
+ /// Sends a message to all members of a group.
+ ///
+ /// Group identifier.
+ /// Sender identifier.
+ /// Encrypted message payload.
public async Task SendMessageToGroup(Guid group, Guid senderId, string message)
{
await Clients
diff --git a/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs b/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs
index e4c48ba..f12e08d 100644
--- a/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs
+++ b/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs
@@ -12,6 +12,12 @@ public MessageHubService(IHubContext hubContext)
_hubContext = hubContext;
}
+ ///
+ /// Sends a real-time notification to all clients connected to the specified group.
+ ///
+ /// Group identifier.
+ /// Identifier of the message sender.
+ /// Encrypted message body.
public void SendMessageToGroup(Guid group, Guid senderId, string message)
{
_hubContext.Clients.Group(group.ToString())
diff --git a/src/Cryptie.Server/Features/Messages/Services/MessagesService.cs b/src/Cryptie.Server/Features/Messages/Services/MessagesService.cs
index b7001cb..08d0814 100644
--- a/src/Cryptie.Server/Features/Messages/Services/MessagesService.cs
+++ b/src/Cryptie.Server/Features/Messages/Services/MessagesService.cs
@@ -7,6 +7,11 @@ namespace Cryptie.Server.Features.Messages.Services;
public class MessagesService(IDatabaseService databaseService, IMessageHubService messageHubService)
: ControllerBase, IMessagesService
{
+ ///
+ /// Sends a message to a specified group on behalf of the authenticated user.
+ ///
+ /// Request containing message and authentication data.
+ /// when the message is sent.
public IActionResult SendMessage([FromBody] SendMessageRequestDto sendMessageRequest)
{
var user = databaseService.GetUserFromToken(sendMessageRequest.SenderToken);
@@ -24,6 +29,11 @@ public IActionResult SendMessage([FromBody] SendMessageRequestDto sendMessageReq
return Ok();
}
+ ///
+ /// Retrieves all messages for a particular group.
+ ///
+ /// Request containing user token and group identifier.
+ /// List of messages.
public IActionResult GetGroupMessages([FromBody] GetGroupMessagesRequestDto request)
{
var user = databaseService.GetUserFromToken(request.UserToken);
@@ -49,6 +59,11 @@ public IActionResult GetGroupMessages([FromBody] GetGroupMessagesRequestDto requ
return Ok(response);
}
+ ///
+ /// Retrieves messages for a group that were sent after the specified timestamp.
+ ///
+ /// Request containing group id, token and timestamp.
+ /// List of messages sent since the provided date.
public IActionResult GetGroupMessagesSince([FromBody] GetGroupMessagesSinceRequestDto request)
{
var user = databaseService.GetUserFromToken(request.UserToken);
diff --git a/src/Cryptie.Server/Features/ServerStatus/Services/ServerStatusService.cs b/src/Cryptie.Server/Features/ServerStatus/Services/ServerStatusService.cs
index c3173d0..e84c2f5 100644
--- a/src/Cryptie.Server/Features/ServerStatus/Services/ServerStatusService.cs
+++ b/src/Cryptie.Server/Features/ServerStatus/Services/ServerStatusService.cs
@@ -4,6 +4,10 @@ namespace Cryptie.Server.Features.ServerStatus.Services;
public class ServerStatusService : ControllerBase, IServerStatusService
{
+ ///
+ /// Simple health-check endpoint.
+ ///
+ /// when the server is running.
public IActionResult GetServerStatus()
{
return Ok();
diff --git a/src/Cryptie.Server/Features/UserManagement/Services/UserManagementService.cs b/src/Cryptie.Server/Features/UserManagement/Services/UserManagementService.cs
index ea0615d..379f35c 100644
--- a/src/Cryptie.Server/Features/UserManagement/Services/UserManagementService.cs
+++ b/src/Cryptie.Server/Features/UserManagement/Services/UserManagementService.cs
@@ -6,6 +6,11 @@ namespace Cryptie.Server.Features.UserManagement.Services;
public class UserManagementService(IDatabaseService databaseService) : ControllerBase, IUserManagementService
{
+ ///
+ /// Returns user GUID associated with a session token.
+ ///
+ /// Request containing session token.
+ /// User identifier on success.
public IActionResult UserGuidFromToken([FromBody] UserGuidFromTokenRequestDto userGuidFromTokenRequest)
{
var user = databaseService.GetUserFromToken(userGuidFromTokenRequest.SessionToken);
@@ -17,6 +22,11 @@ public IActionResult UserGuidFromToken([FromBody] UserGuidFromTokenRequestDto us
});
}
+ ///
+ /// Adds a user to the current user's friend list and creates a private group for them.
+ ///
+ /// Request containing friend login and encryption keys.
+ /// when the friend was added.
public IActionResult AddFriend([FromBody] AddFriendRequestDto addFriendRequest)
{
var friend = databaseService.FindUserByLogin(addFriendRequest.Friend);
@@ -44,6 +54,11 @@ public IActionResult AddFriend([FromBody] AddFriendRequestDto addFriendRequest)
return Ok();
}
+ ///
+ /// Retrieves the display name of a user by their GUID.
+ ///
+ /// Request with the user's id.
+ /// Display name of the user.
public IActionResult NameFromGuid([FromBody] NameFromGuidRequestDto nameFromGuidRequest)
{
var user = databaseService.FindUserById(nameFromGuidRequest.Id);
@@ -55,6 +70,11 @@ public IActionResult NameFromGuid([FromBody] NameFromGuidRequestDto nameFromGuid
});
}
+ ///
+ /// Returns identifiers of groups the user belongs to.
+ ///
+ /// Request containing session token.
+ /// List of group identifiers.
public IActionResult UserGroups([FromBody] UserGroupsRequestDto userGroupsRequest)
{
var user = databaseService.GetUserFromToken(userGroupsRequest.SessionToken);
@@ -68,6 +88,11 @@ public IActionResult UserGroups([FromBody] UserGroupsRequestDto userGroupsReques
});
}
+ ///
+ /// Changes the display name of the authenticated user.
+ ///
+ /// Request containing token and new name.
+ /// when the change was applied.
public IActionResult UserDisplayName([FromBody] UserDisplayNameRequestDto userDisplayNameRequest)
{
var user = databaseService.GetUserFromToken(userDisplayNameRequest.Token);
@@ -78,6 +103,11 @@ public IActionResult UserDisplayName([FromBody] UserDisplayNameRequestDto userDi
return Ok();
}
+ ///
+ /// Returns the user's private key used for end-to-end encryption.
+ ///
+ /// Request containing session token.
+ /// Private key and associated control value.
public IActionResult UserPrivateKey([FromBody] UserPrivateKeyRequestDto userPrivateKeyRequest)
{
var user = databaseService.GetUserFromToken(userPrivateKeyRequest.SessionToken);
@@ -90,6 +120,11 @@ public IActionResult UserPrivateKey([FromBody] UserPrivateKeyRequestDto userPriv
});
}
+ ///
+ /// Retrieves the unique identifier of a user from their login name.
+ ///
+ /// Request containing user login.
+ /// User identifier when found.
public IActionResult GuidFromLogin([FromBody] GuidFromLoginRequestDto guidFromLoginRequest)
{
var user = databaseService.FindUserByLogin(guidFromLoginRequest.Login);
diff --git a/src/Cryptie.Server/Services/DatabaseService.cs b/src/Cryptie.Server/Services/DatabaseService.cs
index 05a06fe..720ecb4 100644
--- a/src/Cryptie.Server/Services/DatabaseService.cs
+++ b/src/Cryptie.Server/Services/DatabaseService.cs
@@ -6,6 +6,11 @@ namespace Cryptie.Server.Services;
public class DatabaseService(IAppDbContext appDbContext) : IDatabaseService
{
+ ///
+ /// Retrieves a user entity from a session token.
+ ///
+ /// Token identifier.
+ /// User entity or null when not found.
public User? GetUserFromToken(Guid guid)
{
return appDbContext.UserTokens
@@ -17,18 +22,33 @@ public class DatabaseService(IAppDbContext appDbContext) : IDatabaseService
.User;
}
+ ///
+ /// Finds a user by its unique identifier.
+ ///
+ /// User identifier.
+ /// User entity or null.
public User? FindUserById(Guid id)
{
var user = appDbContext.Users.Find(id);
return user;
}
+ ///
+ /// Locates a user by login name.
+ ///
+ /// Login name.
+ /// User entity or null.
public User? FindUserByLogin(string login)
{
var user = appDbContext.Users.FirstOrDefault(u => u.Login == login);
return user;
}
+ ///
+ /// Retrieves a group by its identifier including member list.
+ ///
+ /// Group identifier.
+ /// Group entity or null.
public Group? FindGroupById(Guid id)
{
return appDbContext.Groups
@@ -36,6 +56,12 @@ public class DatabaseService(IAppDbContext appDbContext) : IDatabaseService
.SingleOrDefault(g => g.Id == id);
}
+ ///
+ /// Creates a new group and assigns the specified user as a member.
+ ///
+ /// Initial member.
+ /// Name of the group.
+ /// The newly created group.
public Group CreateNewGroup(User user, string name)
{
var newGroup = new Group
@@ -51,6 +77,11 @@ public Group CreateNewGroup(User user, string name)
return createdGroup.Entity;
}
+ ///
+ /// Adds an existing user to an existing group.
+ ///
+ /// User identifier.
+ /// Group identifier.
public void AddUserToGroup(Guid user, Guid group)
{
var userToAdd = appDbContext.Users.SingleOrDefault(u => u.Id == user);
@@ -59,6 +90,11 @@ public void AddUserToGroup(Guid user, Guid group)
appDbContext.SaveChanges();
}
+ ///
+ /// Removes a user from a group.
+ ///
+ /// User identifier.
+ /// Group identifier.
public void RemoveUserFromGroup(Guid user, Guid group)
{
var userToRemove = appDbContext.Users.SingleOrDefault(u => u.Id == user);
@@ -67,6 +103,11 @@ public void RemoveUserFromGroup(Guid user, Guid group)
appDbContext.SaveChanges();
}
+ ///
+ /// Deletes a group from the database.
+ ///
+ /// Group identifier.
+ /// true if removed; otherwise false.
public bool DeleteGroup(Guid groupGuid)
{
var group = appDbContext.Groups.SingleOrDefault(g => g.Id == groupGuid);
@@ -76,6 +117,12 @@ public bool DeleteGroup(Guid groupGuid)
return true;
}
+ ///
+ /// Changes the name of a group.
+ ///
+ /// Group identifier.
+ /// New name.
+ /// true if the group exists and was updated.
public bool ChangeGroupName(Guid groupGuid, string name)
{
var group = appDbContext.Groups.SingleOrDefault(g => g.Id == groupGuid);
@@ -87,6 +134,11 @@ public bool ChangeGroupName(Guid groupGuid, string name)
return true;
}
+ ///
+ /// Creates a TOTP token entity for the user.
+ ///
+ /// User to associate the token with.
+ /// Identifier of the created token.
public Guid CreateTotpToken(User user)
{
var totpToken = appDbContext.TotpTokens.Add(new TotpToken
@@ -101,6 +153,10 @@ public Guid CreateTotpToken(User user)
return totpToken.Entity.Id;
}
+ ///
+ /// Logs a failed login attempt for a real user.
+ ///
+ /// User entity.
public void LogLoginAttempt(User user)
{
appDbContext.UserLoginAttempts.Add(new UserLoginAttempt
@@ -113,6 +169,10 @@ public void LogLoginAttempt(User user)
appDbContext.SaveChanges();
}
+ ///
+ /// Logs a failed login attempt for a honeypot account.
+ ///
+ /// Honeypot login name.
public void LogLoginAttempt(string user)
{
appDbContext.HoneypotLoginAttempts.Add(new HoneypotLoginAttempt
@@ -125,6 +185,11 @@ public void LogLoginAttempt(string user)
appDbContext.SaveChanges();
}
+ ///
+ /// Generates and persists a new session token for the user.
+ ///
+ /// User entity.
+ /// Identifier of the new token.
public Guid GenerateUserToken(User user)
{
var token = appDbContext.UserTokens.Add(new UserToken
@@ -138,12 +203,23 @@ public Guid GenerateUserToken(User user)
return token.Entity.Id;
}
+ ///
+ /// Adds a friend relationship between two users.
+ ///
+ /// User initiating the friendship.
+ /// Friend user.
public void AddFriend(User user, User friend)
{
user.Friends.Add(friend);
appDbContext.SaveChanges();
}
+ ///
+ /// Creates a new group without assigning members.
+ ///
+ /// Name of the group.
+ /// Whether the group is private.
+ /// The created group.
public Group CreateGroup(string name, bool isPrivate = false)
{
var group = appDbContext.Groups.Add(new Group
@@ -157,6 +233,11 @@ public Group CreateGroup(string name, bool isPrivate = false)
return group.Entity;
}
+ ///
+ /// Updates the display name of the specified user.
+ ///
+ /// User entity.
+ /// New display name.
public void ChangeUserDisplayName(User user, string name)
{
user.DisplayName = name;
@@ -164,6 +245,11 @@ public void ChangeUserDisplayName(User user, string name)
appDbContext.SaveChanges();
}
+ ///
+ /// Retrieves stored public key of a user.
+ ///
+ /// User identifier.
+ /// Public key string or empty when not found.
public string GetUserPublicKey(Guid userId)
{
var user = appDbContext.Users
@@ -173,6 +259,12 @@ public string GetUserPublicKey(Guid userId)
return user?.PublicKey ?? string.Empty;
}
+ ///
+ /// Stores new key pair for the user.
+ ///
+ /// User entity.
+ /// Private key string.
+ /// Public key string.
public void SaveUserKeys(User user, string privateKey, string publicKey)
{
user.PrivateKey = privateKey;
@@ -181,6 +273,13 @@ public void SaveUserKeys(User user, string privateKey, string publicKey)
appDbContext.SaveChanges();
}
+ ///
+ /// Persists a new message in the specified group.
+ ///
+ /// Target group.
+ /// Sender user.
+ /// Message content.
+ /// The created entity.
public GroupMessage SendGroupMessage(Group group, User sender, string message)
{
var groupMessage = new GroupMessage
@@ -198,6 +297,12 @@ public GroupMessage SendGroupMessage(Group group, User sender, string message)
return groupMessage;
}
+ ///
+ /// Retrieves a single message by id from a group.
+ ///
+ /// Message identifier.
+ /// Group identifier.
+ /// Message entity or null.
public GroupMessage? GetGroupMessage(Guid messageId, Guid groupId)
{
return appDbContext.GroupMessages
@@ -207,6 +312,11 @@ public GroupMessage SendGroupMessage(Group group, User sender, string message)
.FirstOrDefault(m => m.Id == messageId && m.GroupId == groupId);
}
+ ///
+ /// Retrieves all messages for the specified group ordered by date.
+ ///
+ /// Group identifier.
+ /// List of messages.
public List GetGroupMessages(Guid groupId)
{
return appDbContext.GroupMessages
@@ -216,6 +326,12 @@ public List GetGroupMessages(Guid groupId)
.ToList();
}
+ ///
+ /// Retrieves all messages for a group after the specified timestamp.
+ ///
+ /// Group identifier.
+ /// Earliest timestamp.
+ /// List of messages.
public List GetGroupMessagesSince(Guid groupId, DateTime since)
{
return appDbContext.GroupMessages
@@ -225,6 +341,12 @@ public List GetGroupMessagesSince(Guid groupId, DateTime since)
.ToList();
}
+ ///
+ /// Adds an AES encryption key for a user-group pair.
+ ///
+ /// User identifier.
+ /// Group identifier.
+ /// Encryption key.
public void AddGroupEncryptionKey(Guid userId, Guid groupId, string key)
{
var user = appDbContext.Users
@@ -250,6 +372,12 @@ public void AddGroupEncryptionKey(Guid userId, Guid groupId, string key)
appDbContext.SaveChanges();
}
+ ///
+ /// Retrieves the AES encryption key for a user-group pair.
+ ///
+ /// User identifier.
+ /// Group identifier.
+ /// Encryption key string or empty when not set.
public string getGroupEncryptionKey(Guid userId, Guid groupId)
{
var key = appDbContext.GroupEncryptionKeys