public virtual bool HasPermission(PermissionType permission, Guid? scope)
        {
            if (this.IsAdmin)
            {
                return true;
            }

            if (this.IsUser)
            {
                if (myAuthzs.Any(f => f.Permission == permission && (scope == null || f.Scope == scope)))
                {
                    return true;
                }

                using (var ctx = storeFactory.Create(this.UserLogin))
                {
                    //// Authorization can be assigned directly to the user.
                    //if (ctx.Authorization.Any(f => f.Permission == permission && f.Scope == scope && f.UserName == this.UserLogin))
                    //{
                    //    return true;
                    //}

                    FieldInfo fi = permission.GetType().GetField(permission.ToString());
                    PermissionScopeAttribute[] attributes = (PermissionScopeAttribute[])fi.GetCustomAttributes(typeof(PermissionScopeAttribute), false);
                    foreach (var attrib in attributes)
                    {
                        if (attrib.ScopeType == PermissionScopeType.Organization)
                        {

                            var authzdRoles = ctx.Authorization.IncludePaths("Role").Where(f => f.Permission == permission && f.Scope == scope && f.Role != null).ToList();

                            var me = ctx.Users.IncludePaths("Roles.Role").Single(f => f.Username == this.UserLogin);
                            var myDirectRoles = me.Roles.Select(f => f.Role).ToList();

                            // If my direct membership in a role means that I end up being in a role that's got the authorization, then I get the authorization.
                            if (authzdRoles.Any(f =>
                            {
                                RoleKey key = new RoleKey { Name = f.Role.Name, OrgId = f.Scope };
                                return flattenedRoles.ContainsKey(key) && (from have in myDirectRoles join need in flattenedRoles[key] on have.Id equals need.Id select have).Any();
                            }))
                            {
                                return true;
                            }

                        }
                        else if (attrib.ScopeType == PermissionScopeType.MemberOfOrganization)
                        {
                            // Figure out if the user has permissions on a member due to being able to manage an organization to which the user belongs
                            // Get the member's current org id's
                            IEnumerable<Guid> orgIds = ctx.Members.Where(f => f.Id == scope.Value).SelectMany(
                                f => f.Memberships.Select(g => g.OrganizationId)).AsEnumerable();

                            // If any of the users authorizations are of the given permission on a scope of one of the user's orgs,
                            // then grant the operation.
                            if (myAuthzs.Any(f => f.Permission == permission && orgIds.Any(g => g == f.Scope)))
                            {
                                return true;
                            }
                        }
                        else if (attrib.ScopeType == PermissionScopeType.Member)
                        {
                            if (myAuthzs.Any(f => f.Permission == permission && f.Scope == scope))
                            {
                                return true;
                            }
                        }
                        else
                        {
                            throw new NotImplementedException("Don't know PermissionScope " + attrib.ScopeType.ToString());
                        }

                    }

                    //Type t = PermissionScopeTypeAttribute.GetScopeType(permission);

                    //if (t == typeof(Organization))
                    //{
                    //    var me = ctx.Users.IncludePaths("Roles.Role").Single(f => f.Username == this.UserLogin);
                    //    var myDirectRoles = me.Roles.Select(f => f.Role).ToList();

                    //    // If my direct membership in a role means that I end up being in a role that's got the authorization, then I get the authorization.
                    //    if (authzdRoles.Any(f =>
                    //    {
                    //        RoleKey key = new RoleKey { Name = f.Role.Name, OrgId = f.Scope };
                    //        return flattenedRoles.ContainsKey(key) && (from have in myDirectRoles join need in flattenedRoles[key] on have.Id equals need.Id select have).Any();
                    //    }))
                    //    {
                    //        return true;
                    //    }
                    //}
                }
            }
            return false;
        }
        //            if (myRoles == null)
        //            {
        //                    var me = ctx.Users.IncludePaths("Roles.Role.Organization").Single(
        //f => f.Username == this.UserLogin
        //);
        //                myRoles = me.Roles.Select(f => f.Role).ToList();
        //            }
        //            if (myAuthzs == null)
        //            {
        //                using (var ctx = storeFactory.Create(this.UserLogin))
        //                {
        //                    foreach (var authz in ctx.Authorization.Where(f => f.Role != null))
        //                    {
        //                        //                if (
        //                    }
        //                }
        //            }
        //        }
        //    }
        private void Init()
        {
            if (flattenedRoles.Count == 0)
            {
                using (var ctx = storeFactory.Create(this.UserLogin))
                {
                    flattenedRoles = GetRoleMemberLookup(ctx);
                }
            }

            if (this.IsUser)
            {
                //using (var ctx = storeFactory.Create(this.UserLogin))
                //{
                //    var me =
                //    ctx.Users.IncludePaths("Roles.Role.Organization").Single(
                //        f => f.Username == this.UserLogin
                //        );
                //    myRoles = me.Roles.Select(f => f.Role).ToList();
                //}
                FillMyData();
                RoleKey adminKey = new RoleKey(ADMIN_ROLE, null);
                this.IsAdmin = HasPermission(PermissionType.SiteAdmin, null); // flattenedRoles.ContainsKey(adminKey) && (from have in myRoles join need in flattenedRoles[adminKey] on have.Id equals need.Id select have).Any();
            }
        }
        public virtual void CreateRole(RoleKey role, bool system, RoleKey? parent)
        {
            if (string.IsNullOrWhiteSpace(role.Name))
            {
                throw new ArgumentException("role", "Role name cannot be null or empty");
            }

            using (var ctx = storeFactory.Create(this.UserLogin))
            {
                Role newRole = ctx.Roles.SingleOrDefault(f => f.Name == role.Name && f.OrganizationId == role.OrgId);
                if (newRole != null) throw new InvalidOperationException("Role " + role.Name + " already exists");

                newRole = new Role
                {
                    Name = role.Name,
                    OrganizationId = role.OrgId,
                    SystemRole = system,
                };

                if (parent != null)
                {
                    if (string.IsNullOrWhiteSpace(parent.Value.Name))
                    {
                        throw new ArgumentException("parent", "Parent role name cannot be null or empty");
                    }

                    RoleKey p = parent.Value;

                    var query = ctx.Roles.Where(f => f.Name == p.Name && f.OrganizationId == p.OrgId);
                    //if (parent.Value.OrgId.HasValue)
                    //{
                    //    Guid workaround = parent.Value.OrgId.Value;
                    //    query = query.Where(f => f.Organization.Id == workaround);
                    //}
                    //else
                    //{
                    //    query = query.Where(f => f.Organization == null);
                    //}

                    Role parentRole = query.SingleOrDefault();
                    if (parentRole == null)
                    {
                        throw new InvalidOperationException("Parent role does not exist");
                    }
                    else
                    {
                        newRole.MemberOfRoles.Add(new RoleRoleMembership { Parent = parentRole, Child = newRole, IsSystem = system });
                    }
                }

                ctx.Roles.Add(newRole);
                ctx.SaveChanges();
            }
        }