Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@
Title="@Localizer[nameof(AppStrings.DeleteRole)]"
Message="@Localizer.GetString(nameof(AppStrings.AreYouSureWannaDelete), selectedRoleItem?.Text ?? "")" />

<BitDialog OnOk="WrapHandled(RemoveRoleFromAllUsers)"
<BitDialog OnOk="WrapHandled(RemoveAllUsersFromRole)"
@bind-IsOpen="isRemoveRoleFromAllUsersDialogOpen"
OkText="@Localizer[nameof(AppStrings.Yes)]"
CancelText="@Localizer[nameof(AppStrings.No)]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,13 @@ private void SearchUsers()
}
}

private async Task RemoveRoleFromAllUsers()
private async Task RemoveAllUsersFromRole()
{
if (selectedRoleItem is null) return;

if (await AuthManager.TryEnterElevatedAccessMode(CurrentCancellationToken) is false) return;

await roleManagementController.RemoveRoleFromAllUsers(Guid.Parse(selectedRoleItem.Key!), CurrentCancellationToken);
await roleManagementController.RemoveAllUsersFromRole(Guid.Parse(selectedRoleItem.Key!), CurrentCancellationToken);

selectedRoleUsers.Clear();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,19 +374,26 @@ await identityController

private void CleanModel()
{
if (internalSignInPanelType is SignInPanelType.OtpOnly)
{
model.Password = null;
validatorRef?.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.Password)));
}
else if (internalSignInPanelType is SignInPanelType.PasswordOnly && isOtpSent is false)
{
model.Otp = null;
validatorRef?.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.Otp)));
}

