132 lines
4.1 KiB
C#
132 lines
4.1 KiB
C#
using System.Text.Json;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NodaTime;
|
|
|
|
namespace DysonNetwork.Sphere.Permission;
|
|
|
|
public class PermissionService(AppDatabase db)
|
|
{
|
|
public async Task<bool> HasPermissionAsync(string actor, string area, string key)
|
|
{
|
|
var value = await GetPermissionAsync<bool>(actor, area, key);
|
|
return value;
|
|
}
|
|
|
|
public async Task<T?> GetPermissionAsync<T>(string actor, string area, string key)
|
|
{
|
|
var now = SystemClock.Instance.GetCurrentInstant();
|
|
var groupsId = await db.PermissionGroupMembers
|
|
.Where(n => n.Actor == actor)
|
|
.Where(n => n.ExpiredAt == null || n.ExpiredAt < now)
|
|
.Where(n => n.AffectedAt == null || n.AffectedAt >= now)
|
|
.Select(e => e.GroupId)
|
|
.ToListAsync();
|
|
var permission = await db.PermissionNodes
|
|
.Where(n => n.GroupId == null || groupsId.Contains(n.GroupId.Value))
|
|
.Where(n => (n.Key == key || n.Key == "*") && (n.GroupId != null || n.Actor == actor) && n.Area == area)
|
|
.Where(n => n.ExpiredAt == null || n.ExpiredAt < now)
|
|
.Where(n => n.AffectedAt == null || n.AffectedAt >= now)
|
|
.FirstOrDefaultAsync();
|
|
|
|
return permission is not null ? _DeserializePermissionValue<T>(permission.Value) : default;
|
|
}
|
|
|
|
public async Task<PermissionNode> AddPermissionNode<T>(
|
|
string actor,
|
|
string area,
|
|
string key,
|
|
T value,
|
|
Instant? expiredAt = null,
|
|
Instant? affectedAt = null
|
|
)
|
|
{
|
|
if (value is null) throw new ArgumentNullException(nameof(value));
|
|
|
|
var node = new PermissionNode
|
|
{
|
|
Actor = actor,
|
|
Key = key,
|
|
Area = area,
|
|
Value = _SerializePermissionValue(value),
|
|
ExpiredAt = expiredAt,
|
|
AffectedAt = affectedAt
|
|
};
|
|
|
|
db.PermissionNodes.Add(node);
|
|
await db.SaveChangesAsync();
|
|
|
|
return node;
|
|
}
|
|
|
|
public async Task<PermissionNode> AddPermissionNodeToGroup<T>(
|
|
PermissionGroup group,
|
|
string actor,
|
|
string area,
|
|
string key,
|
|
T value,
|
|
Instant? expiredAt = null,
|
|
Instant? affectedAt = null
|
|
)
|
|
{
|
|
if (value is null) throw new ArgumentNullException(nameof(value));
|
|
|
|
var node = new PermissionNode
|
|
{
|
|
Actor = actor,
|
|
Key = key,
|
|
Area = area,
|
|
Value = _SerializePermissionValue(value),
|
|
ExpiredAt = expiredAt,
|
|
AffectedAt = affectedAt,
|
|
Group = group,
|
|
GroupId = group.Id
|
|
};
|
|
|
|
db.PermissionNodes.Add(node);
|
|
await db.SaveChangesAsync();
|
|
|
|
return node;
|
|
}
|
|
|
|
public async Task RemovePermissionNode(string actor, string area, string key)
|
|
{
|
|
var node = await db.PermissionNodes
|
|
.Where(n => n.Actor == actor && n.Area == area && n.Key == key)
|
|
.FirstOrDefaultAsync();
|
|
if (node is not null) db.PermissionNodes.Remove(node);
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
public async Task RemovePermissionNodeFromGroup<T>(PermissionGroup group, string actor, string area, string key)
|
|
{
|
|
var node = await db.PermissionNodes
|
|
.Where(n => n.GroupId == group.Id)
|
|
.Where(n => n.Actor == actor && n.Area == area && n.Key == key)
|
|
.FirstOrDefaultAsync();
|
|
if (node is null) return;
|
|
db.PermissionNodes.Remove(node);
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
private static T? _DeserializePermissionValue<T>(JsonDocument json)
|
|
{
|
|
return JsonSerializer.Deserialize<T>(json.RootElement.GetRawText());
|
|
}
|
|
|
|
private static JsonDocument _SerializePermissionValue<T>(T obj)
|
|
{
|
|
var str = JsonSerializer.Serialize(obj);
|
|
return JsonDocument.Parse(str);
|
|
}
|
|
|
|
public static PermissionNode NewPermissionNode<T>(string actor, string area, string key, T value)
|
|
{
|
|
return new PermissionNode
|
|
{
|
|
Actor = actor,
|
|
Area = area,
|
|
Key = key,
|
|
Value = _SerializePermissionValue(value),
|
|
};
|
|
}
|
|
} |