_context
_db
AuthMeta
AuthorizedMeta.Current
UserTypeId
public interface IUserCanAccess { bool UserCanAccessEntity(NetSoftDataModel db, int id, string userId, int? labId, UserTypeEnum userTypeId); }
using Microsoft.AspNetCore.Http; using System; public static class SecurityHelper { public static int? GetLabId(HttpRequest request, bool allowNull = false) { /*--- If the user is assigned a lab, return that lab ---*/ if (AuthorizedMeta.Current?.LabId != null) { return AuthorizedMeta.Current.LabId; } /*--- Otherwise, check the query string ---*/ var labId = GetQueryStringItem(request, "labId"); if (labId == null && !allowNull) { throw new Exception("Invalid Lab ID"); } return labId; } private static int? GetQueryStringItem(HttpRequest request, string key) { var val = request.Query.ContainsKey(key) ? request.Query[key][0] : null; if (int.TryParse(val, out int result)) { return result; } return null; } }
using System; [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class ValidateUserCanAccessAttribute : Attribute { public string IdRouteParameterName { get; private set; } public Type EntityType { get; private set; } public ValidateUserCanAccessAttribute(Type entityType, string idRouteParameterName) { EntityType = entityType; IdRouteParameterName = idRouteParameterName; } }
protected void ValidateUserCanAccess<T>(int id) where T : IUserCanAccess, new() { var a = new T(); /* TODO: Replace "Tenant" with the name of your tenant table. */ /* If not a multi-tenant application, replace with string.Empty. */ var labId = a.GetType().Name == "Tenant" ? AuthorizedMeta.Current.LabId : SecurityHelper.GetLabId(Request); if (!a.UserCanAccessEntity(_context, id, AuthMeta.UserId, labId, AuthorizedMeta.Current.UserTypeId)) { throw new UnauthorizedAccessException($"User can't access {a.GetType().Name} {id}."); } }
public IQueryable<T> GetRepoItems<T>() where T: class, new() { var modelType = this.GetType(); var totFullName = (typeof(T)).FullName; var prop = modelType.GetProperties() .FirstOrDefault(p => p.PropertyType.IsGenericType && p.PropertyType.Name == "DbSet`1" && p.PropertyType.GenericTypeArguments[0].FullName == totFullName ); var dbSet = prop.GetValue(this) as DbSet<T>; var q = dbSet?.AsQueryable<T>(); if (q != null && typeof(IWhereUserCanAccess<T>).IsAssignableFrom(typeof(T))) { var userId = AuthorizedMeta.Current.UserId; // Note: AuthorizedMeta.Current.SelectedTenantId gets set in the global authorization // filter code based on a query string parameter. var tenantId = AuthorizedMeta.Current.SelectedTenantId; var userTypeId = AuthorizedMeta.Current.UserTypeId; q = q.Where((new T() as IWhereUserCanAccess<T>).WhereUserCanAccess(userId, tenantId, userTypeId)); } return q; }
public interface IWhereUserCanAccess<T> { Expression<Func<T, bool>> WhereUserCanAccess(string userId, int? selectedTenantId, UserTypeEnum userTypeId); }
IWhereUserCanAccess
public class Item { public Expression<Func<Item, bool>> WhereUserCanAccess(string userId, int? selectedTenantId, UserTypeEnum userTypeId) { return a => !a.IsDeleted && a.TenantId == selectedTenantId; } }
using (var db = new MyDataModel()) { var dbItem = db.GetRepoItems<Item>().FirstOrDefault(a => a.Id == id); }
ScrewTurn Wiki version 3.0.1.400. Some of the icons created by FamFamFam. Except where noted, all contents Copyright © 1999-2024, Patrick Jasinski.