194 lines
5.6 KiB
C#
194 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);
|
||
|
}
|
||
|
}
|