105 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using DysonNetwork.Pass.Localization;
 | 
						|
using DysonNetwork.Shared;
 | 
						|
using DysonNetwork.Shared.Cache;
 | 
						|
using DysonNetwork.Shared.Models;
 | 
						|
using DysonNetwork.Shared.Proto;
 | 
						|
using DysonNetwork.Shared.Registry;
 | 
						|
using Microsoft.EntityFrameworkCore;
 | 
						|
using Microsoft.Extensions.Localization;
 | 
						|
 | 
						|
namespace DysonNetwork.Pass.Realm;
 | 
						|
 | 
						|
public class RealmService(
 | 
						|
    AppDatabase db,
 | 
						|
    RingService.RingServiceClient pusher,
 | 
						|
    IStringLocalizer<NotificationResource> localizer,
 | 
						|
    ICacheService cache
 | 
						|
)
 | 
						|
{
 | 
						|
    private const string CacheKeyPrefix = "account:realms:";
 | 
						|
    
 | 
						|
    public async Task<List<Guid>> GetUserRealms(Guid accountId)
 | 
						|
    {
 | 
						|
        var cacheKey = $"{CacheKeyPrefix}{accountId}";
 | 
						|
        var (found, cachedRealms) = await cache.GetAsyncWithStatus<List<Guid>>(cacheKey);
 | 
						|
        if (found && cachedRealms != null)
 | 
						|
            return cachedRealms;
 | 
						|
 | 
						|
        var realms = await db.RealmMembers
 | 
						|
            .Include(m => m.Realm)
 | 
						|
            .Where(m => m.AccountId == accountId)
 | 
						|
            .Where(m => m.JoinedAt != null && m.LeaveAt == null)
 | 
						|
            .Select(m => m.Realm!.Id)
 | 
						|
            .ToListAsync();
 | 
						|
 | 
						|
        // Cache the result for 5 minutes
 | 
						|
        await cache.SetAsync(cacheKey, realms, TimeSpan.FromMinutes(5));
 | 
						|
        
 | 
						|
        return realms;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public async Task SendInviteNotify(SnRealmMember member)
 | 
						|
    {
 | 
						|
        var account = await db.Accounts
 | 
						|
            .Include(a => a.Profile)
 | 
						|
            .FirstOrDefaultAsync(a => a.Id == member.AccountId);
 | 
						|
        
 | 
						|
        if (account == null) throw new InvalidOperationException("Account not found");
 | 
						|
        
 | 
						|
        CultureService.SetCultureInfo(account.Language);
 | 
						|
 | 
						|
        await pusher.SendPushNotificationToUserAsync(
 | 
						|
            new SendPushNotificationToUserRequest
 | 
						|
            {
 | 
						|
                UserId = account.Id.ToString(),
 | 
						|
                Notification = new PushNotification
 | 
						|
                {
 | 
						|
                    Topic = "invites.realms",
 | 
						|
                    Title = localizer["RealmInviteTitle"],
 | 
						|
                    Body = localizer["RealmInviteBody", member.Realm.Name],
 | 
						|
                    ActionUri = "/realms",
 | 
						|
                    IsSavable = true
 | 
						|
                }
 | 
						|
            }
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    public async Task<bool> IsMemberWithRole(Guid realmId, Guid accountId, params int[] requiredRoles)
 | 
						|
    {
 | 
						|
        if (requiredRoles.Length == 0)
 | 
						|
            return false;
 | 
						|
 | 
						|
        var maxRequiredRole = requiredRoles.Max();
 | 
						|
        var member = await db.RealmMembers
 | 
						|
            .Where(m => m.RealmId == realmId && m.AccountId == accountId && m.JoinedAt != null && m.LeaveAt == null)
 | 
						|
            .FirstOrDefaultAsync();
 | 
						|
        return member?.Role >= maxRequiredRole;
 | 
						|
    }
 | 
						|
 | 
						|
    public async Task<SnRealmMember> LoadMemberAccount(SnRealmMember member)
 | 
						|
    {
 | 
						|
        var account = await db.Accounts
 | 
						|
            .Include(a => a.Profile)
 | 
						|
            .FirstOrDefaultAsync(a => a.Id == member.AccountId);
 | 
						|
        if (account != null)
 | 
						|
            member.Account = account;
 | 
						|
        return member;
 | 
						|
    }
 | 
						|
 | 
						|
    public async Task<List<SnRealmMember>> LoadMemberAccounts(ICollection<SnRealmMember> members)
 | 
						|
    {
 | 
						|
        var accountIds = members.Select(m => m.AccountId).ToList();
 | 
						|
        var accountsDict = await db.Accounts
 | 
						|
            .Include(a => a.Profile)
 | 
						|
            .Where(a => accountIds.Contains(a.Id))
 | 
						|
            .ToDictionaryAsync(a => a.Id, a => a);
 | 
						|
 | 
						|
        return members.Select(m =>
 | 
						|
        {
 | 
						|
            if (accountsDict.TryGetValue(m.AccountId, out var account))
 | 
						|
                m.Account = account;
 | 
						|
            return m;
 | 
						|
        }).ToList();
 | 
						|
    }
 | 
						|
}
 |