Reintroduces separate contexts for users, channels, connections (now split into sessions and connections) and user-channel associations. It builds which is as much assurance as I can give about the stability of this commit, but its also the bare minimum of what i like to commit sooooo A lot of things still need to be broadcast through events throughout the application in order to keep states consistent but we'll cross that bridge when we get to it. I really need to stop using that phrase thingy, I'm overusing it.
193 lines
5.6 KiB
C#
193 lines
5.6 KiB
C#
using SharpChat.Auth;
|
|
|
|
namespace SharpChat.Users;
|
|
|
|
public class UsersContext {
|
|
private readonly Dictionary<string, User> Users = [];
|
|
private readonly Lock @lock = new();
|
|
|
|
public bool UserExists(string id) {
|
|
lock(@lock)
|
|
return Users.ContainsKey(id);
|
|
}
|
|
|
|
public bool UserExists(Func<User, bool> predicate) {
|
|
lock(@lock)
|
|
return Users.Values.Any(predicate);
|
|
}
|
|
|
|
public User? GetUser(string id) {
|
|
lock(@lock)
|
|
return Users.TryGetValue(id, out User? user) ? user : null;
|
|
}
|
|
|
|
public User? GetUser(Func<User, bool> predicate) {
|
|
lock(@lock)
|
|
return Users.Values.FirstOrDefault(predicate);
|
|
}
|
|
|
|
public IEnumerable<User> GetUsers() {
|
|
lock(@lock)
|
|
return [.. Users.Values];
|
|
}
|
|
|
|
public IEnumerable<User> GetUsers(IEnumerable<string> ids) {
|
|
return [.. ids.Select(GetUser).Where(u => u is not null).Cast<User>()];
|
|
}
|
|
|
|
public IEnumerable<User> GetUsers(Func<User, bool> predicate) {
|
|
lock(@lock)
|
|
return [.. Users.Values.Where(predicate)];
|
|
}
|
|
|
|
public IEnumerable<User> GetUsersWithStatus(UserStatus status) {
|
|
return GetUsers(u => u.Status == status);
|
|
}
|
|
|
|
public IEnumerable<User> GetUsersOfMinimumRank(int minRank) {
|
|
return GetUsers(u => u.Rank >= minRank);
|
|
}
|
|
|
|
public User CreateOrUpdateUser(AuthResult authResult) {
|
|
lock(@lock) {
|
|
User? user = GetUser(authResult.UserId);
|
|
return user is null ? CreateUserInternal(
|
|
authResult.UserId,
|
|
authResult.UserName,
|
|
authResult.UserColour,
|
|
authResult.UserRank,
|
|
authResult.UserPermissions
|
|
) : UpdateUserInternal(
|
|
user,
|
|
authResult.UserId,
|
|
authResult.UserName,
|
|
authResult.UserColour,
|
|
authResult.UserRank,
|
|
authResult.UserPermissions
|
|
).User;
|
|
}
|
|
}
|
|
|
|
public User CreateUser(
|
|
string id,
|
|
string name,
|
|
ColourInheritable colour,
|
|
int rank,
|
|
UserPermissions perms,
|
|
string nick = "",
|
|
UserStatus status = UserStatus.Online,
|
|
string statusText = ""
|
|
) {
|
|
lock(@lock)
|
|
return UserExists(id)
|
|
? throw new UserExistsException(nameof(id))
|
|
: CreateUserInternal(id, name, colour, rank, perms, nick, status, statusText);
|
|
}
|
|
|
|
private User CreateUserInternal(
|
|
string id,
|
|
string name,
|
|
ColourInheritable colour,
|
|
int rank,
|
|
UserPermissions perms,
|
|
string nick = "",
|
|
UserStatus status = UserStatus.Online,
|
|
string statusText = ""
|
|
) {
|
|
User user = new(id, name, colour, rank, perms, nick, status, statusText);
|
|
Users.Add(id, user);
|
|
return user;
|
|
}
|
|
|
|
public UserDiff UpdateUser(
|
|
User user,
|
|
string? name = null,
|
|
ColourInheritable? colour = null,
|
|
int? rank = null,
|
|
UserPermissions? perms = null,
|
|
string? nick = null,
|
|
UserStatus? status = null,
|
|
string? statusText = null
|
|
) => UpdateUser(user.UserId, name, colour, rank, perms, nick, status, statusText);
|
|
|
|
public UserDiff UpdateUser(
|
|
string id,
|
|
string? name = null,
|
|
ColourInheritable? colour = null,
|
|
int? rank = null,
|
|
UserPermissions? perms = null,
|
|
string? nick = null,
|
|
UserStatus? status = null,
|
|
string? statusText = null
|
|
) {
|
|
lock(@lock)
|
|
return UpdateUserInternal(
|
|
GetUser(id) ?? throw new UserNotFoundException(nameof(id)),
|
|
id, name, colour, rank, perms, nick, status, statusText
|
|
);
|
|
}
|
|
|
|
private static UserDiff UpdateUserInternal(
|
|
User user,
|
|
string id,
|
|
string? name = null,
|
|
ColourInheritable? colour = null,
|
|
int? rank = null,
|
|
UserPermissions? perms = null,
|
|
string? nick = null,
|
|
UserStatus? status = null,
|
|
string? statusText = null
|
|
) {
|
|
StringDiff nameDiff = new(user.UserName, name);
|
|
if(nameDiff.Changed)
|
|
user.UserName = nameDiff.After;
|
|
|
|
ValueDiff<ColourInheritable> colourDiff = new(user.Colour, colour);
|
|
if(colourDiff.Changed)
|
|
user.Colour = colourDiff.After;
|
|
|
|
ValueDiff<int> rankDiff = new(user.Rank, rank);
|
|
if(rankDiff.Changed)
|
|
user.Rank = rankDiff.After;
|
|
|
|
ValueDiff<UserPermissions> permsDiff = new(user.Permissions, perms);
|
|
if(permsDiff.Changed)
|
|
user.Permissions = permsDiff.After;
|
|
|
|
StringDiff nickDiff = new(user.NickName, nick);
|
|
if(nickDiff.Changed)
|
|
user.NickName = nickDiff.After;
|
|
|
|
ValueDiff<UserStatus> statusDiff = new(user.Status, status);
|
|
if(statusDiff.Changed)
|
|
user.Status = statusDiff.After;
|
|
|
|
StringDiff statusTextDiff = new(user.StatusText, statusText);
|
|
if(statusTextDiff.Changed)
|
|
user.StatusText = statusTextDiff.After;
|
|
|
|
return new(
|
|
user,
|
|
id,
|
|
nameDiff,
|
|
colourDiff,
|
|
rankDiff,
|
|
permsDiff,
|
|
nickDiff,
|
|
statusDiff,
|
|
statusTextDiff
|
|
);
|
|
}
|
|
|
|
public void RemoveUser(User user)
|
|
=> RemoveUserInternal(user.UserId, nameof(user));
|
|
|
|
public void RemoveUser(string id)
|
|
=> RemoveUserInternal(id, nameof(id));
|
|
|
|
private void RemoveUserInternal(string id, string argName) {
|
|
lock(@lock)
|
|
if(!Users.Remove(id))
|
|
throw new UserNotFoundException(argName);
|
|
}
|
|
}
|