Exemplo n.º 1
0
        public async Task <IActionResult> VerifyToken()
        {
            string token = this.GetTokenFromHeader(out string tokenTypeStr);

            if (string.IsNullOrEmpty(token))
            {
                return(this.AuthorizationHeaderMissing());
            }

            if (!TokenTypeExtensions.TryParseTokenType(tokenTypeStr, out var tokenType))
            {
                throw ErtisAuthException.UnsupportedTokenType();
            }

            var validationResult = await this.tokenService.VerifyTokenAsync(token, tokenType);

            if (validationResult.IsValidated)
            {
                return(this.Ok(validationResult));
            }
            else
            {
                return(this.Unauthorized(validationResult));
            }
        }
Exemplo n.º 2
0
        public async Task <IActionResult> WhoAmI()
        {
            string token = this.GetTokenFromHeader(out string tokenTypeStr);

            if (string.IsNullOrEmpty(token))
            {
                return(this.AuthorizationHeaderMissing());
            }

            if (!TokenTypeExtensions.TryParseTokenType(tokenTypeStr, out var tokenType))
            {
                throw ErtisAuthException.UnsupportedTokenType();
            }

            var user = await this.tokenService.WhoAmIAsync(token, tokenType);

            if (user != null)
            {
                return(this.Ok(user));
            }
            else
            {
                return(this.InvalidToken());
            }
        }
Exemplo n.º 3
0
        // ReSharper disable once OutParameterValueIsAlwaysDiscarded.Local
        private bool IsDeletable(string id, string membershipId, out IEnumerable <string> errors)
        {
            var userType = this.GetAsync(membershipId, id).ConfigureAwait(false).GetAwaiter().GetResult();

            if (userType == null)
            {
                throw ErtisAuthException.UserTypeNotFound(id, "_id");
            }

            var query = QueryBuilder.Where(QueryBuilder.Equals("membership_id", membershipId), QueryBuilder.Equals("base_type", userType.Name));
            var inheritedUserTypes = this.QueryAsync(query.ToString()).ConfigureAwait(false).GetAwaiter().GetResult();

            if (inheritedUserTypes.Items.Any())
            {
                errors = new[]
                {
                    $"This user type is currently using as the base type of some other user types. ({string.Join(", ", inheritedUserTypes.Items.Select(x => x["title"]))})"
                };

                return(false);
            }

            errors = null;
            return(true);
        }
Exemplo n.º 4
0
        protected override void Overwrite(Application destination, Application source)
        {
            destination.Id           = source.Id;
            destination.MembershipId = source.MembershipId;
            destination.Sys          = source.Sys;

            if (this.IsIdentical(destination, source))
            {
                throw ErtisAuthException.IdenticalDocument();
            }

            if (string.IsNullOrEmpty(destination.Name))
            {
                destination.Name = source.Name;
            }

            if (string.IsNullOrEmpty(destination.Role))
            {
                destination.Role = source.Role;
            }

            if (destination.Permissions == null)
            {
                destination.Permissions = source.Permissions;
            }

            if (destination.Forbidden == null)
            {
                destination.Forbidden = source.Forbidden;
            }
        }
Exemplo n.º 5
0
        public virtual async Task <TModel> UpdateAsync(TModel model)
        {
            // Overwrite
            var current = await this.GetAsync(model.Id);

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

            this.Overwrite(model, current);

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

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

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

            return(Mapper.Current.Map <TDto, TModel>(updated));
        }
Exemplo n.º 6
0
        public virtual TModel Update(TModel model)
        {
            // Overwrite
            var current = this.Get(model.Id);

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

            this.Overwrite(model, current);

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

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

            var dto        = Mapper.Current.Map <TModel, TDto>(model);
            var updatedDto = this.repository.Update(dto);
            var updated    = Mapper.Current.Map <TDto, TModel>(updatedDto);

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

            return(updated);
        }
        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);
        }