if (currentTab is SignInPanelTab.Email)
{
model.PhoneNumber = null;
if (validatorRef is null) return;

validatorRef.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.PhoneNumber)));
validatorRef?.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.PhoneNumber)));
}
else
{
model.Email = null;
if (validatorRef is null) return;

validatorRef.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.Email)));
validatorRef?.EditContext.NotifyFieldChanged(validatorRef.EditContext.Field(nameof(SignInRequestDto.Email)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.5" />
<PackageVersion Include="EmbedIO" Version="3.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.5" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<PackageReference Condition=" '$(appInsights)' == 'true' OR '$(appInsights)' == '' " Include="Microsoft.ApplicationInsights.AspNetCore" />
<PackageReference Include="Humanizer" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" />
<PackageReference Include="NWebsec.AspNetCore.Middleware" />
<PackageReference Include="QRCoder" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ public async Task<RoleDto> Update(RoleDto roleDto, CancellationToken cancellatio
{
var role = await GetRoleByIdAsync(roleDto.Id, cancellationToken);

if (AppRoles.IsBuiltInRole(role.Name!))
throw new BadRequestException(Localizer[nameof(AppStrings.CanNotChangeBuiltInRole), role.Name!]);

if (role.ConcurrencyStamp != roleDto.ConcurrencyStamp)
throw new ConflictException();

Expand All @@ -95,6 +98,9 @@ public async Task Delete(Guid roleId, string concurrencyStamp, CancellationToken
{
var role = await GetRoleByIdAsync(roleId, cancellationToken);

if (AppRoles.IsBuiltInRole(role.Name!))
throw new BadRequestException(Localizer[nameof(AppStrings.CanNotChangeBuiltInRole), role.Name!]);

if (role.ConcurrencyStamp != concurrencyStamp)
throw new ConflictException();

Expand All @@ -109,6 +115,9 @@ public async Task AddClaims(Guid roleId, List<ClaimDto> claims, CancellationToke

var role = await GetRoleByIdAsync(roleId, cancellationToken);

if (role.Name == AppRoles.SuperAdmin)
throw new BadRequestException(Localizer[nameof(AppStrings.UserCantChangeSuperAdminRoleClaimsErrorMessage)]);

foreach (var claim in claims)
{
var result = await roleManager.AddClaimAsync(role, new(claim.ClaimType!, claim.ClaimValue!));
Expand All @@ -124,6 +133,9 @@ public async Task UpdateClaims(Guid roleId, List<ClaimDto> claims, CancellationT
{
var role = await GetRoleByIdAsync(roleId, cancellationToken);

if (role.Name == AppRoles.SuperAdmin)
throw new BadRequestException(Localizer[nameof(AppStrings.UserCantChangeSuperAdminRoleClaimsErrorMessage)]);

foreach (var claim in claims)
{
var result = await roleManager.RemoveClaimAsync(role, new(claim.ClaimType!, claim.ClaimValue!));
Expand All @@ -144,6 +156,9 @@ public async Task DeleteClaims(Guid roleId, List<ClaimDto> claims, CancellationT
{
var role = await GetRoleByIdAsync(roleId, cancellationToken);

if (role.Name == AppRoles.SuperAdmin)
throw new BadRequestException(Localizer[nameof(AppStrings.UserCantChangeSuperAdminRoleClaimsErrorMessage)]);

foreach (var claim in claims)
{
var result = await roleManager.RemoveClaimAsync(role, new(claim.ClaimType!, claim.ClaimValue!));
Expand Down Expand Up @@ -192,7 +207,7 @@ public async Task ToggleUserRole(UserRoleDto dto, CancellationToken cancellation

[HttpPost("{roleId}")]
[Authorize(Policy = AuthPolicies.ELEVATED_ACCESS)]
public async Task RemoveRoleFromAllUsers(Guid roleId, CancellationToken cancellationToken)
public async Task RemoveAllUsersFromRole(Guid roleId, CancellationToken cancellationToken)
{
var role = await GetRoleByIdAsync(roleId, cancellationToken);

Expand Down Expand Up @@ -230,9 +245,6 @@ private async Task<Role> GetRoleByIdAsync(Guid id, CancellationToken cancellatio
var role = await roleManager.Roles.FirstOrDefaultAsync(r => r.Id == id, cancellationToken)
?? throw new ResourceNotFoundException();

if (role.Name == AppRoles.SuperAdmin)
throw new BadRequestException(Localizer[nameof(AppStrings.UserCantChangeSuperAdminRoleErrorMessage)]);

return role;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
//#endif
using Hangfire.EntityFrameworkCore;
using Boilerplate.Server.Api.Models.Attachments;
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;

namespace Boilerplate.Server.Api.Data;

public partial class AppDbContext(DbContextOptions<AppDbContext> options)
: IdentityDbContext<User, Role, Guid, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>(options)
: IdentityDbContext<User, Role, Guid, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>(options), IDataProtectionKeyContext
{
public DbSet<UserSession> UserSessions { get; set; } = default!;

Expand All @@ -44,6 +45,8 @@ public partial class AppDbContext(DbContextOptions<AppDbContext> options)

public DbSet<Attachment> Attachments { get; set; } = default!;

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = default!;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Net.Http.Headers;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.ResponseCompression;
using Twilio;
using Ganss.Xss;
Expand Down Expand Up @@ -275,6 +276,9 @@ void AddDbContext(DbContextOptionsBuilder options)

AddSwaggerGen(builder);

services.AddDataProtection()
.PersistKeysToDbContext<AppDbContext>(); // It's advised to secure database-stored keys with a certificate by invoking ProtectKeysWithCertificate.

AddIdentity(builder);

var emailSettings = appSettings.Email ?? throw new InvalidOperationException("Email settings are required.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public interface IRoleManagementController : IAppController
Task ToggleUserRole(UserRoleDto dto, CancellationToken cancellationToken);

[HttpPost("{roleId}")]
Task RemoveRoleFromAllUsers(Guid roleId, CancellationToken cancellationToken);
Task RemoveAllUsersFromRole(Guid roleId, CancellationToken cancellationToken);

//#if (notification == true || signalR == true)
[HttpPost]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1292,11 +1292,14 @@
<data name="UserCantRemoveItselfErrorMessage" xml:space="preserve">
<value>شما نمیتوانید کاربر خود را حذف کنید</value>
</data>
<data name="UserCantUnassignAllSuperAdminsErrorMessage" xml:space="preserve">
<data name="UserCantUnassignAllSuperAdminsErrorMessage" xml:space="preserve">
<value>شما نمیتوانید گروه کاربری SuperAdmin از این کاربر بگیرید</value>
</data>
<data name="UserCantChangeSuperAdminRoleErrorMessage" xml:space="preserve">
<value>شما نمیتوانید تغییری در گروه کاربری SuperAdmin ایجاد کنید</value>
<data name="UserCantChangeSuperAdminRoleClaimsErrorMessage" xml:space="preserve">
<value>دسترسی‌های گروه کاربری SuperAdmin قابل ویرایش نیست</value>
</data>
<data name="CanNotChangeBuiltInRole" xml:space="preserve">
<value>شما نمیتوانید تغییری در گروه کاربری {0} ایجاد کنید</value>
</data>
<data name="UserCantRemoveSuperAdminErrorMessage" xml:space="preserve">
<value>شما نمیتوانید این کاربر SuperAdmin را حذف کنید</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1296,10 +1296,13 @@ After reaching {0}, extra sign-ins will have reduced functions.</value>
<value>Are you sure you want to revoke all sessions of {0}?</value>
</data>
<data name="UserCantUnassignAllSuperAdminsErrorMessage" xml:space="preserve">
<value>You can't remove the SuperAdmin role from this user</value>
<value>You can't remove this user from the SuperAdmin user group.</value>
</data>
<data name="UserCantChangeSuperAdminRoleErrorMessage" xml:space="preserve">
<value>You can't change the SuperAdmin role</value>
<data name="UserCantChangeSuperAdminRoleClaimsErrorMessage" xml:space="preserve">
<value>Super admin permissions may not be modified.</value>
</data>
<data name="CanNotChangeBuiltInRole" xml:space="preserve">
<value>User group {0} can't be modified.</value>
</data>
<data name="UserCantRemoveItselfErrorMessage" xml:space="preserve">
<value>You can't remove your own user</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ public class AppRoles


public const string Demo = "demo";

public static bool IsBuiltInRole(string name)
{
return name is SuperAdmin or Demo;
}
}
Loading