open changes

This commit is contained in:
Arne Moerman
2024-12-15 19:08:25 +01:00
parent 586b3558ae
commit ab68df2184
145 changed files with 7428 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
@page "/BlogPost/Create"
<PageTitle>Create</PageTitle>
@*<AuthorizeView Roles="Admin">*@
<AuthorizeView Policy="@ProjectPolicies.BlogPostCreateClaimPolicy.Name">
<Authorized>
<h1>Create</h1>
<h4>BlogPost</h4>
<hr />
@if (blogPost == null)
{
<p><em>Loading...</em></p>
}
else
{
<div class="row">
<div class="col-md-4">
<EditForm Model="@blogPost" OnValidSubmit="@HandleValidSubmit" Context="createBlogPost">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label class="control-label">@nameof(BlogPostViewModel.Title)</label>
<InputText @bind-Value="blogPost.Title" class="form-control" />
<ValidationMessage For="@(() => blogPost.Title)" class="text-danger" />
</div>
<div class="form-group">
<label class="control-label">@nameof(BlogPostViewModel.Content)</label>
<InputText @bind-Value="blogPost.Content" class="form-control" />
<ValidationMessage For="@(() => blogPost.Content)" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</EditForm>
</div>
</div>
<div>
<a href="/BlogPost">Back to List</a>
</div>
}
</Authorized>
<NotAuthorized>
<p>Not Authorized</p>
</NotAuthorized>
</AuthorizeView>

View File

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Components;
using global::Wishlist.Models;
using global::Wishlist.Services;
namespace Wishlist.Pages.BlogPost
{
public partial class Create
{
private BlogPostViewModel? blogPost;
private async void HandleValidSubmit()
{
var model = Mapper.Map<BlogPostViewModel, Models.BlogPost>(blogPost);
bool result = await BlogPostService.AddBlogPostAsync(model);
if (result)
NavigationManager.NavigateTo("/BlogPost");
}
protected override void OnInitialized()
{
blogPost = new();
}
}
}

View File

@@ -0,0 +1,53 @@
@page "/BlogPost/Delete/{id:int}"
<PageTitle>Delete</PageTitle>
@*<AuthorizeView Roles="Admin">*@
<AuthorizeView Policy="@ProjectPolicies.BlogPostDeleteClaimPolicy.Name">
<Authorized>
<h1>Delete</h1>
<h3>Are you sure you want to delete this?</h3>
@if (blogPost == null)
{
<p><em>Loading...</em></p>
}
else
{
<div>
<h4>BlogPost</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@nameof(BlogPost.Id)
</dt>
<dd class="col-sm-10">
@blogPost.Id
</dd>
<dt class="col-sm-2">
@nameof(BlogPost.Title)
</dt>
<dd class="col-sm-10">
@blogPost.Title
</dd>
<dt class="col-sm-2">
@nameof(BlogPost.Content)
</dt>
<dd class="col-sm-10">
@blogPost.Content
</dd>
</dl>
</div>
<div>
<button class="btn btn-danger" @onclick="DeleteButtonClick">Delete</button> |
<a href="/BlogPost">Back to List</a>
</div>
}
</Authorized>
<NotAuthorized>
<p>Not Authorized</p>
</NotAuthorized>
</AuthorizeView>

View File

@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Components;
using global::Wishlist.Models;
using global::Wishlist.Services;
namespace Wishlist.Pages.BlogPost
{
public partial class Delete
{
[Parameter]
public int id { get; set; }
private BlogPostViewModel? blogPost;
protected override async Task OnInitializedAsync()
{
if (blogPost == null)
{
var result = await BlogPostService.GetbyId(id);
if (result != null)
blogPost = Mapper.Map<Models.BlogPost, BlogPostViewModel>(result);
}
}
private async void DeleteButtonClick()
{
bool result = await BlogPostService.DeletebyIdAsync(id);
if (result)
NavigationManager.NavigateTo("/BlogPost");
}
}
}

