8000 fix mixdb permission by nhathoang989 · Pull Request #727 · mixcore/mix.core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix mixdb permission #727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Mix.Database.EntityConfigurations.Base;
using Mix.Database.Services;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;

namespace Mix.Database.Entities.Cms.EntityConfigurations
{
Expand Down Expand Up @@ -44,22 +46,34 @@ public override void Configure(EntityTypeBuilder<MixDatabase> builder)
builder.Property(e => e.ReadPermissions)
.IsRequired(false)
.HasColumnType($"{Config.NString}{Config.MediumLength}")
.HasCharSet(Config.CharSet);
.HasCharSet(Config.CharSet)
.HasConversion(
v => JArray.FromObject(v).ToString(Newtonsoft.Json.Formatting.None),
v => JArray.Parse(v ?? "[]").ToObject<List<string>>());

builder.Property(e => e.CreatePermissions)
.IsRequired(false)
.HasColumnType($"{Config.NString}{Config.MediumLength}")
.HasCharSet(Config.CharSet);
.HasCharSet(Config.CharSet)
.HasConversion(
v => JArray.FromObject(v).ToString(Newtonsoft.Json.Formatting.None),
v => JArray.Parse(v ?? "[]").ToObject<List<string>>());

builder.Property(e => e.UpdatePermissions)
.IsRequired(false)
.HasColumnType($"{Config.NString}{Config.MediumLength}")
.HasCharSet(Config.CharSet);
.HasCharSet(Config.CharSet)
.HasConversion(
v => JArray.FromObject(v).ToString(Newtonsoft.Json.Formatting.None),
v => JArray.Parse(v ?? "[]").ToObject<List<string>>());

builder.Property(e => e.DeletePermissions)
.IsRequired(false)
.HasColumnType($"{Config.NString}{Config.MediumLength}")
.HasCharSet(Config.CharSet);
.HasCharSet(Config.CharSet)
.HasConversion(
v => JArray.FromObject(v).ToString(Newtonsoft.Json.Formatting.None),
v => JArray.Parse(v ?? "[]").ToObject<List<string>>());
}
}
}
11 changes: 6 additions & 5 deletions src/platform/mix.database/Entities/Cms/MixDatabase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Mix.Database.Entities.Cms
Expand All @@ -10,10 +11,10 @@ public class MixDatabase : EntityBase<int>
public string DisplayName { get; set; }
public virtual string Description { get; set; }
public MixDatabaseType Type { get; set; }
public string ReadPermissions { get; set; }
public string CreatePermissions { get; set; }
public string UpdatePermissions { get; set; }
public string DeletePermissions { get; set; }
public List<string> ReadPermissions { get; set; }
public List<string> CreatePermissions { get; set; }
public List<string> UpdatePermissions { get; set; }
public List<string> DeletePermissions { get; set; }
public bool SelfManaged { get; set; }

