diff --git a/src/Cryptie.Server/DatabaseUpdater.cs b/src/Cryptie.Server/DatabaseUpdater.cs
index 9515303..c8450d6 100644
--- a/src/Cryptie.Server/DatabaseUpdater.cs
+++ b/src/Cryptie.Server/DatabaseUpdater.cs
@@ -12,6 +12,11 @@ public DatabaseUpdater(IServiceProvider serviceProvider)
_serviceProvider = serviceProvider;
}
+ ///
+ /// Applies any pending Entity Framework migrations to ensure the database
+ /// schema is up to date.
+ ///
+ /// A task that completes when the migration process finishes.
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..4fef428 100644
--- a/src/Cryptie.Server/DockerStarter.cs
+++ b/src/Cryptie.Server/DockerStarter.cs
@@ -5,6 +5,12 @@ namespace Cryptie.Server;
public class DockerStarter
{
+ ///
+ /// Ensures that a PostgreSQL container is running for the application.
+ /// If an existing container named cryptie-db is found it will be started
+ /// if necessary, otherwise a new one will be created and started.
+ ///
+ /// A task representing the asynchronous start operation.
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..56b26da 100644
--- a/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs
+++ b/src/Cryptie.Server/Features/Authentication/Services/AuthenticationService.cs
@@ -15,6 +15,12 @@ public class AuthenticationService(
IDatabaseService databaseService)
: ControllerBase, IAuthenticationService
{
+ ///
+ /// Handles user login by validating credentials and issuing a TOTP token
+ /// when successful.
+ ///
+ /// Login credentials.
+ /// An describing the outcome.
public IActionResult LoginHandler(LoginRequestDto loginRequest)
{
var user = appDbContext.Users
@@ -40,6 +46,11 @@ public IActionResult LoginHandler(LoginRequestDto loginRequest)
return Ok(new LoginResponseDto { TotpToken = totpToken });
}
+ ///
+ /// Validates a TOTP code and returns a session token if it is correct.
+ ///
+ /// User TOTP request.
+ /// An describing the outcome.
public IActionResult TotpHandler(TotpRequestDto totpRequest)
{
var now = DateTime.UtcNow;
@@ -72,6 +83,11 @@ public IActionResult TotpHandler(TotpRequestDto totpRequest)
});
}
+ ///
+ /// Registers a new user and returns provisioning information for TOTP.
+ ///
+ /// Registration details.
+ /// An with the registration result.
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..72566e0 100644
--- a/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs
+++ b/src/Cryptie.Server/Features/Authentication/Services/DelayService.cs
@@ -7,6 +7,13 @@ public class DelayService : IDelayService
{
private const int TargetMilliseconds = 100;
+ ///
+ /// Executes the provided action ensuring that the total execution time is at least
+ /// milliseconds. This is used to mitigate timing
+ /// attacks on authentication endpoints.
+ ///
+ /// Action that produces the result.
+ /// The result of after the enforced 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..70286b7 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 the specified user or honeypot account should be locked out
+ /// based on recent login attempts.
+ ///
+ /// The real user to check.
+ /// Login string used when user is null.
+ /// true if access should be denied.
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 whether a user account currently has an active lock.
+ ///
+ /// User account.
+ /// Timestamp of oldest valid lock.
+ /// true if a lock exists.
public bool IsUserAccountHasLock(User user, DateTime referenceLockTimestamp)
{
return appDbContext.UserAccountLocks.Any(l => l.User == user && l.Until > referenceLockTimestamp);
}
+ ///
+ /// Checks whether a honeypot login has an active lock.
+ ///
+ /// The honeypot login name.
+ /// Timestamp of oldest valid lock.
+ /// true if locked.
public bool IsUserAccountHasLock(string user, DateTime referenceLockTimestamp)
{
return appDbContext.HoneypotAccountLocks.Any(l => l.Username == user && l.Until > referenceLockTimestamp);
}
+ ///
+ /// Checks if a user has exceeded the allowed number of login attempts.
+ ///
+ /// User account.
+ /// Only attempts newer than this are counted.
+ /// true when attempts are within limit.
public bool IsUserAccountHasTooManyAttempts(User user, DateTime referenceAttemptTimestamp)
{
return appDbContext.UserLoginAttempts.Count(a => a.User == user && a.Timestamp > referenceAttemptTimestamp) <
2;
}
+ ///
+ /// Checks if a honeypot login has too many login attempts.
+ ///
+ /// The honeypot login name.
+ /// Only attempts newer than this are counted.
+ /// true when attempts are within limit.
public bool IsUserAccountHasTooManyAttempts(string user, DateTime referenceAttemptTimestamp)
{
return appDbContext.HoneypotLoginAttempts.Count(a =>
a.Username == user && a.Timestamp > referenceAttemptTimestamp) < 2;
}
+ ///
+ /// Adds a lock entry for the specified user.
+ ///
+ /// User to lock.
public void LockUserAccount(User user)
{
appDbContext.UserAccountLocks.Add(new UserAccountLock
@@ -62,6 +97,10 @@ public void LockUserAccount(User user)
appDbContext.SaveChanges();
}
+ ///
+ /// Adds a lock entry for a honeypot login.
+ ///
+ /// Login string 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..da9dbe3 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
{
+ ///
+ /// Returns privacy flags for the requested groups.
+ ///
+ /// Request containing group identifiers.
+ /// Dictionary of group ids with their privacy status.
public IActionResult IsGroupsPrivate(IsGroupsPrivateRequestDto isGroupsPrivateRequest)
{
var result = new Dictionary();
@@ -22,6 +27,11 @@ public IActionResult IsGroupsPrivate(IsGroupsPrivateRequestDto isGroupsPrivateRe
return Ok(new IsGroupsPrivateResponseDto { GroupStatuses = result });
}
+ ///
+ /// Gets display names for all groups that a user is a member of.
+ ///
+ /// Request including the session token.
+ /// Mapping of group ids to 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..51087de 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 the public key of a specific user.
+ ///
+ /// Request containing the user identifier.
+ /// The user's public key.
public IActionResult getUserKey([FromBody] GetUserKeyRequestDto getUserKeyRequest)
{
var key = databaseService.GetUserPublicKey(getUserKeyRequest.UserId);
@@ -15,6 +20,11 @@ public IActionResult getUserKey([FromBody] GetUserKeyRequestDto getUserKeyReques
});
}
+ ///
+ /// Gets encryption keys for all groups the requesting user is part of.
+ ///
+ /// Request containing the session token.
+ /// Dictionary of group ids with their encryption keys.
public IActionResult getGroupsKey([FromBody] GetGroupsKeyRequestDto getGroupsKeyRequest)
{
var user = databaseService.GetUserFromToken(getGroupsKeyRequest.SessionToken);
diff --git a/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs b/src/Cryptie.Server/Features/Messages/Services/MessageHubService.cs
index e4c48ba..d01fe3c 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 message to all clients in the specified SignalR group.
+ ///
+ /// Group identifier.
+ /// User sending the message.
+ /// Encrypted message content.
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..ad703a3 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 group on behalf of the authenticated user.
+ ///
+ /// Request containing the session token, target group and message.
+ /// Status of the send operation.
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 from a specific group.
+ ///
+ /// Request containing the user token and group id.
+ /// A list of messages in the group.
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 from a group posted after the specified timestamp.
+ ///
+ /// Request containing group id, token and timestamp.
+ /// List of messages newer than 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..a57da58 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 confirming that the server is running.
+ ///
+ /// HTTP 200 response.
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..6478548 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
{
+ ///
+ /// Resolves a user identifier from a valid session token.
+ ///
+ /// Request containing the token.
+ /// User id when the token is valid.
public IActionResult UserGuidFromToken([FromBody] UserGuidFromTokenRequestDto userGuidFromTokenRequest)
{
var user = databaseService.GetUserFromToken(userGuidFromTokenRequest.SessionToken);
@@ -17,6 +22,11 @@ public IActionResult UserGuidFromToken([FromBody] UserGuidFromTokenRequestDto us
});
}
+ ///
+ /// Creates a private group for two users and stores provided encryption keys.
+ ///
+ /// Information about the friend and keys.
+ /// Result of the operation.
public IActionResult AddFriend([FromBody] AddFriendRequestDto addFriendRequest)
{
var friend = databaseService.FindUserByLogin(addFriendRequest.Friend);
@@ -44,6 +54,11 @@ public IActionResult AddFriend([FromBody] AddFriendRequestDto addFriendRequest)
return Ok();
}
+ ///
+ /// Returns the display name of a user identified by GUID.
+ ///
+ /// Request containing the user id.
+ /// User display name.
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 the session token.
+ /// List of group ids.
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 for the authenticated user.
+ ///
+ /// Request containing token and new name.
+ /// HTTP 200 on success.
public IActionResult UserDisplayName([FromBody] UserDisplayNameRequestDto userDisplayNameRequest)
{
var user = databaseService.GetUserFromToken(userDisplayNameRequest.Token);
@@ -78,6 +103,11 @@ public IActionResult UserDisplayName([FromBody] UserDisplayNameRequestDto userDi
return Ok();
}
+ ///
+ /// Retrieves the private key and control value of a user.
+ ///
+ /// Request containing session token.
+ /// The private key pair.
public IActionResult UserPrivateKey([FromBody] UserPrivateKeyRequestDto userPrivateKeyRequest)
{
var user = databaseService.GetUserFromToken(userPrivateKeyRequest.SessionToken);
@@ -90,6 +120,11 @@ public IActionResult UserPrivateKey([FromBody] UserPrivateKeyRequestDto userPriv
});
}
+ ///
+ /// Finds a user identifier by login.
+ ///
+ /// Request containing the login.
+ /// User id or 404.
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..5c004e4 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 associated with the specified session token.
+ ///
+ /// Token identifying the user session.
+ /// The or null when no token is found.
public User? GetUserFromToken(Guid guid)
{
return appDbContext.UserTokens
@@ -17,18 +22,33 @@ public class DatabaseService(IAppDbContext appDbContext) : IDatabaseService
.User;
}
+ ///
+ /// Finds a user by their unique identifier.
+ ///
+ /// User identifier.
+ /// The instance or null if not found.
public User? FindUserById(Guid id)
{
var user = appDbContext.Users.Find(id);
return user;
}
+ ///
+ /// Retrieves a user using their login name.
+ ///
+ /// Login string.
+ /// The matching or null.
public User? FindUserByLogin(string login)
{
var user = appDbContext.Users.FirstOrDefault(u => u.Login == login);
return user;
}
+ ///
+ /// Gets a group with its members populated by identifier.
+ ///
+ /// Group identifier.
+ /// The found 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 provided user as the first member.
+ ///
+ /// User that will own the group.
+ /// Name of the group.
+ /// The created entity.
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 the specified user to a group.
+ ///
+ /// Identifier of the user.
+ /// Identifier of the group.
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.
+ ///
+ /// Identifier of the user.
+ /// Identifier of the group.
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 with the given identifier.
+ ///
+ /// Group identifier.
+ /// true when group existed and was removed.
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 group name.
+ /// true when 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 temporary TOTP token for the specified user.
+ ///
+ /// User for whom the token is generated.
+ /// The 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;
}
+ ///
+ /// Records a login attempt for the given user.
+ ///
+ /// User that attempted to log in.
public void LogLoginAttempt(User user)
{
appDbContext.UserLoginAttempts.Add(new UserLoginAttempt
@@ -113,6 +169,11 @@ public void LogLoginAttempt(User user)
appDbContext.SaveChanges();
}
+ ///
+ /// Records a login attempt made with a username that does not correspond to
+ /// a real user account.
+ ///
+ /// The honeypot username.
public void LogLoginAttempt(string user)
{
appDbContext.HoneypotLoginAttempts.Add(new HoneypotLoginAttempt
@@ -125,6 +186,11 @@ public void LogLoginAttempt(string user)
appDbContext.SaveChanges();
}
+ ///
+ /// Generates and persists a new session token for the specified user.
+ ///
+ /// User for which the token is generated.
+ /// Identifier of the created session token.
public Guid GenerateUserToken(User user)
{
var token = appDbContext.UserTokens.Add(new UserToken
@@ -138,12 +204,23 @@ public Guid GenerateUserToken(User user)
return token.Entity.Id;
}
+ ///
+ /// Adds another user to the given user's friend list.
+ ///
+ /// User who will receive the friend.
+ /// User to be added.
public void AddFriend(User user, User friend)
{
user.Friends.Add(friend);
appDbContext.SaveChanges();
}
+ ///
+ /// Creates a group with the provided name.
+ ///
+ /// Group name.
+ /// Indicates whether the group is private.
+ /// The created entity.
public Group CreateGroup(string name, bool isPrivate = false)
{
var group = appDbContext.Groups.Add(new Group
@@ -157,6 +234,11 @@ public Group CreateGroup(string name, bool isPrivate = false)
return group.Entity;
}
+ ///
+ /// Updates the display name of the specified user.
+ ///
+ /// User to update.
+ /// New display name.
public void ChangeUserDisplayName(User user, string name)
{
user.DisplayName = name;
@@ -164,6 +246,11 @@ public void ChangeUserDisplayName(User user, string name)
appDbContext.SaveChanges();
}
+ ///
+ /// Retrieves the public key of a user.
+ ///
+ /// User identifier.
+ /// The public key or an empty string if the user doesn't exist.
public string GetUserPublicKey(Guid userId)
{
var user = appDbContext.Users
@@ -173,6 +260,12 @@ public string GetUserPublicKey(Guid userId)
return user?.PublicKey ?? string.Empty;
}
+ ///
+ /// Saves the provided key pair for a user.
+ ///
+ /// User to update.
+ /// Private key value.
+ /// Public key value.
public void SaveUserKeys(User user, string privateKey, string publicKey)
{
user.PrivateKey = privateKey;
@@ -181,6 +274,13 @@ public void SaveUserKeys(User user, string privateKey, string publicKey)
appDbContext.SaveChanges();
}
+ ///
+ /// Stores a new message in a group and returns the created entity.
+ ///
+ /// Destination group.
+ /// User sending the message.
+ /// Message content.
+ /// The stored .
public GroupMessage SendGroupMessage(Group group, User sender, string message)
{
var groupMessage = new GroupMessage
@@ -198,6 +298,12 @@ public GroupMessage SendGroupMessage(Group group, User sender, string message)
return groupMessage;
}
+ ///
+ /// Retrieves a specific message from a group.
+ ///
+ /// Identifier of the message.
+ /// Identifier of the group.
+ /// The if found, otherwise null.
public GroupMessage? GetGroupMessage(Guid messageId, Guid groupId)
{
return appDbContext.GroupMessages
@@ -207,6 +313,11 @@ public GroupMessage SendGroupMessage(Group group, User sender, string message)
.FirstOrDefault(m => m.Id == messageId && m.GroupId == groupId);
}
+ ///
+ /// Returns all messages from the specified group ordered by date.
+ ///
+ /// Identifier of the group.
+ /// List of group messages.
public List GetGroupMessages(Guid groupId)
{
return appDbContext.GroupMessages
@@ -216,6 +327,12 @@ public List GetGroupMessages(Guid groupId)
.ToList();
}
+ ///
+ /// Retrieves messages from a group newer than the specified timestamp.
+ ///
+ /// Group identifier.
+ /// Earliest message date to include.
+ /// List of messages posted after .
public List GetGroupMessagesSince(Guid groupId, DateTime since)
{
return appDbContext.GroupMessages
@@ -225,6 +342,12 @@ public List GetGroupMessagesSince(Guid groupId, DateTime since)
.ToList();
}
+ ///
+ /// Stores an encryption key for a user and group pair.
+ ///
+ /// Identifier of the user.
+ /// Identifier of the group.
+ /// AES key to store.
public void AddGroupEncryptionKey(Guid userId, Guid groupId, string key)
{
var user = appDbContext.Users
@@ -250,6 +373,12 @@ public void AddGroupEncryptionKey(Guid userId, Guid groupId, string key)
appDbContext.SaveChanges();
}
+ ///
+ /// Retrieves the stored encryption key for a user in a specific group.
+ ///
+ /// Identifier of the user.
+ /// Identifier of the group.
+ /// The AES key or an empty string when missing.
public string getGroupEncryptionKey(Guid userId, Guid groupId)
{
var key = appDbContext.GroupEncryptionKeys