В настоящее время я пишу фреймворк отдыха, я хотел бы создать способ ограничения доступа к определенным объектам не только через чтение, но и через запись.В настоящее время я создал базовый DbContext, который обрабатывает авторизацию примерно так (я пропустил некоторый код, такой как присвоение опций, потому что они не имеют отношения к проблеме):
public abstract class AuthorizedDbContext : DbContext
{
//...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var constraintOptions = this._authorizationOptions.ConstraintOptions;
constraintOptions.ApplyStaticConstraint(modelBuilder, this);
base.OnModelCreating(modelBuilder);
}
public async override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
this.VerifyResourceAccess();
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
protected void VerifyResourceAccess()
{
if (false == ChangeTracker.HasChanges())
{
return;
}
//WARNING: if you don't set the change tracking behavior to no tracking, you could reload entities by accident
var previousTrackingBehavior = this.ChangeTracker.QueryTrackingBehavior;
this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
this._authorizationOptions.ContextValidator.ValidateAndThrow(this);
this.ChangeTracker.QueryTrackingBehavior = previousTrackingBehavior;
}
}
В настоящее время я внедряю dbcontextвалидатор, который обрабатывает ограничивающие обновления и другие проверки при сохранении изменений.
Пользователь имеет спокойствие, зная, что при использовании этого авторизованного контекста сущности не смогут обновляться без прохождения всех проверок, определенных пользователем вих код.
Эта архитектура отстой, хотя и серьезно ограничивает гибкость пользовательского кода (например), если пользователь хочет использовать IdentityDbContext, это будет невозможно, пока я не создам AuthorizedDbContext, который наследуется от IdentityDbContext<AppUser>
Вместо этого я предпочел бы использовать обертку вокруг их контекста.Например,
//Pseudo-Code
AuthorizedDbContextScope<T>: IDisposable
where T: DbContext
{
public void ApplyConstraints()
{
this._options.DynamicConstraints.Foreach(EntityFrameWorkZ.ApplyDynamicFilterFromAction)
}
}
Единственные проблемы с этой оболочкой: 1. Я не могу раскрыть функциональность DbContext, я не могу переопределить изменения сохранения в области действия, я должен заставить пользователя вызывать изменения сохранения в оболочке..
Я мог бы использовать DynamicProxy для наследования от их DbContext при запуске, но это похоже на избыточное убийство, и это сильно замедлило бы запуск проекта.
Если у кого-нибудь есть предложениекак я могу лучше универсально ограничить свои обновления, пожалуйста, дайте мне знать.
Как можно полностью ограничить изменения в БД без ограничения гибкости наследования в коде пользователя?