Login registration

This commit is contained in:
Paul Schneider
2024-11-23 14:23:47 +00:00
parent 009015ce3c
commit 0bcabbd4ff
22 changed files with 171 additions and 176 deletions

View File

@ -8,27 +8,28 @@ namespace Yavsc.ViewModels.Account
public class RegisterModel
{
[YaStringLength(2,Constants.MaxUserNameLength)]
[YaRegularExpression(Constants.UserNameRegExp)]
[StringLength(Constants.MaxUserNameLength)]
[RegularExpression(Constants.UserNameRegExp)]
[DataType(DataType.Text)]
[Display(Name = "UserName", Description = "User name")]
public string UserName { get; set; }
[YaRequired()]
[YaStringLength(2,102)]
[Required()]
[StringLength( maximumLength:102, MinimumLength = 5)]
// [EmailAddress]
[Display(Name = "Email")]
[Display(Name = "Email", Description = "E-Mail")]
public string Email { get; set; }
[YaStringLength(6,100)]
[StringLength(maximumLength:100, MinimumLength = 6,
ErrorMessage = "Le mot de passe doit contenir au moins 8 caratères")]
[DataType(DataType.Password)]
// ErrorMessage = "Les mots de passe doivent contenir au moins un caractère spécial, qui ne soit ni une lettre ni un chiffre.")]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Compare("Password")]
[Display(Name = "ConfirmPassword", Description ="Password Confirmation")]
public string ConfirmPassword { get; set; }
}
}

View File

@ -19,23 +19,15 @@ namespace Yavsc
public const string CompanyClaimType = "https://schemas.pschneider.fr/identity/claims/Company";
public const string UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9._-]*$";
public const string UserFileNamePatternRegExp = @"^([a-zA-Z0-9._-]*/)*[a-zA-Z0-9._-]+$";
public const string AuthorizePath = "/authorize";
public const string TokenPath = "/token";
public const string LoginPath = "/signin";
public const string LogoutPath = "/signout";
public const string SignalRPath = "/api/signalr";
public const string UserFilesPath = "/files";
public const string AvatarsPath = "/avatars";
public const string GitPath = "/sources";
public const string LiveUserPath = "live";
public const string ApplicationAuthenticationSheme = "ServerCookie";
public const string ExternalAuthenticationSheme = "ExternalCookie";
public const string DefaultFactor = "Default";
public const string MobileAppFactor = "Mobile Application";
public const string EMailFactor = "Email";
public const string SMSFactor = "SMS";
public const string AdminGroupName = "Administrator";
public const string PerformerGroupName = "Performer";

View File

@ -157,40 +157,7 @@ namespace Yavsc.Controllers
// only set explicit expiration here if user chooses "remember me".
// otherwise we rely upon expiration configured in cookie middleware.
AuthenticationProperties props = null;
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
{
props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration),
// Parameters =
};
};
// roles
var roles = _dbContext.UserRoles.Where(r=>r.UserId == user.Id).ToArray();
// issue authentication cookie with subject ID and username
List<Claim> additionalClaims = new List<Claim>();
foreach (var role in roles)
{
var idRole = await _roleManager.Roles.SingleOrDefaultAsync(i=>i.Id == role.RoleId);
if (idRole != null)
{
additionalClaims.Add(new Claim(ClaimTypes.Role, idRole.Name));
}
}
additionalClaims.Add(new Claim(ClaimTypes.Name, user.UserName));
var isUser = new IdentityServerUser(user.Id)
{
DisplayName = user.UserName,
AdditionalClaims = additionalClaims.ToArray()
};
await HttpContext.SignInAsync(isUser, props);
await HttpContext.SignInAsync(user, _roleManager, model.RememberLogin,_dbContext);
if (context != null)
{
@ -231,7 +198,6 @@ namespace Yavsc.Controllers
return View(vm);
}
/// <summary>
/// Show logout page
/// </summary>

View File

@ -392,13 +392,13 @@ namespace Yavsc.Controllers
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
public IActionResult ChangeUserName()
public IActionResult SetUserName()
{
return View(new ChangeUserNameViewModel() { NewUserName = User.Identity.Name });
return View(new SetUserNameViewModel() { UserName = User.Identity.Name });
}
[HttpPost]
public async Task<IActionResult> ChangeUserName(ChangeUserNameViewModel model)
public async Task<IActionResult> SetUserName(SetUserNameViewModel model)
{
if (!ModelState.IsValid)
{
@ -409,7 +409,7 @@ namespace Yavsc.Controllers
{
var oldUserName = user.UserName;
var result = await this._userManager.SetUserNameAsync(user, model.NewUserName);
var result = await this._userManager.SetUserNameAsync(user, model.UserName);
if (result.Succeeded)
{
@ -418,7 +418,7 @@ namespace Yavsc.Controllers
Path.Combine(_siteSettings.Blog,
oldUserName));
var newdir = Path.Combine(_siteSettings.Blog,
model.NewUserName);
model.UserName);
if (userdirinfo.Exists)
userdirinfo.MoveTo(newdir);
// Renames the Avatars files
@ -429,7 +429,7 @@ namespace Yavsc.Controllers
oldUserName+s));
if (fi.Exists)
fi.MoveTo(Path.Combine(_siteSettings.Avatars,
model.NewUserName+s));
model.UserName+s));
}
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(3, "User changed his user name successfully.");