View File

@@ -0,0 +1,49 @@
@page "/BlogPost/Details/{id:int}"
<PageTitle>Details</PageTitle>
<AuthorizeView Policy="@ProjectPolicies.BlogPostReadClaimPolicy.Name">
<Authorized>
<h1>Details</h1>
@if (blogPost == null)
{
<p><em>Loading...</em></p>
}
else
{
<div>
<h4>BlogPost</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@nameof(BlogPost.Id)
</dt>
<dd class="col-sm-10">
@blogPost.Id
</dd>
<dt class="col-sm-2">
@nameof(BlogPost.Title)
</dt>
<dd class="col-sm-10">
@blogPost.Title
</dd>
<dt class="col-sm-2">
@nameof(BlogPost.Content)
</dt>
<dd class="col-sm-10">
@blogPost.Content
</dd>
</dl>
</div>
<div>
<a href="/BlogPost/Edit/@blogPost.Id">Edit</a> |
<a href="/BlogPost">Back to List</a>
</div>
}
</Authorized>
<NotAuthorized>
<p>Not Authorized</p>
</NotAuthorized>
</AuthorizeView>

View File

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Components;
using global::Wishlist.Models;
using global::Wishlist.Services;
namespace Wishlist.Pages.BlogPost
{
public partial class Details
{
[Parameter]
public int id { get; set; }
private BlogPostViewModel? blogPost;
protected override async Task OnInitializedAsync()
{
if (blogPost == null)
{
var result = await BlogPostService.GetbyId(id);
if (result != null)
blogPost = Mapper.Map<Models.BlogPost, BlogPostViewModel>(result);
}
}
}
}

View File

@@ -0,0 +1,56 @@
@page "/BlogPost/Edit/{id:int}"
<PageTitle>Edit</PageTitle>
@*<AuthorizeView Roles="Admin">*@
<AuthorizeView Policy="@ProjectPolicies.BlogPostUpdateClaimPolicy.Name">
<Authorized>
<h1>Edit</h1>
<h4>BlogPost</h4>
<hr />
@if (blogPost == null)
{
<p><em>Loading...</em></p>
}
else
{
<div class="row">
<div class="col-md-4">
<EditForm Model="@blogPost" OnValidSubmit="@HandleValidSubmit" Context="editBlogPost">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label class="control-label">@nameof(BlogPostViewModel.Title)</label>
<InputText @bind-Value="blogPost.Title" class="form-control" />
<ValidationMessage For="@(() => blogPost.Title)" class="text-danger" />
</div>
<div class="form-group">
<label class="control-label">@nameof(BlogPostViewModel.Content)</label>
<InputText @bind-Value="blogPost.Content" class="form-control" />
<ValidationMessage For="@(() => blogPost.Content)" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</EditForm>
</div>
</div>
<div>
<a href="/BlogPost">Back to List</a>
</div>
}
</Authorized>
<NotAuthorized>
<p>Not Authorized</p>
</NotAuthorized>
</AuthorizeView>

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Components;
using Wishlist.Models;
using Wishlist.Services;
namespace Wishlist.Pages.BlogPost
{
public partial class Edit
{
[Parameter]
public int id { get; set; }
private BlogPostViewModel? blogPost;
protected override async Task OnInitializedAsync()
{
if (blogPost == null)
{
var result = await BlogPostService.GetbyId(id);
if (result != null)
blogPost = Mapper.Map<Models.BlogPost, BlogPostViewModel>(result);
}
}
private async void HandleValidSubmit()
{
var model = Mapper.Map<BlogPostViewModel, Models.BlogPost>(blogPost);
bool result = await BlogPostService.UpdateBlogPostAsync(id, model);
if (result)
NavigationManager.NavigateTo("/BlogPost");
}
}
}

View File