public virtual ICollection<MixDatabaseColumn> MixDatabaseColumns { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void OnAuthorization(AuthorizationFilterContext context)

private bool ValidEnpointPermission(AuthorizationFilterContext context)
{
return _permissionService.CheckEndpointPermission(UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method);
return _permissionService.CheckEndpointPermissionAsync(UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method).Result;
}

private bool ValidToken()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void OnAuthorization(AuthorizationFilterContext context)

private bool ValidEnpointPermission(AuthorizationFilterContext context)
{
return _permissionService.CheckEndpointPermission(UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method);
return _permissionService.CheckEndpointPermissionAsync(UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method).Result;
}

private bool ValidToken()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void OnAuthorization(AuthorizationFilterContext context)
{
if (ValidToken())
{
if (!IsInRoles(context.HttpContext.Request.Method, database))
if (!IsInRoles(context.HttpContext.Request.Method, database, context.HttpContext.Request.Path))
{
if (!ValidEnpointPermission(context))
{
Expand All @@ -72,20 +72,27 @@ public void OnAuthorization(AuthorizationFilterContext context)

private bool CheckByPassAuthenticate(string method, string path, MixDatabase database)
{
return
(method == "GET" && (string.IsNullOrEmpty(database.ReadPermissions) || JArray.Parse(database.ReadPermissions).Count == 0))
|| (method == "POST" && path.EndsWith("filter") && (string.IsNullOrEmpty(database.ReadPermissions) || JArray.Parse(database.ReadPermissions).Count == 0))
|| (method == "POST" && (string.IsNullOrEmpty(database.CreatePermissions) || JArray.Parse(database.CreatePermissions).Count == 0))
|| ((method == "PUT" || method == "PATCH") && (string.IsNullOrEmpty(database.UpdatePermissions) || JArray.Parse(database.UpdatePermissions).Count == 0))
|| (method == "DELETE" && (string.IsNullOrEmpty(database.DeletePermissions) || JArray.Parse(database.DeletePermissions).Count == 0));
return method switch {
"GET" => database.ReadPermissions == null
|| database.ReadPermissions.Count == 0,
"POST" => (path.EndsWith("filter") && (database.ReadPermissions == null || database.ReadPermissions.Count == 0))
|| (!path.EndsWith("filter") && (database.CreatePermissions == null || database.CreatePermissions.Count == 0)),
"PUT" => database.UpdatePermissions == null
|| database.UpdatePermissions.Count == 0,
"PATCH" => database.UpdatePermissions == null
|| database.UpdatePermissions.Count == 0,
"DELETE" => database.DeletePermissions == null
|| database.DeletePermissions.Count == 0,
_ => false
};
}

#region Privates

private bool ValidEnpointPermission(AuthorizationFilterContext context)
{
return _permissionService.CheckEndpointPermission(
UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method);
return _permissionService.CheckEndpointPermissionAsync(
UserRoles, context.HttpContext.Request.Path, context.HttpContext.Request.Method).Result;
}

private bool ValidToken()
Expand All @@ -95,7 +102,7 @@ private bool ValidToken()
&& DateTime.UtcNow < expireAt;
}

private bool IsInRoles(string method, MixDatabase database)
private bool IsInRoles(string method, MixDatabase database, string path)
{

UserRoles = _idService.GetClaim(userPrinciple, MixClaims.Role).Split(',', StringSplitOptions.RemoveEmptyEntries)
Expand All @@ -109,7 +116,15 @@ private bool IsInRoles(string method, MixDatabase database)
switch (method)
{
case "GET": return CheckUserInRoles(database.ReadPermissions, UserRoles);
case "POST": return CheckUserInRoles(database.CreatePermissions, UserRoles);
case "POST":
if (path.EndsWith("filter"))
{
return CheckUserInRoles(database.ReadPermissions, UserRoles);
}
else
{
return CheckUserInRoles(database.CreatePermissions, UserRoles);
}
case "PATCH":
case "PUT": return CheckUserInRoles(database.UpdatePermissions, UserRoles);
case "DELETE": return CheckUserInRoles(database.DeletePermissions, UserRoles);
Expand All @@ -118,10 +133,9 @@ private bool IsInRoles(string method, MixDatabase database)
}
}

private bool CheckUserInRoles(string roles, string[] userRoles)
private bool CheckUserInRoles(List<string> allowedRoles, string[] userRoles)
{
var allowedRoles = JArray.Parse(roles).Values<string>().ToArray();
return allowedRoles.Length == 0 || allowedRoles.Any(r => userRoles.Any(ur => ur == $"{r}-{_idService.CurrentTenant.Id}"));
return allowedRoles == null || allowedRoles.Count == 0 || allowedRoles.Any(r => userRoles.Any(ur => ur == $"{r}-{_idService.CurrentTenant.Id}"));
}

#endregion
Expand Down
2 changes: 0 additions & 2 deletions src/platform/mix.library/Startup/MixCommonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ private static IServiceCollection AddMixCommonServices(this IServiceCollection s
services.TryAddScoped<EmailService>();
services.TryAddScoped<IMixEdmService, MixEdmService>();

MixPermissionService permissionSrv = services.GetService<MixPermissionService>();
permissionSrv.Reload().GetAwaiter().GetResult();
return services;
}
}
Expand Down
34 changes: 21 additions & 13 deletions src/platform/mix.service/Services/MixPermissionService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Mix.Constant.Constants;
using Mix.Database.Entities.Account;
using Mix.Database.Entities.Cms;
Expand All @@ -16,17 +17,18 @@ namespace Mix.Service.Services
{
public sealed class MixPermissionService
{
private readonly DatabaseService _databaseService;
private readonly IHttpContextAccessor _httpContextAccessor;
public Dictionary<string, string[]> RoleEndpoints { get; private set; }
private MixCmsAccountContext accountDbContext;
private UnitOfWorkInfo<MixDbDbContext> uow;
private int? _tenantId;
private IServiceScope _serviceScope { get; set; }
private readonly IServiceProvider _servicesProvider;
public MixPermissionService(
IHttpContextAccessor httpContextAccessor)
{
IHttpContextAccessor httpContextAccessor, IServiceProvider servicesProvider)
{
_servicesProvider = servicesProvider;
_httpContextAccessor = httpContextAccessor;
_databaseService = new(httpContextAccessor);
_tenantId = _httpContextAccessor.HttpContext?.Session.GetInt32(MixRequestQueryKeywords.TenantId) ?? 1;
}

Expand All @@ -36,10 +38,10 @@ public async Task Reload()
{
try
{
uow = new(new MixDbDbContext(_databaseService));
uow = GetRequiredService<UnitOfWorkInfo<MixDbDbContext>>();
RoleEndpoints = new Dictionary<string, string[]>();
accountDbContext = new MixCmsAccountContext(_databaseService);
using var cmsDbContext = new MixCmsContext(_databaseService);
accountDbContext = GetRequiredService<MixCmsAccountContext>();
var cmsDbContext = GetRequiredService<MixCmsContext>();

var roles = await accountDbContext.MixRoles.ToListAsync();

Expand Down Expand Up @@ -85,16 +87,22 @@ public async Task Reload()
{
throw new MixException(Heart.Enums.MixErrorStatus.Badrequest, ex);
}
finally
{
uow.Dispose();
accountDbContext.Dispose();
}
}
}

public bool CheckEndpointPermission(string[] userRoles, PathString path, string method)
private T GetRequiredService<T>()
where T : class
{
_serviceScope ??= _servicesProvider.CreateScope();
return _serviceScope.ServiceProvider.GetRequiredService<T>();
}

public async Task<bool> CheckEndpointPermissionAsync(string[] userRoles, PathString path, string method)
{
if(RoleEndpoints == null)
{
await Reload();
}
if (userRoles == null)
{
return false;
Expand Down
0