Improved server share permission handling and share ui

This commit is contained in:
2025-07-24 20:19:49 +02:00
parent 1f94752c54
commit 431cdcb260
19 changed files with 270 additions and 151 deletions

View File

@@ -1,3 +1,4 @@
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using MoonCore.Extended.SingleDb;
using Moonlight.ApiServer.Configuration;
@@ -40,12 +41,15 @@ public class ServersDataContext : DatabaseContext
#region Shares
modelBuilder.Ignore<ServerShareContent>();
modelBuilder.Ignore<ServerShareContent.SharePermission>();
modelBuilder.Entity<ServerShare>(builder =>
{
builder.OwnsOne(x => x.Content, navigationBuilder =>
{
navigationBuilder.ToJson();
navigationBuilder.OwnsMany(x => x.Permissions);
});
});

View File

@@ -9,6 +9,7 @@ using MoonCore.Models;
using Moonlight.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Extensions;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.ApiServer.Models;
using MoonlightServers.ApiServer.Services;
using MoonlightServers.Shared.Constants;
@@ -153,7 +154,7 @@ public class ServersController : Controller
Share = new()
{
SharedBy = owners.First(y => y.Id == x.Server.OwnerId).Username,
Permissions = x.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(x.Content)
}
}).ToArray();
@@ -223,7 +224,7 @@ public class ServersController : Controller
response.Share = new()
{
SharedBy = owner.Username,
Permissions = authorizationResult.Share.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(authorizationResult.Share.Content)
};
}

View File

@@ -7,6 +7,8 @@ using MoonCore.Extended.Abstractions;
using MoonCore.Models;
using Moonlight.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.ApiServer.Models;
using MoonlightServers.ApiServer.Services;
using MoonlightServers.Shared.Constants;
using MoonlightServers.Shared.Enums;
@@ -68,7 +70,7 @@ public class SharesController : Controller
{
Id = x.Id,
Username = users.First(y => y.Id == x.UserId).Username,
Permissions = x.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(x.Content)
}).ToArray();
return new PagedData<ServerShareResponse>()
@@ -104,13 +106,13 @@ public class SharesController : Controller
{
Id = share.Id,
Username = user.Username,
Permissions = share.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(share.Content)
};
return mappedItem;
}
[HttpPost("")]
[HttpPost]
public async Task<ServerShareResponse> Create(
[FromRoute] int serverId,
[FromBody] CreateShareRequest request
@@ -128,10 +130,7 @@ public class SharesController : Controller
var share = new ServerShare()
{
Server = server,
Content = new()
{
Permissions = request.Permissions
},
Content = ShareMapper.MapToServerShareContent(request.Permissions),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
UserId = user.Id
@@ -143,7 +142,7 @@ public class SharesController : Controller
{
Id = finalShare.Id,
Username = user.Username,
Permissions = finalShare.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(finalShare.Content)
};
return mappedItem;
@@ -165,7 +164,8 @@ public class SharesController : Controller
if (share == null)
throw new HttpApiException("A share with that id cannot be found", 404);
share.Content.Permissions = request.Permissions;
share.Content = ShareMapper.MapToServerShareContent(request.Permissions);
share.UpdatedAt = DateTime.UtcNow;
await ShareRepository.Update(share);
@@ -181,7 +181,7 @@ public class SharesController : Controller
{
Id = share.Id,
Username = user.Username,
Permissions = share.Content.Permissions
Permissions = ShareMapper.MapToPermissionLevels(share.Content)
};
return mappedItem;

View File

@@ -93,7 +93,7 @@ public class VariablesController : Controller
};
}
[HttpPut("")]
[HttpPut]
public async Task<ServerVariableDetailResponse> UpdateSingle(
[FromRoute] int serverId,
[FromBody] UpdateServerVariableRequest request
@@ -123,7 +123,7 @@ public class VariablesController : Controller
};
}
[HttpPatch("")]
[HttpPatch]
public async Task<ServerVariableDetailResponse[]> Update(
[FromRoute] int serverId,
[FromBody] UpdateServerVariableRangeRequest request

View File

@@ -45,13 +45,13 @@ public class ShareAuthFilter : IServerAuthorizationFilter
if (string.IsNullOrEmpty(permissionId) || requiredLevel == ServerPermissionLevel.None)
return ServerAuthorizationResult.Success(share);
if (
share.Content.Permissions.TryGetValue(permissionId, out var shareLevel) &&
shareLevel >= requiredLevel
)
{
var possiblePermShare = share.Content.Permissions.FirstOrDefault(x => x.Identifier == permissionId);
if (possiblePermShare == null)
return null;
if (possiblePermShare.Level >= requiredLevel)
return ServerAuthorizationResult.Success(share);
}
return null;
}

View File

@@ -0,0 +1,27 @@
using MoonlightServers.ApiServer.Models;
using MoonlightServers.Shared.Enums;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper]
public static partial class ShareMapper
{
public static ServerShareContent MapToServerShareContent(Dictionary<string, ServerPermissionLevel> permissionLevels)
{
return new ServerShareContent()
{
Permissions = permissionLevels.Select(x => new ServerShareContent.SharePermission()
{
Identifier = x.Key,
Level = x.Value
}).ToList()
};
}
public static Dictionary<string, ServerPermissionLevel> MapToPermissionLevels(
ServerShareContent content)
{
return content.Permissions.ToDictionary(x => x.Identifier, x => x.Level);
}
}

View File

@@ -2,7 +2,13 @@ using MoonlightServers.Shared.Enums;
namespace MoonlightServers.ApiServer.Models;
public class ServerShareContent
public record ServerShareContent
{
public Dictionary<string, ServerPermissionLevel> Permissions { get; set; } = new();
public List<SharePermission> Permissions { get; set; } = new();
public record SharePermission
{
public string Identifier { get; set; }
public ServerPermissionLevel Level { get; set; }
}
}