@@ -0,0 +1,53 @@
@page "/BlogPost"
<PageTitle>Index</PageTitle>
<AuthorizeView Policy="@ProjectPolicies.BlogPostReadClaimPolicy.Name">
<Authorized>
<h1>Index</h1>
<p>
<a href="/BlogPost/Create">Create New</a>
</p>
@if (blogPosts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>@nameof(BlogPostViewModel.Id)</th>
<th>@nameof(BlogPostViewModel.Title)</th>
<th>@nameof(BlogPostViewModel.Content)</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var blogpost in blogPosts)
{
<tr>
<td>@blogpost.Id</td>
<td>@blogpost.Title</td>
<td>@blogpost.Content</td>
<td>
<a href="/BlogPost/Details/@blogpost.Id">Details</a> |
<AuthorizeView Policy="@nameof(ProjectPolicies.BlogPostUpdateClaimPolicy)" Context="editLink">
<a href="/BlogPost/Edit/@blogpost.Id">Edit</a> |
</AuthorizeView>
<AuthorizeView Policy="@nameof(ProjectPolicies.BlogPostDeleteClaimPolicy)" Context="deleteLink">
<a href="/BlogPost/Delete/@blogpost.Id">Delete</a>
</AuthorizeView>
</td>
</tr>
}
</tbody>
</table>
}
</Authorized>
<NotAuthorized>
<p>Not Authorized</p>
</NotAuthorized>
</AuthorizeView>

View File

@@ -0,0 +1,20 @@
using global::Wishlist.Models;
using global::Wishlist.Services;
namespace Wishlist.Pages.BlogPost
{
public partial class Index
{
private IEnumerable<BlogPostViewModel>? blogPosts;
protected override async Task OnInitializedAsync()
{
if (blogPosts == null)
{
var result = await BlogPostService.GetAllAsync();
blogPosts = Mapper.Map<IEnumerable<Models.BlogPost>, IEnumerable<BlogPostViewModel>>(result);
}
}
}
}

View File

@@ -0,0 +1,8 @@
@using AutoMapper;
@using global::Wishlist.Data;
@using global::Wishlist.Models;
@using global::Wishlist.Services;
@inject IMapper Mapper;
@inject NavigationManager NavigationManager;
@inject BlogPostService BlogPostService;

View File

@@ -0,0 +1,42 @@
@page
@model Wishlist.Pages.ErrorModel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Error</title>
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/site.css" rel="stylesheet" asp-append-version="true" />
</head>
<body>
<div class="main">
<div class="content px-4">
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics;
namespace Wishlist.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _logger;
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}

View File

@@ -0,0 +1,67 @@
@page "/"
@using global::Wishlist.Data;
@using global::Wishlist.Models;
@using global::Wishlist.Services;
@using global::Wishlist.ViewModels;
@using System.Security.Claims;
@inject UserService UserService
@inject RoleService RoleService
@inject AuthenticationStateProvider AuthenticationStateProvider
<PageTitle>Index</PageTitle>
Welcome to your new app.
@if (roles != null)
{
<p>
<b>Roles and Claims:</b> <br />
@foreach (var role in roles)
{
<b>@("Role: ")</b>
@($"{role.Name} ")
<b>@("Claims: ")</b>
@($"{string.Join(",", role.RoleClaims.Select(x => $"({@x.ClaimType} - {x.ClaimValue})"))}")
<br />
}
<b>Default Users:</b> <br />
<b>User:</b> admin@admin.com <b>Pass:</b>123456<br />
<b>User:</b> user@user.com <b>Pass:</b>123456<br />
</p>
}
<AuthorizeView>
<Authorized>
@if (appUser != null && appUser.Value.userVM != null)
{
<p>
<b>(@appUser.Value.userVM.Email) User Roles and Claims:</b><br />
<b>User Role:</b> @string.Join(",", appUser.Value.userVM.RoleNames)
<b>User Claims:</b> @string.Join(",", appUser.Value.userVM.Claims.Select(x => $"({x.Type}-{x.Value})"))
</p>
}
</Authorized>
</AuthorizeView>
@code {
private ApplicationRole[]? roles;
private (ApplicationUser? user, ApplicationUserViewModel? userVM)? appUser = null;
private Dictionary<string, List<(string Type, string Value)>>? userRoleswithClaims = null;
protected override async Task OnInitializedAsync()
{
roles = (await RoleService.GetAllRoleswithClaimsAsync()).ToArray();
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
if (authState.User is null || authState.User.Identity is null || authState.User.Identity.Name is null) return;
appUser = await UserService.GetUserbyUserNameAsync(authState.User.Identity.Name);
}
}

