From 9289207085f61e8aca9349b20253f844dc05908e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 22 Feb 2026 19:54:10 +0000 Subject: [PATCH] refactoring the login --- .vscode/launch.json | 3 +- .vscode/settings.json | 1 + src/Abstract/Constants.cs | 2 +- .../Accounting/AccountController.cs | 278 ++++++++---------- .../Communicating/BlogspotController.cs | 15 +- src/Org/Services/BlogSpotService.cs | 24 +- src/Org/Views/Account/Login.cshtml | 6 +- src/Org/Views/Account/Signin.cshtml | 4 +- src/Org/Views/Blogspot/Create.cshtml | 2 +- src/Org/Views/Blogspot/Edit.cshtml | 13 +- src/Org/Views/Shared/SignIn.cshtml | 58 ---- src/Org/Views/Shared/_LoginPartial.cshtml | 2 +- src/Org/Views/_ViewImports.cshtml | 1 - src/Server/Models/Blog/BlogPost.cs | 78 +++-- src/Server/Services/BlogPostEdition.cs | 13 - src/Server/ViewModels/Account/SignInModel.cs | 1 - .../ViewModels/BlogSpot/BlogPostBase.cs | 26 -- .../ViewModels/BlogSpot/BlogPostEdit.cs | 50 ---- 18 files changed, 209 insertions(+), 368 deletions(-) delete mode 100644 src/Org/Views/Shared/SignIn.cshtml delete mode 100644 src/Server/Services/BlogPostEdition.cs delete mode 100644 src/Server/ViewModels/BlogSpot/BlogPostBase.cs delete mode 100644 src/Server/ViewModels/BlogSpot/BlogPostEdit.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index afe0a774..59243ba7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,7 +28,8 @@ "justMyCode": false, "serverReadyAction": { "action": "openExternally", - "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + "pattern": "\\bNow listening on:\\s+(https?://\\S+)", + "killOnServerStop": true }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/.vscode/settings.json b/.vscode/settings.json index d6837c8e..79924b17 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "cSpell.words": [ "appsettings", + "asciidoctor", "Cratie", "Newtonsoft", "Npgsql", diff --git a/src/Abstract/Constants.cs b/src/Abstract/Constants.cs index 31518601..88a3a431 100644 --- a/src/Abstract/Constants.cs +++ b/src/Abstract/Constants.cs @@ -20,7 +20,7 @@ namespace Yavsc 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 LoginPath = "~/signin"; + public const string SigninPath = "~/signin"; public const string LogoutPath = "~/signout"; public const string AccessDeniedPath = "~/Account/AccessDenied"; diff --git a/src/Org/Controllers/Accounting/AccountController.cs b/src/Org/Controllers/Accounting/AccountController.cs index 78235f2a..161891a3 100644 --- a/src/Org/Controllers/Accounting/AccountController.cs +++ b/src/Org/Controllers/Accounting/AccountController.cs @@ -23,6 +23,7 @@ using IdentityServer8.Events; using IdentityServer8.Extensions; using IdentityModel; using Yavsc.Server.Helpers; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Yavsc.Controllers { @@ -82,31 +83,134 @@ namespace Yavsc.Controllers } + public async Task SignIn(SignInModel model, [FromForm] string button) + { + if (Request.Method == "POST") // "hGbkk9B94NAae#aG" + + { + if (model.Provider == null || model.Provider == "LOCAL") + { + if (ModelState.IsValid) + { + var user = await _userManager.FindByNameAsync(model.UserName); + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); + if (user != null) + { + + + var signin = await _signInManager.CheckPasswordSignInAsync(user, model.Password, true); + + // validate username/password against in-memory store + if (signin.Succeeded) + { + await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId)); + + // only set explicit expiration here if user chooses "remember me". + // otherwise we rely upon expiration configured in cookie middleware. + await HttpContext.SignInAsync(user, _roleManager, model.RememberMe, _dbContext); + var authResult = await HttpContext.AuthenticateAsync(); + if (!authResult.Succeeded) + { + return this.Unauthorized(); + } + String bearer = await HttpContext.GetTokenAsync("Bearer", "Bearer"); + HttpContext.Response.Cookies.Append("Bearer", bearer); + + if (context != null) + { + if (context.IsNativeClient()) + { + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage("Redirect", model.ReturnUrl); + } + + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + return Redirect(model.ReturnUrl); + } + + // request for a local page + if (Url.IsLocalUrl(model.ReturnUrl)) + { + return Redirect(model.ReturnUrl); + } + else if (string.IsNullOrEmpty(model.ReturnUrl)) + { + return Redirect("~/"); + } + else + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); + } + } + } + + await _events.RaiseAsync(new UserLoginFailureEvent(model.UserName, "invalid credentials", clientId: context?.Client.ClientId)); + ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); + } + } + else + { + + // Note: the "provider" parameter corresponds to the external + // authentication provider choosen by the user agent. + if (string.IsNullOrEmpty(model.Provider)) + { + _logger.LogWarning("Provider not specified"); + return BadRequest(); + } + + // Instruct the middleware corresponding to the requested external identity + // provider to redirect the user agent to its own authorization endpoint. + // Note: the authenticationScheme parameter must match the value configured in Startup.cs + + // Note: the "returnUrl" parameter corresponds to the endpoint the user agent + // will be redirected to after a successful authentication and not + // the redirect_uri of the requesting client application. + if (string.IsNullOrEmpty(model.ReturnUrl)) + { + _logger.LogWarning("ReturnUrl not specified"); + return BadRequest(); + } + // Note: this still is not the redirect uri given to the third party provider, at building the challenge. + var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { model.ReturnUrl }, protocol: "https", host: Config.Authority); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(model.Provider, redirectUrl); + // var properties = new AuthenticationProperties{RedirectUri=ReturnUrl}; + return new ChallengeResult(model.Provider, properties); + + } + } + return View(model); + } + /// /// Entry point into the login workflow /// - [HttpGet] - public async Task Login(string returnUrl) + [HttpGet(Constants.SigninPath)] + public async Task Signin(SignInModel model) { // build a model so we know what to show on the login page - var vm = await BuildLoginViewModelAsync(returnUrl); + var vm = await BuildLoginViewModelAsync(model); if (vm.IsExternalLoginOnly) { // we only have one option for logging in and it's an external provider - return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl }); + return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, model.ReturnUrl }); } - + ModelState.Clear(); return View("Signin", vm); } /// /// Handle postback from username/password login /// - [HttpPost(Constants.LoginPath)] + /// + [HttpPost(Constants.SigninPath)] [ValidateAntiForgeryToken] [AllowAnonymous] - public async Task Login([FromForm] SignInModel model, [FromForm] string button) + + public async Task Signin([FromForm] SignInModel model, [FromForm] string button) { // check if we are in the context of an authorization request @@ -273,28 +377,25 @@ namespace Yavsc.Controllers /*****************************************/ /* helper APIs for the AccountController */ /*****************************************/ - private async Task BuildLoginViewModelAsync(string returnUrl) + private async Task BuildLoginViewModelAsync(SignInModel model) { - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) { var local = context.IdP == IdentityServer8.IdentityServerConstants.LocalIdentityProvider; // this is meant to short circuit the UI and only trigger the one external IdP - var vm = new SignInModel - { - EnableLocalLogin = local, - ReturnUrl = returnUrl, - UserName = context?.LoginHint, - IsExternalLoginOnly = false - }; + + model.EnableLocalLogin = local; + model.UserName = context?.LoginHint; + model.IsExternalLoginOnly = false; if (!local) { - vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; + model.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; } - return vm; + return model; } var schemes = await _schemeProvider.GetAllSchemesAsync(); @@ -322,22 +423,12 @@ namespace Yavsc.Controllers } } - return new SignInModel - { - RememberMe = AccountOptions.AllowRememberLogin, - EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, - ReturnUrl = returnUrl, - UserName = context?.LoginHint, - ExternalProviders = providers.ToArray() - }; - } + model.RememberMe = AccountOptions.AllowRememberLogin; + model.EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin; + model.UserName = context?.LoginHint; + model.ExternalProviders = providers.ToArray(); - private async Task BuildLoginViewModelAsync(SignInModel model) - { - var vm = await BuildLoginViewModelAsync(model.ReturnUrl); - vm.UserName = model.UserName; - vm.RememberMe = model.RememberMe; - return vm; + return model; } private async Task BuildLogoutViewModelAsync(string logoutId) @@ -432,28 +523,6 @@ namespace Yavsc.Controllers return System.Guid.NewGuid().ToString(); } - [AllowAnonymous] - [HttpGet(Constants.LoginPath)] - public ActionResult SignIn(string returnUrl = null) - { - // Note: the "returnUrl" parameter corresponds to the endpoint the user agent - // will be redirected to after a successful authentication and not - // the redirect_uri of the requesting client application against the third - // party identity provider. - return View(new SignInModel - { - ReturnUrl = returnUrl ?? "/", - ExternalProviders = [], - EnableLocalLogin = true - }); - /* - Note: When using an external login provider, redirect the query : - var properties = _signInManager.ConfigureExternalAuthenticationProperties(OpenIdConnectDefaults.AuthenticationScheme, returnUrl); - return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties); - */ - - } - [AllowAnonymous] public ActionResult AccessDenied(string requestUrl = null) { @@ -466,106 +535,7 @@ namespace Yavsc.Controllers return View("AccessDenied", requestUrl); } - public async Task SignIn(SignInModel model) - { - if (Request.Method == "POST") // "hGbkk9B94NAae#aG" - { - if (model.Provider == null || model.Provider == "LOCAL") - { - if (ModelState.IsValid) - { - var user = await _userManager.FindByNameAsync(model.UserName); - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (user != null) - { - - - var signin = await _signInManager.CheckPasswordSignInAsync(user, model.Password, true); - - // validate username/password against in-memory store - if (signin.Succeeded) - { - await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId)); - - // only set explicit expiration here if user chooses "remember me". - // otherwise we rely upon expiration configured in cookie middleware. - await HttpContext.SignInAsync(user, _roleManager, model.RememberMe, _dbContext); - var authResult = await HttpContext.AuthenticateAsync(); - if (!authResult.Succeeded) - { - return this.Unauthorized(); - } - String bearer = await HttpContext.GetTokenAsync("Bearer", "Bearer"); - HttpContext.Response.Cookies.Append("Bearer", bearer); - - if (context != null) - { - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", model.ReturnUrl); - } - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return Redirect(model.ReturnUrl); - } - - // request for a local page - if (Url.IsLocalUrl(model.ReturnUrl)) - { - return Redirect(model.ReturnUrl); - } - else if (string.IsNullOrEmpty(model.ReturnUrl)) - { - return Redirect("~/"); - } - else - { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); - } - } - } - - await _events.RaiseAsync(new UserLoginFailureEvent(model.UserName, "invalid credentials", clientId: context?.Client.ClientId)); - ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); - } - } - else - { - - // Note: the "provider" parameter corresponds to the external - // authentication provider choosen by the user agent. - if (string.IsNullOrEmpty(model.Provider)) - { - _logger.LogWarning("Provider not specified"); - return BadRequest(); - } - - // Instruct the middleware corresponding to the requested external identity - // provider to redirect the user agent to its own authorization endpoint. - // Note: the authenticationScheme parameter must match the value configured in Startup.cs - - // Note: the "returnUrl" parameter corresponds to the endpoint the user agent - // will be redirected to after a successful authentication and not - // the redirect_uri of the requesting client application. - if (string.IsNullOrEmpty(model.ReturnUrl)) - { - _logger.LogWarning("ReturnUrl not specified"); - return BadRequest(); - } - // Note: this still is not the redirect uri given to the third party provider, at building the challenge. - var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { model.ReturnUrl }, protocol: "https", host: Config.Authority); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(model.Provider, redirectUrl); - // var properties = new AuthenticationProperties{RedirectUri=ReturnUrl}; - return new ChallengeResult(model.Provider, properties); - - } - } - return View(model); - } // // GET: /Account/Register diff --git a/src/Org/Controllers/Communicating/BlogspotController.cs b/src/Org/Controllers/Communicating/BlogspotController.cs index 456fab93..3cbf9eb3 100644 --- a/src/Org/Controllers/Communicating/BlogspotController.cs +++ b/src/Org/Controllers/Communicating/BlogspotController.cs @@ -2,13 +2,9 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Yavsc.Models; -using Yavsc.ViewModels.Auth; using Microsoft.AspNetCore.Mvc.Rendering; using Yavsc.Models.Blog; -using Yavsc.Helpers; using Microsoft.Extensions.Options; -using Microsoft.EntityFrameworkCore; -using Yavsc.ViewModels.Blog; using Yavsc.Server.Exceptions; using Yavsc.Server.Helpers; @@ -97,22 +93,23 @@ namespace Yavsc.Controllers [Authorize()] public IActionResult Create(string title) { - var result = new BlogPostCreateViewModel + var result = new BlogPostEditViewModel + (new BlogPost { Title = title - }; + }, true); SetLangItems(); return View(result); } // POST: Blog/Create [HttpPost, Authorize, ValidateAntiForgeryToken] - public IActionResult Create(BlogPostEditViewModel blogInput) + public IActionResult Create(BlogPost blogInput) { if (ModelState.IsValid) { BlogPost post = blogSpotService.Create(User.GetUserId(), - BlogPostEditViewModel.FromViewModel(blogInput)); + blogInput); return RedirectToAction("Index"); } return View("Edit", blogInput); @@ -133,6 +130,8 @@ namespace Yavsc.Controllers { return NotFound(); } + + SetLangItems(); return View(blog); diff --git a/src/Org/Services/BlogSpotService.cs b/src/Org/Services/BlogSpotService.cs index ceebdaa7..cf5a0906 100644 --- a/src/Org/Services/BlogSpotService.cs +++ b/src/Org/Services/BlogSpotService.cs @@ -1,5 +1,3 @@ - - using System.Diagnostics; using System.Security.Claims; using Microsoft.AspNetCore.Authorization; @@ -11,14 +9,12 @@ using Yavsc.Models.Blog; using Yavsc.Server.Exceptions; using Yavsc.Server.Helpers; using Yavsc.ViewModels.Auth; -using Yavsc.ViewModels.Blog; public class BlogSpotService { private readonly ApplicationDbContext _context; private readonly IAuthorizationService _authorizationService; - public BlogSpotService(ApplicationDbContext context, IAuthorizationService authorizationService) { @@ -26,15 +22,8 @@ public class BlogSpotService _context = context; } - public BlogPost Create(string userId, BlogPostEditViewModel blogInput) + public BlogPost Create(string userId, BlogPost post) { - BlogPost post = new BlogPost - { - Title = blogInput.Title, - Content = blogInput.Content, - Photo = blogInput.Photo, - AuthorId = userId - }; _context.BlogSpot.Add(post); _context.SaveChanges(userId); return post; @@ -42,17 +31,18 @@ public class BlogSpotService public async Task GetPostForEdition(ClaimsPrincipal user, long blogPostId) { var blog = await _context.BlogSpot.Include(x => x.Author).Include(x => x.ACL).SingleAsync(m => m.Id == blogPostId); - var auth = await _authorizationService.AuthorizeAsync(user, blog, new EditPermission()); + var auth = await _authorizationService.AuthorizeAsync(user, blog, new EditPermission()); if (!auth.Succeeded) { throw new AuthorizationFailureException(auth); - } - return BlogPostEditViewModel.From(blog); + } + var pub = await _context.blogSpotPublications.AnyAsync(x => x.BlogpostId == blog.Id); + + return new BlogPostEditViewModel(blog, pub); } public async Task Details(ClaimsPrincipal user, long blogPostId) { - BlogPost blog = await _context.BlogSpot .Include(p => p.Author) .Include(p => p.Tags) @@ -91,7 +81,7 @@ public class BlogSpotService // saves the change _context.Update(blog); var publication = await _context.blogSpotPublications.SingleOrDefaultAsync - (p=>p.BlogpostId==blogEdit.Id); + (p => p.BlogpostId == blogEdit.Id); if (publication != null) { if (!blogEdit.Publish) diff --git a/src/Org/Views/Account/Login.cshtml b/src/Org/Views/Account/Login.cshtml index e4ccb1d8..b0ee8e88 100644 --- a/src/Org/Views/Account/Login.cshtml +++ b/src/Org/Views/Account/Login.cshtml @@ -2,7 +2,7 @@
-
+
@@ -84,4 +84,4 @@
}
- \ No newline at end of file + diff --git a/src/Org/Views/Account/Signin.cshtml b/src/Org/Views/Account/Signin.cshtml index e6fabd05..079882b3 100644 --- a/src/Org/Views/Account/Signin.cshtml +++ b/src/Org/Views/Account/Signin.cshtml @@ -2,7 +2,7 @@
- +
diff --git a/src/Org/Views/Blogspot/Create.cshtml b/src/Org/Views/Blogspot/Create.cshtml index ed4a62e9..cee73565 100644 --- a/src/Org/Views/Blogspot/Create.cshtml +++ b/src/Org/Views/Blogspot/Create.cshtml @@ -1,4 +1,4 @@ -@model BlogPostCreateViewModel +@model BlogPostEditViewModel @{ ViewData["Title"] = "Blog post edition"; diff --git a/src/Org/Views/Blogspot/Edit.cshtml b/src/Org/Views/Blogspot/Edit.cshtml index 3aa35912..0c17575c 100644 --- a/src/Org/Views/Blogspot/Edit.cshtml +++ b/src/Org/Views/Blogspot/Edit.cshtml @@ -1,5 +1,4 @@ @model BlogPostEditViewModel - @{ ViewData["Title"] = "Blog post edition"; } @@ -55,7 +54,6 @@

@Model.Title

-
@Model.Content

@@ -84,7 +82,8 @@
- @@ -112,6 +111,14 @@
@await Component.InvokeAsync("Directory","") + + +
+ + +
@{ await Html.RenderPartialAsync("_PostFilesPartial"); }
diff --git a/src/Org/Views/Shared/SignIn.cshtml b/src/Org/Views/Shared/SignIn.cshtml deleted file mode 100644 index 36db474c..00000000 --- a/src/Org/Views/Shared/SignIn.cshtml +++ /dev/null @@ -1,58 +0,0 @@ - - -@using Yavsc.ViewModels.Account -@model SignInModel -@{ - ViewData["Title"] = "Log in"; -} - -
-

@ViewData["Title"]

-
- -

Use a local account to log in

-
-
-
- -
- - -
-
-
- -
- - -
-
-
-
-
- - -
-
-
-
-
- -
-
-

- Register as a new user? -

-

- Forgot your password -

- - - - @Html.AntiForgeryToken() -
- -
-

Use another service to log in:

- -
diff --git a/src/Org/Views/Shared/_LoginPartial.cshtml b/src/Org/Views/Shared/_LoginPartial.cshtml index 40120630..193ce34f 100644 --- a/src/Org/Views/Shared/_LoginPartial.cshtml +++ b/src/Org/Views/Shared/_LoginPartial.cshtml @@ -52,7 +52,7 @@ else Register } diff --git a/src/Org/Views/_ViewImports.cshtml b/src/Org/Views/_ViewImports.cshtml index c8cbeb79..1e1ae37f 100755 --- a/src/Org/Views/_ViewImports.cshtml +++ b/src/Org/Views/_ViewImports.cshtml @@ -14,7 +14,6 @@ @using Yavsc.Abstract.Models.Messaging; @using Yavsc.Billing; @using Yavsc.Server.Models.Calendar; -@using Yavsc.ViewModels.Blog; @using Yavsc.ViewModels.Haircut; @using Yavsc.ViewModels.Administration; @using Yavsc.ViewModels.Account; diff --git a/src/Server/Models/Blog/BlogPost.cs b/src/Server/Models/Blog/BlogPost.cs index 0a2483f8..d3711a91 100644 --- a/src/Server/Models/Blog/BlogPost.cs +++ b/src/Server/Models/Blog/BlogPost.cs @@ -1,63 +1,85 @@ -using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; -using Yavsc; using Yavsc.Abstract.Identity; using Yavsc.Abstract.Identity.Security; -using Yavsc.Attributes.Validation; using Yavsc.Interfaces; using Yavsc.Models.Access; using Yavsc.Models.Relationship; -using Yavsc.ViewModels.Blog; namespace Yavsc.Models.Blog { - public class BlogPost : BlogPostBase, - IBlogPost, ICircleAuthorized, ITaggable + public class BlogPostEditViewModel : BlogPost + { + public BlogPostEditViewModel(BlogPost post, bool publish) + { + Id = post.Id; + AuthorId = post.AuthorId; + ACL = post.ACL; + Content = post.Content; + Title = post.Title; + Publish = publish; + } + public bool Publish { get; set; } + + } + + public class BlogPost : + IBlogPost, ICircleAuthorized, ITaggable { [Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [Display(Name="Identifiant du post")] - public long Id { get; set; } + [Display(Name = "Identifiant du post")] + public long Id { get; set; } - [Display(Name="Identifiant de l'auteur")] + [StringLength(1024)] + public string? Photo { get; set; } + + [StringLength(1024)] + [Required] + public string Title { get; set; } + + [StringLength(56224)] + public string? Content { get; set; } + + [InverseProperty("Target")] + [Display(Name = "Liste de contrôle d'accès")] + public virtual List? ACL { get; set; } + + [Display(Name = "Identifiant de l'auteur")] [ForeignKey("Author")] - public string? AuthorId { get; set; } + public string? AuthorId { get; set; } - [Display(Name="Auteur")] - public virtual ApplicationUser? Author { set; get; } + [Display(Name = "Auteur")] + public virtual ApplicationUser? Author { set; get; } - [Display(Name="Date de création")] + [Display(Name = "Date de création")] public DateTime DateCreated { get; set; } - [Display(Name="Créateur")] + [Display(Name = "Créateur")] public string? UserCreated { get; set; } - [Display(Name="Dernière modification")] + [Display(Name = "Dernière modification")] public DateTime DateModified { get; set; } - [Display(Name="Utilisateur ayant modifé le dernier")] - public string? UserModified + [Display(Name = "Utilisateur ayant modifé le dernier")] + public string? UserModified { get; set; } public bool AuthorizeCircle(long circleId) { - return ACL?.Any( i=>i.CircleId == circleId) ?? true; + return ACL?.Any(i => i.CircleId == circleId) ?? true; } public ICircleAuthorization[] GetACL() @@ -67,26 +89,26 @@ namespace Yavsc.Models.Blog public void Tag(Tag tag) { - var existent = Tags.SingleOrDefault(t => t.PostId == Id && t.TagId == tag.Id); - if (existent==null) Tags.Add(new BlogTag { PostId = Id, Tag = tag } ); + var existent = Tags.SingleOrDefault(t => t.PostId == Id && t.TagId == tag.Id); + if (existent == null) Tags.Add(new BlogTag { PostId = Id, Tag = tag }); } public void DeTag(Tag tag) { - var existent = Tags.SingleOrDefault(t => (( t.TagId == tag.Id) && t.PostId == Id)); - if (existent!=null) Tags.Remove(existent); + var existent = Tags.SingleOrDefault(t => ((t.TagId == tag.Id) && t.PostId == Id)); + if (existent != null) Tags.Remove(existent); } public string[] GetTags() { - return Tags.Select(t=>t.Tag.Name).ToArray(); + return Tags.Select(t => t.Tag.Name).ToArray(); } [InverseProperty("Post")] - public virtual List Tags { get; set; } + public virtual List Tags { get; set; } [InverseProperty("Post")] - public virtual List Comments { get; set; } + public virtual List Comments { get; set; } IApplicationUser IBlogPost.Author { get => this.Author; } } diff --git a/src/Server/Services/BlogPostEdition.cs b/src/Server/Services/BlogPostEdition.cs deleted file mode 100644 index da2fc9ce..00000000 --- a/src/Server/Services/BlogPostEdition.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Yavsc.Models.Blog; - -public class BlogPostEdition -{ - public string Content { get; internal set; } - public string Title { get; internal set; } - public string Photo { get; internal set; } - - internal static BlogPostEdition From(BlogPost blog) - { - throw new NotImplementedException(); - } -} diff --git a/src/Server/ViewModels/Account/SignInModel.cs b/src/Server/ViewModels/Account/SignInModel.cs index 46320a11..272563d5 100755 --- a/src/Server/ViewModels/Account/SignInModel.cs +++ b/src/Server/ViewModels/Account/SignInModel.cs @@ -40,7 +40,6 @@ namespace Yavsc.ViewModels.Account /// public string? Provider { get; set; } - /// /// This value does NOT indicate the OAuth client method recieving the code, /// but the one called once authorized. diff --git a/src/Server/ViewModels/BlogSpot/BlogPostBase.cs b/src/Server/ViewModels/BlogSpot/BlogPostBase.cs deleted file mode 100644 index cd431608..00000000 --- a/src/Server/ViewModels/BlogSpot/BlogPostBase.cs +++ /dev/null @@ -1,26 +0,0 @@ - -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using Yavsc.Models.Access; - -namespace Yavsc.ViewModels.Blog -{ - public class BlogPostBase - { - [StringLength(1024)] - public string? Photo { get; set; } - - [StringLength(1024)] - [Required] - public string Title { get; set; } - - [StringLength(56224)] - public string? Content { get; set; } - - [InverseProperty("Target")] - [Display(Name = "Liste de contrôle d'accès")] - public virtual List? ACL { get; set; } - - - } -} diff --git a/src/Server/ViewModels/BlogSpot/BlogPostEdit.cs b/src/Server/ViewModels/BlogSpot/BlogPostEdit.cs deleted file mode 100644 index e6f2af67..00000000 --- a/src/Server/ViewModels/BlogSpot/BlogPostEdit.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Yavsc.Models.Blog; - -namespace Yavsc.ViewModels.Blog; - - -public class BlogPostCreateViewModel : BlogPostBase -{ - public bool Publish { get; set; } -} - -public class BlogPostEditViewModel : BlogPostCreateViewModel -{ - - [Required] - - public required long Id { get; set; } - - - public BlogPostEditViewModel() - { - - } - - - public static BlogPostEditViewModel From(BlogPost blogInput) - { - return new BlogPostEditViewModel - { - Id = blogInput.Id, - Title = blogInput.Title, - Publish = false, - Photo = blogInput.Photo, - Content = blogInput.Content, - ACL = blogInput.ACL - }; - } - public static BlogPostEditViewModel FromViewModel(BlogPostEditViewModel blogInput) - { - return new BlogPostEditViewModel - { - Id = blogInput.Id, - Title = blogInput.Title, - Publish = false, - Photo = blogInput.Photo, - Content = blogInput.Content, - ACL = blogInput.ACL - }; - } -}