/// <summary> /// Return the list of all objects that the subject has access to, and the reason for the access. /// </summary> /// <param name="subjectId">The role or user </param> /// <param name="settings">Settings</param> /// <returns>List of access reasons.</returns> public IReadOnlyList <AccessReason> GetTypeAccessReasons(long subjectId, [NotNull] TypeAccessReasonSettings settings) { // Get list of applicable access rules // null permission = matches any permission // null securableEntityTypes = matches any type IReadOnlyList <AccessRuleQuery> queries = QueryRepository.GetQueries(subjectId, null, null).ToList( ); // Preload all applicable access rules IEnumerable <long> accessRuleIds = queries.Select(query => query.AccessRuleId); IDictionary <long, AccessRule> accessRules = EntityRepository.Get <AccessRule>(accessRuleIds).ToDictionary(e => e.Id); // Build initial list of reasons List <AccessReason> reasons = new List <AccessReason>( ); foreach (AccessRuleQuery ruleQuery in queries) { AccessRule accessRule; if (!accessRules.TryGetValue(ruleQuery.AccessRuleId, out accessRule)) { continue; // assert false } bool allInstances = ruleQuery.DoesQueryGrantAllOfTypes(ruleQuery.ControlsAccessForTypeId); bool perUser = !allInstances && ruleQuery.DoesQueryReferToCurrentUser( ); AccessRuleScope scope = allInstances ? AccessRuleScope.AllInstances : (perUser ? AccessRuleScope.PerUser : AccessRuleScope.SomeInstances); AccessReason reason = new AccessReason { AccessRuleQuery = ruleQuery, AccessRule = accessRule, SubjectId = accessRule.AllowAccessBy?.Id ?? 0, TypeId = ruleQuery.ControlsAccessForTypeId, Description = "Access rule: " + (accessRule.AccessRuleReport?.Name ?? accessRule.Name), AccessRuleScope = scope }; AddPermissionsToReason(reason); reasons.Add(reason); } // Add implicit reasons due to relationship security AddReasonsByGroup(reasons); IEnumerable <AccessReason> result = reasons; result = FilterReasonsToUserTypes(result, settings); result = FilterOverlappingReasons(result); return(result.ToList( )); }
/// <summary> /// Filter the list of reasons to exclude system types. /// </summary> /// <param name="reasons">The full list of reasons to filter.</param> /// <param name="settings">Settings</param> /// <returns>List of access reasons.</returns> private IEnumerable <AccessReason> FilterReasonsToUserTypes(IEnumerable <AccessReason> reasons, [NotNull] TypeAccessReasonSettings settings) { HashSet <long> whitelist; if (settings.AdvancedTypes) { whitelist = new HashSet <long>(Entity.GetInstancesOfType("core:managedType").Select(e => e.Id)); whitelist.Add(new EntityRef("core:resource").Id); whitelist.Add(new EntityRef("core:userAccount").Id); } else { whitelist = new HashSet <long>(Entity.GetInstancesOfType("core:definition").Select(e => e.Id)); whitelist.Add(new EntityRef("core:userAccount").Id); } return(reasons.Where(reason => whitelist.Contains(reason.TypeId))); }