Exemplo n.º 8
0
        public static string ExtractToken(string authorizationHeader, out string tokenType)
        {
            if (string.IsNullOrEmpty(authorizationHeader))
            {
                tokenType = null;
                return(null);
            }

            var parts = authorizationHeader.Split(' ');

            if (parts.Length > 2)
            {
                throw ErtisAuthException.InvalidToken();
            }

            if (parts.Length == 2)
            {
                var supportedTokenTypes = Enum.GetValues(typeof(SupportedTokenTypes)).Cast <SupportedTokenTypes>().Select(x => x.ToString());
                if (!supportedTokenTypes.Contains(parts[0]))
                {
                    throw ErtisAuthException.UnsupportedTokenType();
                }

                tokenType = parts[0];
                return(parts[1]);
            }

            tokenType = null;
            return(parts[0]);
        }
Exemplo n.º 9
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
            });
        }
Exemplo n.º 10
0
        public async Task <IActionResult> Migrate([FromBody] MigrationModel model)
        {
            if (model.Membership == null)
            {
                throw ErtisAuthException.ValidationError(new[] { "membership is required" });
            }

            if (model.User == null)
            {
                throw ErtisAuthException.ValidationError(new[] { "user is required" });
            }

            if (!this.Request.Headers.ContainsKey("ConnectionString"))
            {
                throw ErtisAuthException.ValidationError(new[] { "ConnectionString must be post in header" });
            }

            var connectionString = this.Request.Headers["ConnectionString"];

            var membership = new Membership
            {
                Name                  = model.Membership.Name,
                ExpiresIn             = model.Membership.ExpiresIn,
                RefreshTokenExpiresIn = model.Membership.RefreshTokenExpiresIn,
                HashAlgorithm         = model.Membership.HashAlgorithm,
                DefaultEncoding       = model.Membership.DefaultEncoding,
                SecretKey             = model.Membership.SecretKey,
            };

            var user = new UserWithPasswordHash
            {
                Username     = model.User.Username,
                EmailAddress = model.User.EmailAddress,
                FirstName    = model.User.FirstName,
                LastName     = model.User.LastName,
                PasswordHash = model.User.Password,
                Role         = model.User.Role,
                Forbidden    = model.User.Forbidden,
                Permissions  = model.User.Permissions
            };

            Application application = null;

            if (model.Application != null)
            {
                application = new Application
                {
                    Name = model.Application.Name,
                    Role = model.Application.Role
                };
            }

            this.Request.HttpContext.Items.Add("SysUtilizer", "migration");

            var migrationResult = await this.migrationService.MigrateAsync(connectionString, membership, user, application);

            return(this.Ok(migrationResult));
        }
Exemplo n.º 11
0
        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));
        }
Exemplo n.º 12
0
        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));
        }
Exemplo n.º 13
0
        public override async ValueTask <bool> DeleteAsync(string id)
        {
            var membershipBoundedResources = await this.GetMembershipBoundedResourcesAsync(id);

            if (membershipBoundedResources.Any())
            {
                throw ErtisAuthException.MembershipCouldNotDeleted(id);
            }

            return(await base.DeleteAsync(id));
        }
Exemplo n.º 14
0
        private async Task <Membership> CheckMembershipAsync(string membershipId)
        {
            var membership = await this._membershipService.GetAsync(membershipId);

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

            return(membership);
        }
Exemplo n.º 15
0
        public IPaginationCollection <dynamic> GetDynamic(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection)
        {
            var membership = this.membershipService.Get(membershipId);

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

            return(this.repository.Query(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection));
        }
Exemplo n.º 16
0
        public async Task <IPaginationCollection <dynamic> > GetDynamicAsync(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection)
        {
            var membership = await this.membershipService.GetAsync(membershipId);

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

            return(await this.eventRepository.QueryAsync(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection));
        }
Exemplo n.º 17
0
        public override bool Delete(string id)
        {
            var membershipBoundedResources = this.GetMembershipBoundedResources(id);

            if (membershipBoundedResources.Any())
            {
                throw ErtisAuthException.MembershipCouldNotDeleted(id);
            }

            return(base.Delete(id));
        }
