private async Task <List <RoleListData> > GetRoleAssignments(string userId, string groupId) { IBaseSpecification <GroupUserEntity, RoleListData> getGroupRoleSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => x.UserId == userId) .Where(x => x.GroupId == groupId) .Select(x => new RoleListData( x.Role.Id, x.Role.Name)) .Build(); RoleListData role = await _groupUserDAO.SingleOrDefault(getGroupRoleSpecification); if (role == null) { _logger.LogInformation($"User has no groupRole. UserId {userId}, GroupId {groupId}"); return(new List <RoleListData>()); } IBaseSpecification <RoleAssignmentEntity, RoleListData> getRoleAssigmentsSpecification = SpecificationBuilder .Create <RoleAssignmentEntity>() .Where(x => x.RoleId == role.Id) .Select(x => new RoleListData( x.CanAssigneRole.Id, x.CanAssigneRole.Name)) .Build(); List <RoleListData> canAssigneRoles = await _roleAssignmentDAO.Get(getRoleAssigmentsSpecification); if (!canAssigneRoles.Any(x => x.Id == role.Id)) { canAssigneRoles.Add(role); } return(canAssigneRoles); }
public async Task <Result <AuditDetailsModel> > Get(long id) { string userId = _httpContextAccessor.HttpContext.User.GetUserId(); IBaseSpecification <AuditEntity, AuditDetailsModel> selectSpecification = SpecificationBuilder .Create <AuditEntity>() .Where(x => x.Id == id) .WithUser(userId) .Select(x => new AuditDetailsModel( x.Id, x.ActionType.GetDescription(), x.Created.ToString("o"), x.ResourceName, x.ObjectMetadata)) .Build(); AuditDetailsModel auditDetailsModal = await _auditDAO.SingleOrDefault(selectSpecification); if (auditDetailsModal == null) { _logger.LogError($"No audit. AuditId {id}, UserId {userId}"); return(Result.Fail <AuditDetailsModel>("no_audit", "No Audit")); } return(Result.Ok(auditDetailsModal)); }
public async Task <Result> RemoveAsync(string id) { IBaseSpecification <GroupEntity, GroupEntity> specification = SpecificationBuilder .Create <GroupEntity>() .Where(x => x.Id == id) .Include(x => x.Invites) .Include(x => x.Users) .Build(); Result <GroupEntity> getGroupResult = await _groupStore.SingleOrDefault(specification); if (getGroupResult.Failure) { return(Result.Fail(getGroupResult)); } _logger.LogInformation($"Removing group. GroupId {id}"); GroupEntity groupEntity = getGroupResult.Value; string guid = Guid.NewGuid().ToString(); groupEntity.Name = $"deleted_group_{guid}"; bool updateResult = await _groupDAO.Update(groupEntity); if (!updateResult) { _logger.LogError($"Failed to update group for deleting. GroupId {id}"); return(Result.Fail(FAILED_TO_UPDATE_USER)); } if (groupEntity.Invites.Any()) { _logger.LogInformation($"Removing group invites. GroupId {groupEntity.Id}"); bool removeGroupInvitesResult = await _inviteDAO.RemoveRange(groupEntity.Invites); if (!removeGroupInvitesResult) { _logger.LogError($"Failed to remove group invites. GroupId {groupEntity.Id}"); } } if (groupEntity.Users.Any()) { _logger.LogInformation($"Removing group users. GroupId {groupEntity.Id}"); bool removeGroupUsersResult = await _groupUserDAO.RemoveRange(groupEntity.Users); if (!removeGroupUsersResult) { _logger.LogError($"Failed to remove group users. GroupId {groupEntity.Id}"); } } bool removeResult = await _groupDAO.Remove(groupEntity); if (!removeResult) { _logger.LogError($"Failed to remove Group. GroupId {id}"); return(Result.Fail("failed_to_remove_group", "Failed to remove group")); } return(Result.Ok()); }
private async Task <Result> AddAdminRole(string userId, string groupId) { IBaseSpecification <RoleEntity, RoleEntity> getGroupAdminRoleSpecification = SpecificationBuilder .Create <RoleEntity>() .Where(x => x.Type == Data.Enums.Entity.RoleTypes.Group) .WithName(IdentityUIRoles.GROUP_ADMIN) .Build(); RoleEntity role = await _roleDAO.SingleOrDefault(getGroupAdminRoleSpecification); if (role == null) { _logger.LogError($"GroupAdmin role not found. RoleName {IdentityUIRoles.GROUP_ADMIN}"); return(Result.Fail(ROLE_NOT_FOUND)); } Result result = await _groupUserService.AddUserToGroupWithValidation(userId, groupId, role.Id); if (result.Failure) { return(Result.Fail(result)); } return(Result.Ok()); }
public static OperationOutcome ValidateEntry(ResourceEntry entry) { OperationOutcome result = new OperationOutcome(); result.Issue = new List<OperationOutcome.OperationOutcomeIssueComponent>(); ICollection<ValidationResult> vresults = new List<ValidationResult>(); // Phase 1, validate against low-level rules built into the FHIR datatypes // todo: The API no longer seems to have the FhirValidator class. /* (!FhirValidator.TryValidate(entry.Resource, vresults, recurse: true)) { foreach (var vresult in vresults) result.Issue.Add(createValidationResult("[.NET validation] " + vresult.ErrorMessage, vresult.MemberNames)); } */ // Phase 2, validate against the XML schema var xml = FhirSerializer.SerializeResourceToXml(entry.Resource); var doc = XDocument.Parse(xml); doc.Validate(SchemaCollection.ValidationSchemaSet, (source, args) => result.Issue.Add( createValidationResult("[XSD validation] " + args.Message,null) )); // Phase 3, validate against a profile, if present var profileTags = entry.GetAssertedProfiles(); if (profileTags.Count() == 0) { // If there's no profile specified, at least compare it to the "base" profile string baseProfile = CoreZipArtifactSource.CORE_SPEC_PROFILE_URI_PREFIX + entry.Resource.GetCollectionName(); profileTags = new Uri[] { new Uri(baseProfile, UriKind.Absolute) }; } var artifactSource = ArtifactResolver.CreateOffline(); var specProvider = new SpecificationProvider(artifactSource); foreach (var profileTag in profileTags) { var specBuilder = new SpecificationBuilder(specProvider); specBuilder.Add(StructureFactory.PrimitiveTypes()); specBuilder.Add(StructureFactory.MetaTypes()); specBuilder.Add(StructureFactory.NonFhirNamespaces()); specBuilder.Add(profileTag.ToString()); specBuilder.Expand(); string path = Directory.GetCurrentDirectory(); var spec = specBuilder.ToSpecification(); var nav = doc.CreateNavigator(); nav.MoveToFirstChild(); Report report = spec.Validate(nav); var errors = report.Errors; foreach (var error in errors) { result.Issue.Add(createValidationResult("[Profile validator] " + error.Message, null)); } } if(result.Issue.Count == 0) return null; else return result; }
public async Task <Result <DataTableResult <GroupUserTableModel> > > Get(string groupId, DataTableRequest request) { ValidationResult validationResult = _dataTableValidator.Validate(request); if (!validationResult.IsValid) { _logger.LogWarning($"Invalid DataTableRequest model"); return(Result.Fail <DataTableResult <GroupUserTableModel> >(validationResult.ToResultError())); } ISelectSpecificationBuilder <GroupUserEntity, GroupUserTableModel> specificationBuilder = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => x.GroupId == groupId) .SearchByUsernameEmailId(request.Search) .OrderByDessending(x => x._CreatedDate) .Select(x => new GroupUserTableModel( x.Id, x.UserId, x.User.UserName, x.User.Email, x.RoleId, x.Role.Name)); IBaseSpecification <GroupUserEntity, GroupUserTableModel> countSpecification = specificationBuilder.Build(); IBaseSpecification <GroupUserEntity, GroupUserTableModel> dataSpecification = specificationBuilder .Paginate(request.Start, request.Length) .Build(); int count = await _groupUserDAO.Count(countSpecification); List <GroupUserTableModel> groupUsers = await _groupUserDAO.Get(dataSpecification); DataTableResult <GroupUserTableModel> dataTableResult = new DataTableResult <GroupUserTableModel>( draw: request.Draw, recordsTotal: count, recordsFiltered: count, data: groupUsers); return(Result.Ok(dataTableResult)); }
public void Should_ThrowException_When_Member_And_NullMemberSelector() { var builder = new SpecificationBuilder <MemberClass>(); Assert.Throws <ArgumentNullException>(() => { builder.Member <string>(null); }); }
public Task <Result <GroupAdminSettingsDetailsModel> > Get(string groupId) { IBaseSpecification <GroupEntity, GroupAdminSettingsDetailsModel> specification = SpecificationBuilder .Create <GroupEntity>() .Where(x => x.Id == groupId) .Select(x => new GroupAdminSettingsDetailsModel( x.Name)) .Build(); return(_groupStore.SingleOrDefault(specification)); }
public Task <Result <GroupAdminUserDetailsModel> > Get(long groupUserId) { IBaseSpecification <GroupUserEntity, GroupAdminUserDetailsModel> specification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => x.Id == groupUserId) .Select(x => new GroupAdminUserDetailsModel( x.User.Id, x.Id, x.User.UserName, x.User.Email, x.User.FirstName, x.User.LastName, x.User.PhoneNumber, x.User.EmailConfirmed, x.User.PhoneNumberConfirmed, x.User.TwoFactorEnabled, x.User.Enabled, x.User.LockoutEnd.HasValue ? x.User.LockoutEnd.Value.ToString("o") : null)) .Build(); return(_groupUserStore.SingleOrDefault(specification)); }
public Scope(SpecificationBuilder self, string word) { this.self = self; this.word = word; }
public It(SpecificationBuilder self) { this.self = self; }
public async Task <Core.Models.Result.Result> UpdateProfileImage(string userId, UploadProfileImageRequest uploadProfileImageRequest) { if (uploadProfileImageRequest == null || uploadProfileImageRequest.File == null) { _logger.LogWarning($"No image. UserId {userId}"); return(Result.Fail(PROFILE_IMAGE_NOT_FOUND).ToOldResult()); } //TODO: changed how image format is validated string imageExtension = Path.GetExtension(uploadProfileImageRequest.File.FileName); if (!VALID_IMAGE_FORMATS.Contains(imageExtension.ToUpper())) { _logger.LogWarning($"Invalid image format. UserId {userId}, image extension {imageExtension}"); return(Result.Fail(INVALID_PROFILE_IMAGE_FORMAT, VALID_IMAGE_FORMATS).ToOldResult()); } if (uploadProfileImageRequest.File.Length > _identityUIOptions.MaxProfileImageSize) { _logger.LogWarning($"Image is to big. UserId {userId}, image size {uploadProfileImageRequest.File.Length}"); return(Result.Fail(PROFILE_IMAGE_TOO_BIG, _identityUIOptions.MaxProfileImageSize / 1024).ToOldResult()); } if (uploadProfileImageRequest.File.FileName.Length > 250) { _logger.LogWarning($"Image name is to long. Image name length {uploadProfileImageRequest.File.FileName.Length}"); return(Result.Fail(PROFILE_IMAGE_NAME_TOO_LONG, 250).ToOldResult()); } byte[] image; using (MemoryStream memoryStream = new MemoryStream()) { await uploadProfileImageRequest.File.CopyToAsync(memoryStream); image = memoryStream.ToArray(); } string blobCacheKey = string.Format(BLOBL_CACHE_KEY, userId); string urlCacheKey = string.Format(URL_CACHE_KEY, userId); _memoryCache.Remove(blobCacheKey); _memoryCache.Remove(urlCacheKey); IBaseSpecification <UserImageEntity, UserImageEntity> getUserImageSpecification = SpecificationBuilder .Create <UserImageEntity>() .Where(x => x.UserId == userId) .Build(); UserImageEntity userImage = await _userImageDAO.SingleOrDefault(getUserImageSpecification); if (userImage == null) { UserImageEntity newUserImage = new UserImageEntity( userId: userId, blobImage: image, fileName: uploadProfileImageRequest.File.FileName); bool addResult = await _userImageDAO.Add(newUserImage); if (!addResult) { _logger.LogError($"Failed to add user image. UserId {userId}"); return(Result.Fail(FAILED_TO_ADD_PROFILE_IMAGE).ToOldResult()); } return(Result.Ok().ToOldResult()); } userImage.BlobImage = image; userImage.FileName = uploadProfileImageRequest.File.FileName; bool updateResult = await _userImageDAO.Update(userImage); if (!updateResult) { _logger.LogError($"Failed to update user image. UserId {userId}"); return(Result.Fail(FAILED_TO_UPDATE_PROFILE_IMAGE).ToOldResult()); } return(Result.Ok().ToOldResult()); }
public async Task <Core.Models.Result.Result <FileData> > GetProfileImage(string userId) { string cacheKey = string.Format(BLOBL_CACHE_KEY, userId); if (_memoryCache.TryGetValue(cacheKey, out FileData image)) { return(Result.Ok(image).ToOldResult()); } IBaseSpecification <UserImageEntity, UserImageEntity> getUserImageSpecification = SpecificationBuilder .Create <UserImageEntity>() .Where(x => x.UserId == userId) .Build(); UserImageEntity userImage = await _userImageDAO.SingleOrDefault(getUserImageSpecification); if (userImage == null) { _logger.LogInformation($"No profile image. UserId {userId}"); Result <FileData> defaultImage = await _defaultProfileImageService.Get(); if (defaultImage.Failure) { return(Result.Fail <FileData>(defaultImage).ToOldResult()); } _memoryCache.Set(cacheKey, defaultImage.Value, IMAGE_IN_CACHE_TIME_SPAN); return(Result.Ok(defaultImage.Value).ToOldResult()); } FileData fileData = new FileData( fileName: userImage.FileName, file: userImage.BlobImage); _memoryCache.Set(cacheKey, fileData, IMAGE_IN_CACHE_TIME_SPAN); return(Result.Ok(fileData).ToOldResult()); }
public async Task <Core.Models.Result.Result <string> > GetProfileImageURL(string userId) { string cacheKey = string.Format(URL_CACHE_KEY, userId); if (_memoryCache.TryGetValue(cacheKey, out string imageUrl)) { return(Result.Ok <string>(imageUrl).ToOldResult()); } IBaseSpecification <UserImageEntity, UserImageEntity> getUserImageSpecification = SpecificationBuilder .Create <UserImageEntity>() .Where(x => x.UserId == userId) .Build(); UserImageEntity userImage = await _userImageDAO.SingleOrDefault(getUserImageSpecification); if (userImage == null) { _logger.LogError($"No profile image. UserId {userId}"); return(Result.Fail <string>(PROFILE_IMAGE_NOT_FOUND).ToOldResult()); } _memoryCache.Set(cacheKey, userImage.URL, IMAGE_IN_CACHE_TIME_SPAN); return(Result.Ok <string>(userImage.URL).ToOldResult()); }
public virtual async Task <Result> ValidateUser(string id) { IBaseSpecification <AppUserEntity, AppUserEntity> userExistsSpecification = SpecificationBuilder .Create <AppUserEntity>() .WithId(id) .Build(); bool userExist = await _userDAO.Exist(userExistsSpecification); if (!userExist) { _logger.LogError($"No user. UserId {id}"); return(Result.Fail(USER_NOT_FOUND)); } IBaseSpecification <GroupUserEntity, GroupUserEntity> userAlreadyInGroupSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => x.UserId == id) .Build(); bool userAlreadyInGroup = await _groupUserDAO.Exist(userAlreadyInGroupSpecification); if (userAlreadyInGroup) { _logger.LogError($"User is already in a group. UserId {id}"); return(Result.Fail(USER_IS_ALREADY_IN_GROUP)); } return(Result.Ok()); }
public async Task <Result <DataTableResult <GroupInviteTableModel> > > Get(string groupId, DataTableRequest dataTableRequest) { ValidationResult validationResult = _dataTableRequestValidator.Validate(dataTableRequest); if (!validationResult.IsValid) { _logger.LogWarning($"Invalid {nameof(DataTableRequest)} model"); return(Result.Fail <DataTableResult <GroupInviteTableModel> >(validationResult.ToResultError())); } ISelectSpecificationBuilder <InviteEntity, GroupInviteTableModel> specificationBuilder = SpecificationBuilder .Create <InviteEntity>() .Where(x => x.GroupId == groupId) .SearchByEmail(dataTableRequest.Search) .OrderByDessending(x => x._CreatedDate) .Select(x => new GroupInviteTableModel( x.Id, x.Email, x.GroupRole.Name, x.Status.GetDescription(), x.ExpiresAt.ToString("o"))); IBaseSpecification <InviteEntity, GroupInviteTableModel> countSpecification = specificationBuilder.Build(); IBaseSpecification <InviteEntity, GroupInviteTableModel> dataSpecification = specificationBuilder .Paginate(dataTableRequest.Start, dataTableRequest.Length) .Build(); int count = await _inviteDAO.Count(countSpecification); var data = await _inviteDAO.Get(dataSpecification); DataTableResult <GroupInviteTableModel> dataTableResult = new DataTableResult <GroupInviteTableModel>( draw: dataTableRequest.Draw, recordsTotal: count, recordsFiltered: count, data: data); return(Result.Ok(dataTableResult)); }
public static OperationOutcome ValidateEntry(ResourceEntry entry) { OperationOutcome result = new OperationOutcome(); result.Issue = new List <OperationOutcome.OperationOutcomeIssueComponent>(); ICollection <ValidationResult> vresults = new List <ValidationResult>(); // Phase 1, validate against low-level rules built into the FHIR datatypes // todo: The API no longer seems to have the FhirValidator class. /* * (!FhirValidator.TryValidate(entry.Resource, vresults, recurse: true)) * { * foreach (var vresult in vresults) * result.Issue.Add(createValidationResult("[.NET validation] " + vresult.ErrorMessage, vresult.MemberNames)); * } */ // Phase 2, validate against the XML schema var xml = FhirSerializer.SerializeResourceToXml(entry.Resource); var doc = XDocument.Parse(xml); doc.Validate(SchemaCollection.ValidationSchemaSet, (source, args) => result.Issue.Add(createValidationResult("[XSD validation] " + args.Message, null))); // Phase 3, validate against a profile, if present var profileTags = entry.GetAssertedProfiles(); if (profileTags.Count() == 0) { // If there's no profile specified, at least compare it to the "base" profile string baseProfile = CoreZipArtifactSource.CORE_SPEC_PROFILE_URI_PREFIX + entry.Resource.GetCollectionName(); profileTags = new Uri[] { new Uri(baseProfile, UriKind.Absolute) }; } var artifactSource = ArtifactResolver.CreateOffline(); var specProvider = new SpecificationProvider(artifactSource); foreach (var profileTag in profileTags) { var specBuilder = new SpecificationBuilder(specProvider); specBuilder.Add(StructureFactory.PrimitiveTypes()); specBuilder.Add(StructureFactory.MetaTypes()); specBuilder.Add(StructureFactory.NonFhirNamespaces()); specBuilder.Add(profileTag.ToString()); specBuilder.Expand(); string path = Directory.GetCurrentDirectory(); var spec = specBuilder.ToSpecification(); var nav = doc.CreateNavigator(); nav.MoveToFirstChild(); Report report = spec.Validate(nav); var errors = report.Errors; foreach (var error in errors) { result.Issue.Add(createValidationResult("[Profile validator] " + error.Message, null)); } } if (result.Issue.Count == 0) { return(null); } else { return(result); } }
public async Task <Core.Models.Result.Result> AcceptInvite(AcceptInviteRequest acceptInvite) { ValidationResult acceptInviteValidationResult = _acceptInviteValidator.Validate(acceptInvite); if (!acceptInviteValidationResult.IsValid) { _logger.LogWarning($"Invalid {typeof(AcceptInviteRequest).Name} model"); } IBaseSpecification <InviteEntity, InviteEntity> getInviteSpecification = SpecificationBuilder .Create <InviteEntity>() .Where(x => x.Token == acceptInvite.Code) .Where(x => x.Status == Data.Enums.Entity.InviteStatuses.Pending) .Build(); InviteEntity inviteEntity = await _inviteDAO.SingleOrDefault(getInviteSpecification); if (inviteEntity == null) { _logger.LogError($"No Invite. Token {acceptInvite.Code}"); return(Core.Models.Result.Result.Fail("no_invite", "No Invite")); } if (inviteEntity.ExpiresAt < DateTimeOffset.UtcNow) { _logger.LogError($"Invite has expired"); return(Core.Models.Result.Result.Fail("no_invite", "No Invite")); } if (inviteEntity.GroupId != null) { Result groupValidResult = await _groupUserService.ValidateGroup(inviteEntity.GroupId); if (groupValidResult.Failure) { return(Result.Fail(groupValidResult).ToOldResult()); } Result groupRoleValidResult = await _groupUserService.RoleIsValid(inviteEntity.GroupRoleId); if (groupRoleValidResult.Failure) { return(Result.Fail(groupRoleValidResult).ToOldResult()); } } acceptInvite.Email = inviteEntity.Email; Result <AppUserEntity> addUserResult = await AddUser(acceptInvite, sendConfirmationMail : false, emailConfirmed : true); if (addUserResult.Failure) { return(addUserResult.ToOldResult()); } AppUserEntity appUser = addUserResult.Value; inviteEntity.Update(Data.Enums.Entity.InviteStatuses.Accepted); bool updateInvite = await _inviteDAO.Update(inviteEntity); if (!updateInvite) { _logger.LogWarning($"Failed to update invite status. InnivteId {inviteEntity.Id}, UserId {appUser.Id}"); } if (inviteEntity.GroupId != null) { Result addToGroupResult = await _groupUserService.AddUserToGroupWithoutValidation(appUser.Id, inviteEntity.GroupId, inviteEntity.GroupRoleId); } if (inviteEntity.RoleId != null) { Result addToGlobalRole = await AddToGlobalRole(appUser, inviteEntity.RoleId); } return(Core.Models.Result.Result.Ok()); }
public async Task <Result <AuditAdminDetailsModel> > Get(long id) { IBaseSpecification <AuditEntity, AuditAdminDetailsModel> selectSpecification = SpecificationBuilder .Create <AuditEntity>() .Where(x => x.Id == id) .Select(x => new AuditAdminDetailsModel( x.Id, x.ActionType.GetDescription(), x.ObjectType, x.ObjectIdentifier, x.ObjectMetadata, x.SubjectType.GetDescription(), x.SubjectIdentifier, x.Host, x.RemoteIp, x.ResourceName, x.UserAgent, x.TraceIdentifier, x.AppVersion, x.Created.ToString("o"))) .Build(); AuditAdminDetailsModel auditDetailsModel = await _auditDAO.SingleOrDefault(selectSpecification); if (auditDetailsModel == null) { _logger.LogError($"No audit. AuditId {id}."); return(Result.Fail <AuditAdminDetailsModel>("no_audit", "No Audit")); } return(Result.Ok(auditDetailsModel)); }
public async Task <Result <GroupedStatisticsViewModel> > GetIndexViewModel(string groupId) { IBaseSpecification <GroupUserEntity, GroupUserEntity> getAllUsersSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Build(); int allUsers = await _groupUserStore.Count(getAllUsersSpecification); IBaseSpecification <GroupUserEntity, GroupUserEntity> getActiveUsersSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => x.User.Sessions.Any()) .Build(); int activeUsers = await _groupUserStore.Count(getActiveUsersSpecification); IBaseSpecification <GroupUserEntity, GroupUserEntity> getUnconfirmedUsersSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => !x.User.EmailConfirmed) .Build(); int unconfirmedUsers = await _groupUserStore.Count(getUnconfirmedUsersSpecification); IBaseSpecification <GroupUserEntity, GroupUserEntity> getDisabledUsersSpecification = SpecificationBuilder .Create <GroupUserEntity>() .Where(x => !x.User.Enabled) .Build(); int disabledUsers = await _groupUserStore.Count(getDisabledUsersSpecification); GroupedStatisticsViewModel viewModel = new GroupedStatisticsViewModel( groupId: groupId, usersCount: allUsers, activeUsersCount: activeUsers, unconfirmedUsersCount: unconfirmedUsers, disabledUsersCount: disabledUsers); return(Result.Ok(viewModel)); }
public void Should_AddCommand_ThrowException_When_NullCommand() { var builder = new SpecificationBuilder <MemberClass>(); Assert.Throws <ArgumentNullException>(() => { builder.AddCommand(null); }); }
public async Task <Result <DataTableResult <GroupAttributeTableModel> > > Get(string groupId, DataTableRequest dataTableRequest) { ValidationResult validationResult = _dataTableValidator.Validate(dataTableRequest); if (!validationResult.IsValid) { _logger.LogWarning($"Invalid {nameof(dataTableRequest)} model"); return(Result.Fail <DataTableResult <GroupAttributeTableModel> >(validationResult.ToResultError())); } ISelectSpecificationBuilder <GroupAttributeEntity, GroupAttributeTableModel> specificationBuilder = SpecificationBuilder .Create <GroupAttributeEntity>() .Where(x => x.GroupId == groupId) .SearchByKey(dataTableRequest.Search) .OrderByDessending(x => x._CreatedDate) .Select(x => new GroupAttributeTableModel( x.Id, x.Key, x.Value)); IBaseSpecification <GroupAttributeEntity, GroupAttributeTableModel> countSpecification = specificationBuilder.Build(); IBaseSpecification <GroupAttributeEntity, GroupAttributeTableModel> dataSpecification = specificationBuilder .Paginate(dataTableRequest.Start, dataTableRequest.Length) .Build(); int count = await _groupAttributeDAO.Count(countSpecification); List <GroupAttributeTableModel> data = await _groupAttributeDAO.Get(countSpecification); DataTableResult <GroupAttributeTableModel> dataTableResult = new DataTableResult <GroupAttributeTableModel>( draw: dataTableRequest.Draw, recordsTotal: count, recordsFiltered: count, data: data); return(Result.Ok(dataTableResult)); }