/// <summary> /// Copies the authorization. /// </summary> /// <param name="sourceEntity">The source entity.</param> /// <param name="targetEntity">The target entity.</param> public static void CopyAuthorization(ISecured sourceEntity, ISecured targetEntity) { using (var rockContext = new RockContext()) { CopyAuthorization(sourceEntity, targetEntity, rockContext); } }
/// <summary> /// Determines whether the specified entity is private. Entity is considered private if only the current user /// has access. In this scenario, the first rule would give current user access, and second rule would deny /// all users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <returns> /// <c>true</c> if the specified entity is private; otherwise, <c>false</c>. /// </returns> public static bool IsPrivate(ISecured entity, string action, Person person) { if (person != null) { // If there's no Authorizations object, create it if (Authorizations == null) { Load(); } // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if (Authorizations.Keys.Contains(entity.TypeId) && Authorizations[entity.TypeId].Keys.Contains(entity.Id) && Authorizations[entity.TypeId][entity.Id].Keys.Contains(action) && Authorizations[entity.TypeId][entity.Id][action].Count == 2) { AuthRule firstRule = Authorizations[entity.TypeId][entity.Id][action][0]; AuthRule secondRule = Authorizations[entity.TypeId][entity.Id][action][1]; // If first rule allows current user, and second rule denies all other users then entity is private if (firstRule.AllowOrDeny == "A" && firstRule.SpecialRole == SpecialRole.None && firstRule.PersonId == person.Id && secondRule.AllowOrDeny == "D" && secondRule.SpecialRole == SpecialRole.AllUsers) { return(true); } } } return(false); }
/// <summary> /// This is a heavily modified version of the Security.ItemAuthorized private method. It should perform /// nearly 99% of the same functionality. It's use is to find the explicit Auth record that matches the /// entity in question. /// </summary> /// <param name="entity">The entity whose auth records we are searching for.</param> /// <param name="action">The action that is to be authorized.</param> /// <param name="person">The person requesting permissions.</param> /// <param name="isRootEntity">True if this is the first call, false when called recursively.</param> /// <param name="checkParentAuthority">True if the parent authorities should be checked, otherwise false.</param> /// <param name="authoritative">On return this contains the ISecured object that had the explicit Auth record defined.</param> /// <returns>An Auth object if a permission was found, otherwise null.</returns> Auth ItemAuthorized(ISecured entity, string action, Person person, bool isRootEntity, bool checkParentAuthority, out ISecured authoritative) { var auth = MatchingAuth(entity, action, person); if (auth != null) { authoritative = entity; return(auth); } if (checkParentAuthority) { Auth parentAuthorized = null; ISecured parentAuthority = null; if (isRootEntity && entity.ParentAuthorityPre != null) { parentAuthorized = ItemAuthorized(entity.ParentAuthorityPre, action, person, false, false, out parentAuthority); } if (parentAuthorized == null && entity.ParentAuthority != null) { parentAuthorized = ItemAuthorized(entity.ParentAuthority, action, person, false, true, out parentAuthority); } if (parentAuthorized != null) { authoritative = parentAuthority; return(parentAuthorized); } } authoritative = null; return(null); }
/// <summary> /// Handles the Click event of the control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void gUnlock_Click(object sender, EventArgs e) { RowEventArgs args = ( RowEventArgs )e; var auth = new AuthService(new RockContext()).Get(args.RowKeyId); if (auth != null && auth.Id != 0) { var rockContext = new RockContext(); var person = ppPerson.PersonId.HasValue ? new PersonService(new RockContext()).Get(ppPerson.PersonId.Value) : CurrentPerson; ISecured entity = GetEntity(); var explicitAuth = new AuthService(rockContext).Queryable() .Where(a => a.EntityTypeId == auth.EntityTypeId && a.EntityId == auth.EntityId && a.Action == auth.Action) .Where(a => a.PersonAlias.PersonId == person.Id) .FirstOrDefault(); if (explicitAuth != null) { explicitAuth.AllowOrDeny = "A"; rockContext.SaveChanges(); Authorization.RefreshAction(entity.TypeId, entity.Id, auth.Action); } else { Authorization.AllowPerson(entity, auth.Action, person); } nbPoppedLock.Text = string.Format("An explicit Allow rule has been added for {0}", person.FullName); BindGrid(entity, person); } }
/// <summary> /// Handles the Click event of the control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void btnCheck_Click(object sender, EventArgs e) { ISecured entity = null; pnlResult.Visible = false; nbWarning.Text = string.Empty; // // Find the entity they are searching for or display an error if we couldn't parse the Id. // entity = GetEntity(); // // If the entity was not found, display an error. // if (entity == null) { nbWarning.Text = "Could not find the entity, maybe the wrong Id was specified."; return; } // // Get the selected person or use the currently logged in person. // var person = ppPerson.PersonId.HasValue ? new PersonService(new RockContext()).Get(ppPerson.PersonId.Value) : CurrentPerson; BindGrid(entity, person); pnlResult.Visible = true; }
/// <summary> /// Updates authorization rules for the entity so that the current person is allowed to perform the specified action. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void AllowPerson( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( person != null ) { rockContext = rockContext ?? new RockContext(); // If there's no Authorizations object, create it if ( Authorizations == null ) { Load( rockContext ); } var authService = new AuthService( rockContext ); // If there are not entries in the Authorizations object for this entity type and entity instance, create // the dictionary entries if ( !Authorizations.Keys.Contains( entity.TypeId ) ) { Authorizations.Add( entity.TypeId, new Dictionary<int, Dictionary<string, List<AuthRule>>>() ); } if ( !Authorizations[entity.TypeId].Keys.Contains( entity.Id ) ) { Authorizations[entity.TypeId].Add( entity.Id, new Dictionary<string, List<AuthRule>>() ); } List<AuthRule> rules = null; if ( Authorizations[entity.TypeId][entity.Id].Keys.Contains( action ) ) { rules = Authorizations[entity.TypeId][entity.Id][action]; } else { rules = new List<AuthRule>(); Authorizations[entity.TypeId][entity.Id].Add( action, rules ); } int order = 0; Auth auth = new Auth(); auth.EntityTypeId = entity.TypeId; auth.EntityId = entity.Id; auth.Order = order++; auth.Action = action; auth.AllowOrDeny = "A"; auth.SpecialRole = SpecialRole.None; auth.PersonId = person.Id; authService.Add( auth ); foreach(var rule in rules) { var existingAuth = authService.Get( rule.Id ); existingAuth.Order = order++; } rockContext.SaveChanges(); rules.Insert(0, new AuthRule( auth ) ); } }
/// <summary> /// Evaluates whether a selected user is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity"></param> /// <param name="action"></param> /// <param name="user"></param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, System.Web.Security.MembershipUser user ) { // If there's no Authorizations object, create it if ( Authorizations == null ) Load(); // If there's no entry in the Authorizations object for this entity type, return the default authorization if ( !Authorizations.Keys.Contains( entity.AuthEntity ) ) return entity.DefaultAuthorization( action ); // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( Authorizations[entity.AuthEntity].Keys.Contains( entity.Id ) && Authorizations[entity.AuthEntity][entity.Id].Keys.Contains( action ) ) foreach ( AuthRule authRule in Authorizations[entity.AuthEntity][entity.Id][action] ) { if ( authRule.UserOrRoleName == "*" ) return authRule.AllowOrDeny == "A"; if ( user != null ) if ( ( authRule.UserOrRole == "U" && user.UserName == authRule.UserOrRoleName ) || ( authRule.UserOrRole == "R" && System.Web.Security.Roles.IsUserInRole( user.UserName, authRule.UserOrRoleName ) ) ) return authRule.AllowOrDeny == "A"; } // If not match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization if ( entity.ParentAuthority != null ) return Authorized( entity.ParentAuthority, action, user ); else return entity.DefaultAuthorization( action ); }
/// <summary> /// Gets the ordered explicit authorization rules for an entity. The first rule in the list /// should be checked first, and so on. The order follows from the first explicit rule on the /// entity to the last explicit rule on the entity, then the first explicit rule on the parent /// entity to the last explicit rule on the parent entity and so on. /// </summary> /// <param name="entity">The entity.</param> /// <returns>A collection of explicit authorization rules in the proper order.</returns> private static List <string> GetOrderedExplicitAuthorizationRules(ISecured entity) { var explicitRules = new List <string>(); if (entity == null) { return(explicitRules); } // // Get the ancestor authorization rules. // var parentEntity = entity.ParentAuthority; if (parentEntity != null) { explicitRules = GetOrderedExplicitAuthorizationRules(parentEntity); } var authRules = Authorization.AuthRules(entity.TypeId, entity.Id, Authorization.VIEW); // // Walk each rule in descending order so that the final order is correct // since we insert rules at index 0. // foreach (var rule in authRules.OrderByDescending(a => a.Order)) { string entityIdentifier; if (rule.SpecialRole != SpecialRole.None) { entityIdentifier = $"S:{( int ) rule.SpecialRole}"; } else if (rule.GroupId.HasValue) { var role = RoleCache.Get(rule.GroupId.Value); if (role == null) { continue; } entityIdentifier = $"G:{role.Guid}"; } else if (rule.PersonId.HasValue) { /* Not currently supported, maybe in the future. -dsh */ continue; } else { continue; } explicitRules.Insert(0, $"{entityIdentifier}:{rule.AllowOrDeny}"); } return(explicitRules); }
public static void CopyAuthorization( ISecured sourceEntity, ISecured targetEntity, int? personId ) { using ( new Rock.Helpers.UnitOfWorkScope() ) { // If there's no Authorizations object, create it if ( Authorizations == null ) Load(); AuthService authService = new AuthService(); // Delete the current authorizations for the target entity foreach(Auth auth in authService.GetAuthsByEntityTypeAndEntityId(targetEntity.AuthEntity, targetEntity.Id)) authService.DeleteAuth(auth); Dictionary<string, List<AuthRule>> newActions = new Dictionary<string, List<AuthRule>>(); int order = 0; foreach ( KeyValuePair<string, List<AuthRule>> action in Authorizations[sourceEntity.AuthEntity][sourceEntity.Id] ) if (targetEntity.SupportedActions.Contains(action.Key)) { newActions.Add( action.Key, new List<AuthRule>() ); foreach ( AuthRule rule in action.Value ) { Auth auth = new Auth(); auth.EntityType = targetEntity.AuthEntity; auth.EntityId = targetEntity.Id; auth.Order = order; auth.Action = action.Key; auth.AllowOrDeny = rule.AllowOrDeny; auth.UserOrRole = rule.UserOrRole; auth.UserOrRoleName = rule.UserOrRoleName; authService.AddAuth(auth); authService.Save(auth, personId); newActions[action.Key].Add( new AuthRule( rule.AllowOrDeny, rule.UserOrRole, rule.UserOrRoleName ) ); order++; } } if ( !Authorizations.ContainsKey( targetEntity.AuthEntity ) ) Authorizations.Add( targetEntity.AuthEntity, new Dictionary<int, Dictionary<string, List<AuthRule>>>() ); Dictionary<int, Dictionary<string, List<AuthRule>>> entityType = Authorizations[targetEntity.AuthEntity]; if ( !entityType.ContainsKey( targetEntity.Id ) ) entityType.Add( targetEntity.Id, new Dictionary<string, List<AuthRule>>() ); entityType[targetEntity.Id] = newActions; } }
/// <summary> /// Initializes a new instance of the /// <see cref="NotAuthorizedToEditException" /> /// class. /// </summary> /// /// <param name="person"> /// The <see cref="Person" /> performing the edit, /// whose authorizations should be checked. /// </param> /// /// <param name="entity"> /// The <see cref="ISecured" /> entity being edited. /// </param> public NotAuthorizedToEditException(Person person, ISecured entity) : base ( String .Format ( "{0} is not authorized to edit {1}.", (String.IsNullOrWhiteSpace(person.FullName) ? "Person" : person.FullName.Trim()), (String.IsNullOrWhiteSpace(entity.TypeName) ? "entity" : entity.TypeName.Trim()) ) ) { }
/// <summary> /// Updates authorization rules for the entity so that the current person is allowed to perform the specified action. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void AllowPerson(ISecured entity, string action, Person person, RockContext rockContext = null) { if (rockContext != null) { MyAllowPerson(entity, action, person, rockContext); } else { using (var myRockContext = new RockContext()) { MyAllowPerson(entity, action, person, myRockContext); } } }
/// <summary> /// Checks if principal Users has access to some action (AccessRight). /// </summary> /// <param name="secured"> Secured entity. </param> /// <param name="right"> AccessRight action </param> /// <param name="principal"> Current principal. </param> /// <returns> Value indicates if action is approved for selected role. </returns> //public static bool IsAllowed(this ISecured secured, AccessRight right, IPrincipal principal, IUsersInRolesRepository uic) //{ // var user = principal.Identity.Name; // var roles = uic.GetAll(); // var v = roles.Any(role => secured.IsAllowed(right, user)); // return v; //} private static Access GetAccess(ISecured secured, AccessRight right, string role) { var access = secured.Permissions.GetAccess(right, role); if (access != Access.Inherit) { return(access); } var securedChild = secured as ISecuredChild; return(securedChild == null || securedChild.Parent == null ? Access.Inherit : GetAccess(securedChild.Parent, right, role)); }
/// <summary> /// Checks if role has access to some action (AccessRight). /// </summary> /// <param name="secured"> Secured entity. </param> /// <param name="right"> AccessRight action </param> /// <param name="role"> Role to check against. </param> /// <returns> Value indicates if action is approved for selected role. </returns> public static bool IsAllowed(this ISecured secured, AccessRight right, string role) { if (CmsContext.UnrestrictedRoles.Any(x => x == role)) { return(true); } var access = GetAccess(secured, right, role); if (access == Access.Inherit) { access = GetApplicationAccess(secured, right, role); } return(access == Access.Allow); }
private static void MyMakeUnPrivate(ISecured entity, string action, Person person, RockContext rockContext) { if (IsPrivate(entity, action, person)) { var authService = new AuthService(rockContext); // if is private, then there are only two rules for this action that should be deleted foreach (AuthRule authRule in Authorizations[entity.TypeId][entity.Id][action]) { var oldAuth = authService.Get(authRule.Id); authService.Delete(oldAuth); } rockContext.SaveChanges(); Authorizations[entity.TypeId][entity.Id][action] = new List <AuthRule>(); } }
private static bool?ItemAuthorized(ISecured entity, string action, SpecialRole specialRole) { // If there's no Authorizations object, create it if (Authorizations == null) { Load(); } var entityTypeId = entity.TypeId; // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if (Authorizations.Keys.Contains(entityTypeId) && Authorizations[entityTypeId].Keys.Contains(entity.Id) && Authorizations[entityTypeId][entity.Id].Keys.Contains(action)) { foreach (AuthRule authRule in Authorizations[entityTypeId][entity.Id][action]) { if (authRule.SpecialRole == specialRole) { return(authRule.AllowOrDeny == "A"); } } } // If no match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization bool?parentAuthorized = null; if (entity.ParentAuthorityPre != null) { parentAuthorized = ItemAuthorized(entity.ParentAuthorityPre, action, specialRole); } if (!parentAuthorized.HasValue && entity.ParentAuthority != null) { parentAuthorized = ItemAuthorized(entity.ParentAuthority, action, specialRole); } return(parentAuthorized); }
private void AddParentRules(List <MyAuthRule> rules, ISecured parent, string action) { if (parent != null) { var entityType = Rock.Web.Cache.EntityTypeCache.Read(parent.TypeId); foreach (AuthRule rule in Authorization.AuthRules(parent.TypeId, parent.Id, action)) { if (!rules.Exists(r => r.SpecialRole == rule.SpecialRole && r.PersonId == rule.PersonId && r.GroupId == rule.GroupId)) { var myRule = new MyAuthRule(rule); myRule.EntityTitle = string.Format("{0} ({1})", parent.ToString(), entityType.FriendlyName ?? entityType.Name).TrimStart(); rules.Add(myRule); } } AddParentRules(rules, parent.ParentAuthority, action); } }
/// <summary> /// Checks to see if the person is authorized to VIEW /// </summary> /// <param name="securedModel">The secured model.</param> /// <param name="person">The person.</param> /// <exception cref="System.Web.Http.HttpResponseException"> /// </exception> protected virtual void CheckCanView(ISecured securedModel, Person person) { if (securedModel != null) { if (IsProxy(securedModel)) { if (!securedModel.IsAuthorized(Rock.Security.Authorization.VIEW, person)) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } } else { // Need to reload using service with a proxy enabled so that if model has custom // parent authorities, those properties can be lazy-loaded and checked for authorization SetProxyCreation(true); ISecured reloadedModel = (ISecured)Service.Get(securedModel.Id); if (reloadedModel != null && !reloadedModel.IsAuthorized(Rock.Security.Authorization.VIEW, person)) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } } } }
/// <summary> /// Evaluates whether a selected user is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="specialRole">The special role.</param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, SpecialRole specialRole ) { return ItemAuthorized( entity, action, specialRole, true, true ) ?? entity.IsAllowedByDefault( action ); }
/// <summary> /// Updates authorization rules for the entity so that the current person is allowed to perform the specified action. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void AllowPerson( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( rockContext != null ) { MyAllow( entity, action, person, null, SpecialRole.None, rockContext ); } else { using ( var myRockContext = new RockContext() ) { MyAllow( entity, action, person, null, SpecialRole.None, myRockContext ); } } }
/// <summary> /// Updates the bulk update security. /// </summary> private static void UpdateBulkUpdateSecurity() { var rockContext = new RockContext(); var authService = new Rock.Model.AuthService(rockContext); var bulkUpdateBlockType = BlockTypeCache.Get(Rock.SystemGuid.BlockType.BULK_UPDATE.AsGuid()); var bulkUpdateBlocks = new BlockService(rockContext).Queryable().Where(a => a.BlockTypeId == bulkUpdateBlockType.Id).ToList(); foreach (var bulkUpdateBlock in bulkUpdateBlocks) { var alreadyUpdated = authService.Queryable().Where(a => (a.Action == "EditConnectionStatus" || a.Action == "EditRecordStatus") && a.EntityTypeId == bulkUpdateBlock.TypeId && a.EntityId == bulkUpdateBlock.Id).Any(); if (alreadyUpdated) { // EditConnectionStatus and/or EditRecordStatus has already been set, so don't copy VIEW auth to it continue; } var groupIdAuthRules = new HashSet <int>(); var personIdAuthRules = new HashSet <int>(); var specialRoleAuthRules = new HashSet <SpecialRole>(); var authRulesToAdd = new List <AuthRule>(); Dictionary <ISecured, List <AuthRule> > parentAuthRulesList = new Dictionary <ISecured, List <AuthRule> >(); ISecured secured = bulkUpdateBlock; while (secured != null) { var entityType = secured.TypeId; List <AuthRule> authRules = Authorization.AuthRules(secured.TypeId, secured.Id, Authorization.VIEW).OrderBy(a => a.Order).ToList(); foreach (var rule in authRules) { if (rule.GroupId.HasValue) { if (!groupIdAuthRules.Contains(rule.GroupId.Value)) { groupIdAuthRules.Add(rule.GroupId.Value); authRulesToAdd.Add(rule); } } else if (rule.PersonId.HasValue) { if (!personIdAuthRules.Contains(rule.PersonId.Value)) { personIdAuthRules.Add(rule.PersonId.Value); authRulesToAdd.Add(rule); } } else if (rule.SpecialRole != SpecialRole.None) { if (!specialRoleAuthRules.Contains(rule.SpecialRole)) { specialRoleAuthRules.Add(rule.SpecialRole); authRulesToAdd.Add(rule); } } } secured = secured.ParentAuthority; } List <Auth> authsToAdd = new List <Auth>(); foreach (var auth in authRulesToAdd) { authsToAdd.Add(AddAuth(bulkUpdateBlock, auth, "EditConnectionStatus")); authsToAdd.Add(AddAuth(bulkUpdateBlock, auth, "EditRecordStatus")); } int authOrder = 0; authsToAdd.ForEach(a => a.Order = authOrder++); authService.AddRange(authsToAdd); Authorization.RefreshAction(bulkUpdateBlock.TypeId, bulkUpdateBlock.Id, "EditConnectionStatus"); Authorization.RefreshAction(bulkUpdateBlock.TypeId, bulkUpdateBlock.Id, "EditRecordStatus"); } rockContext.SaveChanges(); }
/// <summary> /// Evaluates whether a selected user is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity"></param> /// <param name="action"></param> /// <param name="user"></param> /// <returns></returns> public static bool Authorized(ISecured entity, string action, Rock.CMS.User user) { // return Authorized( entity, action, user != null ? user.Person.Guid.ToString() : string.Empty ); //} ///// <summary> ///// Evaluates whether a selected user is allowed to perform the selected action on the selected ///// entity. ///// </summary> ///// <param name="entity">The entity.</param> ///// <param name="action">The action.</param> ///// <param name="userName">Name of the user.</param> ///// <returns></returns> //private static bool Authorized( ISecured entity, string action, string userName ) //{ // If there's no Authorizations object, create it if (Authorizations == null) { Load(); } // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if (Authorizations.Keys.Contains(entity.AuthEntity) && Authorizations[entity.AuthEntity].Keys.Contains(entity.Id) && Authorizations[entity.AuthEntity][entity.Id].Keys.Contains(action)) { string userName = user != null?user.Person.Guid.ToString() : string.Empty; foreach (AuthRule authRule in Authorizations[entity.AuthEntity][entity.Id][action]) { // All Users if (authRule.SpecialRole == SpecialRole.AllUsers) { return(authRule.AllowOrDeny == "A"); } // All Authenticated Users if (authRule.SpecialRole == SpecialRole.AllAuthenticatedUsers && userName.Trim() != string.Empty) { return(authRule.AllowOrDeny == "A"); } // All Unauthenticated Users if (authRule.SpecialRole == SpecialRole.AllUnAuthenticatedUsers && userName.Trim() == string.Empty) { return(authRule.AllowOrDeny == "A"); } if (authRule.SpecialRole == SpecialRole.None && userName != string.Empty) { // See if person has been authorized to entity if (authRule.PersonId.HasValue && user.PersonId.HasValue && authRule.PersonId.Value == user.PersonId.Value) { return(authRule.AllowOrDeny == "A"); } // See if person is in role authorized if (authRule.GroupId.HasValue) { Role role = Role.Read(authRule.GroupId.Value); if (role != null && role.UserInRole(userName)) { return(authRule.AllowOrDeny == "A"); } } } } } // If not match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization if (entity.ParentAuthority != null) { return(Authorized(entity.ParentAuthority, action, user)); } else { return(entity.DefaultAuthorization(action)); } }
/// <summary> /// Copies the authorization. /// </summary> /// <param name="sourceEntity">The source entity.</param> /// <param name="targetEntity">The target entity.</param> public static void CopyAuthorization( ISecured sourceEntity, ISecured targetEntity ) { using ( var rockContext = new RockContext() ) { CopyAuthorization( sourceEntity, targetEntity, rockContext ); } }
/// <summary> /// Adds the parent rules. /// </summary> /// <param name="authService">The authentication service.</param> /// <param name="itemRules">The item rules.</param> /// <param name="parentRules">The parent rules.</param> /// <param name="parent">The parent.</param> /// <param name="action">The action.</param> /// <param name="recurse">if set to <c>true</c> [recurse].</param> private void AddParentRules( AuthService authService, List<AuthRule> itemRules, List<MyAuthRule> parentRules, ISecured parent, string action, bool recurse ) { if ( parent != null ) { var entityType = Rock.Web.Cache.EntityTypeCache.Read( parent.TypeId ); foreach ( var auth in authService.GetAuths( parent.TypeId, parent.Id, action ) ) { var rule = new AuthRule( auth ); if ( !itemRules.Exists( r => r.SpecialRole == rule.SpecialRole && r.PersonId == rule.PersonId && r.GroupId == rule.GroupId ) && !parentRules.Exists( r => r.AuthRule.SpecialRole == rule.SpecialRole && r.AuthRule.PersonId == rule.PersonId && r.AuthRule.GroupId == rule.GroupId ) ) { var myRule = new MyAuthRule( rule ); myRule.EntityTitle = string.Format( "{0} <small>({1})</small>", parent.ToString(), entityType.FriendlyName ?? entityType.Name ).TrimStart(); parentRules.Add( myRule ); } } if ( recurse ) { AddParentRules( authService, itemRules, parentRules, parent.ParentAuthority, action, true ); } } }
/// <summary> /// Removes that two authorization rules that made the entity private. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void MakeUnPrivate( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( rockContext != null ) { MyMakeUnPrivate( entity, action, person, rockContext ); } else { using ( var myRockContext = new RockContext() ) { MyMakeUnPrivate( entity, action, person, myRockContext ); } } }
/// <summary> /// Removes that two authorization rules that made the entity private. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void MakeUnPrivate( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( IsPrivate( entity, action, person ) ) { rockContext = rockContext ?? new RockContext(); var authService = new AuthService( rockContext ); // if is private, then there are only two rules for this action that should be deleted foreach ( AuthRule authRule in Authorizations[entity.TypeId][entity.Id][action] ) { var oldAuth = authService.Get( authRule.Id ); authService.Delete( oldAuth ); } rockContext.SaveChanges(); Authorizations[entity.TypeId][entity.Id][action] = new List<AuthRule>(); } }
/// <summary> /// Evaluates whether a selected person is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, Rock.Model.Person person, RockContext rockContext = null ) { // If there's no Authorizations object, create it if ( Authorizations == null ) { rockContext = rockContext ?? new RockContext(); Load( rockContext ); } var entityTypeId = entity.TypeId; // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( Authorizations.Keys.Contains( entityTypeId ) && Authorizations[entityTypeId].Keys.Contains( entity.Id ) && Authorizations[entityTypeId][entity.Id].Keys.Contains( action ) ) { string userName = person != null ? person.Guid.ToString() : string.Empty; foreach ( AuthRule authRule in Authorizations[entityTypeId][entity.Id][action] ) { // All Users if ( authRule.SpecialRole == SpecialRole.AllUsers ) { return authRule.AllowOrDeny == "A"; } // All Authenticated Users if ( authRule.SpecialRole == SpecialRole.AllAuthenticatedUsers && userName.Trim() != string.Empty ) { return authRule.AllowOrDeny == "A"; } // All Unauthenticated Users if ( authRule.SpecialRole == SpecialRole.AllUnAuthenticatedUsers && userName.Trim() == string.Empty ) { return authRule.AllowOrDeny == "A"; } if ( authRule.SpecialRole == SpecialRole.None && person != null ) { // See if person has been authorized to entity if ( authRule.PersonId.HasValue && authRule.PersonId.Value == person.Id ) { return authRule.AllowOrDeny == "A"; } // See if person is in role authorized if ( authRule.GroupId.HasValue ) { Role role = Role.Read( authRule.GroupId.Value ); if ( role != null && role.IsUserInRole( userName ) ) { return authRule.AllowOrDeny == "A"; } } } } } // If no match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization if ( entity.ParentAuthority != null ) { return Authorized( entity.ParentAuthority, action, person ); } else { return entity.IsAllowedByDefault( action ); } }
/// <summary> /// Evaluates whether a selected user is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="specialRole">The special role.</param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, SpecialRole specialRole ) { // If there's no Authorizations object, create it if ( Authorizations == null ) { Load( new RockContext() ); } var entityTypeId = entity.TypeId; // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( Authorizations.Keys.Contains( entityTypeId ) && Authorizations[entityTypeId].Keys.Contains( entity.Id ) && Authorizations[entityTypeId][entity.Id].Keys.Contains( action ) ) { foreach ( AuthRule authRule in Authorizations[entityTypeId][entity.Id][action] ) { if ( authRule.SpecialRole == specialRole ) { return authRule.AllowOrDeny == "A"; } } } // If no match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization if ( entity.ParentAuthority != null ) { return Authorized( entity.ParentAuthority, action, specialRole ); } else { return entity.IsAllowedByDefault( action ); } }
/// <summary> /// Copies the authorizations from one <see cref="ISecured" /> object to another /// </summary> /// <param name="sourceEntity">The source entity.</param> /// <param name="targetEntity">The target entity.</param> /// <param name="rockContext">The rock context.</param> /// <remarks> /// If a rockContext value is included, this method will save any previous changes made to the context /// </remarks> public static void CopyAuthorization( ISecured sourceEntity, ISecured targetEntity, RockContext rockContext = null ) { rockContext = rockContext ?? new RockContext(); // If there's no Authorizations object, create it if ( Authorizations == null ) { Load( rockContext ); } var sourceEntityTypeId = sourceEntity.TypeId; var targetEntityTypeId = targetEntity.TypeId; AuthService authService = new AuthService( rockContext ); // Delete the current authorizations for the target entity foreach ( Auth auth in authService.Get( targetEntityTypeId, targetEntity.Id ) ) { authService.Delete( auth ); } Dictionary<string, List<AuthRule>> newActions = new Dictionary<string, List<AuthRule>>(); int order = 0; if ( Authorizations.ContainsKey( sourceEntityTypeId ) && Authorizations[sourceEntityTypeId].ContainsKey( sourceEntity.Id ) ) { foreach ( KeyValuePair<string, List<AuthRule>> action in Authorizations[sourceEntityTypeId][sourceEntity.Id] ) { if ( targetEntity.SupportedActions.ContainsKey( action.Key ) ) { newActions.Add( action.Key, new List<AuthRule>() ); foreach ( AuthRule rule in action.Value ) { Auth auth = new Auth(); auth.EntityTypeId = targetEntityTypeId; auth.EntityId = targetEntity.Id; auth.Order = order; auth.Action = action.Key; auth.AllowOrDeny = rule.AllowOrDeny; auth.SpecialRole = rule.SpecialRole; auth.PersonId = rule.PersonId; auth.GroupId = rule.GroupId; authService.Add( auth ); newActions[action.Key].Add( new AuthRule( rule.Id, rule.EntityId, rule.AllowOrDeny, rule.SpecialRole, rule.PersonId, rule.GroupId, rule.Order ) ); order++; } } } } rockContext.SaveChanges(); if ( !Authorizations.ContainsKey( targetEntityTypeId ) ) { Authorizations.Add( targetEntityTypeId, new Dictionary<int, Dictionary<string, List<AuthRule>>>() ); } Dictionary<int, Dictionary<string, List<AuthRule>>> entityType = Authorizations[targetEntityTypeId]; if ( !entityType.ContainsKey( targetEntity.Id ) ) { entityType.Add( targetEntity.Id, new Dictionary<string, List<AuthRule>>() ); } entityType[targetEntity.Id] = newActions; }
/// <summary> /// Finds the auth rules. /// </summary> /// <param name="securableObject">The securable object.</param> /// <returns></returns> public static IQueryable<AuthRule> FindAuthRules( ISecured securableObject ) { return ( from action in securableObject.SupportedActions from rule in AuthRules( securableObject.TypeId, securableObject.Id, action.Key ) select rule ).AsQueryable(); }
/// <summary> /// Determines whether the specified entity is private. Entity is considered private if only the current user /// has access. In this scenario, the first rule would give current user access, and second rule would deny /// all users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> /// <returns> /// <c>true</c> if the specified entity is private; otherwise, <c>false</c>. /// </returns> public static bool IsPrivate( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( person != null ) { // If there's no Authorizations object, create it if ( Authorizations == null ) { rockContext = rockContext ?? new RockContext(); Load( rockContext ); } // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( Authorizations.Keys.Contains( entity.TypeId ) && Authorizations[entity.TypeId].Keys.Contains( entity.Id ) && Authorizations[entity.TypeId][entity.Id].Keys.Contains( action ) && Authorizations[entity.TypeId][entity.Id][action].Count == 2 ) { AuthRule firstRule = Authorizations[entity.TypeId][entity.Id][action][0]; AuthRule secondRule = Authorizations[entity.TypeId][entity.Id][action][1]; // If first rule allows current user, and second rule denies all other users then entity is private if ( firstRule.AllowOrDeny == "A" && firstRule.SpecialRole == SpecialRole.None && firstRule.PersonId == person.Id && secondRule.AllowOrDeny == "D" && secondRule.SpecialRole == SpecialRole.AllUsers ) { return true; } } } return false; }
private static Access GetApplicationAccess(ISecured secured, AccessRight right, string role) { var application = CmsContext.Current.GetApplication(secured.GetType()) as ISecured; return(application == null ? Access.Deny : application.Permissions.GetAccess(right, role)); }
/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> public override void OnActionExecuting(HttpActionContext actionContext) { var principal = actionContext.Request.GetUserPrincipal(); Person person = null; if (principal != null && principal.Identity != null) { using (var rockContext = new RockContext()) { string userName = principal.Identity.Name; UserLogin userLogin = null; if (userName.StartsWith("rckipid=")) { var personService = new PersonService(rockContext); var impersonatedPerson = personService.GetByImpersonationToken(userName.Substring(8)); if (impersonatedPerson != null) { userLogin = impersonatedPerson.GetImpersonatedUser(); } } else { var userLoginService = new UserLoginService(rockContext); userLogin = userLoginService.GetByUserName(userName); } if (userLogin != null) { person = userLogin.Person; var pinAuthentication = AuthenticationContainer.GetComponent(typeof(Security.Authentication.PINAuthentication).FullName); // Don't allow PIN authentications. if (userLogin.EntityTypeId != null) { var userLoginEntityType = EntityTypeCache.Get(userLogin.EntityTypeId.Value); if (userLoginEntityType != null && userLoginEntityType.Id == pinAuthentication.EntityType.Id) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); return; } } } } } var reflectedHttpActionDescriptor = ( ReflectedHttpActionDescriptor )actionContext.ActionDescriptor; var controller = actionContext.ActionDescriptor.ControllerDescriptor; var controllerClassName = controller.ControllerType.FullName; var actionMethod = actionContext.Request.Method.Method; var apiId = RestControllerService.GetApiId(reflectedHttpActionDescriptor.MethodInfo, actionMethod, controller.ControllerName); ISecured item = RestActionCache.Get(apiId); if (item == null) { // if there isn't a RestAction in the database, use the Controller as the secured item item = RestControllerCache.Get(controllerClassName); if (item == null) { item = new RestController(); } } if (actionContext.Request.Properties.Keys.Contains("Person")) { person = actionContext.Request.Properties["Person"] as Person; } else { actionContext.Request.Properties.Add("Person", person); /* 12/12/2019 BJW * * Setting this current person item was only done in put, post, and patch in the ApiController * class. Set it here so that it is always set for all methods, including delete. This enhances * history logging done in the pre and post save model hooks (when the pre-save event is called * we can access DbContext.GetCurrentPersonAlias and log who deleted the record). * * Task: https://app.asana.com/0/1120115219297347/1153140643799337/f */ System.Web.HttpContext.Current.AddOrReplaceItem("CurrentPerson", person); } string action = actionMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) ? Security.Authorization.VIEW : Security.Authorization.EDIT; bool authorized = false; if (item.IsAuthorized(action, person)) { authorized = true; } else if (actionContext.Request.Headers.Contains("X-Rock-App-Id") && actionContext.Request.Headers.Contains("X-Rock-Mobile-Api-Key")) { // Normal authorization failed, but this is a Mobile App request so check // if the application itself has been given permission. var appId = actionContext.Request.Headers.GetValues("X-Rock-App-Id").First().AsIntegerOrNull(); var mobileApiKey = actionContext.Request.Headers.GetValues("X-Rock-Mobile-Api-Key").First(); if (appId.HasValue) { using (var rockContext = new RockContext()) { var appUser = Mobile.MobileHelper.GetMobileApplicationUser(appId.Value, mobileApiKey, rockContext); if (appUser != null && item.IsAuthorized(action, appUser.Person)) { authorized = true; } } } } if (!authorized) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); } }
/// <summary> /// Renders the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception> public override void Render(Context context, TextWriter result) { // first ensure that entity commands are allowed in the context if (!this.IsAuthorized(context)) { result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name)); base.Render(context, result); return; } bool hasFilter = false; var modelName = string.Empty; // get a service for the entity based off it's friendly name if (_entityName == "business") { modelName = "Rock.Model.Person"; } else { modelName = "Rock.Model." + _entityName; } // Check first to see if this is a core model. use the createIfNotFound = false option var entityTypeCache = EntityTypeCache.Get(modelName, false); if (entityTypeCache == null) { var entityTypes = EntityTypeCache.All(); // If not, look for first plug-in model that has same friendly name entityTypeCache = entityTypes .Where(e => e.IsEntity && !e.Name.StartsWith("Rock.Model") && e.FriendlyName != null && e.FriendlyName.RemoveSpaces().ToLower() == _entityName) .OrderBy(e => e.Id) .FirstOrDefault(); // If still null check to see if this was a duplicate class and full class name was used as entity name if (entityTypeCache == null) { modelName = _entityName.Replace('_', '.'); entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, modelName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); } } if (entityTypeCache != null) { Type entityType = entityTypeCache.GetEntityType(); if (entityType != null) { // Get the appropriate database context for this entity type. // Note that this may be different from the standard RockContext if the entity is sourced from a plug-in. var dbContext = Reflection.GetDbContextForEntityType(entityType); // Check if there is a RockContext in the Lava context. If so then use the RockContext passed in. if (dbContext is RockContext) { var lavaContext = context.Registers["RockContext"]; if (lavaContext.IsNotNull()) { dbContext = (DbContext)lavaContext; } } // Disable change-tracking for this data context to improve performance - objects supplied to a Lava context are read-only. dbContext.Configuration.AutoDetectChangesEnabled = false; // Create an instance of the entity's service IService serviceInstance = Reflection.GetServiceForEntityType(entityType, dbContext); ParameterExpression paramExpression = Expression.Parameter(entityType, "x"); Expression queryExpression = null; // the base expression we'll use to build our query from // Parse markup var parms = ParseMarkup(_markup, context); if (parms.Any(p => p.Key == "id")) { string propertyName = "Id"; List <string> selectionParms = new List <string>(); selectionParms.Add(PropertyComparisonConversion("==").ToString()); selectionParms.Add(parms["id"].ToString()); selectionParms.Add(propertyName); var entityProperty = entityType.GetProperty(propertyName); queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType); hasFilter = true; } else { // where clause expression if (parms.Any(p => p.Key == "where")) { queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache); if (queryExpression != null) { hasFilter = true; } } // DataView expression if (parms.Any(p => p.Key == "dataview")) { var dataViewId = parms["dataview"].AsIntegerOrNull(); if (dataViewId.HasValue) { var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache); if (queryExpression == null) { queryExpression = dataViewExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dataViewExpression); } } } // process dynamic filter expressions (from the query string) if (parms.Any(p => p.Key == "dynamicparameters")) { var dynamicFilters = parms["dynamicparameters"].Split(',') .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x)) .ToList(); foreach (var dynamicFilter in dynamicFilters) { var dynamicFilterValue = HttpContext.Current.Request[dynamicFilter]; var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression); if (dynamicFilterExpression != null) { if (queryExpression == null) { queryExpression = dynamicFilterExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression); } } } } } // Make the query from the expression. /* [2020-10-08] DL * "Get" is intentionally used here rather than "GetNoTracking" to allow lazy-loading of navigation properties from the Lava context. * (Refer https://github.com/SparkDevNetwork/Rock/issues/4293) */ MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) }); if (getMethod != null) { // get a listing of ids and build it into the query expression if (parms.Any(p => p.Key == "ids")) { List <int> value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList(); MemberExpression propertyExpression = Expression.Property(paramExpression, "Id"); ConstantExpression constantExpression = Expression.Constant(value, typeof(List <int>)); Expression containsExpression = Expression.Call(constantExpression, typeof(List <int>).GetMethod("Contains", new Type[] { typeof(int) }), propertyExpression); if (queryExpression != null) { queryExpression = Expression.AndAlso(queryExpression, containsExpression); } else { queryExpression = containsExpression; } hasFilter = true; } var getResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null }); var queryResult = getResult as IQueryable <IEntity>; // process entity specific filters switch (_entityName) { case "person": { queryResult = PersonFilters((IQueryable <Person>)queryResult, parms); break; } case "business": { queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms); break; } } // if there was a dynamic expression add it now if (parms.Any(p => p.Key == "expression")) { queryResult = queryResult.Where(parms["expression"]); hasFilter = true; } var queryResultExpression = queryResult.Expression; // add sort expressions if (parms.Any(p => p.Key == "sort")) { string orderByMethod = "OrderBy"; foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList()) { string propertyName; var direction = SortDirection.Ascending; if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase)) { direction = SortDirection.Descending; propertyName = column.Left(column.Length - 5); } else { propertyName = column; } string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod; if (entityType.GetProperty(propertyName) != null) { // sorting a entity property var memberExpression = Expression.Property(paramExpression, propertyName); LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } else { // sorting on an attribute // get attribute id int?attributeId = null; foreach (var attribute in AttributeCache.GetByEntityType(entityTypeCache.Id)) { if (attribute.Key == propertyName) { attributeId = attribute.Id; break; } } if (attributeId.HasValue) { // get AttributeValue queryable and parameter if (dbContext is RockContext) { var attributeValues = new AttributeValueService(dbContext as RockContext).Queryable(); ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v"); MemberExpression idExpression = Expression.Property(paramExpression, "Id"); var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value); LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } else { throw new Exception(string.Format("The database context for type {0} does not support RockContext attribute value queries.", entityTypeCache.FriendlyName)); } } } orderByMethod = "ThenBy"; } } // check to ensure we had some form of filter (otherwise we'll return all results in the table) if (!hasFilter) { throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist."); } // reassemble the queryable with the sort expressions queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>; if (parms.GetValueOrNull("count").AsBoolean()) { int countResult = queryResult.Count(); context.Scopes.Last()["count"] = countResult; } else { // Run security check on each result if enabled and entity is not a person (we do not check security on people) if (parms["securityenabled"].AsBoolean() && _entityName != "person") { var items = queryResult.ToList(); var itemsSecured = new List <IEntity>(); Person person = GetCurrentPerson(context); foreach (IEntity item in items) { ISecured itemSecured = item as ISecured; if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person)) { itemsSecured.Add(item); /* * 8/13/2020 - JME * It might seem logical to break out of the loop if there is limit parameter provided once the * limit is reached. This though has two issues. * * FIRST * Depending how it was implemented it can have the effect of breaking when an offset is * provided. * {% contentchannelitem where:'ContentChannelId == 1' limit:'3' %} * {% for item in contentchannelitemItems %} * {{ item.Id }} - {{ item.Title }}<br> * {% endfor %} * {% endcontentchannelitem %} * Returns 3 items (correct) * * {% contentchannelitem where:'ContentChannelId == 1' limit:'3' offset:'1' %} * {% for item in contentchannelitemItems %} * {{ item.Id }} - {{ item.Title }}<br> * {% endfor %} * {% endcontentchannelitem %} * Returns only 2 items (incorrect) - because of the offset * * SECOND * If the limit is moved before the security check it's possible that the security checks * will remove items and will therefore not give you the amount of items that you asked for. * * Unfortunately this has to be an inefficent process to ensure pagination works. I will also * add a detailed note to the documentation to encourage people to disable security checks, * especially when used with pagination, in the Lava docs. */ } } queryResult = itemsSecured.AsQueryable(); } // offset if (parms.Any(p => p.Key == "offset")) { queryResult = queryResult.Skip(parms["offset"].AsInteger()); } // limit, default to 1000 if (parms.Any(p => p.Key == "limit")) { queryResult = queryResult.Take(parms["limit"].AsInteger()); } else { queryResult = queryResult.Take(1000); } var resultList = queryResult.ToList(); // if there is only one item to return set an alternative non-array based variable if (resultList.Count == 1) { context.Scopes.Last()[_entityName] = resultList.FirstOrDefault(); } context.Scopes.Last()[parms["iterator"]] = resultList; } } } } else { result.Write(string.Format("Could not find a model for {0}.", _entityName)); base.Render(context, result); } base.Render(context, result); }
/// <summary> /// Adds the parent rules. /// </summary> /// <param name="authService">The authentication service.</param> /// <param name="itemRules">The item rules.</param> /// <param name="parentRules">The parent rules.</param> /// <param name="parent">The parent.</param> /// <param name="action">The action.</param> private void AddParentRules(AuthService authService, List <AuthRule> itemRules, List <MyAuthRule> parentRules, ISecured parent, string action) { if (parent != null) { var entityType = Rock.Web.Cache.EntityTypeCache.Read(parent.TypeId); foreach (var auth in authService.GetAuths(parent.TypeId, parent.Id, action)) { var rule = new AuthRule(auth); if (!itemRules.Exists(r => r.SpecialRole == rule.SpecialRole && r.PersonId == rule.PersonId && r.GroupId == rule.GroupId) && !parentRules.Exists(r => r.SpecialRole == rule.SpecialRole && r.PersonId == rule.PersonId && r.GroupId == rule.GroupId)) { var myRule = new MyAuthRule(rule); myRule.EntityTitle = string.Format("{0} <small>({1})</small>", parent.ToString(), entityType.FriendlyName ?? entityType.Name).TrimStart(); parentRules.Add(myRule); } } AddParentRules(authService, itemRules, parentRules, parent.ParentAuthority, action); } }
/// <summary> /// Bind the grid to the authorization records found in the database. /// </summary> /// <param name="entitySecured">The securable entity to query authorization records of.</param> /// <param name="person">The person whose access level we are checking.</param> void BindGrid(ISecured entitySecured, Person person) { // // Walk all the supported actions and build a row of results. // List <AuthGridRow> rows = new List <AuthGridRow>(); foreach (var action in entitySecured.SupportedActions) { ISecured authorative = null; var auth = ItemAuthorized(entitySecured, action.Key, person, true, true, out authorative); if (auth != null) { var authEntity = authorative as IEntity; string friendlyName = "Unknown"; if (auth.SpecialRole != SpecialRole.None) { friendlyName = auth.SpecialRole.ToStringSafe().SplitCase(); } else if (auth.PersonAlias != null) { friendlyName = auth.PersonAlias.ToStringSafe(); } else if (auth.Group != null) { friendlyName = auth.Group.ToStringSafe(); } var row = new AuthGridRow(); row.Id = auth.Id; row.Action = auth.Action; if (authEntity != null) { row.EntityType = authEntity.TypeName; row.EntityId = authEntity.Id != 0 ? ( int? )authEntity.Id : null; row.EntityName = authEntity.Id != 0 ? authEntity.ToString() : "(Entity Administration Security)"; } else { row.EntityId = null; if (authorative as GlobalDefault != null) { row.EntityType = "(Global Default)"; row.EntityName = string.Empty; } else { row.EntityType = "Unknown"; row.EntityName = "Unknown"; } } row.Access = auth.AllowOrDeny == "A" ? "<span class='label label-success'>Allow</span>" : "<span class='label label-danger'>Deny</span>"; row.Role = friendlyName; row.IsUnlockable = auth.AllowOrDeny != "A"; rows.Add(row); } else { var row = new AuthGridRow(); row.Id = 0; row.Action = action.Key; row.EntityType = string.Empty; row.EntityId = null; row.EntityName = string.Empty; row.Access = "<span class='label label-default'>Unknown</span>"; row.Role = "No explicit permissions found"; row.IsUnlockable = false; rows.Add(row); } } gResults.DataSource = rows; gResults.DataBind(); }
/// <summary> /// Checks the can edit. /// </summary> /// <param name="securedModel">The secured model.</param> protected virtual void CheckCanEdit(ISecured securedModel) { CheckCanEdit(securedModel, GetPerson()); }
/// <summary> /// Evaluates whether a selected person is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, Rock.Model.Person person ) { return ItemAuthorized( entity, action, person, true, true ) ?? entity.IsAllowedByDefault( action ); }
/// <summary> /// Determines whether the specified entity is private. Entity is considered private if only the current user /// has access. In this scenario, the first rule would give current user access, and second rule would deny /// all users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <returns> /// <c>true</c> if the specified entity is private; otherwise, <c>false</c>. /// </returns> public static bool IsPrivate( ISecured entity, string action, Person person ) { bool isPrivate = false; if ( person != null ) { Load(); lock ( _lock ) { // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( _authorizations != null && _authorizations.Keys.Contains( entity.TypeId ) && _authorizations[entity.TypeId].Keys.Contains( entity.Id ) && _authorizations[entity.TypeId][entity.Id].Keys.Contains( action ) && _authorizations[entity.TypeId][entity.Id][action].Count == 2 ) { AuthRule firstRule = _authorizations[entity.TypeId][entity.Id][action][0]; AuthRule secondRule = _authorizations[entity.TypeId][entity.Id][action][1]; // If first rule allows current user, and second rule denies all other users then entity is private if ( firstRule.AllowOrDeny == 'A' && firstRule.SpecialRole == SpecialRole.None && firstRule.PersonId == person.Id && secondRule.AllowOrDeny == 'D' && secondRule.SpecialRole == SpecialRole.AllUsers ) { isPrivate = true; } } } } return isPrivate; }
protected override void OnInit(EventArgs e) { string entityParam = PageParameter("EntityTypeId"); Type type = null; // Get Entity Type int entityTypeId = 0; if (Int32.TryParse(entityParam, out entityTypeId)) { var entityType = EntityTypeCache.Read(entityTypeId); if (entityType != null) { entityParam = entityType.FriendlyName; type = entityType.GetEntityType(); } } // Get Entity Id int entityId = 0; if (!Int32.TryParse(PageParameter("EntityId"), out entityId)) { entityId = 0; } // Get object type if (type != null) { if (entityId == 0) { iSecured = (ISecured)Activator.CreateInstance(type); } else { // Get the context type since this may be for a non-rock core object Type contextType = null; var contexts = Rock.Reflection.SearchAssembly(type.Assembly, typeof(System.Data.Entity.DbContext)); if (contexts.Any()) { contextType = contexts.First().Value; } Type serviceType = typeof(Rock.Data.Service <>); Type[] modelType = { type }; Type service = serviceType.MakeGenericType(modelType); var getMethod = service.GetMethod("Get", new Type[] { typeof(int) }); if (contextType != null) { var context = Activator.CreateInstance(contextType); var serviceInstance = Activator.CreateInstance(service, new object[] { context }); iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured; } else { var serviceInstance = Activator.CreateInstance(service); iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured; } } var block = iSecured as Rock.Model.Block; if (block != null) { // If the entity is a block, get the cachedblock's supported action, as the RockPage may have // added additional actions when the cache was created. foreach (var action in BlockCache.Read(block.Id).SupportedActions) { if (!block.SupportedActions.Contains(action)) { block.SupportedActions.Add(action); } } iSecured = block; } if (iSecured != null && iSecured.IsAuthorized("Administrate", CurrentPerson)) { rptActions.DataSource = iSecured.SupportedActions; rptActions.DataBind(); rGrid.DataKeyNames = new string[] { "id" }; rGrid.GridReorder += new GridReorderEventHandler(rGrid_GridReorder); rGrid.GridRebind += new GridRebindEventHandler(rGrid_GridRebind); rGrid.RowDataBound += new GridViewRowEventHandler(rGrid_RowDataBound); rGrid.ShowHeaderWhenEmpty = false; rGrid.EmptyDataText = string.Empty; rGrid.ShowActionRow = false; rGridParentRules.DataKeyNames = new string[] { "id" }; rGridParentRules.ShowHeaderWhenEmpty = false; rGridParentRules.EmptyDataText = string.Empty; rGridParentRules.ShowActionRow = false; BindRoles(); string script = string.Format(@" Sys.Application.add_load(function () {{ $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}'); }}); ", HttpUtility.JavaScriptStringEncode(iSecured.ToString())); this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true); } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = "Unfortunately, you are not able to edit security because you do not belong to a role that has been configured to allow administration of this item."; nbMessage.Visible = true; } } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = string.Format("The requested entity type ('{0}') could not be loaded to determine security attributes.", entityParam); nbMessage.Visible = true; } base.OnInit(e); }
private void AddParentRules( List<MyAuthRule> rules, ISecured parent, string action ) { if ( parent != null ) { var entityType = Rock.Web.Cache.EntityTypeCache.Read( parent.TypeId ); foreach ( AuthRule rule in Authorization.AuthRules( parent.TypeId, parent.Id, action ) ) if ( !rules.Exists( r => r.SpecialRole == rule.SpecialRole && r.PersonId == rule.PersonId && r.GroupId == rule.GroupId ) ) { var myRule = new MyAuthRule( rule ); myRule.EntityTitle = string.Format( "{0} ({1})", parent.ToString(), entityType.FriendlyName ?? entityType.Name ).TrimStart(); rules.Add( myRule ); } AddParentRules( rules, parent.ParentAuthority, action ); } }
/// <summary> /// Evaluates whether a selected user is allowed to perform the selected action on the selected /// entity. /// </summary> /// <param name="entity"></param> /// <param name="action"></param> /// <param name="user"></param> /// <returns></returns> public static bool Authorized( ISecured entity, string action, Rock.CMS.User user ) { // return Authorized( entity, action, user != null ? user.Person.Guid.ToString() : string.Empty ); //} ///// <summary> ///// Evaluates whether a selected user is allowed to perform the selected action on the selected ///// entity. ///// </summary> ///// <param name="entity">The entity.</param> ///// <param name="action">The action.</param> ///// <param name="userName">Name of the user.</param> ///// <returns></returns> //private static bool Authorized( ISecured entity, string action, string userName ) //{ // If there's no Authorizations object, create it if ( Authorizations == null ) Load(); // If there are entries in the Authorizations object for this entity type and entity instance, evaluate each // one to find the first one specific to the selected user or a role that the selected user belongs // to. If a match is found return whether the user is allowed (true) or denied (false) access if ( Authorizations.Keys.Contains( entity.AuthEntity ) && Authorizations[entity.AuthEntity].Keys.Contains( entity.Id ) && Authorizations[entity.AuthEntity][entity.Id].Keys.Contains( action ) ) { string userName = user != null ? user.Person.Guid.ToString() : string.Empty; foreach ( AuthRule authRule in Authorizations[entity.AuthEntity][entity.Id][action] ) { // All Users if ( authRule.SpecialRole == SpecialRole.AllUsers ) return authRule.AllowOrDeny == "A"; // All Authenticated Users if (authRule.SpecialRole == SpecialRole.AllAuthenticatedUsers && userName.Trim() != string.Empty) return authRule.AllowOrDeny == "A"; // All Unauthenticated Users if ( authRule.SpecialRole == SpecialRole.AllUnAuthenticatedUsers && userName.Trim() == string.Empty ) return authRule.AllowOrDeny == "A"; if ( authRule.SpecialRole == SpecialRole.None && userName != string.Empty ) { // See if person has been authorized to entity if ( authRule.PersonId.HasValue && user.PersonId.HasValue && authRule.PersonId.Value == user.PersonId.Value ) return authRule.AllowOrDeny == "A"; // See if person is in role authorized if (authRule.GroupId.HasValue) { Role role = Role.Read( authRule.GroupId.Value ); if ( role != null && role.UserInRole( userName ) ) return authRule.AllowOrDeny == "A"; } } } } // If not match was found for the selected user on the current entity instance, check to see if the instance // has a parent authority defined and if so evaluate that entities authorization rules. If there is no // parent authority return the defualt authorization if ( entity.ParentAuthority != null ) return Authorized( entity.ParentAuthority, action, user ); else return entity.DefaultAuthorization( action ); }
/// <summary> /// Makes the entity private for the selected action and person /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> private static void MyMakePrivate( ISecured entity, string action, Person person, RockContext rockContext ) { if ( !IsPrivate( entity, action, person ) ) { if ( person != null ) { var personAlias = new PersonAliasService( rockContext ).GetPrimaryAlias( person.Id ); if ( personAlias != null ) { var authService = new AuthService( rockContext ); // Delete any existing rules in database foreach ( Auth auth in authService .GetAuths( entity.TypeId, entity.Id, action ) ) { authService.Delete( auth ); } rockContext.SaveChanges(); // Create the rules in the database Auth auth1 = new Auth(); auth1.EntityTypeId = entity.TypeId; auth1.EntityId = entity.Id; auth1.Order = 0; auth1.Action = action; auth1.AllowOrDeny = "A"; auth1.SpecialRole = SpecialRole.None; auth1.PersonAlias = personAlias; auth1.PersonAliasId = personAlias.Id; authService.Add( auth1 ); Auth auth2 = new Auth(); auth2.EntityTypeId = entity.TypeId; auth2.EntityId = entity.Id; auth2.Order = 1; auth2.Action = action; auth2.AllowOrDeny = "D"; auth2.SpecialRole = SpecialRole.AllUsers; authService.Add( auth2 ); rockContext.SaveChanges(); // Reload the static dictionary for this action ReloadAction( entity.TypeId, entity.Id, action, rockContext ); } } } }
/// <summary> /// Copies the authorizations from one <see cref="ISecured"/> object to another /// </summary> /// <param name="sourceEntity">The source entity.</param> /// <param name="targetEntity">The target entity.</param> /// <param name="personId">The person id.</param> public static void CopyAuthorization(ISecured sourceEntity, ISecured targetEntity, int?personId) { using (new Rock.Data.UnitOfWorkScope()) { // If there's no Authorizations object, create it if (Authorizations == null) { Load(); } AuthService authService = new AuthService(); // Delete the current authorizations for the target entity foreach (Auth auth in authService.GetByEntityTypeAndEntityId(targetEntity.AuthEntity, targetEntity.Id)) { authService.Delete(auth, personId); } Dictionary <string, List <AuthRule> > newActions = new Dictionary <string, List <AuthRule> >(); int order = 0; if (Authorizations.ContainsKey(sourceEntity.AuthEntity) && Authorizations[sourceEntity.AuthEntity].ContainsKey(sourceEntity.Id)) { foreach (KeyValuePair <string, List <AuthRule> > action in Authorizations[sourceEntity.AuthEntity][sourceEntity.Id]) { if (targetEntity.SupportedActions.Contains(action.Key)) { newActions.Add(action.Key, new List <AuthRule>()); foreach (AuthRule rule in action.Value) { Auth auth = new Auth(); auth.EntityType = targetEntity.AuthEntity; auth.EntityId = targetEntity.Id; auth.Order = order; auth.Action = action.Key; auth.AllowOrDeny = rule.AllowOrDeny; auth.SpecialRole = rule.SpecialRole; auth.PersonId = rule.PersonId; auth.GroupId = rule.GroupId; authService.Add(auth, personId); authService.Save(auth, personId); newActions[action.Key].Add(new AuthRule(rule.Id, rule.AllowOrDeny, rule.SpecialRole, rule.PersonId, rule.GroupId, rule.Order)); order++; } } } } if (!Authorizations.ContainsKey(targetEntity.AuthEntity)) { Authorizations.Add(targetEntity.AuthEntity, new Dictionary <int, Dictionary <string, List <AuthRule> > >()); } Dictionary <int, Dictionary <string, List <AuthRule> > > entityType = Authorizations[targetEntity.AuthEntity]; if (!entityType.ContainsKey(targetEntity.Id)) { entityType.Add(targetEntity.Id, new Dictionary <string, List <AuthRule> >()); } entityType[targetEntity.Id] = newActions; } }
public void UpdateSecurity(ISecured secured) { //TODO!!!: When writing security check for antecedentid = referenceid &/or version=0 //First check user and owner rights, black list and white list against record //Then get ok if (secured.SecurityID.HasValue) { //Call Edit if (CheckOwnership(secured, ActionPermission.Read | ActionPermission.Update)) { using (new TransactionScope(TransactionScopeOption.Suppress)) { var c = new XODBC(ApplicationConnectionString,null); if (secured.IsBlack) { var s = (from o in c.SecurityBlacklists where o.SecurityBlacklistID==secured.SecurityID && o.Version==0 && o.VersionDeletedBy==null select o).Single(); s.AccessorContactID = secured.AccessorContactID; s.AccessorApplicationID = secured.AccessorApplicationID; s.AccessorCompanyID = secured.AccessorCompanyID; s.AccessorProjectID = secured.AccessorProjectID; s.AccessorRoleID = secured.AccessorRoleID; s.CanCreate = secured.CanCreate; s.CanRead = secured.CanRead; s.CanDelete = secured.CanDelete; s.CanUpdate = secured.CanUpdate; s.VersionUpdated = DateTime.UtcNow; s.VersionUpdatedBy = secured.OwnerContactID; } else { var s = (from o in c.SecurityWhitelists where o.SecurityWhitelistID == secured.SecurityID && o.Version== 0 && o.VersionDeletedBy == null select o).Single(); s.AccessorContactID = secured.AccessorContactID; s.AccessorApplicationID = secured.AccessorApplicationID; s.AccessorCompanyID = secured.AccessorCompanyID; s.AccessorProjectID = secured.AccessorProjectID; s.AccessorRoleID = secured.AccessorRoleID; s.CanCreate = secured.CanCreate; s.CanRead = secured.CanRead; s.CanDelete = secured.CanDelete; s.CanUpdate = secured.CanUpdate; s.VersionUpdated = DateTime.UtcNow; s.VersionUpdatedBy = secured.OwnerContactID; } c.SaveChanges(); } } else throw new AuthorityException(string.Format("Incorrect permission for action: \"Update\" Contact: {0} Record: {1}", secured.AccessorContactID, secured.OwnerReferenceID)); } else { //Call New if (CheckOwnership(secured, ActionPermission.Read | ActionPermission.Create)) { using (new TransactionScope(TransactionScopeOption.Suppress)) { var c = new XODBC(ApplicationConnectionString,null); if (secured.IsBlack) { var s = new SecurityBlacklist { SecurityBlacklistID = Guid.NewGuid(), AccessorContactID = secured.AccessorContactID, AccessorApplicationID = secured.AccessorApplicationID, AccessorCompanyID = secured.AccessorCompanyID, AccessorProjectID = secured.AccessorProjectID, AccessorRoleID = secured.AccessorRoleID, OwnerApplicationID = secured.OwnerApplicationID, OwnerCompanyID = secured.OwnerCompanyID, OwnerContactID = secured.OwnerContactID, OwnerEntitySystemType = secured.OwnerEntitySystemType, OwnerField = secured.OwnerField, OwnerProjectID = secured.OwnerProjectID, OwnerReferenceID = secured.OwnerReferenceID, OwnerTableType = secured.OwnerTableType, CanCreate = secured.CanCreate, CanRead = secured.CanRead, CanDelete = secured.CanDelete, CanUpdate = secured.CanUpdate, VersionOwnerContactID = secured.OwnerContactID, VersionOwnerCompanyID = secured.OwnerCompanyID, VersionUpdated = DateTime.UtcNow, VersionUpdatedBy = secured.OwnerContactID }; c.SecurityBlacklists.AddObject(s); } else { var s = new SecurityWhitelist { SecurityWhitelistID = Guid.NewGuid(), AccessorContactID = secured.AccessorContactID, AccessorApplicationID = secured.AccessorApplicationID, AccessorCompanyID = secured.AccessorCompanyID, AccessorProjectID = secured.AccessorProjectID, AccessorRoleID = secured.AccessorRoleID, OwnerApplicationID = secured.OwnerApplicationID, OwnerCompanyID = secured.OwnerCompanyID, OwnerContactID = secured.OwnerContactID, OwnerEntitySystemType = secured.OwnerEntitySystemType, OwnerField = secured.OwnerField, OwnerProjectID = secured.OwnerProjectID, OwnerReferenceID = secured.OwnerReferenceID, OwnerTableType = secured.OwnerTableType, CanCreate = secured.CanCreate, CanRead = secured.CanRead, CanDelete = secured.CanDelete, CanUpdate = secured.CanUpdate, VersionOwnerContactID = secured.OwnerContactID, VersionOwnerCompanyID = secured.OwnerCompanyID, VersionUpdated = DateTime.UtcNow, VersionUpdatedBy = secured.OwnerContactID }; c.SecurityWhitelists.AddObject(s); } c.SaveChanges(); } } else throw new AuthorityException(string.Format("Incorrect permission for action: \"Create\" Contact: {0} Record: {1}", secured.AccessorContactID, secured.OwnerReferenceID)); } }
/// <summary> /// Allows the security role. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="group">The group.</param> /// <param name="rockContext">The rock context.</param> public static void AllowSecurityRole( ISecured entity, string action, Group group, RockContext rockContext = null ) { if ( rockContext != null ) { MyAllow( entity, action, null, group, SpecialRole.None, rockContext ); } else { using ( var myRockContext = new RockContext() ) { MyAllow( entity, action, null, group, SpecialRole.None, myRockContext ); } } }
/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> public override void OnActionExecuting(HttpActionContext actionContext) { var controller = actionContext.ActionDescriptor.ControllerDescriptor; string controllerClassName = controller.ControllerType.FullName; string actionMethod = actionContext.Request.Method.Method; string actionPath = actionContext.Request.GetRouteData().Route.RouteTemplate.Replace("{controller}", controller.ControllerName); //// find any additional arguments that aren't part of the RouteTemplate that qualified the action method //// for example: ~/person/search?name={name}&includeHtml={includeHtml}&includeDetails={includeDetails}&includeBusinesses={includeBusinesses} //// is a different action method than ~/person/search?name={name} var routeQueryParams = actionContext.ActionArguments.Where(a => !actionPath.Contains("{" + a.Key + "}")); if (routeQueryParams.Any()) { var actionPathQueryString = routeQueryParams.Select(a => string.Format("{0}={{{0}}}", a.Key)).ToList().AsDelimited("&"); actionPath += "?" + actionPathQueryString; } ISecured item = RestActionCache.Get(actionMethod + actionPath); if (item == null) { item = RestControllerCache.Get(controllerClassName); if (item == null) { item = new RestController(); } } Person person = null; if (actionContext.Request.Properties.Keys.Contains("Person")) { person = actionContext.Request.Properties["Person"] as Person; } else { var principal = actionContext.Request.GetUserPrincipal(); if (principal != null && principal.Identity != null) { using (var rockContext = new RockContext()) { string userName = principal.Identity.Name; UserLogin userLogin = null; if (userName.StartsWith("rckipid=")) { Rock.Model.PersonService personService = new Model.PersonService(rockContext); Rock.Model.Person impersonatedPerson = personService.GetByImpersonationToken(userName.Substring(8), false, null); if (impersonatedPerson != null) { userLogin = impersonatedPerson.GetImpersonatedUser(); } } else { var userLoginService = new Rock.Model.UserLoginService(rockContext); userLogin = userLoginService.GetByUserName(userName); } if (userLogin != null) { person = userLogin.Person; actionContext.Request.Properties.Add("Person", person); } } } } string action = actionMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) ? Rock.Security.Authorization.VIEW : Rock.Security.Authorization.EDIT; if (!item.IsAuthorized(action, person)) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); } }
/// <summary> /// Allows all users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="rockContext">The rock context.</param> public static void AllowAllUsers( ISecured entity, string action, RockContext rockContext = null ) { if ( rockContext != null ) { MyAllowAllUsers( entity, action, rockContext ); } else { using ( var myRockContext = new RockContext() ) { MyAllowAllUsers( entity, action, myRockContext ); } } }
/// <summary> /// Find the matching Auth record for this entity, action and person combination. Only explicit /// Auth records are checked. /// </summary> /// <param name="entity">The entity whose Auth records we are going to search for.</param> /// <param name="action">The type of action that is to be authenticated.</param> /// <param name="person">The person that is requesting permission.</param> /// <returns>An Auth object if an explicit permission was found, otherwise null.</returns> Auth MatchingAuth(ISecured entity, string action, Person person) { var rockContext = new RockContext(); var authService = new AuthService(rockContext); var rules = authService.Get(entity.TypeId, entity.Id).Where(a => a.Action == action).ToList(); bool matchFound = false; bool authorized = false; foreach (var authRule in rules) { // All Users if (authRule.SpecialRole == SpecialRole.AllUsers) { matchFound = true; authorized = authRule.AllowOrDeny == "A"; return(authRule); } // All Authenticated Users if (!matchFound && authRule.SpecialRole == SpecialRole.AllAuthenticatedUsers && person != null) { matchFound = true; authorized = authRule.AllowOrDeny == "A"; return(authRule); } // All Unauthenticated Users if (!matchFound && authRule.SpecialRole == SpecialRole.AllUnAuthenticatedUsers && person == null) { matchFound = true; authorized = authRule.AllowOrDeny == "A"; return(authRule); } if (!matchFound && authRule.SpecialRole == SpecialRole.None && person != null) { // See if person has been authorized to entity if (authRule.PersonAliasId.HasValue && person.Aliases.Where(a => a.Id == authRule.PersonAliasId.Value).Any()) { matchFound = true; authorized = authRule.AllowOrDeny == "A"; return(authRule); } // See if person is in role authorized if (!matchFound && authRule.GroupId.HasValue) { var role = RoleCache.Get(authRule.GroupId.Value); if (role != null && role.IsPersonInRole(person.Guid)) { matchFound = true; authorized = authRule.AllowOrDeny == "A"; return(authRule); } } } } return(null); }
/// <summary> /// If the entity is currently private for selected person, removes all the rules /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> private static void MyMakeUnPrivate( ISecured entity, string action, Person person, RockContext rockContext ) { if ( IsPrivate( entity, action, person ) ) { var authService = new AuthService( rockContext ); // Delete any existing rules in database foreach ( Auth auth in authService .GetAuths( entity.TypeId, entity.Id, action ) ) { authService.Delete( auth ); } // Reload the static dictionary for this action ReloadAction( entity.TypeId, entity.Id, action, rockContext ); } }
/// <summary> /// Copies the authorizations from one <see cref="ISecured" /> object to another /// </summary> /// <param name="sourceEntity">The source entity.</param> /// <param name="targetEntity">The target entity.</param> /// <param name="rockContext">The rock context.</param> /// <param name="action">Optional action (if ommitted or left blank, all actions will be copied).</param> /// <remarks> /// This method will save any previous changes made to the context /// </remarks> public static void CopyAuthorization( ISecured sourceEntity, ISecured targetEntity, RockContext rockContext, string action = "" ) { Load(); var sourceEntityTypeId = sourceEntity.TypeId; var targetEntityTypeId = targetEntity.TypeId; AuthService authService = new AuthService( rockContext ); // Delete the current authorizations for the target entity foreach ( Auth auth in authService.Get( targetEntityTypeId, targetEntity.Id ).ToList() ) { if ( string.IsNullOrWhiteSpace( action ) || auth.Action.Equals( action, StringComparison.OrdinalIgnoreCase ) ) { authService.Delete( auth ); } } rockContext.SaveChanges(); // Copy target auths to source auths int order = 0; foreach ( Auth sourceAuth in authService.Get( sourceEntityTypeId, sourceEntity.Id ).ToList() ) { if ( ( string.IsNullOrWhiteSpace( action ) || sourceAuth.Action.Equals( action, StringComparison.OrdinalIgnoreCase ) ) && targetEntity.SupportedActions.ContainsKey( sourceAuth.Action ) ) { Auth auth = new Auth(); auth.EntityTypeId = targetEntityTypeId; auth.EntityId = targetEntity.Id; auth.Action = sourceAuth.Action; auth.AllowOrDeny = sourceAuth.AllowOrDeny; auth.GroupId = sourceAuth.GroupId; auth.PersonAliasId = sourceAuth.PersonAliasId; auth.SpecialRole = sourceAuth.SpecialRole; auth.Order = order++; authService.Add( auth ); rockContext.SaveChanges(); } } ReloadEntity( targetEntityTypeId, targetEntity.Id, rockContext ); }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnInit( EventArgs e ) { int? entityTypeId = PageParameter( "EntityTypeId" ).AsIntegerOrNull(); string entityTypeName = string.Empty; Type type = null; // Get Entity Type if ( entityTypeId.HasValue ) { var entityType = EntityTypeCache.Read( entityTypeId.Value ); if ( entityType != null ) { entityTypeName = entityType.FriendlyName; type = entityType.GetEntityType(); } } // Get Entity Id int entityId = PageParameter( "EntityId" ).AsIntegerOrNull() ?? 0; // Get object type if ( type != null ) { if ( entityId == 0 ) { iSecured = (ISecured)Activator.CreateInstance( type ); } else { // Get the context type since this may be for a non-rock core object Type contextType = null; var contexts = Rock.Reflection.SearchAssembly( type.Assembly, typeof( Rock.Data.DbContext ) ); if ( contexts.Any() ) { contextType = contexts.First().Value; } else { contextType = typeof( RockContext ); } Type serviceType = typeof( Rock.Data.Service<> ); Type[] modelType = { type }; Type service = serviceType.MakeGenericType( modelType ); var getMethod = service.GetMethod( "Get", new Type[] { typeof( int ) } ); var context = Activator.CreateInstance( contextType ); var serviceInstance = Activator.CreateInstance( service, new object[] { context } ); iSecured = getMethod.Invoke( serviceInstance, new object[] { entityId } ) as ISecured; } var block = iSecured as Rock.Model.Block; if ( block != null ) { // If the entity is a block, get any actions that were updated or added by the block type using // one or more SecurityActionAttributes. foreach ( var action in BlockCache.Read( block.Id ).BlockType.SecurityActions ) { if ( block.SupportedActions.ContainsKey( action.Key ) ) { block.SupportedActions[action.Key] = action.Value; } else { block.SupportedActions.Add( action.Key, action.Value ); } } iSecured = block; } if ( iSecured != null && iSecured.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson ) ) { if ( iSecured.SupportedActions.Any() ) { lActionDescription.Text = iSecured.SupportedActions.FirstOrDefault().Value; } rptActions.DataSource = iSecured.SupportedActions; rptActions.DataBind(); rGrid.DataKeyNames = new string[] { "Id" }; rGrid.GridReorder += new GridReorderEventHandler( rGrid_GridReorder ); rGrid.GridRebind += new GridRebindEventHandler( rGrid_GridRebind ); rGrid.RowDataBound += new GridViewRowEventHandler( rGrid_RowDataBound ); rGrid.ShowHeaderWhenEmpty = false; rGrid.EmptyDataText = string.Empty; rGrid.ShowActionRow = false; rGridParentRules.DataKeyNames = new string[] { "Id" }; rGridParentRules.ShowHeaderWhenEmpty = false; rGridParentRules.EmptyDataText = string.Empty; rGridParentRules.ShowActionRow = false; BindRoles(); string scriptFormat = @" Sys.Application.add_load(function () {{ $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}'); }}); "; string script = string.Format( scriptFormat, HttpUtility.JavaScriptStringEncode( iSecured.ToString() ) ); this.Page.ClientScript.RegisterStartupScript( this.GetType(), string.Format( "set-html-{0}", this.ClientID ), script, true ); } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = "Unfortunately, you are not able to edit security because you do not belong to a role that has been configured to allow administration of this item."; nbMessage.Visible = true; } } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = string.Format( "The requested entity type ('{0}') could not be loaded to determine security attributes.", entityTypeName ); nbMessage.Visible = true; } base.OnInit( e ); }
/// <summary> /// Makes the entity private by setting up two authorization rules, one granting the selected person, and /// then another that denies all other users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="person">The person.</param> /// <param name="rockContext">The rock context.</param> public static void MakePrivate( ISecured entity, string action, Person person, RockContext rockContext = null ) { if ( !IsPrivate( entity, action, person ) ) { if ( person != null ) { rockContext = rockContext ?? new RockContext(); // If there's no Authorizations object, create it if ( Authorizations == null ) { Load( rockContext ); } var authService = new AuthService( rockContext ); // If there are not entries in the Authorizations object for this entity type and entity instance, create // the dictionary entries if ( !Authorizations.Keys.Contains( entity.TypeId ) ) { Authorizations.Add( entity.TypeId, new Dictionary<int, Dictionary<string, List<AuthRule>>>() ); } if ( !Authorizations[entity.TypeId].Keys.Contains( entity.Id ) ) { Authorizations[entity.TypeId].Add( entity.Id, new Dictionary<string, List<AuthRule>>() ); } if ( !Authorizations[entity.TypeId][entity.Id].Keys.Contains( action ) ) { Authorizations[entity.TypeId][entity.Id].Add( action, new List<AuthRule>() ); } else { // If existing rules exist, delete them. foreach ( AuthRule authRule in Authorizations[entity.TypeId][entity.Id][action] ) { var oldAuth = authService.Get( authRule.Id ); authService.Delete( oldAuth ); } } var rules = new List<AuthRule>(); Auth auth1 = new Auth(); auth1.EntityTypeId = entity.TypeId; auth1.EntityId = entity.Id; auth1.Order = 0; auth1.Action = action; auth1.AllowOrDeny = "A"; auth1.SpecialRole = SpecialRole.None; auth1.PersonId = person.Id; authService.Add( auth1 ); Auth auth2 = new Auth(); auth2.EntityTypeId = entity.TypeId; auth2.EntityId = entity.Id; auth2.Order = 1; auth2.Action = action; auth2.AllowOrDeny = "D"; auth2.SpecialRole = SpecialRole.AllUsers; authService.Add( auth2 ); rockContext.SaveChanges(); rules.Add( new AuthRule( auth1 ) ); rules.Add( new AuthRule( auth2 ) ); Authorizations[entity.TypeId][entity.Id][action] = rules; } } }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnInit(EventArgs e) { int? entityTypeId = PageParameter("EntityTypeId").AsIntegerOrNull(); string entityTypeName = string.Empty; Type type = null; // Get Entity Type if (entityTypeId.HasValue) { var entityType = EntityTypeCache.Read(entityTypeId.Value); if (entityType != null) { entityTypeName = entityType.FriendlyName; type = entityType.GetEntityType(); } } // Get Entity Id int entityId = PageParameter("EntityId").AsIntegerOrNull() ?? 0; // Get object type if (type != null) { if (entityId == 0) { iSecured = (ISecured)Activator.CreateInstance(type); } else { // Get the context type since this may be for a non-rock core object Type contextType = null; var contexts = Rock.Reflection.SearchAssembly(type.Assembly, typeof(Rock.Data.DbContext)); if (contexts.Any()) { contextType = contexts.First().Value; } else { contextType = typeof(RockContext); } Type serviceType = typeof(Rock.Data.Service <>); Type[] modelType = { type }; Type service = serviceType.MakeGenericType(modelType); var getMethod = service.GetMethod("Get", new Type[] { typeof(int) }); var context = Activator.CreateInstance(contextType); var serviceInstance = Activator.CreateInstance(service, new object[] { context }); iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured; } var block = iSecured as Rock.Model.Block; if (block != null) { // If the entity is a block, get any actions that were updated or added by the block type using // one or more SecurityActionAttributes. var blockCache = BlockCache.Read(block.Id); if (blockCache != null && blockCache.BlockType != null) { foreach (var action in BlockCache.Read(block.Id).BlockType.SecurityActions) { if (block.SupportedActions.ContainsKey(action.Key)) { block.SupportedActions[action.Key] = action.Value; } else { block.SupportedActions.Add(action.Key, action.Value); } } } iSecured = block; } if (iSecured != null) { if (iSecured.IsAuthorized(Authorization.ADMINISTRATE, CurrentPerson)) { if (iSecured.SupportedActions.Any()) { lActionDescription.Text = iSecured.SupportedActions.FirstOrDefault().Value; } rptActions.DataSource = iSecured.SupportedActions; rptActions.DataBind(); rGrid.DataKeyNames = new string[] { "Id" }; rGrid.GridReorder += new GridReorderEventHandler(rGrid_GridReorder); rGrid.GridRebind += new GridRebindEventHandler(rGrid_GridRebind); rGrid.RowDataBound += new GridViewRowEventHandler(rGrid_RowDataBound); rGrid.ShowHeaderWhenEmpty = false; rGrid.EmptyDataText = string.Empty; rGrid.ShowActionRow = false; rGridParentRules.DataKeyNames = new string[] { "Id" }; rGridParentRules.ShowHeaderWhenEmpty = false; rGridParentRules.EmptyDataText = string.Empty; rGridParentRules.ShowActionRow = false; BindRoles(); string scriptFormat = @" Sys.Application.add_load(function () {{ $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}'); }}); "; string script = string.Format(scriptFormat, HttpUtility.JavaScriptStringEncode(iSecured.ToString())); this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true); } else { nbMessage.Text = "Unfortunately, you are not able to edit security because you do not belong to a role that has been configured to allow administration of this item."; } } else { nbMessage.Text = "The item you are trying to secure does not exist or does not implement ISecured."; } } else { nbMessage.Text = string.Format("The requested entity type ('{0}') could not be loaded to determine security attributes.", entityTypeName); } base.OnInit(e); }
protected override void OnInit(EventArgs e) { // Read parameter values string entityName = Authorization.DecodeEntityTypeName(PageParameter("EntityType")); int entityId = 0; if (!Int32.TryParse(PageParameter("EntityId"), out entityId)) { entityId = 0; } // Get object type Type type = Type.GetType(entityName); if (type != null) { if (entityId == 0) { iSecured = (ISecured)Activator.CreateInstance(type); } else { iSecured = type.InvokeMember("Read", System.Reflection.BindingFlags.InvokeMethod, null, type, new object[] { entityId }) as ISecured; } if (iSecured.IsAuthorized("Administrate", CurrentPerson)) { rptActions.DataSource = iSecured.SupportedActions; rptActions.DataBind(); rGrid.DataKeyNames = new string[] { "id" }; rGrid.GridReorder += new GridReorderEventHandler(rGrid_GridReorder); rGrid.GridRebind += new GridRebindEventHandler(rGrid_GridRebind); rGrid.RowDataBound += new GridViewRowEventHandler(rGrid_RowDataBound); rGrid.ShowHeaderWhenEmpty = false; rGrid.EmptyDataText = string.Empty; rGrid.ShowActionRow = false; rGridParentRules.DataKeyNames = new string[] { "id" }; rGridParentRules.ShowHeaderWhenEmpty = false; rGridParentRules.EmptyDataText = string.Empty; rGridParentRules.ShowActionRow = false; BindRoles(); string script = string.Format(@" Sys.Application.add_load(function () {{ $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}'); }}); ", iSecured.ToString()); this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true); } } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = string.Format("Could not load the requested entity type ('{0}') to determine security attributes", entityName); nbMessage.Visible = true; } base.OnInit(e); }
/// <summary> /// Renders the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception> public override void Render(Context context, TextWriter result) { // first ensure that entity commands are allowed in the context if (!this.IsAuthorized(context)) { result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name)); base.Render(context, result); return; } bool hasFilter = false; // get a service for the entity based off it's friendly name var entityTypes = EntityTypeCache.All(); var model = string.Empty; if (_entityName == "business") { model = "Rock.Model.Person"; } else { model = "Rock.Model." + _entityName; } // Check first to see if this is a core model var entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); // If not, look for first plugin model that has same friendly name if (entityTypeCache == null) { entityTypeCache = entityTypes .Where(e => e.IsEntity && !e.Name.StartsWith("Rock.Model") && e.FriendlyName != null && e.FriendlyName.RemoveSpaces().ToLower() == _entityName) .OrderBy(e => e.Id) .FirstOrDefault(); } // If still null check to see if this was a duplicate class and full class name was used as entity name if (entityTypeCache == null) { model = _entityName.Replace('_', '.'); entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); } if (entityTypeCache != null) { Type entityType = entityTypeCache.GetEntityType(); if (entityType != null) { // Get the database context Type contextType = null; Rock.Data.DbContext dbContext = null; var contexts = Rock.Reflection.SearchAssembly(entityType.Assembly, typeof(Rock.Data.DbContext)); if (contexts.Any()) { contextType = contexts.First().Value; dbContext = Activator.CreateInstance(contextType) as Rock.Data.DbContext; } if (dbContext == null) { dbContext = _rockContext; } // create an instance of the entity's service Type[] modelType = { entityType }; Type genericServiceType = typeof(Rock.Data.Service <>); Type modelServiceType = genericServiceType.MakeGenericType(modelType); Rock.Data.IService serviceInstance = Activator.CreateInstance(modelServiceType, new object[] { dbContext }) as IService; ParameterExpression paramExpression = Expression.Parameter(entityType, "x"); Expression queryExpression = null; // the base expression we'll use to build our query from // parse markup var parms = ParseMarkup(_markup, context); if (parms.Any(p => p.Key == "id")) { string propertyName = "Id"; List <string> selectionParms = new List <string>(); selectionParms.Add(PropertyComparisonConverstion("==").ToString()); selectionParms.Add(parms["id"].ToString()); selectionParms.Add(propertyName); var entityProperty = entityType.GetProperty(propertyName); queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType); hasFilter = true; } else { // where clause expression if (parms.Any(p => p.Key == "where")) { queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache); if (queryExpression != null) { hasFilter = true; } } // dataview expression if (parms.Any(p => p.Key == "dataview")) { var dataViewId = parms["dataview"].AsIntegerOrNull(); if (dataViewId.HasValue) { var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache); if (queryExpression == null) { queryExpression = dataViewExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dataViewExpression); } } } // process dynamic filter expressions (from the query string) if (parms.Any(p => p.Key == "dynamicparameters")) { var dynamicFilters = parms["dynamicparameters"].Split(',') .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x)) .ToList(); foreach (var dynamicFilter in dynamicFilters) { var dynamicFilterValue = HttpContext.Current.Request[dynamicFilter]; var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression); if (dynamicFilterExpression != null) { if (queryExpression == null) { queryExpression = dynamicFilterExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression); } } } } } // make the query from the expression MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) }); if (getMethod != null) { var queryResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null }) as IQueryable <IEntity>; // process entity specific filters switch (_entityName) { case "person": { queryResult = PersonFilters((IQueryable <Person>)queryResult, parms); break; } case "business": { queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms); break; } } // if there was a dynamic expression add it now if (parms.Any(p => p.Key == "expression")) { queryResult = queryResult.Where(parms["expression"]); hasFilter = true; } // get a listing of ids if (parms.Any(p => p.Key == "ids")) { var value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList(); queryResult = queryResult.Where(x => value.Contains(x.Id)); hasFilter = true; } var queryResultExpression = queryResult.Expression; // add sort expressions if (parms.Any(p => p.Key == "sort")) { string orderByMethod = "OrderBy"; foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList()) { string propertyName; var direction = SortDirection.Ascending; if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase)) { direction = SortDirection.Descending; propertyName = column.Left(column.Length - 5); } else { propertyName = column; } string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod; if (entityType.GetProperty(propertyName) != null) { // sorting a entity property var memberExpression = Expression.Property(paramExpression, propertyName); LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } else { // sorting on an attribute // get attribute id int?attributeId = null; foreach (var id in AttributeCache.GetByEntity(entityTypeCache.Id).SelectMany(a => a.AttributeIds)) { var attribute = AttributeCache.Get(id); if (attribute.Key == propertyName) { attributeId = id; } } if (attributeId.HasValue) { // get AttributeValue queryable and parameter var attributeValues = _rockContext.Set <AttributeValue>(); ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v"); MemberExpression idExpression = Expression.Property(paramExpression, "Id"); var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value); LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } } orderByMethod = "ThenBy"; } } // reassemble the queryable with the sort expressions queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>; if (parms.GetValueOrNull("count").AsBoolean()) { int countResult = queryResult.Count(); context.Scopes.Last()["count"] = countResult; } else { // run security check on each result var items = queryResult.ToList(); var itemsSecured = new List <IEntity>(); Person person = GetCurrentPerson(context); foreach (IEntity item in items) { ISecured itemSecured = item as ISecured; if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person)) { itemsSecured.Add(item); } } queryResult = itemsSecured.AsQueryable(); // offset if (parms.Any(p => p.Key == "offset")) { queryResult = queryResult.Skip(parms["offset"].AsInteger()); } // limit, default to 1000 if (parms.Any(p => p.Key == "limit")) { queryResult = queryResult.Take(parms["limit"].AsInteger()); } else { queryResult = queryResult.Take(1000); } // check to ensure we had some form of filter (otherwise we'll return all results in the table) if (!hasFilter) { throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist."); } var resultList = queryResult.ToList(); // if there is only one item to return set an alternative non-array based variable if (resultList.Count == 1) { context.Scopes.Last()[_entityName] = resultList.FirstOrDefault(); } context.Scopes.Last()[parms["iterator"]] = resultList; } } } } else { result.Write(string.Format("Could not find a model for {0}.", _entityName)); base.Render(context, result); } base.Render(context, result); }
public void DeleteSecurity(ISecured secured) { //TODO!!!: When writing security check for antecedentid = referenceid &/or version=0 if (secured.SecurityID.HasValue) { if (CheckOwnership(secured, ActionPermission.Read | ActionPermission.Delete)) { using (new TransactionScope(TransactionScopeOption.Suppress)) { var c = new XODBC(ApplicationConnectionString,null); if (secured.IsBlack) { var s = (from o in c.SecurityBlacklists where o.SecurityBlacklistID == secured.SecurityID && o.Version == 0 && o.VersionDeletedBy == null select o).Single(); c.SecurityBlacklists.DeleteObject(s); } else { var s = (from o in c.SecurityWhitelists where o.SecurityWhitelistID == secured.SecurityID && o.Version == 0 && o.VersionDeletedBy == null select o).Single(); c.SecurityWhitelists.DeleteObject(s); } c.SaveChanges(); } } else throw new AuthorityException(string.Format("Incorrect permission for action: \"Delete\" Contact: {0} Record: {1}", secured.AccessorContactID, secured.OwnerReferenceID)); } else throw new NotSupportedException("Can not delete a security record without an ID."); }
protected override void OnInit( EventArgs e ) { // Read parameter values string entityName = Authorization.DecodeEntityTypeName( PageParameter( "EntityType" ) ); int entityId = 0; if (!Int32.TryParse( PageParameter( "EntityId" ), out entityId )) { entityId = 0; } // Get object type Type type = Type.GetType( entityName ); if ( type != null ) { if (entityId == 0) { iSecured = (ISecured)Activator.CreateInstance(type); } else { iSecured = type.InvokeMember( "Read", System.Reflection.BindingFlags.InvokeMethod, null, type, new object[] { entityId } )as ISecured; } if ( iSecured.IsAuthorized( "Administrate", CurrentPerson ) ) { rptActions.DataSource = iSecured.SupportedActions; rptActions.DataBind(); rGrid.DataKeyNames = new string[] { "id" }; rGrid.GridReorder += new GridReorderEventHandler( rGrid_GridReorder ); rGrid.GridRebind += new GridRebindEventHandler( rGrid_GridRebind ); rGrid.RowDataBound += new GridViewRowEventHandler( rGrid_RowDataBound ); rGrid.ShowHeaderWhenEmpty = false; rGrid.EmptyDataText = string.Empty; rGrid.ShowActionRow = false; rGridParentRules.DataKeyNames = new string[] { "id" }; rGridParentRules.ShowHeaderWhenEmpty = false; rGridParentRules.EmptyDataText = string.Empty; rGridParentRules.ShowActionRow = false; BindRoles(); string script = string.Format( @" Sys.Application.add_load(function () {{ $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}'); }}); ", iSecured.ToString() ); this.Page.ClientScript.RegisterStartupScript( this.GetType(), string.Format( "set-html-{0}", this.ClientID ), script, true ); } } else { rGrid.Visible = false; rGridParentRules.Visible = false; nbMessage.Text = string.Format("Could not load the requested entity type ('{0}') to determine security attributes", entityName); nbMessage.Visible = true; } base.OnInit( e ); }
public bool CheckOwnership(ISecured secured, ActionPermission permission) { using (new TransactionScope(TransactionScopeOption.Suppress)) { var c = new XODBC(ApplicationConnectionString,null); var verified = new System.Data.Objects.ObjectParameter("verified", typeof(byte)); c.X_SP_GetSecuredRight(secured.OwnerContactID, secured.OwnerApplicationID, secured.OwnerTableType, secured.OwnerReferenceID, secured.OwnerField, secured.CanRead || ((ActionPermission.Read & permission) == ActionPermission.Read) , secured.CanCreate || ((ActionPermission.Create & permission) == ActionPermission.Create) , secured.CanUpdate || ((ActionPermission.Update & permission) == ActionPermission.Update) , secured.CanDelete || ((ActionPermission.Delete & permission) == ActionPermission.Delete) , verified); return (bool)verified.Value; } }
/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> public override void OnActionExecuting(HttpActionContext actionContext) { var reflectedHttpActionDescriptor = ( ReflectedHttpActionDescriptor )actionContext.ActionDescriptor; var controller = actionContext.ActionDescriptor.ControllerDescriptor; string controllerClassName = controller.ControllerType.FullName; string actionMethod = actionContext.Request.Method.Method; var apiId = RestControllerService.GetApiId(reflectedHttpActionDescriptor.MethodInfo, actionMethod, controller.ControllerName); ISecured item = RestActionCache.Get(apiId); if (item == null) { // if there isn't a RestAction in the database, use the Controller as the secured item item = RestControllerCache.Get(controllerClassName); if (item == null) { item = new RestController(); } } Person person = null; if (actionContext.Request.Properties.Keys.Contains("Person")) { person = actionContext.Request.Properties["Person"] as Person; } else { var principal = actionContext.Request.GetUserPrincipal(); if (principal != null && principal.Identity != null) { using (var rockContext = new RockContext()) { string userName = principal.Identity.Name; UserLogin userLogin = null; if (userName.StartsWith("rckipid=")) { Rock.Model.PersonService personService = new Model.PersonService(rockContext); Rock.Model.Person impersonatedPerson = personService.GetByImpersonationToken(userName.Substring(8)); if (impersonatedPerson != null) { userLogin = impersonatedPerson.GetImpersonatedUser(); } } else { var userLoginService = new Rock.Model.UserLoginService(rockContext); userLogin = userLoginService.GetByUserName(userName); } if (userLogin != null) { person = userLogin.Person; actionContext.Request.Properties.Add("Person", person); /* 12/12/2019 BJW * * Setting this current person item was only done in put, post, and patch in the ApiController * class. Set it here so that it is always set for all methods, including delete. This enhances * history logging done in the pre and post save model hooks (when the pre-save event is called * we can access DbContext.GetCurrentPersonAlias and log who deleted the record). * * Task: https://app.asana.com/0/1120115219297347/1153140643799337/f */ System.Web.HttpContext.Current.AddOrReplaceItem("CurrentPerson", person); } } } } string action = actionMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) ? Rock.Security.Authorization.VIEW : Rock.Security.Authorization.EDIT; if (!item.IsAuthorized(action, person)) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); } }
/// <summary> /// Mies the allow all users. /// </summary> /// <param name="entity">The entity.</param> /// <param name="action">The action.</param> /// <param name="rockContext">The rock context.</param> private static void MyAllowAllUsers( ISecured entity, string action, RockContext rockContext ) { var authService = new AuthService( rockContext ); // Delete any existing rules in database foreach ( Auth auth in authService .GetAuths( entity.TypeId, entity.Id, action ) ) { authService.Delete( auth ); } rockContext.SaveChanges(); // Create the rule in the database Auth auth1 = new Auth(); auth1.EntityTypeId = entity.TypeId; auth1.EntityId = entity.Id; auth1.Order = 0; auth1.Action = action; auth1.AllowOrDeny = "A"; auth1.SpecialRole = SpecialRole.AllUsers; authService.Add( auth1 ); rockContext.SaveChanges(); // Reload the static dictionary for this action ReloadAction( entity.TypeId, entity.Id, action, rockContext ); }