Exemplo n.º 18
0
        protected override void Overwrite(UserType destination, UserType source)
        {
            destination.Id           = source.Id;
            destination.MembershipId = source.MembershipId;
            destination.Sys          = source.Sys;

            if (this.IsIdentical(destination, source))
            {
                throw ErtisAuthException.IdenticalDocument();
            }
        }
Exemplo n.º 19
0
        public virtual async Task <TModel> GetAsync(string membershipId, string id)
        {
            var membership = await this.membershipService.GetAsync(membershipId);

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

            var dto = await this.repository.FindOneAsync(x => x.Id == id && x.MembershipId == membershipId);

            return(Mapper.Current.Map <TDto, TModel>(dto));
        }
Exemplo n.º 20
0
        public override ErtisAuthEventBase Get(string membershipId, string id)
        {
            var membership = this.membershipService.Get(membershipId);

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

            var dto = this.repository.FindOne(x => x.Id == id && x.MembershipId == membershipId);

            return(DtoToModel(dto));
        }
Exemplo n.º 21
0
        public override async ValueTask <ErtisAuthEventBase> GetAsync(string membershipId, string id)
        {
            var membership = await this.membershipService.GetAsync(membershipId);

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

            var dto = await this.repository.FindOneAsync(x => x.Id == id && x.MembershipId == membershipId);

            return(DtoToModel(dto));
        }
Exemplo n.º 22
0
        private async Task <UserType> GetUserTypeAsync(DynamicObject model, string membershipId, bool fallbackWithOriginUserType = false)
        {
            if (model.TryGetValue("user_type", out string userTypeName, out _) && !string.IsNullOrEmpty(userTypeName))
            {
                var userType = await this._userTypeService.GetByNameOrSlugAsync(membershipId, userTypeName);

                if (userType == null)
                {
                    throw ErtisAuthException.UserTypeNotFound(userTypeName, "name");
                }

                return(userType);
            }
Exemplo n.º 23
0
        protected override void Overwrite(MailHook destination, MailHook source)
        {
            destination.Id           = source.Id;
            destination.MembershipId = source.MembershipId;
            destination.Sys          = source.Sys;

            if (this.IsIdentical(destination, source))
            {
                throw ErtisAuthException.IdenticalDocument();
            }

            if (string.IsNullOrEmpty(destination.Name))
            {
                destination.Name = source.Name;
            }

            if (string.IsNullOrEmpty(destination.Description))
            {
                destination.Description = source.Description;
            }

            if (string.IsNullOrEmpty(destination.Event))
            {
                destination.Event = source.Event;
            }

            if (string.IsNullOrEmpty(destination.Status))
            {
                destination.Status = source.Status;
            }

            if (string.IsNullOrEmpty(destination.MailSubject))
            {
                destination.MailSubject = source.MailSubject;
            }

            if (string.IsNullOrEmpty(destination.MailTemplate))
            {
                destination.MailTemplate = source.MailTemplate;
            }

            if (string.IsNullOrEmpty(destination.FromName))
            {
                destination.FromName = source.FromName;
            }

            if (string.IsNullOrEmpty(destination.FromAddress))
            {
                destination.FromAddress = source.FromAddress;
            }
        }
Exemplo n.º 24
0
        public async Task <ITokenValidationResult> VerifyTokenAsync(string token, SupportedTokenTypes tokenType, bool fireEvent = true)
        {
            switch (tokenType)
            {
            case SupportedTokenTypes.Bearer:
                return(await this.VerifyBearerTokenAsync(token, fireEvent));

            case SupportedTokenTypes.Basic:
                return(await this.VerifyBasicTokenAsync(token, fireEvent));

            default:
                throw ErtisAuthException.UnsupportedTokenType();
            }
        }
        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);
        }