View File

@@ -0,0 +1,94 @@
@using Microsoft.AspNetCore.Hosting
@using Microsoft.AspNetCore.Mvc.ViewEngines
@inject IWebHostEnvironment Environment
@inject ICompositeViewEngine Engine
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Wishlist</title>
<environment include="Development">
<link rel="stylesheet" href="~/Identity/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/Identity/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"
integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"
asp-fallback-href="~/Identity/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/Identity/css/site.css" asp-append-version="true" />
</environment>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" href="~/">Wishlist</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
@{
var result = Engine.FindView(ViewContext, "_LoginPartial", isMainPage: false);
}
@if (result.Success)
{
await Html.RenderPartialAsync("_LoginPartial");
}
else
{
throw new InvalidOperationException("The default Identity UI layout requires a partial view '_LoginPartial' " +
"usually located at '/Pages/_LoginPartial' or at '/Views/Shared/_LoginPartial' to work. Based on your configuration " +
$"we have looked at it in the following locations: {System.Environment.NewLine}{string.Join(System.Environment.NewLine, result.SearchedLocations)}.");
}
</div>
</div>
</nav>
</header>
<div class="container">
<partial name="_CookieConsentPartial" optional />
<main role="main" class="pb-1">
@RenderBody()
</main>
</div>
<footer class="footer border-top pl-3 text-muted">
<div class="container">
&copy; 2023 - Wishlist
@{
var foundPrivacy = Url.Page("/Privacy", new { area = "" });
}
@if (foundPrivacy != null)
{
<a asp-area="" asp-page="/Privacy">Privacy</a>
}
</div>
</footer>
<environment include="Development">
<script src="~/Identity/lib/jquery/dist/jquery.js"></script>
<script src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/Identity/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
asp-fallback-src="~/Identity/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
asp-fallback-src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj">
</script>
<script src="~/Identity/js/site.js" asp-append-version="true"></script>
</environment>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@@ -0,0 +1,28 @@
@using Wishlist.Models;
@using Microsoft.AspNetCore.Identity
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
</li>
<li class="nav-item">
<form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/Index", new { area = "" })">
<button id="logout" type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" id="register" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" id="login" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>

View File

@@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-R3vNCHsZ+A2Lo3d5A6XNP7fdQkeswQWTIPfiYwSpEP3YV079R+93YzTeZRah7f/F">
</script>
</environment>

View File

@@ -0,0 +1,5 @@
<h3>Create</h3>
@code {
}

View File

@@ -0,0 +1,5 @@
<h3>Delete</h3>
@code {
}

View File

@@ -0,0 +1,5 @@
<h3>Detail</h3>
@code {
}

View File

@@ -0,0 +1,5 @@
<h3>Edit</h3>
@code {
}

View File

@@ -0,0 +1,5 @@
<h3>Index</h3>
@code {
}

View File

@@ -0,0 +1,8 @@
@page "/"
@namespace Wishlist.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />

View File

@@ -0,0 +1,32 @@
@using Microsoft.AspNetCore.Components.Web
@namespace Wishlist.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="Wishlist.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
</body>
</html>

View File

@@ -0,0 +1,6 @@
@using Microsoft.AspNetCore.Identity
@using global::Wishlist.Areas.Identity
Wishlist.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers