Example #1
0
        public static bool HasOwnUpdatePermission(this Role role, Rbac rbac, Utilizer utilizer)
        {
            if (rbac.Action.Slug != Rbac.GetSegment(Rbac.CrudActions.Update).Slug)
            {
                return(false);
            }

            if (rbac.Resource == "users" && utilizer.Type == Utilizer.UtilizerType.User)
            {
                if (rbac.Object == utilizer.Id)
                {
                    return(true);
                }
            }

            if (rbac.Resource == "applications" && utilizer.Type == Utilizer.UtilizerType.Application)
            {
                if (rbac.Object == utilizer.Id)
                {
                    return(true);
                }
            }

            return(false);
        }
        public virtual TModel Create(Utilizer utilizer, string membershipId, TModel model)
        {
            // Check membership
            var membership = this.membershipService.Get(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }
            else
            {
                model.MembershipId = membershipId;
            }

            // Model validation
            if (!this.ValidateModel(model, out var errors))
            {
                throw ErtisAuthException.ValidationError(errors);
            }

            // Check existing
            if (this.IsAlreadyExist(model, membershipId))
            {
                throw this.GetAlreadyExistError(model);
            }

            // Insert to database
            var dto         = Mapper.Current.Map <TModel, TDto>(model);
            var insertedDto = this.repository.Insert(dto);
            var inserted    = Mapper.Current.Map <TDto, TModel>(insertedDto);

            this.OnCreated?.Invoke(this, new CreateResourceEventArgs <TModel>(utilizer, inserted));

            return(inserted);
        }
        public virtual bool?BulkDelete(Utilizer utilizer, string membershipId, string[] ids)
        {
            var isAllDeleted = true;
            var isAllFailed  = true;

            foreach (var id in ids)
            {
                var current = this.Get(membershipId, id);
                if (current != null)
                {
                    var isDeleted = this.repository.Delete(id);
                    if (isDeleted)
                    {
                        this.OnDeleted?.Invoke(this, new DeleteResourceEventArgs <TModel>(utilizer, current));
                    }

                    isAllDeleted &= isDeleted;
                    isAllFailed  &= !isDeleted;
                }
            }

            if (isAllDeleted)
            {
                return(true);
            }
            else if (isAllFailed)
            {
                return(false);
            }
            else
            {
                return(null);
            }
        }
        public static bool?HasPermission(this Utilizer utilizer, Rbac rbac)
        {
            bool isPermittedFilter(string permission)
            {
                if (Ubac.TryParse(permission, out var userUbac))
                {
                    bool isResourcePermitted = userUbac.Resource.IsAll() || userUbac.Resource.Equals(rbac.Resource, StringComparison.CurrentCultureIgnoreCase);
                    bool isActionPermitted   = userUbac.Action.IsAll() || userUbac.Action.Equals(rbac.Action, StringComparison.CurrentCultureIgnoreCase);
                    bool isObjectPermitted   = userUbac.Object.IsAll() || userUbac.Object.Equals(rbac.Object);

                    bool isPermitted = isResourcePermitted && isActionPermitted && isObjectPermitted;

                    if (isPermitted)
                    {
                        return(true);
                    }
                }

                return(false);
            }

            var matchedPermissions = utilizer.Permissions?.Where(isPermittedFilter) ?? new string[] {};
            var matchedForbiddens  = utilizer.Forbidden?.Where(isPermittedFilter) ?? new string[] {};

            var permissions = matchedPermissions as string[] ?? matchedPermissions.ToArray();
            var forbiddens  = matchedForbiddens as string[] ?? matchedForbiddens.ToArray();

            if (!permissions.Any() && !forbiddens.Any())
            {
                return(null);
            }

            return(!forbiddens.Any() && permissions.Any());
        }
Example #5
0
        private async Task InitializeAsync()
        {
            var memberships = await this.membershipService.GetAsync(0, null, false, null, null);

            if (memberships?.Items != null)
            {
                foreach (var membership in memberships.Items)
                {
                    var utilizer = new Utilizer
                    {
                        Role         = Rbac.ReservedRoles.Administrator,
                        Type         = Utilizer.UtilizerType.System,
                        MembershipId = membership.Id
                    };

                    var role = await this.GetByNameAsync(Rbac.ReservedRoles.Administrator, membership.Id);

                    if (role == null)
                    {
                        await this.CreateAsync(utilizer, membership.Id, new Role
                        {
                            Name         = Rbac.ReservedRoles.Administrator,
                            Description  = "Administrator",
                            MembershipId = membership.Id,
                            Permissions  = RoleHelper.AssertAdminPermissionsForReservedResources()
                        });
                    }
                }
            }
        }
Example #6
0
        public static Utilizer GetUtilizer(this ControllerBase controller)
        {
            var claimUser        = controller.User;
            var utilizerIdentity = claimUser.Identities.FirstOrDefault(x => x.NameClaimType == "Utilizer");

            if (utilizerIdentity != null)
            {
                var idClaim        = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerIdClaimName);
                var usernameClaim  = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerUsernameClaimName);
                var typeClaim      = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTypeClaimName);
                var roleClaim      = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerRoleClaimName);
                var tokenClaim     = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTokenClaimName);
                var tokenTypeClaim = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTokenTypeClaimName);

                TokenTypeExtensions.TryParseTokenType(tokenTypeClaim?.Value, out var tokenType);

                return(new Utilizer
                {
                    Id = idClaim?.Value,
                    Username = usernameClaim?.Value,
                    Type = Utilizer.ParseType(typeClaim?.Value),
                    Role = roleClaim?.Value,
                    Token = tokenClaim?.Value,
                    TokenType = tokenType
                });
            }

            return(new Utilizer());
        }
        public async ValueTask <Role> UpdateAsync(Utilizer utilizer, string membershipId, Role model)
        {
            model.MembershipId = membershipId;
            var current = await this.GetAsync(membershipId, model.Id);

            if (current != null)
            {
                model.Sys = new SysModel
                {
                    CreatedAt  = model.Sys.CreatedAt,
                    CreatedBy  = model.Sys.CreatedBy,
                    ModifiedAt = DateTime.Now,
                    ModifiedBy = utilizer.Username
                };
            }
            else
            {
                model.Sys = new SysModel
                {
                    CreatedAt  = DateTime.Now,
                    CreatedBy  = utilizer.Username,
                    ModifiedAt = DateTime.Now,
                    ModifiedBy = utilizer.Username
                };
            }

            var index = this.MockRepository.FindIndex(x => x.MembershipId == membershipId && x.Id == model.Id);

            this.MockRepository.RemoveAt(index);
            this.MockRepository.Insert(index, model);
            return(model);
        }
Example #8
0
        public async Task <dynamic> MigrateAsync(string connectionString, Membership _membership, UserWithPassword _user)
        {
            // Validation
            var databaseInformation = Ertis.MongoDB.Helpers.ConnectionStringHelper.ParseConnectionString(connectionString);
            var connectionString1   = Ertis.MongoDB.Helpers.ConnectionStringHelper.GenerateConnectionString(this.databaseSettings);
            var connectionString2   = Ertis.MongoDB.Helpers.ConnectionStringHelper.GenerateConnectionString(databaseInformation);

            if (connectionString1 != connectionString2)
            {
                throw ErtisAuthException.MigrationRejected("Connection string could not validated");
            }

            // 1. Membership
            var membership = await this.membershipService.CreateAsync(new Membership
            {
                Name                  = _membership.Name,
                DefaultEncoding       = _membership.DefaultEncoding,
                HashAlgorithm         = _membership.HashAlgorithm,
                ExpiresIn             = _membership.ExpiresIn,
                RefreshTokenExpiresIn = _membership.RefreshTokenExpiresIn,
                SecretKey             = string.IsNullOrEmpty(_membership.SecretKey) ? GenerateRandomSecretKey(32) : _membership.SecretKey
            });

            // Utilizer
            var utilizer = new Utilizer
            {
                Role         = Rbac.ReservedRoles.Administrator,
                Type         = Utilizer.UtilizerType.System,
                MembershipId = membership.Id
            };

            // 2. Role
            var adminRole = await this.roleService.CreateAsync(utilizer, membership.Id, new Role
            {
                Name         = Rbac.ReservedRoles.Administrator,
                Description  = "Administrator",
                MembershipId = membership.Id,
                Permissions  = RoleHelper.AssertAdminPermissionsForReservedResources()
            });

            // 3. User (admin)
            var adminUser = await this.userService.CreateAsync(utilizer, membership.Id, new UserWithPassword
            {
                Username     = _user.Username,
                FirstName    = _user.FirstName,
                LastName     = _user.LastName,
                EmailAddress = _user.EmailAddress,
                Role         = adminRole.Name,
                MembershipId = membership.Id,
                PasswordHash = this.cryptographyService.CalculatePasswordHash(membership, _user.PasswordHash)
            });

            return(new
            {
                membership,
                user = adminUser,
                role = adminRole
            });
        }
        public override bool Delete(Utilizer utilizer, string membershipId, string id)
        {
            // Is Deletable?
            if (!this.IsDeletable(id, membershipId, out var _))
            {
                throw ErtisAuthException.UserTypeCanNotBeDelete();
            }

            return(base.Delete(utilizer, membershipId, id));
        }
        public override async ValueTask <bool> DeleteAsync(Utilizer utilizer, string membershipId, string id)
        {
            // Is Deletable?
            if (!this.IsDeletable(id, membershipId, out var _))
            {
                throw ErtisAuthException.UserTypeCanNotBeDelete();
            }

            return(await base.DeleteAsync(utilizer, membershipId, id));
        }
Example #11
0
        public override async Task <User> UpdateAsync(Utilizer utilizer, string membershipId, User model)
        {
            var currentUser = await this.GetUserWithPasswordAsync(model.Id, membershipId);

            var passwordHash = currentUser.PasswordHash;

            if (model is UserWithPassword userWithPassword && !string.IsNullOrEmpty(userWithPassword.PasswordHash) && userWithPassword.PasswordHash != passwordHash)
            {
                passwordHash = userWithPassword.PasswordHash;
            }

            return(await base.UpdateAsync(utilizer, membershipId, new UserWithPassword(model) { PasswordHash = passwordHash }));
        }
        public virtual async Task <bool> DeleteAsync(Utilizer utilizer, string membershipId, string id)
        {
            var current = await this.GetAsync(membershipId, id);

            if (current != null)
            {
                this.OnDeleted?.Invoke(this, new DeleteResourceEventArgs <TModel>(utilizer, current));
                return(await this.repository.DeleteAsync(id));
            }
            else
            {
                return(false);
            }
        }
        public virtual bool Delete(Utilizer utilizer, string membershipId, string id)
        {
            var current = this.Get(membershipId, id);

            if (current != null)
            {
                this.OnDeleted?.Invoke(this, new DeleteResourceEventArgs <TModel>(utilizer, current));
                return(this.repository.Delete(id));
            }
            else
            {
                return(false);
            }
        }
        public async ValueTask <Role> CreateAsync(Utilizer utilizer, string membershipId, Role model)
        {
            model.MembershipId = membershipId;
            model.Sys          = new SysModel
            {
                CreatedAt = DateTime.Now,
                CreatedBy = utilizer.Username
            };

            await Task.CompletedTask;

            this.MockRepository.Add(model);
            return(model);
        }
        public virtual async ValueTask <TModel> UpdateAsync(Utilizer utilizer, string membershipId, TModel model)
        {
            // Check membership
            var membership = await this.membershipService.GetAsync(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }
            else
            {
                model.MembershipId = membershipId;
            }

            // Overwrite
            var current = await this.GetAsync(membershipId, model.Id);

            if (current == null)
            {
                throw this.GetNotFoundError(model.Id);
            }

            this.Overwrite(model, current);

            // Touch model
            model = await this.TouchAsync(model, CrudOperation.Update);

            // Model validation
            if (!this.ValidateModel(model, out var errors))
            {
                throw ErtisAuthException.ValidationError(errors);
            }

            // Check existing
            if (await this.IsAlreadyExistAsync(model, membershipId, current))
            {
                throw this.GetAlreadyExistError(model);
            }

            model.MembershipId = membershipId;
            var dto        = Mapper.Current.Map <TModel, TDto>(model);
            var updatedDto = await this.repository.UpdateAsync(dto);

            var updated = Mapper.Current.Map <TDto, TModel>(updatedDto);

            this.OnUpdated?.Invoke(this, new UpdateResourceEventArgs <TModel>(utilizer, current, updated));

            return(updated);
        }
        public async ValueTask <bool> DeleteAsync(Utilizer utilizer, string membershipId, string id)
        {
            var index = this.MockRepository.FindIndex(x => x.MembershipId == membershipId && x.Id == id);

            if (index >= 0)
            {
                await Task.CompletedTask;
                this.MockRepository.RemoveAt(index);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #17
0
        public async Task SetPasswordAsync(Utilizer utilizer, string membershipId, string resetToken, string usernameOrEmailAddress, string password)
        {
            if (string.IsNullOrEmpty(usernameOrEmailAddress))
            {
                throw ErtisAuthException.ValidationError(new []
                {
                    "Username or email required!"
                });
            }

            var membership = await this.membershipService.GetAsync(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }

            var user = await this.GetUserWithPasswordAsync(usernameOrEmailAddress, usernameOrEmailAddress, membershipId);

            if (user == null)
            {
                throw ErtisAuthException.UserNotFound(usernameOrEmailAddress, "username or email_address");
            }

            if (utilizer.Role == Rbac.ReservedRoles.Administrator || utilizer.Id == user.Id)
            {
                if (this.jwtService.TryDecodeToken(resetToken, out var securityToken))
                {
                    var expireTime = securityToken.ValidTo.ToLocalTime();
                    if (DateTime.Now > expireTime)
                    {
                        // Token was expired!
                        throw ErtisAuthException.TokenWasExpired();
                    }

                    await this.ChangePasswordAsync(utilizer, membershipId, user.Id, password);
                }
                else
                {
                    // Reset token could not decoded!
                    throw ErtisAuthException.InvalidToken();
                }
            }
            else
            {
                throw ErtisAuthException.AccessDenied("Unauthorized access");
            }
        }
Example #18
0
        private async Task FireOnCreatedEvent(string membershipId, Utilizer utilizer, DynamicObject inserted)
        {
            if (this._eventService != null)
            {
                await this._eventService.FireEventAsync(this, new ErtisAuthEvent
                {
                    Document     = inserted.ToDynamic(),
                    Prior        = null,
                    EventTime    = DateTime.Now,
                    EventType    = ErtisAuthEventType.UserCreated,
                    MembershipId = membershipId,
                    UtilizerId   = utilizer.Id
                });
            }

            this.OnCreated?.Invoke(this, new CreateResourceEventArgs <DynamicObject>(utilizer, inserted));
        }
Example #19
0
        public async Task <ResetPasswordToken> ResetPasswordAsync(Utilizer utilizer, string membershipId, string usernameOrEmailAddress)
        {
            if (string.IsNullOrEmpty(usernameOrEmailAddress))
            {
                throw ErtisAuthException.ValidationError(new []
                {
                    "Username or email required!"
                });
            }

            var membership = await this.membershipService.GetAsync(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }

            var user = await this.GetUserWithPasswordAsync(usernameOrEmailAddress, usernameOrEmailAddress, membershipId);

            if (user == null)
            {
                throw ErtisAuthException.UserNotFound(usernameOrEmailAddress, "username or email_address");
            }

            if (utilizer.Role == Rbac.ReservedRoles.Administrator || utilizer.Id == user.Id)
            {
                var tokenClaims = new TokenClaims(Guid.NewGuid().ToString(), user, membership);
                tokenClaims.AddClaim("token_type", "reset_token");
                var resetToken         = this.jwtService.GenerateToken(tokenClaims, HashAlgorithms.SHA2_256, Encoding.UTF8);
                var resetPasswordToken = new ResetPasswordToken(resetToken, TimeSpan.FromHours(1));

                await this.eventService.FireEventAsync(this, new ErtisAuthEvent
                {
                    EventType    = ErtisAuthEventType.UserPasswordReset,
                    UtilizerId   = user.Id,
                    Document     = resetPasswordToken,
                    MembershipId = membershipId
                });

                return(resetPasswordToken);
            }
            else
            {
                throw ErtisAuthException.AccessDenied("Unauthorized access");
            }
        }
        public override Application Create(Utilizer utilizer, string membershipId, Application model)
        {
            var membership = this.membershipService.Get(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }

            var application = base.Create(utilizer, membershipId, model);

            if (application != null)
            {
                application.Secret = $"{application.Id}:{membership.SecretKey}";
                application        = this.Update(utilizer, membershipId, application);
            }

            return(application);
        }
Example #21
0
        public async Task <User> ChangePasswordAsync(Utilizer utilizer, string membershipId, string userId, string newPassword)
        {
            if (string.IsNullOrEmpty(newPassword))
            {
                throw ErtisAuthException.ValidationError(new []
                {
                    "Password can not be null or empty!"
                });
            }

            var membership = await this.membershipService.GetAsync(membershipId);

            if (membership == null)
            {
                throw ErtisAuthException.MembershipNotFound(membershipId);
            }

            var user = await this.GetAsync(membershipId, userId);

            if (user == null)
            {
                throw ErtisAuthException.UserNotFound(userId, "_id");
            }

            var userWithPassword = Mapper.Current.Map <User, UserWithPassword>(user);
            var passwordHash     = this.cryptographyService.CalculatePasswordHash(membership, newPassword);

            userWithPassword.PasswordHash = passwordHash;

            var updatedUser = await this.UpdateAsync(utilizer, membershipId, userWithPassword);

            await this.eventService.FireEventAsync(this, new ErtisAuthEvent
            {
                EventType    = ErtisAuthEventType.UserPasswordChanged,
                UtilizerId   = user.Id,
                Document     = updatedUser,
                Prior        = userWithPassword,
                MembershipId = membershipId
            });

            return(updatedUser);
        }
Example #22
0
        private static bool CheckPermission(Role role, Rbac rbac, Utilizer utilizer)
        {
            var hasUbacPermission = utilizer.HasPermission(rbac);

            if (hasUbacPermission != null)
            {
                return(hasUbacPermission.Value);
            }

            if (role.HasPermission(rbac))
            {
                return(true);
            }
            else if (role.HasOwnUpdatePermission(rbac, utilizer))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #23
0
        public static Utilizer GetUtilizer(this ControllerBase controller)
        {
            var claimUser        = controller.User;
            var utilizerIdentity = claimUser.Identities.FirstOrDefault(x => x.NameClaimType == "Utilizer");

            if (utilizerIdentity != null)
            {
                var idClaim           = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerIdClaimName);
                var typeClaim         = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTypeClaimName);
                var roleClaim         = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerRoleClaimName);
                var membershipIdClaim = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.MembershipIdClaimName);

                return(new Utilizer
                {
                    Id = idClaim?.Value,
                    Type = Utilizer.ParseType(typeClaim?.Value),
                    Role = roleClaim?.Value,
                    MembershipId = membershipIdClaim?.Value
                });
            }

            return(new Utilizer());
        }
        public static Utilizer ConvertToUtilizer(this ClaimsIdentity utilizerIdentity)
        {
            var idClaim           = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerIdClaimName);
            var typeClaim         = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTypeClaimName);
            var usernameClaim     = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerUsernameClaimName);
            var roleClaim         = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerRoleClaimName);
            var membershipIdClaim = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.MembershipIdClaimName);
            var tokenClaim        = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTokenClaimName);
            var tokenTypeClaim    = utilizerIdentity.Claims.FirstOrDefault(x => x.Type == Utilizer.UtilizerTokenTypeClaimName);

            TokenTypeExtensions.TryParseTokenType(tokenTypeClaim?.Value, out var tokenType);

            return(new Utilizer
            {
                Id = idClaim?.Value,
                Type = Utilizer.ParseType(typeClaim?.Value),
                Username = usernameClaim?.Value,
                Role = roleClaim?.Value,
                MembershipId = membershipIdClaim?.Value,
                Token = tokenClaim?.Value,
                TokenType = tokenType
            });
        }
        public static Utilizer GetUtilizer(this ControllerBase controller)
        {
            var claimUser        = controller.User;
            var utilizerIdentity = claimUser.Identities.FirstOrDefault(x => x.NameClaimType == "Utilizer");

            if (utilizerIdentity != null)
            {
                var utilizerSampling = utilizerIdentity.ConvertToUtilizer();

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (utilizerSampling.Type == Utilizer.UtilizerType.User)
                {
                    var userService = controller.HttpContext.RequestServices.GetService <IUserService>();
                    if (userService != null)
                    {
                        var      dynamicObject = userService.GetAsync(utilizerSampling.MembershipId, utilizerSampling.Id).ConfigureAwait(false).GetAwaiter().GetResult();
                        var      user          = dynamicObject.Deserialize <User>();
                        Utilizer utilizer      = user;
                        return(utilizer);
                    }
                }
                else if (utilizerSampling.Type == Utilizer.UtilizerType.Application)
                {
                    var applicationService = controller.HttpContext.RequestServices.GetService <IApplicationService>();
                    if (applicationService != null)
                    {
                        Utilizer application = applicationService.Get(utilizerSampling.MembershipId, utilizerSampling.Id);
                        return(application);
                    }
                }

                return(utilizerSampling);
            }

            return(new Utilizer());
        }
Example #26
0
 public Task <bool?> BulkDeleteAsync(Utilizer utilizer, string membershipId, string[] ids)
 {
     throw new NotImplementedException();
 }
Example #27
0
 ValueTask <bool?> IDeletableMembershipBoundedService.BulkDeleteAsync(Utilizer utilizer, string membershipId, string[] ids)
 {
     throw new NotImplementedException();
 }
Example #28
0
 public bool?BulkDelete(Utilizer utilizer, string membershipId, string[] ids)
 {
     throw new NotImplementedException();
 }
Example #29
0
 public Task <DynamicObject> UpdateAsync(Utilizer utilizer, string membershipId, string userId, DynamicObject model)
 {
     throw new NotImplementedException();
 }
Example #30
0
 public Task <bool> CheckPasswordAsync(Utilizer utilizer, string password)
 {
     throw new NotImplementedException();
 }