Exemplo n.º 26
0
        private static void CheckReservedUserTypeName(string name)
        {
            var reservedNames = new[]
            {
                OriginUserType.Name,
            };

            foreach (var reservedName in reservedNames)
            {
                if (name == reservedName)
                {
                    throw ErtisAuthException.ReservedUserTypeName(reservedName);
                }
            }
        }
        protected async ValueTask <TModel> GetAsync(string membershipId, Expression <Func <TDto, bool> > expression)
        {
            var membership = await this.membershipService.GetAsync(membershipId);

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

            var entities = await this.repository.FindAsync(expression);

            var entity = entities.Items.FirstOrDefault(x => x.MembershipId == membershipId);

            return(Mapper.Current.Map <TDto, TModel>(entity));
        }
Exemplo n.º 28
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");
            }
        }
Exemplo n.º 29
0
        public async Task <IActionResult> WhoAmI()
        {
            string token = this.GetTokenFromHeader(out string tokenTypeStr);

            if (string.IsNullOrEmpty(token))
            {
                return(this.AuthorizationHeaderMissing());
            }

            if (!TokenTypeExtensions.TryParseTokenType(tokenTypeStr, out var tokenType))
            {
                throw ErtisAuthException.UnsupportedTokenType();
            }

            switch (tokenType)
            {
            case SupportedTokenTypes.None:
                throw ErtisAuthException.UnsupportedTokenType();

            case SupportedTokenTypes.Basic:
                var application = await this.tokenService.WhoAmIAsync(new BasicToken(token));

                if (application != null)
                {
                    return(this.Ok(application));
                }
                else
                {
                    return(this.InvalidToken());
                }

            case SupportedTokenTypes.Bearer:
                var user = await this.tokenService.WhoAmIAsync(BearerToken.CreateTemp(token));

                if (user != null)
                {
                    return(this.Ok(user));
                }
                else
                {
                    return(this.InvalidToken());
                }

            default:
                throw ErtisAuthException.UnsupportedTokenType();
            }
        }
Exemplo n.º 30
0
        private void VerifyRolePermissions(Role role, string subjectId, HttpContext httpContext)
        {
            var endpoint = httpContext.GetEndpoint();

            // Subject
            var rbacSubjectSegment = new RbacSegment(subjectId);

            // Resource
            var rbacResourceSegment = RbacSegment.All;
            var resourceMetadata    = endpoint?.Metadata?.FirstOrDefault(x => x.GetType() == typeof(RbacResourceAttribute));

            if (resourceMetadata is RbacResourceAttribute rbacResourceAttribute)
            {
                rbacResourceSegment = rbacResourceAttribute.ResourceSegment;
            }

            // Action
            var rbacActionSegment = RbacSegment.All;
            var actionMetadata    = endpoint?.Metadata?.FirstOrDefault(x => x.GetType() == typeof(RbacActionAttribute));

            if (actionMetadata is RbacActionAttribute rbacActionAttribute)
            {
                rbacActionSegment = rbacActionAttribute.ActionSegment;
            }

            // Object
            var rbacObjectSegment = RbacSegment.All;
            var objectMetadata    = endpoint?.Metadata?.FirstOrDefault(x => x.GetType() == typeof(RbacObjectAttribute));
            var routeData         = httpContext.GetRouteData();

            if (routeData?.Values != null && objectMetadata is RbacObjectAttribute rbacObjectAttribute)
            {
                if (routeData.Values.ContainsKey(rbacObjectAttribute.RouteParameterName))
                {
                    var rbacObject = routeData.Values[rbacObjectAttribute.RouteParameterName];
                    rbacObjectSegment = new RbacSegment(rbacObject.ToString());
                }
            }

            var rbac = new Rbac(rbacSubjectSegment, rbacResourceSegment, rbacActionSegment, rbacObjectSegment);

            if (!role.HasPermission(rbac))
            {
                throw ErtisAuthException.AccessDenied("Your authorization role is unauthorized for this action");
            }
        }