UserManagement #8
7
CouchLog/Components/AdminSettings/Pages/Index.razor
Normal file
7
CouchLog/Components/AdminSettings/Pages/Index.razor
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@page "/AdminSettings"
|
||||||
|
|
||||||
|
<h3>Index</h3>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
}
|
||||||
177
CouchLog/Components/AdminSettings/Pages/UserManagement.razor
Normal file
177
CouchLog/Components/AdminSettings/Pages/UserManagement.razor
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
@page "/AdminSettings/UserManagement"
|
||||||
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
|
@using CouchLog.Data
|
||||||
|
@using Microsoft.AspNetCore.Identity
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using Microsoft.AspNetCore.Components.QuickGrid
|
||||||
|
|
||||||
|
@inject ApplicationDbContext CouchLogDB
|
||||||
|
@inject UserManager<ApplicationUser> UserManager
|
||||||
|
@inject RoleManager<IdentityRole> RoleManager
|
||||||
|
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
|
<h3 class="mb-0">UserManagement</h3>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-primary"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#exampleModal">
|
||||||
|
Add User
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<QuickGrid Items="@gridUsers.AsQueryable()">
|
||||||
|
<PropertyColumn Title="#" Property="@(u => u.Index)" />
|
||||||
|
<PropertyColumn Title="Username" Property="@(u => u.UserName)" />
|
||||||
|
<PropertyColumn Title="Role" Property="@(u => u.Role)" />
|
||||||
|
|
||||||
|
<TemplateColumn Title="">
|
||||||
|
@if(context.UserId != currentUserId)
|
||||||
|
{
|
||||||
|
<button class="btn btn-danger btn-sm" @onclick="() => DeleteUser(context)">Delete</button>
|
||||||
|
}
|
||||||
|
</TemplateColumn>
|
||||||
|
</QuickGrid>
|
||||||
|
</div>
|
||||||
|
<!-- #region UserCreate Modal -->
|
||||||
|
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true" style="color: black">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" style="color: black" id="exampleModalLabel">Create User</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<!-- 1. Username Input mit Binding und Bootstrap Klasse -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="newUsernameInput" class="form-label">Username:</label>
|
||||||
|
<input type="text" class="form-control" id="newUsernameInput" @bind="newUsername" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2. Select mit Binding -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Role:</label>
|
||||||
|
<select class="form-select" @bind="newUserRoleId">
|
||||||
|
<!-- WICHTIG: Eine leere Option als Standard, damit man weiß, ob etwas gewählt wurde -->
|
||||||
|
<option value="" selected disabled>Bitte Rolle wählen...</option>
|
||||||
|
|
||||||
|
@foreach (var role in roles)
|
||||||
|
{
|
||||||
|
<option value="@role.Id">@role.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary" @onclick="CreateUserAsync">Create User</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- #endregion -->
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
string newUsername = "";
|
||||||
|
string newUserRoleId = "";
|
||||||
|
List<UserGridItem> gridUsers = new();
|
||||||
|
List<IdentityRole> roles = new();
|
||||||
|
string? currentUserId;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
|
currentUserId = authState.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
|
||||||
|
var users = await CouchLogDB.Users.ToListAsync();
|
||||||
|
roles = await CouchLogDB.Roles.ToListAsync();
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
gridUsers.Clear();
|
||||||
|
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
var role = await UserManager.GetRolesAsync(user);
|
||||||
|
|
||||||
|
gridUsers.Add(new UserGridItem
|
||||||
|
{
|
||||||
|
Index = index++,
|
||||||
|
UserId = user.Id,
|
||||||
|
UserName = user.UserName!,
|
||||||
|
Role = role.FirstOrDefault() ?? "-"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserGridItem
|
||||||
|
{
|
||||||
|
public int Index { get; set; }
|
||||||
|
public string UserId { get; set; } = "";
|
||||||
|
public string UserName { get; set; } = "";
|
||||||
|
public string Role { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task DeleteUser(UserGridItem user)
|
||||||
|
{
|
||||||
|
if (user.UserId == currentUserId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var identityUser = await UserManager.FindByIdAsync(user.UserId);
|
||||||
|
|
||||||
|
if (identityUser is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var result = await UserManager.DeleteAsync(identityUser);
|
||||||
|
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
gridUsers.Remove(user);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Optional: Fehler anzeigen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CreateUserAsync()
|
||||||
|
{
|
||||||
|
// Validierung
|
||||||
|
if (string.IsNullOrWhiteSpace(newUsername) || string.IsNullOrWhiteSpace(newUserRoleId))
|
||||||
|
{
|
||||||
|
// Fehlermeldung anzeigen oder abbrechen
|
||||||
|
Console.WriteLine("Bitte Benutzername und Rolle angeben.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hier deine Logik zum Erstellen des Users
|
||||||
|
var roleIdToUse = newUserRoleId;
|
||||||
|
var usernameToUse = newUsername;
|
||||||
|
|
||||||
|
ApplicationUser newUser = new ApplicationUser
|
||||||
|
{
|
||||||
|
UserName = newUsername,
|
||||||
|
EmailConfirmed = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await UserManager.CreateAsync(newUser, "NewPassword123!");
|
||||||
|
|
||||||
|
IdentityRole roleName = roles.FirstOrDefault(r => r.Id == newUserRoleId);
|
||||||
|
|
||||||
|
if(result.Succeeded)
|
||||||
|
{
|
||||||
|
await UserManager.AddToRoleAsync(newUser, roleName.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal schließen oder Formular zurücksetzen
|
||||||
|
newUsername = "";
|
||||||
|
newUserRoleId = "";
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo(NavigationManager.Uri, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
CouchLog/Components/AdminSettings/Pages/_Imports.razor
Normal file
2
CouchLog/Components/AdminSettings/Pages/_Imports.razor
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@using CouchLog.Components.AdminSettings.Shared
|
||||||
|
@layout AdminSettingsLayout
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
@inherits LayoutComponentBase
|
||||||
|
@layout CouchLog.Components.Layout.MainLayout
|
||||||
|
|
||||||
|
<h1>Manage CouchLog</h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2></h2>
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<AdminSettingsNavMenu />
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9">
|
||||||
|
@Body
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@using Microsoft.AspNetCore.Identity
|
||||||
|
@using CouchLog.Data
|
||||||
|
|
||||||
|
@inject SignInManager<ApplicationUser> SignInManager
|
||||||
|
|
||||||
|
<ul class="nav nav-pills flex-column">
|
||||||
|
<li class="nav-item">
|
||||||
|
<NavLink class="nav-link" href="/AdminSettings/UserManagement" Match="NavLinkMatch.All">User Management</NavLink>
|
||||||
|
</li>
|
||||||
|
<!--
|
||||||
|
<li class="nav-item">
|
||||||
|
<NavLink class="nav-link" href=""></NavLink>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<NavLink class="nav-link" href=""></NavLink>
|
||||||
|
</li>
|
||||||
|
-->
|
||||||
|
</ul>
|
||||||
@@ -6,10 +6,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="top-row px-4">
|
|
||||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article class="content px-4">
|
<article class="content px-4">
|
||||||
@Body
|
@Body
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
@page "/AdminSettings"
|
|
||||||
|
|
||||||
@using Microsoft.AspNetCore.Authorization
|
|
||||||
|
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
<PageTitle>Admin Settings</PageTitle>
|
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
<PageTitle>GlobalList</PageTitle>
|
<PageTitle>GlobalList</PageTitle>
|
||||||
|
|
||||||
<div class="container-fluid mt-4">
|
<div class="container-fluid mt-4">
|
||||||
|
<!-- #region CreateEntity -->
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<h2>Global List</h2>
|
<h2>Global List</h2>
|
||||||
<button class="btn btn-info" type="button" @onclick="ToogleCollapseNewGlobalEntity">@(isCollapseNewGlobalEntityOpen ? "X" : "Add Entity")</button>
|
<button class="btn btn-info" type="button" @onclick="ToogleCollapseNewGlobalEntity">@(isCollapseNewGlobalEntityOpen ? "X" : "Add Entity")</button>
|
||||||
@@ -59,13 +60,17 @@
|
|||||||
</EditForm>
|
</EditForm>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- #endregion -->
|
||||||
|
|
||||||
|
<!-- #region Show Entitys -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach (var Entity in GlobalEntities)
|
@foreach (var Entity in GlobalEntities)
|
||||||
{
|
{
|
||||||
<div name="Enity-Container" class="col-12 col-md-6 col-lg-3 mb-4 Entity-Container">
|
<div name="Enity-Container" class="col-12 col-md-6 col-lg-3 mb-4 Entity-Container">
|
||||||
<div name="Entity-Container-Card" class="Entity-Container-Card">
|
<div name="Entity-Container-Card" class="Entity-Container-Card">
|
||||||
<div class="Entity-Container-Menu-Button">
|
|
||||||
<button type="button" class="Entity-Container-Menu-Button" data-bs-toogle="modal" data-bs-target="@Entity.Id">⋮</button>
|
<div class="Entity-Container-Menu-Button dropdown ms-1">
|
||||||
|
<button type="button" class="Entity-Container-Menu-Button btn menu-btn" data-bs-toggle="modal" data-bs-target="#modal-@Entity.Id">⋮</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="@Entity.Id" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
<div class="modal fade" id="@Entity.Id" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
@@ -103,8 +108,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="modal-@Entity.Id" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Optionen</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<button class="btn btn-danger" type="button" @onclick="() => DeleteEntity(Entity)">Delete Entity</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Schließen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- #endregion -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@@ -268,4 +291,24 @@
|
|||||||
GenreIds.Add(GenreId);
|
GenreIds.Add(GenreId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task DeleteEntity(GlobalEntity entity)
|
||||||
|
{
|
||||||
|
if(entity.PicturePath != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(Path.Combine("wwwroot", entity.PicturePath));
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CouchLogDB.GlobalEntities.Remove(entity);
|
||||||
|
|
||||||
|
await CouchLogDB.SaveChangesAsync();
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo(NavigationManager.Uri, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -58,21 +58,22 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.QuickGrid" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.Build" Version="18.0.2" />
|
<PackageReference Include="Microsoft.Build" Version="18.0.2" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="5.0.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="5.0.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.DotNet.Scaffolding.Shared" Version="9.0.0" />
|
<PackageReference Include="Microsoft.DotNet.Scaffolding.Shared" Version="10.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.1">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 18
|
||||||
VisualStudioVersion = 17.14.36511.14
|
VisualStudioVersion = 18.1.11304.174 d18.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouchLog", "CouchLog.csproj", "{4FBF15C3-5FC5-4605-9EBC-3F7DA1ADC47A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouchLog", "CouchLog.csproj", "{4FBF15C3-5FC5-4605-9EBC-3F7DA1ADC47A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 113 KiB |
Reference in New Issue
Block a user