// Check read authorization on all the entities of a dataset. usefull when a get, getcollection or save action is configured with includes, to make sure related objects can be read for the given user claims. // dataset : the dataset to check // entitiesToIgnore : for these entities, the check should be skipped // mode : define if an entity not authorized should be removed from the dataset or an exception thrown public PermissionLevel CheckReadAuthorizationsOnDataSet(IObjectsDataSet dataset, UserClaims claims, IEnumerable <IDataObject> entitiesToIgnore, DataSetAuthorizationCheckMode mode, Parameters parameters, out string message) { message = null; SecurityPredicate predicate = null; // Work on a clone of the dataset so as not to mess with the original (causes save problems otherwise, e.g. if main entity !IsDirty) dataset = dataset.Clone(); foreach (var entity in dataset.GetAllObjects()) { var permissionLevel = CanRead(entity, claims, out message, out predicate); if (permissionLevel != PermissionLevel.Authorized) { if (mode == DataSetAuthorizationCheckMode.RemoveFromDataSet) { dataset.RemoveObject(entity); continue; } else { string explanation = Explain(EntityAccessEnum.READ, GetEntityAuthorizations(entity).EntityDisplayName); message = FormatAccessDeniedMessage(explanation, predicate); return(PermissionLevel.Denied); } } if (predicate != null) { // If the security filter needs related data, load it first: if (!String.IsNullOrEmpty(predicate.Includes)) { DataObjectHelper.RecurseLoadIncludes(entity, parameters, predicate.Includes, skipSecurity: true); } if (!DoesPredicateAccept(entity, predicate.Filter, predicate.Includes, EntityAccessEnum.READ)) { if (mode == DataSetAuthorizationCheckMode.RemoveFromDataSet) { dataset.RemoveObject(entity); continue; } else { string explanation = Explain(EntityAccessEnum.READ, GetEntityAuthorizations(entity).EntityDisplayName); message = FormatAccessDeniedMessage(explanation, predicate); return(PermissionLevel.Denied); } } } } return(PermissionLevel.Authorized); }
public bool IsAuthorized( IDataObject entity, SecurityPredicate predicate, EntityAccessEnum action, ref string message, Parameters parameters = null) { if (parameters == null) { // connect to existing transaction by using the existing parameters var transaction = ApplicationSettings.Resolve <ITransactionProvider>().GetTransaction(parameters) as DatabaseDataProviderTransaction; parameters = transaction.Parameters; // this following line is probably no necessary. just for safety parameters = parameters ?? new Parameters(); } var entityAuthorizations = GetEntityAuthorizations(entity); // If the security filter needs related data, load related data first: if (!String.IsNullOrEmpty(predicate.Includes)) { DataObjectHelper.RecurseLoadIncludes(entity, parameters, predicate.Includes, skipSecurity: true); } // First check the submitted data : is submitted data authorized? if (predicate.IsEvaluateDataset) { if (!DoesPredicateAccept(entity, predicate.DatasetFilter, predicate.Includes, action)) { string explanation = Explain(action, entityAuthorizations.EntityDisplayName); message = FormatAccessDeniedMessage(explanation, predicate); return(false); } } // Then check existing data in database if (predicate.IsEvaluateDatabase && !entity.IsNew) { // Important: We fetch a fresh copy (including the includes) to eliminate possibility of hacker messing with the dataset dynamic provider = ApplicationSettings.Container.Resolve <IEntityDataProvider>().GetDataProviderForEntity(entity); var existingEntity = provider.Get(entity, null, includes: String.IsNullOrEmpty(predicate.Includes) ? null : predicate.Includes.Split(',').ToList(), parameters: parameters, skipSecurity: true); if (!DoesPredicateAccept(existingEntity, predicate.DatasetFilter, predicate.Includes, action)) { string explanation = Explain(action, entityAuthorizations.EntityDisplayName); message = FormatAccessDeniedMessage(explanation, predicate); return(false); } } return(true); }