View File

@ -152,10 +152,6 @@ namespace Yavsc.Controllers
{
return NotFound();
}
ViewBag.Files = Yavsc.Helpers.FileSystemHelpers.GetFileName(null);
// Yavsc.Helpers.GetUserFiles(User, null);
return View(estimate);
}

View File

@ -67,8 +67,7 @@ namespace Yavsc.Controllers
}
public async Task<IActionResult> About()
{
FileInfo fi = new FileInfo("wwwroot/version");
return View("About", fi.Exists ? _localizer["Version logicielle: "] + await fi.OpenText().ReadToEndAsync() : _localizer["Aucune information sur la version logicielle n'est publiée."]);
return View("About");
}
public IActionResult Privacy()
{

View File

@ -1,9 +1,6 @@
using System.Globalization;
using System.Security.Permissions;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using IdentityServer4;
using IdentityServer4.Test;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
@ -11,7 +8,6 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Localization;
@ -25,7 +21,6 @@ using Yavsc.Interface;
using Yavsc.Models;
using Yavsc.Models.Billing;
using Yavsc.Models.Haircut;
using Yavsc.Models.Market;
using Yavsc.Models.Workflow;
using Yavsc.Services;
using Yavsc.Settings;
@ -36,8 +31,7 @@ namespace Yavsc.Extensions;
internal static class HostingExtensions
{
public static IApplicationBuilder ConfigureFileServerApp(this IApplicationBuilder app,
public static IApplicationBuilder ConfigureFileServerApp(this IApplicationBuilder app,
bool enableDirectoryBrowsing = false)
{
@ -180,8 +174,9 @@ internal static class HostingExtensions
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services
.AddIdentityServer(options =>
services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
@ -194,7 +189,7 @@ internal static class HostingExtensions
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddDeveloperSigningCredential()
.AddAspNetIdentity<ApplicationUser>()
;
services.AddSession();

View File

@ -0,0 +1,54 @@
using System.Security.Claims;
using IdentityServer4;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Access;
namespace Yavsc.Extensions;
internal static class HttpContextExtensions
{
public static async Task SignInAsync(this HttpContext context,
ApplicationUser user, RoleManager<IdentityRole> roleManager,
bool rememberMe,
ApplicationDbContext applicationDbContext)
{
AuthenticationProperties props = null;
if (AccountOptions.AllowRememberLogin && rememberMe)
{
props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration),
// Parameters =
};
};
// roles
var roles = applicationDbContext.UserRoles.Where(r => r.UserId == user.Id).ToArray();
// issue authentication cookie with subject ID and username
List<Claim> additionalClaims = new List<Claim>();
foreach (var role in roles)
{
var idRole = await roleManager.Roles.SingleOrDefaultAsync(i => i.Id == role.RoleId);
if (idRole != null)
{
additionalClaims.Add(new Claim(ClaimTypes.Role, idRole.Name));
}
}
additionalClaims.Add(new Claim(ClaimTypes.Name, user.UserName));
var isUser = new IdentityServerUser(user.Id)
{
DisplayName = user.UserName,
AdditionalClaims = additionalClaims.ToArray()
};
await context.SignInAsync(isUser, props);
}
}

View File

@ -65,6 +65,11 @@ namespace Yavsc.Helpers
}
}
public static string GetAvatarUri(this ApplicationUser user)
{
return $"/{Config.SiteSetup.Avatars}/{user.UserName}.png";
}
public static string InitPostToFileSystem(
this ClaimsPrincipal user,
string subpath)

View File

@ -1,14 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Yavsc.Attributes.Validation;
namespace Yavsc.ViewModels.Manage
{
public class ChangeUserNameViewModel
{
[YaRequired]
[Display(Name = "New user name"),RegularExpression(Constants.UserNameRegExp)]
public string NewUserName { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using Yavsc.Attributes.Validation;
namespace Yavsc.ViewModels.Manage
{
public class SetUserNameViewModel
{
[Required]
[Display(Name = "User name"),RegularExpression(Constants.UserNameRegExp)]
public string UserName { get; set; }
}
}

View File

@ -0,0 +1,8 @@
@model RegisterModel
<partial name="_ValidationSummary" />
<form method="post">
@Html.EditorForModel()
<button class="btn btn-primary" name="button"
value="Register">Register</button>
</form>

View File

@ -69,22 +69,7 @@ $('span.field-validation-valid[data-valmsg-for="Content"]').html(
<h1 class="blogtitle" ismarkdown>@Model.Title</h1>
<img class="blogphoto" alt="" src="@Model.Photo" >
<div class="blogpost">
@Html.AsciiDocFor(model => model.Content)
<p class="blog" asp-for="Content"></p>
<hr/>
<div class="meta">
@Html.DisplayFor(model => model.Author)
@Html.DisplayNameFor(model => model.DateModified) :
@Html.DisplayFor(model => model.DateModified)
@Html.DisplayNameFor(model => model.DateCreated) :
@Html.DisplayFor(model => model.DateCreated)
@await Component.InvokeAsync("Tagger",Model)
@Html.DisplayForModel()
</div>
<div id="comments">

View File

@ -1,14 +1,10 @@
@using System.Diagnostics
@{
ViewData["Title"] = SR["About"] + " " + SiteSettings.Value.Title;
}
<h1>@ViewData["Title"]</h1>
<h1>@SiteSettings.Value.Title - À Propos</h1>
**Version de Development**
<asciidoc>
= À propos de Yavsc
== L'objectif
Cette application est construite pour mettre en relation des artistes
@ -91,38 +87,4 @@ et programme la suppression complète de ces dites informations dans les quinze
à compter de la demande, sauf demande contradictoire.
L'opération est annulable, jusqu'à deux semaines après sa programmation.
</asciidoc>
<p>
@Model
</p>
@{
var version = FileVersionInfo.GetVersionInfo(typeof(IdentityServer4.Hosting.IdentityServerMiddleware).Assembly.Location).ProductVersion.Split('+').First();
}
<div class="welcome-page">
<h1>
<img src="~/icon.jpg">
Welcome to IdentityServer4
<small class="text-muted">(version @version)</small>
</h1>
<ul>
<li>
IdentityServer publishes a
<a href="~/.well-known/openid-configuration">discovery document</a>
where you can find metadata and links to all the endpoints, key material, etc.
</li>
<li>
Click <a href="~/diagnostics">here</a> to see the claims for your current session.
</li>
<li>
Click <a href="~/grants">here</a> to manage your stored grants.
</li>
<li>
Here are links to the
<a href="https://github.com/identityserver/IdentityServer4">source code repository</a>,
and <a href="https://github.com/IdentityServer/IdentityServer4/tree/main/samples">ready to use samples</a>.
</li>
</ul>
</div>
<p>@Model</p>

View File

@ -1,16 +1,13 @@
@{
ViewData["Title"] = @SR["About"]+" "+@SiteSettings.Value.Title;
}
<h1>@ViewData["Title"]</h1>
<h1>@SiteSettings.Value.Title - objetivo</h1>
<environment names="freefield,Development">
<asciidoc>
## O objetivo
= O objetivo
Esta aplicação é construída para conectar artistas
do campo musical com seu público.
## Operation
== Operation
Os usuários do site são artista, cliente ou administrador. Todos eles têm direito ao seu blog.
Para artistas, é uma maneira de promover seus negócios.
@ -52,7 +49,7 @@ Depois que o serviço associado tiver sido executado, os pagamentos relativos se
Para um contrato executado e não honrado pelo cliente, o processo de processo de recuperação é contratado, caso contrário, o contrato é arquivado,
Os certificados de pagamento estão disponíveis para o artista e a fatura é marcada como paga e depois repassada ao cliente.
### Para o artista
=== Para o artista
O artista escolhe vários parâmetros que farão o seu perfil:
@ -65,7 +62,7 @@ O artista escolhe vários parâmetros que farão o seu perfil:
* Parâmetros adicionais dependendo do tipo de atividade, por exemplo, para
conjuntos, seu tamanho, se houver, seu repertório ou indicações do estilo de sua música)
### Para o cliente
=== Para o cliente
Ele escolhe um lugar e uma data para declarar um evento futuro
(Ele pode programar o quanto quiser).
@ -75,7 +72,7 @@ com base em um de seus projetos de eventos, a negociação de um contrato de ser
Ele tem acesso ao conhecimento de dias conhecidos como artistas livres pelo sistema.
## Confidencialidade
== Confidencialidade
Em nenhum momento, nenhum endereço de correspondência, nenhum endereço de e-mail e nenhum número de telefone
não são transmitidos para clientes ou artistas. Apenas o sistema tem acesso a essas informações.
@ -158,6 +155,4 @@ A "pré-produção" exibe os seguintes sites:
</asciidoc>
</environment>
<p>
@Model
</p>
<p>@Model</p>

View File

@ -0,0 +1,32 @@
@using System.Diagnostics
@{
var version = FileVersionInfo.GetVersionInfo(typeof(IdentityServer4.Hosting.IdentityServerMiddleware).Assembly.Location).ProductVersion.Split('+').First();
}
<div class="welcome-page">
<h1>
<img src="~/icon.jpg">
Welcome to IdentityServer4
<small class="text-muted">(version @version)</small>
</h1>
<ul>
<li>
IdentityServer publishes a
<a href="~/.well-known/openid-configuration">discovery document</a>
where you can find metadata and links to all the endpoints, key material, etc.
</li>
<li>
Click <a href="~/diagnostics">here</a> to see the claims for your current session.
</li>
<li>
Click <a href="~/grants">here</a> to manage your stored grants.
</li>
<li>
Here are links to the
<a href="https://github.com/identityserver/IdentityServer4">source code repository</a>,
and <a href="https://github.com/IdentityServer/IdentityServer4/tree/main/samples">ready to use samples</a>.
</li>
</ul>
</div>

View File

@ -14,18 +14,19 @@
<dd>
@Model.UserName
<a asp-action="SetUserName">[modifier]</a>
</dd>
<dt>EMail:</dt>
<dt>E-mail</dt>
<dd>
@Model.EMail
@if (Model.EmailConfirmed) {
<text>(Adresse E-mail confirmée"])</text>
<text>(Adresse E-mail confirmée)</text>
} else {
<text>
<i> (Adresse non confirmée."])</i>
<i> (Adresse non confirmée.)</i>
<form asp-action="SendConfirationEmail" asp-controller="Account" enctype="multipart/form-data">
<input type="submit" value="Confirmer cette adresse"]"/>
</form>
@ -35,7 +36,7 @@
<dd>
<dl>
<dt>AllowMonthlyEmail:</dt>
<dt>Allow Monthly Email</dt>
<dd>
<a asp-action="ProfileEMailUsage"> @Html.DisplayFor(m=>m.AllowMonthlyEmail) [modifier]
</a>
@ -46,7 +47,8 @@
<dt>FullName:</dt>
<dd>
@Html.DisplayFor(m=>m.FullName) <a asp-action="SetFullName">[modifier]</a>
@Html.DisplayFor(m=>m.FullName)
<a asp-action="SetFullName">[modifier]</a>
</dd>
@if (Model.Roles.Count()>0) {

View File

@ -1,19 +1,19 @@
@model ChangeUserNameViewModel
@model SetUserNameViewModel
@{
ViewData["Title"] = "Changer de nom d'utilisateur";
}
<h2>@ViewData["Title"].</h2>
<form asp-controller="Manage" asp-action="ChangeUserName" method="post" class="form-horizontal" role="form">
<form asp-controller="Manage" asp-action="SetUserName" method="post" class="form-horizontal" role="form">
<h4>Change user name form</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="NewUserName" class="col-md-2 control-label"></label>
<label asp-for="UserName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="NewUserName" class="form-control" />
<span asp-validation-for="NewUserName" class="text-danger"></span>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
</div>
</form>

View File

@ -34,7 +34,7 @@
<td>
<asciidoc summary="256">@item.Content</asciidoc>
@if (trunked) { <a asp-action="Details" asp-route-id="@item.Id" class="bloglink">...</a> }
<span style="font-size:x-small;">(@item.Author.UserName </span>,
<span style="font-size:x-small;">(@Html.DisplayFor(m => item.Author)</span>,
<span style="font-size:xx-small;">
posté le @item.DateCreated.ToString("dddd d MMM yyyy à H:mm")
@if ((item.DateModified - item.DateCreated).Minutes > 0){ 

View File

@ -1,12 +1,14 @@
@model ApplicationUser
@{
var avuri = "/Avatars/"+Model.UserName+".s.png";
var userPosted = Model.Posts!=null && Model.Posts.Count()>1;
}
<div class="userinfo">
<h3>
<img src="@avuri" asp-append-version="true" class="smalltofhol" />
</h3>
@if (Model.Posts!=null && Model.Posts.Count()>1) { <a asp-controller="Blogspot" asp-action="UserPosts"
asp-route-id="@Model.UserName" class="btn btn-primary">index de ses articles</a>
@if (userPosted) { <a asp-controller="Blogspot" asp-action="UserPosts"
asp-route-id="@Model.UserName" class="btn btn-primary">
<img src="@avuri" asp-append-version="true" class="smalltofhol" alt="" title="@Model.UserName"/>
</a>
}else {
Html.LabelFor(m=>m.UserName);
}
</div>

View File

@ -35,7 +35,7 @@
@addTagHelper *, Yavsc
@inject IAuthorizationService AuthorizationService
@inject Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer<Yavsc.Startup> SR
@inject Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer<Yavsc.YavscLocalization> SR
@inject Microsoft.Extensions.Options.IOptions<SiteSettings> SiteSettings
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

View File

@ -13,6 +13,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />