
* When account updates occur for a user, send an event to them to tell them to refresh their account information (if they are on the site at the time). This way if we revoke permissions, the site will reactively adapt. * Some cleanup on the user preferences to remove some calls we don't need anymore. * Removed old bulk cleanup bookmark code as it's no longer needed. * Tweaked the messaging for stat collection to reflect what we collect now versus when this was initially implemented. * Implemented the ability for users to configure their servers to save bookmarks as webP. Reorganized the tabs for Admin dashboard to account for upcoming features. * Implemented the ability to bulk convert bookmarks (as many times as the user wants). Added a display of Reoccurring Jobs to the Tasks admin tab. Currently it's just placeholder, but will be enhanced further later in the release. * Tweaked the wording around the convert switch. * Moved System actions to the task tab * Added a controller just for Tachiyomi so we can have dedicated APIs for that client. Deprecated an existing API on the Reader route. * Fixed the unit tests
114 lines
3.7 KiB
C#
114 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using API.Data;
|
|
|
|
namespace API.SignalR.Presence
|
|
{
|
|
public interface IPresenceTracker
|
|
{
|
|
Task UserConnected(string username, string connectionId);
|
|
Task UserDisconnected(string username, string connectionId);
|
|
Task<string[]> GetOnlineAdmins();
|
|
Task<List<string>> GetConnectionsForUser(string username);
|
|
|
|
}
|
|
|
|
internal class ConnectionDetail
|
|
{
|
|
public List<string> ConnectionIds { get; set; }
|
|
public bool IsAdmin { get; set; }
|
|
}
|
|
|
|
// TODO: This can respond to UserRoleUpdate events to handle online users
|
|
/// <summary>
|
|
/// This is a singleton service for tracking what users have a SignalR connection and their difference connectionIds
|
|
/// </summary>
|
|
public class PresenceTracker : IPresenceTracker
|
|
{
|
|
private readonly IUnitOfWork _unitOfWork;
|
|
private static readonly Dictionary<string, ConnectionDetail> OnlineUsers = new Dictionary<string, ConnectionDetail>();
|
|
|
|
public PresenceTracker(IUnitOfWork unitOfWork)
|
|
{
|
|
_unitOfWork = unitOfWork;
|
|
}
|
|
|
|
public async Task UserConnected(string username, string connectionId)
|
|
{
|
|
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
|
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
|
lock (OnlineUsers)
|
|
{
|
|
if (OnlineUsers.ContainsKey(username))
|
|
{
|
|
OnlineUsers[username].ConnectionIds.Add(connectionId);
|
|
}
|
|
else
|
|
{
|
|
OnlineUsers.Add(username, new ConnectionDetail()
|
|
{
|
|
ConnectionIds = new List<string>() {connectionId},
|
|
IsAdmin = isAdmin
|
|
});
|
|
}
|
|
}
|
|
|
|
// Update the last active for the user
|
|
user.LastActive = DateTime.Now;
|
|
await _unitOfWork.CommitAsync();
|
|
}
|
|
|
|
public Task UserDisconnected(string username, string connectionId)
|
|
{
|
|
lock (OnlineUsers)
|
|
{
|
|
if (!OnlineUsers.ContainsKey(username)) return Task.CompletedTask;
|
|
|
|
OnlineUsers[username].ConnectionIds.Remove(connectionId);
|
|
|
|
if (OnlineUsers[username].ConnectionIds.Count == 0)
|
|
{
|
|
OnlineUsers.Remove(username);
|
|
}
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public static Task<string[]> GetOnlineUsers()
|
|
{
|
|
string[] onlineUsers;
|
|
lock (OnlineUsers)
|
|
{
|
|
onlineUsers = OnlineUsers.OrderBy(k => k.Key).Select(k => k.Key).ToArray();
|
|
}
|
|
|
|
return Task.FromResult(onlineUsers);
|
|
}
|
|
|
|
public Task<string[]> GetOnlineAdmins()
|
|
{
|
|
// TODO: This might end in stale data, we want to get the online users, query against DB to check if they are admins then return
|
|
string[] onlineUsers;
|
|
lock (OnlineUsers)
|
|
{
|
|
onlineUsers = OnlineUsers.Where(pair => pair.Value.IsAdmin).OrderBy(k => k.Key).Select(k => k.Key).ToArray();
|
|
}
|
|
|
|
|
|
return Task.FromResult(onlineUsers);
|
|
}
|
|
|
|
public Task<List<string>> GetConnectionsForUser(string username)
|
|
{
|
|
List<string> connectionIds;
|
|
lock (OnlineUsers)
|
|
{
|
|
connectionIds = OnlineUsers.GetValueOrDefault(username)?.ConnectionIds;
|
|
}
|
|
|
|
return Task.FromResult(connectionIds ?? new List<string>());
|
|
}
|
|
}
|
|
}
|