Got a login

dotnet-7.0
Paul Schneider 1 year ago
parent 908d461552
commit b46c4b3447
61 changed files with 7793 additions and 609 deletions

@ -19,10 +19,10 @@ namespace Yavsc
public const string CompanyClaimType = "https://schemas.pschneider.fr/identity/claims/Company"; 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 UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9._-]*$";
public const string UserFileNamePatternRegExp = @"^([a-zA-Z0-9._-]*/)*[a-zA-Z0-9._-]+$"; public const string UserFileNamePatternRegExp = @"^([a-zA-Z0-9._-]*/)*[a-zA-Z0-9._-]+$";
public const string AuthorizePath = "~/authorize"; public const string AuthorizePath = "/authorize";
public const string TokenPath = "~/token"; public const string TokenPath = "/token";
public const string LoginPath = "~/signin"; public const string LoginPath = "/signin";
public const string LogoutPath = "~/signout"; public const string LogoutPath = "/signout";
public const string SignalRPath = "/api/signalr"; public const string SignalRPath = "/api/signalr";

@ -1,19 +0,0 @@
using System.Threading.Tasks;
using Yavsc.Abstract.Manage;
namespace Yavsc.Services
{
public interface IEmailSender
{
/// <summary>
/// Sends en email.
/// </summary>
/// <param name="username">user name in database</param>
/// <param name="email">user's email</param>
/// <param name="subject">email subject</param>
/// <param name="message">message</param>
/// <returns>the message id</returns>
Task<EmailSentViewModel> SendEmailAsync(string username, string email, string subject, string message);
}
}

@ -9,11 +9,11 @@ using Yavsc.Models.Bank;
using Yavsc.Models.Access; using Yavsc.Models.Access;
namespace Yavsc.Models namespace Yavsc.Models
{ {
public class ApplicationUser : IdentityUser, IBaseTrackedEntity [Table("AspNetUsers")]
public class ApplicationUser : IdentityUser
{ {
/// <summary> /// <summary>
/// Another me, as a byte array. /// Another me, as a byte array.TG7@Eu%80rufzkhbb
/// This value points a picture that may be used /// This value points a picture that may be used
/// to present the user /// to present the user
/// </summary> /// </summary>
@ -113,24 +113,5 @@ namespace Yavsc.Models
[InverseProperty("Member")] [InverseProperty("Member")]
public virtual List<CircleMember> Membership { get; set; } public virtual List<CircleMember> Membership { get; set; }
public DateTime DateCreated
{
get; set;
}
public string UserCreated
{
get; set;
}
public DateTime DateModified
{
get; set;
}
public string UserModified
{
get; set;
}
} }
} }

@ -1,7 +0,0 @@
namespace Yavsc.Server.Services
{
public class TranslationService
{
}
}

@ -1,7 +0,0 @@
namespace Yavsc
{
public class ThirdPartyFiles {
}
}

@ -10,8 +10,7 @@ namespace Yavsc.Server.Settings
new Dictionary<string, Func<ApplicationUser, bool>> new Dictionary<string, Func<ApplicationUser, bool>>
{ {
{ "allow-monthly", u => u.AllowMonthlyEmail }, { "allow-monthly", u => u.AllowMonthlyEmail },
{ "email-not-confirmed", u => !u.EmailConfirmed && u.DateCreated < DateTime.Now.AddDays(-7) }, { "email-not-confirmed", u => !u.EmailConfirmed }
{ "user-to-remove", u => !u.EmailConfirmed && u.DateCreated < DateTime.Now.AddDays(-14) }
}; };
} }
} }

@ -6,14 +6,15 @@ using Yavsc.Attributes.Validation;
namespace Yavsc.ViewModels.Account namespace Yavsc.ViewModels.Account
{ {
// TODO external autentication providers // TODO external autentication providers
public class SignInViewModel
public class SignInModel
{ {
/// <summary> /// <summary>
/// Local user's name. /// Local user's name.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[YaRequired] [YaRequired]
public string UserName { get; set; } public string EMail { get; set; }
/// <summary> /// <summary>
/// Local user's password . /// Local user's password .
@ -46,11 +47,6 @@ namespace Yavsc.ViewModels.Account
/// <returns></returns> /// <returns></returns>
public string ReturnUrl { get; set; } public string ReturnUrl { get; set; }
/// <summary>
/// Lists external identity provider descriptions.
/// </summary>
/// <returns>an enumeration of the descriptions.</returns>
public IEnumerable<YaAuthenticationDescription> ExternalProviders { get; set; }
} }
public class YaAuthenticationDescription { public class YaAuthenticationDescription {

@ -18,7 +18,5 @@ namespace Yavsc.ViewModels.Account
[Display(Name = "Confirmer le mot de passe")] [Display(Name = "Confirmer le mot de passe")]
[Compare("Password", ErrorMessage = "Le mot de passe et sa confirmation ne sont pas les mêmes.")] [Compare("Password", ErrorMessage = "Le mot de passe et sa confirmation ne sont pas les mêmes.")]
public string ConfirmPassword { get; set; } public string ConfirmPassword { get; set; }
public string Code { get; set; }
} }
} }

@ -24,20 +24,20 @@ namespace Yavsc.Controllers
// GET: api/ApplicationUserApi // GET: api/ApplicationUserApi
[HttpGet] [HttpGet]
public IEnumerable<UserInfo> GetApplicationUser() public IEnumerable<UserInfo> GetApplicationUser(int skip=0, int take = 25)
{ {
return _context.Users.OrderByDescending(u => u.DateModified).Take(25) return _context.Users.Skip(skip).Take(take)
.Select(u=> new UserInfo { .Select(u=> new UserInfo{
UserId = u.Id, UserId = u.Id,
UserName = u.UserName, UserName = u.UserName,
Avatar = u.Avatar }); Avatar = u.Avatar});
} }
[HttpGet("search/{pattern}")] [HttpGet("search/{pattern}")]
public IEnumerable<UserInfo> SearchApplicationUser(string pattern) public IEnumerable<UserInfo> SearchApplicationUser(string pattern, int skip=0, int take = 25)
{ {
return _context.Users.Where(u => u.UserName.Contains(pattern)) return _context.Users.Where(u => u.UserName.Contains(pattern))
.OrderByDescending(u => u.DateModified).Take(25) .Skip(skip).Take(take)
.Select(u=> new UserInfo { .Select(u=> new UserInfo {
UserId = u.Id, UserId = u.Id,
UserName = u.UserName, UserName = u.UserName,

@ -1,3 +1,4 @@
using System.Web;
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -13,6 +14,8 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Yavsc.Helpers; using Yavsc.Helpers;
using Yavsc.Abstract.Manage; using Yavsc.Abstract.Manage;
using Microsoft.AspNetCore.Identity.UI.Services;
using Yavsc.Interface;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
@ -23,7 +26,7 @@ namespace Yavsc.Controllers
private const int defaultLen = 10; private const int defaultLen = 10;
private readonly UserManager<ApplicationUser> _userManager; private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager; private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender; private readonly ITrueEmailSender _emailSender;
// private readonly ISmsSender _smsSender; // private readonly ISmsSender _smsSender;
private readonly ILogger _logger; private readonly ILogger _logger;
readonly SiteSettings _siteSettings; readonly SiteSettings _siteSettings;
@ -39,7 +42,7 @@ namespace Yavsc.Controllers
public AccountController( public AccountController(
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager, SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
ILoggerFactory loggerFactory, IOptions<TwilioSettings> twilioSettings, ILoggerFactory loggerFactory, IOptions<TwilioSettings> twilioSettings,
IStringLocalizer<Yavsc.YavscLocalisation> localizer, IStringLocalizer<Yavsc.YavscLocalisation> localizer,
@ -65,12 +68,9 @@ namespace Yavsc.Controllers
} }
[Authorize(Roles = Constants.AdminGroupName)] [Authorize(Roles = Constants.AdminGroupName)]
[Route("Account/UserList/{page?}/{len?}")] [Route("Account/UserList/{pageNum}/{len?}")]
public async Task<IActionResult> UserList(string page, string len) public async Task<IActionResult> UserList(int pageNum, int pageLen = defaultLen)
{ {
int pageNum = page!=null ? int.Parse(page) : 0;
int pageLen = len!=null ? int.Parse(len) : defaultLen;
var users = _dbContext.Users.OrderBy(u=>u.UserName); var users = _dbContext.Users.OrderBy(u=>u.UserName);
var shown = pageNum * pageLen; var shown = pageNum * pageLen;
var toShow = users.Skip(shown).Take(pageLen); var toShow = users.Skip(shown).Take(pageLen);
@ -96,7 +96,7 @@ namespace Yavsc.Controllers
// will be redirected to after a successful authentication and not // will be redirected to after a successful authentication and not
// the redirect_uri of the requesting client application against the third // the redirect_uri of the requesting client application against the third
// party identity provider. // party identity provider.
return View(new SignInViewModel return View(new SignInModel
{ {
ReturnUrl = returnUrl ?? "/", ReturnUrl = returnUrl ?? "/",
}); });
@ -122,16 +122,17 @@ namespace Yavsc.Controllers
[AllowAnonymous] [AllowAnonymous]
[HttpPost(Constants.LoginPath)] [HttpPost(Constants.LoginPath)]
public async Task<IActionResult> SignIn(SignInViewModel model) public async Task<IActionResult> SignIn(SignInModel model)
{ {
if (Request.Method == "POST") if (Request.Method == "POST") // "hGbkk9B94NAae#aG"
{ {
if (model.Provider ==null || model.Provider == "LOCAL") if (model.Provider ==null || model.Provider == "LOCAL")
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var user = _dbContext.Users.Include(u=>u.Membership).FirstOrDefault( var user = _dbContext.Users.Include(u=>u.Membership).FirstOrDefault(
u=>u.UserName == model.UserName); u=>u.Email == model.EMail);
if (user != null) if (user != null)
{ {
@ -149,7 +150,7 @@ namespace Yavsc.Controllers
} }
// This doesn't count login failures towards account lockout // This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true // To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false); var result = await _signInManager.PasswordSignInAsync(model.EMail, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded) if (result.Succeeded)
{ {
@ -171,7 +172,7 @@ namespace Yavsc.Controllers
} }
else else
{ {
ModelState.AddModelError(string.Empty, $"Invalid login attempt. ({model.UserName}, {model.Password})"); ModelState.AddModelError(string.Empty, $"Invalid login attempt. ({model.EMail}, {model.Password})");
return this.ViewOk(model); return this.ViewOk(model);
} }
} }
@ -245,19 +246,11 @@ namespace Yavsc.Controllers
// Send an email with this link // Send an email with this link
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code }, protocol: "https", host: Startup.Authority); var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code }, protocol: "https", host: Startup.Authority);
var emailSent = await _emailSender.SendEmailAsync(model.UserName, model.Email, _localizer["ConfirmYourAccountTitle"], await _emailSender.SendEmailAsync(model.UserName, model.Email, _localizer["ConfirmYourAccountTitle"],
string.Format(_localizer["ConfirmYourAccountBody"], _siteSettings.Title, callbackUrl, _siteSettings.Slogan, _siteSettings.Audience)); string.Format(_localizer["ConfirmYourAccountBody"], _siteSettings.Title, callbackUrl, _siteSettings.Slogan, _siteSettings.Audience));
// No, wait for more than a login pass submission: // No, wait for more than a login pass submission:
// do not await _signInManager.SignInAsync(user, isPersistent: false); // do not await _signInManager.SignInAsync(user, isPersistent: false);
if (emailSent==null)
{
_logger.LogWarning("User created with error sending email confirmation request");
this.NotifyWarning(
"E-mail confirmation",
_localizer["ErrorSendingEmailForConfirm"]
);
}
else
this.NotifyInfo( this.NotifyInfo(
"E-mail confirmation", "E-mail confirmation",
_localizer["EmailSentForConfirm"] _localizer["EmailSentForConfirm"]
@ -305,7 +298,7 @@ namespace Yavsc.Controllers
string.Format(this._localizer["ConfirmYourAccountBody"], string.Format(this._localizer["ConfirmYourAccountBody"],
_siteSettings.Title, callbackUrl, _siteSettings.Slogan, _siteSettings.Title, callbackUrl, _siteSettings.Slogan,
_siteSettings.Audience)); _siteSettings.Audience));
return res; return new EmailSentViewModel { EMail = user.Email, Sent = true, MessageId = res };
} }
private async Task<EmailSentViewModel> SendEMailFactorAsync(ApplicationUser user, string provider) private async Task<EmailSentViewModel> SendEMailFactorAsync(ApplicationUser user, string provider)
@ -318,7 +311,7 @@ namespace Yavsc.Controllers
string.Format(this._localizer["AccountEmailFactorBody"], string.Format(this._localizer["AccountEmailFactorBody"],
_siteSettings.Title, callbackUrl, _siteSettings.Slogan, _siteSettings.Title, callbackUrl, _siteSettings.Slogan,
_siteSettings.Audience, code)); _siteSettings.Audience, code));
return res; return new EmailSentViewModel { EMail = user.Email, Sent = true, MessageId = res };;
} }
// //
// POST: /Account/LogOff // POST: /Account/LogOff
@ -553,10 +546,12 @@ namespace Yavsc.Controllers
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713 // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link // Send an email with this link
var code = await _userManager.GeneratePasswordResetTokenAsync(user); var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code }, var callbackUrl = _siteSettings.Audience + "/Account/ResetPassword/" +
protocol: "https", host: Startup.Authority); HttpUtility.UrlEncode(user.Id) + "/" + HttpUtility.UrlEncode(code);
var sent = await _emailSender.SendEmailAsync(user.UserName, user.Email, _localizer["Reset Password"], var sent = await _emailSender.SendEmailAsync(user.UserName, user.Email, _localizer["Reset Password"],
_localizer["Please reset your password by following this link:"] + " <" + callbackUrl + ">"); _localizer["Please reset your password by "] + " <a href=\"" +
callbackUrl + "\" >following this link</a>");
return View("ForgotPasswordConfirmation", sent); return View("ForgotPasswordConfirmation", sent);
} }
@ -574,21 +569,23 @@ namespace Yavsc.Controllers
} }
// GET: /Account/ResetPassword // GET: /Account/ResetPassword
[HttpGet] [HttpGet("/Account/ResetPassword/{id}/{code}")]
[AllowAnonymous] [AllowAnonymous]
public async Task<IActionResult> ResetPassword(string UserId) public async Task<IActionResult> ResetPassword(string id, string code)
{ {
var user = await _userManager.FindByIdAsync(UserId); var user = await _userManager.FindByIdAsync(id);
if (user==null) return new BadRequestResult(); if (user==null) return new BadRequestResult();
// We just serve the form to reset here. // We just serve the form to reset here.
return View(); return View(new ResetPasswordViewModel { });
} }
// POST: /Account/ResetPassword // POST: /Account/ResetPassword
[HttpPost] [HttpPost("/Account/ResetPassword/{id}/{code}")]
[AllowAnonymous] [AllowAnonymous]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model) public async Task<IActionResult> ResetPassword([FromRoute] string id,
[FromRoute] string code,
ResetPasswordViewModel model)
{ {
if (!ModelState.IsValid) if (!ModelState.IsValid)
{ {
@ -600,7 +597,9 @@ namespace Yavsc.Controllers
// Don't reveal that the user does not exist // Don't reveal that the user does not exist
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account"); return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
} }
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); // code : "CfDJ8DmPlC3R8%2fNMqGlHZHZMwbjaXxgD3GW3H75Ubt+4Sbw%2fn%2fdg9X8Bll+CLIh%2fquI+Z96XEkx7bfrZiB+wpPb+b5%2ffgzgy+cQnKfX9J7%2fLNro+F3uE5JkXSlUc1WqVW2mVQrpWHjx1Dbn2n77TTGym3ttQoECsTR%2foo27dW9U11pmRJuTiwPBJZBOt0ffIRmgDDHh2f0VySTQEwjfRiLdCwctL%2fmh21ympJMKJl5PZnTVs"
var result = await _userManager.ResetPasswordAsync(user,
HttpUtility.UrlDecode(code), model.Password);
if (result.Succeeded) if (result.Succeeded)
{ {

@ -14,6 +14,7 @@ using Yavsc.ViewModels.Calendar;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Services; using Yavsc.Services;
using Yavsc.ViewModels.Manage; using Yavsc.ViewModels.Manage;
using Microsoft.AspNetCore.Identity.UI.Services;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {

@ -7,6 +7,7 @@ using Microsoft.Extensions.Localization;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
using Helpers; using Helpers;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Models; using Models;
@ -14,6 +15,8 @@ namespace Yavsc.Controllers
using Models.Relationship; using Models.Relationship;
using Models.Workflow; using Models.Workflow;
using Services; using Services;
using Yavsc.Interface;
using Yavsc.Settings;
public class CommandController : Controller public class CommandController : Controller
{ {
@ -21,7 +24,7 @@ namespace Yavsc.Controllers
protected ApplicationDbContext _context; protected ApplicationDbContext _context;
protected GoogleAuthSettings _googleSettings; protected GoogleAuthSettings _googleSettings;
protected IYavscMessageSender _MessageSender; protected IYavscMessageSender _MessageSender;
protected IEmailSender _emailSender; protected ITrueEmailSender _emailSender;
protected IStringLocalizer _localizer; protected IStringLocalizer _localizer;
protected SiteSettings _siteSettings; protected SiteSettings _siteSettings;
protected SmtpSettings _smtpSettings; protected SmtpSettings _smtpSettings;
@ -33,7 +36,7 @@ namespace Yavsc.Controllers
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
ICalendarManager calendarManager, ICalendarManager calendarManager,
IStringLocalizer<Yavsc.YavscLocalisation> localizer, IStringLocalizer<Yavsc.YavscLocalisation> localizer,
IEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SmtpSettings> smtpSettings, IOptions<SmtpSettings> smtpSettings,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)

@ -22,6 +22,9 @@ namespace Yavsc.Controllers
using PayPal.PayPalAPIInterfaceService.Model; using PayPal.PayPalAPIInterfaceService.Model;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.UI.Services;
using Yavsc.Interface;
using Yavsc.Settings;
public class HairCutCommandController : CommandController public class HairCutCommandController : CommandController
{ {
@ -32,7 +35,7 @@ namespace Yavsc.Controllers
IYavscMessageSender GCMSender, IYavscMessageSender GCMSender,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
IStringLocalizer<Yavsc.YavscLocalisation> localizer, IStringLocalizer<Yavsc.YavscLocalisation> localizer,
IEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SmtpSettings> smtpSettings, IOptions<SmtpSettings> smtpSettings,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
ICalendarManager calManager, ICalendarManager calManager,

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<key id="ab1c0839-2078-41c1-b8be-72fa977278d4" version="1">
<creationDate>2023-04-05T20:58:19.6046151Z</creationDate>
<activationDate>2023-04-05T20:58:19.598076Z</activationDate>
<expirationDate>2023-07-04T20:58:19.598076Z</expirationDate>
<descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
<descriptor>
<encryption algorithm="AES_256_CBC" />
<validation algorithm="HMACSHA256" />
<masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
<!-- Warning: the key below is in an unencrypted form. -->
<value>fc3m/BUIbMxSbIjZ7fBO4iIiQZVjA5IVlrEFCwBsBJDvYbJJkaCphoeP15iJEsd2Zv3x946xfNyo+c+9WU2xoQ==</value>
</masterKey>
</descriptor>
</descriptor>
</key>

@ -0,0 +1,15 @@
namespace Yavsc.Interface
{
public interface ITrueEmailSender
{
//
// Résumé :
// This API supports the ASP.NET Core Identity default UI infrastructure and is
// not intended to be used directly from your code. This API may change or be removed
// in future releases.
Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,219 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class userreload : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Activities_Activities_ParentCode",
table: "Activities");
migrationBuilder.DropForeignKey(
name: "FK_AspNetUsers_BankIdentity_BankInfoId",
table: "AspNetUsers");
migrationBuilder.DropForeignKey(
name: "FK_AspNetUsers_Locations_PostalAddressId",
table: "AspNetUsers");
migrationBuilder.DropIndex(
name: "IX_AspNetUsers_BankInfoId",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "BankInfoId",
table: "AspNetUsers");
migrationBuilder.Sql("delete from \"BankIdentity\"");
migrationBuilder.AddColumn<string>(
name: "UserId",
table: "BankIdentity",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AlterColumn<long>(
name: "PostalAddressId",
table: "AspNetUsers",
type: "bigint",
nullable: true,
oldClrType: typeof(long),
oldType: "bigint");
migrationBuilder.AlterColumn<string>(
name: "Email",
table: "AspNetUsers",
type: "character varying(256)",
maxLength: 256,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(256)",
oldMaxLength: 256,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "DedicatedGoogleCalendar",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512);
migrationBuilder.AlterColumn<string>(
name: "ParentCode",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddUniqueConstraint(
name: "AK_AspNetUsers_Email",
table: "AspNetUsers",
column: "Email");
migrationBuilder.CreateIndex(
name: "IX_BankIdentity_UserId",
table: "BankIdentity",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_Activities_Activities_ParentCode",
table: "Activities",
column: "ParentCode",
principalTable: "Activities",
principalColumn: "Code");
migrationBuilder.AddForeignKey(
name: "FK_AspNetUsers_Locations_PostalAddressId",
table: "AspNetUsers",
column: "PostalAddressId",
principalTable: "Locations",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_BankIdentity_AspNetUsers_UserId",
table: "BankIdentity",
column: "UserId",
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Activities_Activities_ParentCode",
table: "Activities");
migrationBuilder.DropForeignKey(
name: "FK_AspNetUsers_Locations_PostalAddressId",
table: "AspNetUsers");
migrationBuilder.DropForeignKey(
name: "FK_BankIdentity_AspNetUsers_UserId",
table: "BankIdentity");
migrationBuilder.DropIndex(
name: "IX_BankIdentity_UserId",
table: "BankIdentity");
migrationBuilder.DropUniqueConstraint(
name: "AK_AspNetUsers_Email",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "UserId",
table: "BankIdentity");
migrationBuilder.AlterColumn<long>(
name: "PostalAddressId",
table: "AspNetUsers",
type: "bigint",
nullable: false,
defaultValue: 0L,
oldClrType: typeof(long),
oldType: "bigint",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Email",
table: "AspNetUsers",
type: "character varying(256)",
maxLength: 256,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(256)",
oldMaxLength: 256);
migrationBuilder.AlterColumn<string>(
name: "DedicatedGoogleCalendar",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512,
oldNullable: true);
migrationBuilder.AddColumn<long>(
name: "BankInfoId",
table: "AspNetUsers",
type: "bigint",
nullable: false,
defaultValue: 0L);
migrationBuilder.AlterColumn<string>(
name: "ParentCode",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUsers_BankInfoId",
table: "AspNetUsers",
column: "BankInfoId");
migrationBuilder.AddForeignKey(
name: "FK_Activities_Activities_ParentCode",
table: "Activities",
column: "ParentCode",
principalTable: "Activities",
principalColumn: "Code",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_AspNetUsers_BankIdentity_BankInfoId",
table: "AspNetUsers",
column: "BankInfoId",
principalTable: "BankIdentity",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_AspNetUsers_Locations_PostalAddressId",
table: "AspNetUsers",
column: "PostalAddressId",
principalTable: "Locations",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,42 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class nullableFullname : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "FullName",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512);
migrationBuilder.Sql("update \"AspNetUsers\" SET \"UserName\" = \"Email\";");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "FullName",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512,
oldNullable: true);
}
}
}

@ -294,9 +294,6 @@ namespace Yavsc.Migrations
.HasColumnType("character varying(512)") .HasColumnType("character varying(512)")
.HasDefaultValue("/images/Users/icon_user.png"); .HasDefaultValue("/images/Users/icon_user.png");
b.Property<long>("BankInfoId")
.HasColumnType("bigint");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("text"); .HasColumnType("text");
@ -308,7 +305,6 @@ namespace Yavsc.Migrations
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("DedicatedGoogleCalendar") b.Property<string>("DedicatedGoogleCalendar")
.IsRequired()
.HasMaxLength(512) .HasMaxLength(512)
.HasColumnType("character varying(512)"); .HasColumnType("character varying(512)");
@ -321,6 +317,7 @@ namespace Yavsc.Migrations
.HasColumnType("bigint"); .HasColumnType("bigint");
b.Property<string>("Email") b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("character varying(256)"); .HasColumnType("character varying(256)");
@ -328,7 +325,6 @@ namespace Yavsc.Migrations
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<string>("FullName") b.Property<string>("FullName")
.IsRequired()
.HasMaxLength(512) .HasMaxLength(512)
.HasColumnType("character varying(512)"); .HasColumnType("character varying(512)");
@ -359,7 +355,6 @@ namespace Yavsc.Migrations
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<long?>("PostalAddressId") b.Property<long?>("PostalAddressId")
.IsRequired()
.HasColumnType("bigint"); .HasColumnType("bigint");
b.Property<string>("SecurityStamp") b.Property<string>("SecurityStamp")
@ -382,7 +377,7 @@ namespace Yavsc.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("BankInfoId"); b.HasAlternateKey("Email");
b.HasIndex("NormalizedEmail") b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex"); .HasDatabaseName("EmailIndex");
@ -547,12 +542,18 @@ namespace Yavsc.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("WicketCode") b.Property<string>("WicketCode")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("BankIdentity"); b.ToTable("BankIdentity");
}); });
@ -2099,7 +2100,6 @@ namespace Yavsc.Migrations
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("ParentCode") b.Property<string>("ParentCode")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("Photo") b.Property<string>("Photo")
@ -2685,19 +2685,9 @@ namespace Yavsc.Migrations
modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => modelBuilder.Entity("Yavsc.Models.ApplicationUser", b =>
{ {
b.HasOne("Yavsc.Models.Bank.BankIdentity", "BankInfo")
.WithMany()
.HasForeignKey("BankInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress")
.WithMany() .WithMany()
.HasForeignKey("PostalAddressId") .HasForeignKey("PostalAddressId");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("BankInfo");
b.Navigation("PostalAddress"); b.Navigation("PostalAddress");
}); });
@ -2713,6 +2703,17 @@ namespace Yavsc.Migrations
b.Navigation("Balance"); b.Navigation("Balance");
}); });
modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b =>
{
b.HasOne("Yavsc.Models.ApplicationUser", "User")
.WithMany("BankInfo")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b =>
{ {
b.HasOne("Yavsc.Models.Billing.Estimate", null) b.HasOne("Yavsc.Models.Billing.Estimate", null)
@ -3231,9 +3232,7 @@ namespace Yavsc.Migrations
{ {
b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") b.HasOne("Yavsc.Models.Workflow.Activity", "Parent")
.WithMany("Children") .WithMany("Children")
.HasForeignKey("ParentCode") .HasForeignKey("ParentCode");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Parent"); b.Navigation("Parent");
}); });
@ -3434,6 +3433,8 @@ namespace Yavsc.Migrations
b.Navigation("AccountBalance") b.Navigation("AccountBalance")
.IsRequired(); .IsRequired();
b.Navigation("BankInfo");
b.Navigation("BlackList"); b.Navigation("BlackList");
b.Navigation("Book"); b.Navigation("Book");

@ -52,10 +52,14 @@ namespace Yavsc.Models
builder.Entity<DeviceDeclaration>().Property(x => x.DeclarationDate).HasDefaultValueSql("LOCALTIMESTAMP"); builder.Entity<DeviceDeclaration>().Property(x => x.DeclarationDate).HasDefaultValueSql("LOCALTIMESTAMP");
builder.Entity<BlogTag>().HasKey(x => new { x.PostId, x.TagId }); builder.Entity<BlogTag>().HasKey(x => new { x.PostId, x.TagId });
builder.Entity<ApplicationUser>().Property(u => u.FullName).IsRequired(false);
builder.Entity<ApplicationUser>().Property(u => u.DedicatedGoogleCalendar).IsRequired(false);
builder.Entity<ApplicationUser>().HasMany<ChatConnection>(c => c.Connections); builder.Entity<ApplicationUser>().HasMany<ChatConnection>(c => c.Connections);
builder.Entity<ApplicationUser>().Property(u => u.Avatar).HasDefaultValue(Constants.DefaultAvatar); builder.Entity<ApplicationUser>().Property(u => u.Avatar).HasDefaultValue(Constants.DefaultAvatar);
builder.Entity<ApplicationUser>().Property(u => u.DiskQuota).HasDefaultValue(Constants.DefaultFSQ); builder.Entity<ApplicationUser>().Property(u => u.DiskQuota).HasDefaultValue(Constants.DefaultFSQ);
builder.Entity<ApplicationUser>().HasAlternateKey(u => u.Email);
builder.Entity<BlackListed>().HasOne<ApplicationUser>(bl => bl.User);
builder.Entity<BlackListed>().HasOne<ApplicationUser>(bl => bl.Owner);
builder.Entity<UserActivity>().HasKey(u => new { u.DoesCode, u.UserId }); builder.Entity<UserActivity>().HasKey(u => new { u.DoesCode, u.UserId });
builder.Entity<Instrumentation>().HasKey(u => new { u.InstrumentId, u.UserId }); builder.Entity<Instrumentation>().HasKey(u => new { u.InstrumentId, u.UserId });
builder.Entity<CircleAuthorizationToBlogPost>().HasKey(a => new { a.CircleId, a.BlogPostId }); builder.Entity<CircleAuthorizationToBlogPost>().HasKey(a => new { a.CircleId, a.BlogPostId });
@ -67,8 +71,6 @@ namespace Yavsc.Models
builder.Entity<Models.Cratie.Option>().HasKey(o => new { o.Code, o.CodeScrutin }); builder.Entity<Models.Cratie.Option>().HasKey(o => new { o.Code, o.CodeScrutin });
builder.Entity<Notification>().Property(n => n.icon).HasDefaultValue("exclam"); builder.Entity<Notification>().Property(n => n.icon).HasDefaultValue("exclam");
builder.Entity<ChatRoomAccess>().HasKey(p => new { room = p.ChannelName, user = p.UserId }); builder.Entity<ChatRoomAccess>().HasKey(p => new { room = p.ChannelName, user = p.UserId });
builder.Entity<BlackListed>().HasOne<ApplicationUser>(bl => bl.User);
builder.Entity<BlackListed>().HasOne<ApplicationUser>(bl => bl.Owner);
builder.Entity<BlogTrad>().HasKey(tr => new { post = tr.PostId, lang = tr.Lang }); builder.Entity<BlogTrad>().HasKey(tr => new { post = tr.PostId, lang = tr.Lang });
builder.Entity<InstrumentRating>().HasAlternateKey(i => new { Instrument= i.InstrumentId, owner = i.OwnerId }); builder.Entity<InstrumentRating>().HasAlternateKey(i => new { Instrument= i.InstrumentId, owner = i.OwnerId });

@ -0,0 +1,3 @@
Support for ASP.NET Core Identity was added to your project.
For setup and configuration information, see https://go.microsoft.com/fwlink/?linkid=2116645.

@ -15,6 +15,7 @@ using System.Reflection;
using Yavsc.Abstract.Templates; using Yavsc.Abstract.Templates;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using RazorEngine.Configuration; using RazorEngine.Configuration;
using Yavsc.Interface;
namespace Yavsc.Lib namespace Yavsc.Lib
{ {
@ -30,16 +31,14 @@ namespace Yavsc.Lib
readonly IStringLocalizer<EMailer> stringLocalizer; readonly IStringLocalizer<EMailer> stringLocalizer;
readonly ApplicationDbContext dbContext; readonly ApplicationDbContext dbContext;
readonly IEmailSender mailSender;
readonly ILogger logger; readonly ILogger logger;
public EMailer(ApplicationDbContext context, IEmailSender sender, public EMailer(ApplicationDbContext context,
IStringLocalizer<EMailer> localizer, IStringLocalizer<EMailer> localizer,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {
stringLocalizer = localizer; stringLocalizer = localizer;
mailSender = sender;
logger = loggerFactory.CreateLogger<EMailer>(); logger = loggerFactory.CreateLogger<EMailer>();

@ -1,3 +1,4 @@
using System.Text;
using System; using System;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -7,10 +8,13 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MimeKit; using MimeKit;
using Yavsc.Abstract.Manage; using Yavsc.Abstract.Manage;
using Microsoft.AspNetCore.Identity.UI.Services;
using Yavsc.Interface;
using Yavsc.Settings;
namespace Yavsc.Services namespace Yavsc.Services
{ {
public class MailSender : IEmailSender public class MailSender : IEmailSender, ITrueEmailSender
{ {
readonly SiteSettings siteSettings; readonly SiteSettings siteSettings;
readonly SmtpSettings smtpSettings; readonly SmtpSettings smtpSettings;
@ -22,10 +26,9 @@ namespace Yavsc.Services
ILoggerFactory loggerFactory ILoggerFactory loggerFactory
) )
{ {
siteSettings = sitesOptions?.Value; siteSettings = sitesOptions.Value;
smtpSettings = smtpOptions?.Value; smtpSettings = smtpOptions.Value;
logger = loggerFactory.CreateLogger<MailSender>(); logger = loggerFactory.CreateLogger<MailSender>();
} }
/// <summary> /// <summary>
@ -39,52 +42,42 @@ namespace Yavsc.Services
/// </returns> /// </returns>
public async Task<EmailSentViewModel> SendEmailAsync(string username, string email, string subject, string message) public async Task SendEmailAsync(string email, string subject, string htmlMessage)
{ {
EmailSentViewModel model = new EmailSentViewModel{ EMail = email }; await SendEmailAsync("", email, subject, htmlMessage);
try }
{
logger.LogInformation($"sendEmail for {email} : {message}");
MimeMessage msg = new MimeMessage();
msg.From.Add(new MailboxAddress(
siteSettings.Owner.Name,
siteSettings.Owner.EMail));
msg.To.Add(new MailboxAddress(username, email));
msg.Body = new TextPart("plain")
{
Text = message
};
msg.Subject = subject;
msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId(
siteSettings.Authority
);
using (SmtpClient sc = new SmtpClient())
{
sc.Connect(
smtpSettings.Host,
smtpSettings.Port,
SecureSocketOptions.Auto);
if (smtpSettings.UserName!=null) { public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage)
NetworkCredential creds = new NetworkCredential( {
smtpSettings.UserName, smtpSettings.Password, smtpSettings.Domain); logger.LogInformation($"SendEmail for {email} : {subject}");
await sc.AuthenticateAsync(System.Text.Encoding.UTF8, creds, System.Threading.CancellationToken.None); MimeMessage msg = new ();
} msg.From.Add(new MailboxAddress(siteSettings.Owner.Name,
siteSettings.Owner.EMail));
msg.To.Add(new MailboxAddress(name, email));
msg.Body = new TextPart("html")
{
Text = htmlMessage
};
msg.Subject = subject;
msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId(
siteSettings.Authority
);
using (SmtpClient sc = new ())
{
sc.Connect(
smtpSettings.Server,
smtpSettings.Port,
SecureSocketOptions.Auto);
await sc.SendAsync(msg); if (smtpSettings.UserName!=null) {
model.MessageId = msg.MessageId; NetworkCredential creds = new (
model.Sent = true; // a duplicate info to remove from the view model, that equals to MessageId == null smtpSettings.UserName, smtpSettings.Password);
logger.LogInformation($"Sent : {msg}"); await sc.AuthenticateAsync(System.Text.Encoding.UTF8, creds, System.Threading.CancellationToken.None);
} }
await sc.SendAsync(msg);
logger.LogInformation($"Sent : {msg.MessageId}");
} }
catch (Exception ex) return msg.MessageId;
{
model.Sent = false;
model.ErrorMessage = ex.Message;
return model;
}
return model;
} }
} }
} }

@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using Yavsc.Interface;
using Yavsc.Interfaces.Workflow; using Yavsc.Interfaces.Workflow;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Google.Messaging; using Yavsc.Models.Google.Messaging;
@ -12,7 +14,7 @@ namespace Yavsc.Services
public class YavscMessageSender : IYavscMessageSender public class YavscMessageSender : IYavscMessageSender
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
readonly IEmailSender _emailSender; readonly ITrueEmailSender _emailSender;
readonly SiteSettings siteSettings; readonly SiteSettings siteSettings;
readonly ApplicationDbContext _dbContext; readonly ApplicationDbContext _dbContext;
readonly IConnexionManager _cxManager; readonly IConnexionManager _cxManager;
@ -21,7 +23,7 @@ namespace Yavsc.Services
public YavscMessageSender( public YavscMessageSender(
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IOptions<SiteSettings> sitesOptions, IOptions<SiteSettings> sitesOptions,
IEmailSender emailSender, ITrueEmailSender emailSender,
ApplicationDbContext dbContext, ApplicationDbContext dbContext,
IConnexionManager cxManager, IConnexionManager cxManager,
IHubContext<ChatHub> hubContext IHubContext<ChatHub> hubContext
@ -90,24 +92,12 @@ namespace Yavsc.Services
_logger.LogDebug($"Sending to {user.UserName} <{user.Email}> : {body}"); _logger.LogDebug($"Sending to {user.UserName} <{user.Email}> : {body}");
var mailSent = await _emailSender.SendEmailAsync(
user.UserName,
user.Email,
$"{ev.Sender} (un client) vous demande un rendez-vous",
body + Environment.NewLine
);
if (!mailSent.Sent) result.message_id = await _emailSender.SendEmailAsync(user.UserName, user.Email,
{ $"{ev.Sender} (un client) vous demande un rendez-vous",
result.message_id = mailSent.MessageId; body + Environment.NewLine);
result.error = mailSent.ErrorMessage;
response.failure++;
}
else
{
result.message_id = mailSent.MessageId;
response.success++; response.success++;
}
var cxids = _cxManager.GetConnexionIds(user.UserName); var cxids = _cxManager.GetConnexionIds(user.UserName);
if (cxids == null) if (cxids == null)
{ {

@ -1,15 +1,13 @@
namespace Yavsc.Settings
namespace Yavsc
{ {
public class SmtpSettings public class SmtpSettings
{ {
public string Host { get; set; } public string Server { get; set; }
public int Port { get; set; } public int Port { get; set; }
public string SenderName { get; set; }
public string SenderEmail { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string Password { get; set; } public string Password { get; set; }
public string Domain { get; set; }
public bool EnableSSL { get; set; }
} }
} }

@ -0,0 +1,8 @@
namespace Yavsc
{
public class DataProtectionSettings
{
public Dictionary<string,string> Keys { get; set; }
public int ExpiresInHours { get; set; }
}
}

@ -1,84 +0,0 @@
using System;
using System.IO;
using System.IO.Pipelines;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
namespace Yavsc
{
class YaSendFileWrapper : IHttpResponseBodyFeature
{
private readonly Stream _output;
private readonly ILogger _logger;
internal YaSendFileWrapper(Stream output, ILogger logger)
{
_output = output;
_logger = logger;
}
public async Task SendFileAsync(string fileName, long offset, long? length, CancellationToken cancel)
{
cancel.ThrowIfCancellationRequested();
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentNullException("fileName");
}
if (!File.Exists(fileName))
{
throw new FileNotFoundException(string.Empty, fileName);
}
FileInfo fileInfo = new FileInfo(fileName);
if (offset < 0 || offset > fileInfo.Length)
{
throw new ArgumentOutOfRangeException("offset", offset, string.Empty);
}
if (length.HasValue && (length.Value < 0 || length.Value > fileInfo.Length - offset))
{
throw new ArgumentOutOfRangeException("length", length, string.Empty);
}
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, maxbufferlen, FileOptions.Asynchronous | FileOptions.SequentialScan);
try
{
fileStream.Seek(offset, SeekOrigin.Begin);
_logger.LogInformation(string.Format("Copying bytes range:{0},{1} filename:{2} ", offset, (!length.HasValue) ? null : (offset + length), fileName));
// await CopyToAsync(fileStream, _output, length, cancel);
await CopyToAsync(fileStream, _output);
}
finally
{
fileStream.Dispose();
}
}
private const int maxbufferlen = 65536;
public Stream Stream => throw new NotImplementedException();
public PipeWriter Writer => throw new NotImplementedException();
private async Task CopyToAsync(FileStream fileStream, Stream output)
{
await Task.Run(() => fileStream.CopyTo(output, maxbufferlen));
}
public void DisableBuffering()
{
throw new NotImplementedException();
}
public Task StartAsync(CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task CompleteAsync()
{
throw new NotImplementedException();
}
}
}

@ -7,30 +7,6 @@ using Yavsc.ViewModels.Auth;
namespace Yavsc namespace Yavsc
{ {
public static class YaFileSServerExtenstions
{
public static IApplicationBuilder UseYaFileServer(this IApplicationBuilder builder, FileServerOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
if (options.EnableDefaultFiles)
{
builder = builder.UseDefaultFiles(options.DefaultFilesOptions);
}
if (options.EnableDirectoryBrowsing)
{
builder = builder.UseDirectoryBrowser(options.DirectoryBrowserOptions);
}
return builder.UseYaSendFileFallback().UseStaticFiles(options.StaticFileOptions);
}
public static IApplicationBuilder UseYaSendFileFallback(this IApplicationBuilder builder)
{
return builder.UseMiddleware<YaSendFileMiddleware>(new object[0]);
}
}
public partial class Startup public partial class Startup
{ {

@ -11,13 +11,15 @@ using Newtonsoft.Json;
using Google.Apis.Util.Store; using Google.Apis.Util.Store;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Yavsc.Helpers; using Yavsc.Helpers;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Services; using Yavsc.Services;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Yavsc.Interface;
using Yavsc.Settings;
using Microsoft.AspNetCore.DataProtection;
namespace Yavsc namespace Yavsc
{ {
@ -29,6 +31,7 @@ namespace Yavsc
public static string Authority { get; private set; } public static string Authority { get; private set; }
public static string Temp { get; set; } public static string Temp { get; set; }
public static SiteSettings SiteSetup { get; private set; } public static SiteSettings SiteSetup { get; private set; }
public SmtpSettings SmtpSetup { get; private set; }
public static GoogleServiceAccount GServiceAccount { get; private set; } public static GoogleServiceAccount GServiceAccount { get; private set; }
public static string HostingFullName { get; set; } public static string HostingFullName { get; set; }
@ -38,38 +41,39 @@ namespace Yavsc
public Startup( IWebHostEnvironment env) public Startup(IWebHostEnvironment env)
{ {
AppDomain.CurrentDomain.UnhandledException += OnUnHandledException; AppDomain.CurrentDomain.UnhandledException += OnUnHandledException;
var devtag = env.IsDevelopment() ? "D" : ""; string devtag = env.IsDevelopment() ? "D" : "";
var prodtag = env.IsProduction() ? "P" : ""; string prodtag = env.IsProduction() ? "P" : "";
var stagetag = env.IsStaging() ? "S" : ""; string stagetag = env.IsStaging() ? "S" : "";
HostingFullName = $"{env.EnvironmentName} [{prodtag}/{devtag}/{stagetag}]"; HostingFullName = $"{env.EnvironmentName} [{prodtag}/{devtag}/{stagetag}]";
// Set up configuration sources. // Set up configuration sources.
var builder = new ConfigurationBuilder() IConfigurationBuilder builder = new ConfigurationBuilder()
.AddEnvironmentVariables() .AddEnvironmentVariables()
.AddJsonFile("appsettings.json") .AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
builder.AddEnvironmentVariables(); _ = builder.AddEnvironmentVariables();
Configuration = builder.Build(); Configuration = builder.Build();
var auth = Configuration["Site:Authority"];
var cxstr = Configuration["ConnectionStrings:Default"];
ConnectionString = cxstr; ConnectionString = Configuration["ConnectionStrings:Default"];
AppDomain.CurrentDomain.SetData(Constants.YavscConnectionStringEnvName, ConnectionString); AppDomain.CurrentDomain.SetData(Constants.YavscConnectionStringEnvName, ConnectionString);
var googleClientFile = Configuration["Authentication:Google:GoogleWebClientJson"]; string? googleClientFile = Configuration["Authentication:Google:GoogleWebClientJson"];
var googleServiceAccountJsonFile = Configuration["Authentication:Google:GoogleServiceAccountJson"]; string? googleServiceAccountJsonFile = Configuration["Authentication:Google:GoogleServiceAccountJson"];
if (googleClientFile != null) if (googleClientFile != null)
{
GoogleWebClientConfiguration = new ConfigurationBuilder().AddJsonFile(googleClientFile).Build(); GoogleWebClientConfiguration = new ConfigurationBuilder().AddJsonFile(googleClientFile).Build();
}
if (googleServiceAccountJsonFile != null) if (googleServiceAccountJsonFile != null)
{ {
var safile = new FileInfo(googleServiceAccountJsonFile); FileInfo safile = new FileInfo(googleServiceAccountJsonFile);
GServiceAccount = JsonConvert.DeserializeObject<GoogleServiceAccount>(safile.OpenText().ReadToEnd()); GServiceAccount = JsonConvert.DeserializeObject<GoogleServiceAccount>(safile.OpenText().ReadToEnd());
} }
} }
@ -89,23 +93,24 @@ namespace Yavsc
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddSignalR();
// Database connection
services.AddOptions(); IConfigurationSection siteSettings = Configuration.GetSection("Site");
var siteSettings = Configuration.GetSection("Site"); _ = services.Configure<SiteSettings>(siteSettings);
services.Configure<SiteSettings>(siteSettings); IConfigurationSection smtpSettings = Configuration.GetSection("Smtp");
var smtpSettings = Configuration.GetSection("Smtp"); _ = services.Configure<SmtpSettings>(smtpSettings);
services.Configure<SmtpSettings>(smtpSettings); IConfigurationSection protectionSettings = Configuration.GetSection("DataProtection");
var googleSettings = Configuration.GetSection("Authentication").GetSection("Google"); _ = services.Configure<DataProtectionSettings>(smtpSettings);
services.Configure<GoogleAuthSettings>(googleSettings);
var cinfoSettings = Configuration.GetSection("Authentication").GetSection("Societeinfo"); IConfigurationSection googleSettings = Configuration.GetSection("Authentication").GetSection("Google");
services.Configure<CompanyInfoSettings>(cinfoSettings); _ = services.Configure<GoogleAuthSettings>(googleSettings);
var oauthFacebookSettings = Configuration.GetSection("Authentication").GetSection("Facebook"); IConfigurationSection cinfoSettings = Configuration.GetSection("Authentication").GetSection("Societeinfo");
services.Configure<FacebookOAuth2AppSettings>(oauthFacebookSettings); _ = services.Configure<CompanyInfoSettings>(cinfoSettings);
var paypalSettings = Configuration.GetSection("Authentication").GetSection("PayPal"); IConfigurationSection oauthFacebookSettings = Configuration.GetSection("Authentication").GetSection("Facebook");
services.Configure<PayPalSettings>(paypalSettings); _ = services.Configure<FacebookOAuth2AppSettings>(oauthFacebookSettings);
IConfigurationSection paypalSettings = Configuration.GetSection("Authentication").GetSection("PayPal");
_ = services.Configure<PayPalSettings>(paypalSettings);
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>))); services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>)));
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>))); services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>)));
@ -114,16 +119,16 @@ namespace Yavsc
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<RequestLocalizationOptions>), typeof(OptionsManager<RequestLocalizationOptions>))); services.Add(ServiceDescriptor.Singleton(typeof(IOptions<RequestLocalizationOptions>), typeof(OptionsManager<RequestLocalizationOptions>)));
services.Add(ServiceDescriptor.Singleton(typeof(IDiskUsageTracker), typeof(DiskUsageTracker))); services.Add(ServiceDescriptor.Singleton(typeof(IDiskUsageTracker), typeof(DiskUsageTracker)));
services.Configure<RequestLocalizationOptions>(options => _ = services.Configure<RequestLocalizationOptions>(options =>
{ {
var supportedCultures = new[] CultureInfo[] supportedCultures = new[]
{ {
new CultureInfo("en"), new CultureInfo("en"),
new CultureInfo("fr"), new CultureInfo("fr"),
new CultureInfo("pt") new CultureInfo("pt")
}; };
var supportedUICultures = new[] CultureInfo[] supportedUICultures = new[]
{ {
new CultureInfo("fr"), new CultureInfo("fr"),
new CultureInfo("en"), new CultureInfo("en"),
@ -145,56 +150,36 @@ namespace Yavsc
}; };
}); });
// Add framework services. services.AddSignalR();
services.AddEntityFrameworkNpgsql()
.AddDbContext<ApplicationDbContext>();
services.AddCors( services.AddOptions();
options => _ = services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder =>
{ {
builder.WithOrigins("*"); options.AddPolicy("CorsPolicy", builder =>
{
_ = builder.WithOrigins("*");
});
}); });
}
);
// Add session related services.
services.AddSession();
// Add the system clock service // Add the system clock service
services.AddSingleton<ISystemClock, SystemClock>(); _ = services.AddSingleton<ISystemClock, SystemClock>();
services.AddAuthorization(options => _ = services.AddSingleton<IConnexionManager, HubConnectionManager>();
{ _ = services.AddSingleton<ILiveProcessor, LiveProcessor>();
_ = services.AddSingleton<IFileSystemAuthManager, FileSystemAuthManager>();
// Add framework services.
/*services.AddSingleton<IAuthorizationHandler, HasBadgeHandler>();
options.AddPolicy("AdministratorOnly", policy =>
{
policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Constants.AdminGroupName);
});
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes("yavsc")
.RequireAuthenticatedUser().Build());
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
});
services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options =>
{
options.Authority = siteSettings.GetValue<string>("ExternalUrl");
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
/* FIXME services.AddSingleton<IAuthorizationHandler, HasBadgeHandler>();
services.AddSingleton<IAuthorizationHandler, HasTemporaryPassHandler>(); services.AddSingleton<IAuthorizationHandler, HasTemporaryPassHandler>();
services.AddSingleton<IAuthorizationHandler, BlogEditHandler>(); services.AddSingleton<IAuthorizationHandler, BlogEditHandler>();
services.AddSingleton<IAuthorizationHandler, BlogViewHandler>(); services.AddSingleton<IAuthorizationHandler, BlogViewHandler>();
@ -202,13 +187,18 @@ namespace Yavsc
services.AddSingleton<IAuthorizationHandler, BillViewHandler>(); services.AddSingleton<IAuthorizationHandler, BillViewHandler>();
services.AddSingleton<IAuthorizationHandler, PostUserFileHandler>(); services.AddSingleton<IAuthorizationHandler, PostUserFileHandler>();
services.AddSingleton<IAuthorizationHandler, ViewFileHandler>(); services.AddSingleton<IAuthorizationHandler, ViewFileHandler>();
services.AddSingleton<IAuthorizationHandler, SendMessageHandler>(); */ services.AddSingleton<IAuthorizationHandler, SendMessageHandler>();*/
_ = services.AddDbContext<ApplicationDbContext>()
.AddIdentity<ApplicationUser, IdentityRole>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddSingleton<IConnexionManager, HubConnectionManager>();
services.AddSingleton<ILiveProcessor, LiveProcessor>();
services.AddSingleton<IFileSystemAuthManager, FileSystemAuthManager>();
services.AddMvc(config => _ = services.AddMvc(config =>
{ {
/* var policy = new AuthorizationPolicyBuilder() /* var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser() .RequireAuthenticatedUser()
@ -231,31 +221,64 @@ namespace Yavsc
options.ResourcesPath = "Resources"; options.ResourcesPath = "Resources";
}).AddDataAnnotationsLocalization(); }).AddDataAnnotationsLocalization();
// services.AddScoped<LanguageActionFilter>(); // services.AddScoped<LanguageActionFilter>();
// Inject ticket formatting // Inject ticket formatting
services.AddTransient(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>)); // services.AddTransient(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>));
services.AddTransient<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>(); // services.AddTransient<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
services.AddTransient<ISecureDataFormat<AuthenticationTicket>, TicketDataFormat>(); // services.AddTransient<ISecureDataFormat<AuthenticationTicket>, TicketDataFormat>();
// Add application services. // Add application services.
services.AddTransient<IEmailSender, MailSender>(); _ = services.AddTransient<ITrueEmailSender, MailSender>();
services.AddTransient<IYavscMessageSender, YavscMessageSender>(); _ = services.AddTransient<Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, MailSender>();
services.AddTransient<IBillingService, BillingService>(); _ = services.AddTransient<IYavscMessageSender, YavscMessageSender>();
services.AddTransient<IDataStore, FileDataStore>((sp) => new FileDataStore("googledatastore", false)); _ = services.AddTransient<IBillingService, BillingService>();
services.AddTransient<ICalendarManager, CalendarManager>(); _ = services.AddTransient<IDataStore, FileDataStore>((sp) => new FileDataStore("googledatastore", false));
_ = services.AddTransient<ICalendarManager, CalendarManager>();
// TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>(); // TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddLocalization(options => _ = services.AddLocalization(options =>
{ {
options.ResourcesPath = "Resources"; options.ResourcesPath = "Resources";
}); });
var datadi = new DirectoryInfo(protectionSettings.GetSection("Keys").GetValue<string>("Dir"));
// Add session related services.
services.AddSession();
services.AddDataProtection().PersistKeysToFileSystem(datadi);
services.AddIdentity<ApplicationUser, IdentityRole>() services.AddAuthorization(options =>
.AddDefaultTokenProviders() {
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews(); options.AddPolicy("AdministratorOnly", policy =>
{
_ = policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Constants.AdminGroupName);
});
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes("Bearer")
.RequireAuthenticatedUser().Build());
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
});
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = siteSettings.GetValue<string>("Authority");
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
_ = services.AddControllersWithViews()
.AddNewtonsoftJson();
} }
@ -265,10 +288,11 @@ namespace Yavsc
public void Configure( public void Configure(
IApplicationBuilder app, IApplicationBuilder app,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
IOptions<SmtpSettings> smtpSettings,
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
IOptions<PayPalSettings> payPalSettings, IOptions<PayPalSettings> payPalSettings,
IOptions<GoogleAuthSettings> googleSettings, IOptions<GoogleAuthSettings> googleSettings,
IStringLocalizer<Yavsc.YavscLocalisation> localizer, IStringLocalizer<YavscLocalisation> localizer,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IWebHostEnvironment env) IWebHostEnvironment env)
{ {
@ -276,47 +300,52 @@ namespace Yavsc
GoogleSettings = googleSettings.Value; GoogleSettings = googleSettings.Value;
ResourcesHelpers.GlobalLocalizer = localizer; ResourcesHelpers.GlobalLocalizer = localizer;
SiteSetup = siteSettings.Value; SiteSetup = siteSettings.Value;
SmtpSetup = smtpSettings.Value;
Authority = siteSettings.Value.Authority; Authority = siteSettings.Value.Authority;
var blogsDir = siteSettings.Value.Blog; string blogsDir = siteSettings.Value.Blog ?? throw new Exception("blogsDir is not set.");
if (blogsDir == null) throw new Exception("blogsDir is not set."); string billsDir = siteSettings.Value.Bills ?? throw new Exception("billsDir is not set.");
var billsDir = siteSettings.Value.Bills;
if (billsDir == null) throw new Exception("billsDir is not set.");
AbstractFileSystemHelpers.UserFilesDirName = new DirectoryInfo(blogsDir).FullName; AbstractFileSystemHelpers.UserFilesDirName = new DirectoryInfo(blogsDir).FullName;
AbstractFileSystemHelpers.UserBillsDirName = new DirectoryInfo(billsDir).FullName; AbstractFileSystemHelpers.UserBillsDirName = new DirectoryInfo(billsDir).FullName;
Temp = siteSettings.Value.TempDir; Temp = siteSettings.Value.TempDir;
PayPalSettings = payPalSettings.Value; PayPalSettings = payPalSettings.Value;
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
// TODO implement an installation & upgrade procedure // TODO implement an installation & upgrade procedure
// Create required directories // Create required directories
foreach (string dir in new string[] { AbstractFileSystemHelpers.UserFilesDirName, AbstractFileSystemHelpers.UserBillsDirName, SiteSetup.TempDir }) foreach (string dir in new string[] { AbstractFileSystemHelpers.UserFilesDirName, AbstractFileSystemHelpers.UserBillsDirName, SiteSetup.TempDir })
{ {
if (dir == null) throw new Exception(nameof(dir)); if (dir == null)
{
throw new Exception(nameof(dir));
}
DirectoryInfo di = new DirectoryInfo(dir); DirectoryInfo di = new(dir);
if (!di.Exists) di.Create(); if (!di.Exists)
{
di.Create();
}
} }
_logger = loggerFactory.CreateLogger<Startup>(); _logger = loggerFactory.CreateLogger<Startup>();
app.UseStatusCodePagesWithReExecute("/Home/Status/{0}"); _ = app.UseStatusCodePagesWithReExecute("/Home/Status/{0}");
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); _ = app.UseDeveloperExceptionPage();
app.UseWelcomePage("/welcome"); _ = app.UseWelcomePage("/welcome");
app.UseMigrationsEndPoint();
} }
else else
{ {
// For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859 // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
app.UseExceptionHandler("/Home/Error"); _ = app.UseExceptionHandler("/Home/Error");
try try
{ {
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>() using IServiceScope serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
.CreateScope()) .CreateScope();
{ serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>()
serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>() .Database.Migrate();
.Database.Migrate();
}
} }
catch (TargetInvocationException ex) catch (TargetInvocationException ex)
{ {
@ -325,20 +354,23 @@ namespace Yavsc
{ {
// TODO (or not) Hit the developper // TODO (or not) Hit the developper
} }
else throw ex; else
{
throw ex;
}
} }
} }
// before fixing the security protocol, let beleive our lib it's done with it. // before fixing the security protocol, let beleive our lib it's done with it.
var cxmgr = PayPal.Manager.ConnectionManager.Instance; // _ = PayPal.Manager.ConnectionManager.Instance;
// then, fix it. // then, fix it.
// ServicePointManager.SecurityProtocol = (SecurityProtocolType)0xC00; // Tls12, required by PayPal // ServicePointManager.SecurityProtocol = (SecurityProtocolType)0xC00; // Tls12, required by PayPal
app.UseSession(); // _ = app.UseSession();
ConfigureFileServerApp(app, SiteSetup, env, authorizationService); ConfigureFileServerApp(app, SiteSetup, env, authorizationService);
app.UseRequestLocalization(); _ = app.UseRequestLocalization();
ConfigureWorkflow(); ConfigureWorkflow();
ConfigureWebSocketsApp(app); ConfigureWebSocketsApp(app);
@ -349,8 +381,11 @@ Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.
CheckApp(env, loggerFactory); CheckApp(env, loggerFactory);
app.UseStatusCodePages().UseStaticFiles().UseAuthentication(); app.UseSession();
app.UseMvcWithDefaultRoute();
_ = app.UseStatusCodePages().UseStaticFiles().UseAuthentication();
_ = app.UseMvcWithDefaultRoute();
} }
} }

@ -1,6 +0,0 @@
namespace Yavsc
{
internal class UserTokenProvider
{
}
}

@ -1,54 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
namespace Yavsc
{
public class YaSendFileMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
//
// Résumé :
// Creates a new instance of the SendFileMiddleware.
//
// Paramètres :
// next:
// The next middleware in the pipeline.
//
// loggerFactory:
// An Microsoft.Extensions.Logging.ILoggerFactory instance used to create loggers.
public YaSendFileMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
if (loggerFactory == null)
{
throw new ArgumentNullException("loggerFactory");
}
_next = next;
_logger = loggerFactory.CreateLogger<YaSendFileMiddleware>();
}
public Task Invoke(HttpContext context)
{
if (context.Response.StatusCode < 400 || context.Response.StatusCode >= 600 )
{
if (context.Features.Get<YaSendFileWrapper>() == null)
{
context.Features.Set(new YaSendFileWrapper(context.Response.Body, _logger));
}
}
return _next(context);
}
}
}

@ -6,7 +6,7 @@
<h2>@ViewData["Title"]</h2> <h2>@ViewData["Title"]</h2>
<form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal" role="form"> <form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal" role="form">
<h4>Enter your user name or e-mail."]</h4> <h4>Enter your user name or e-mail.</h4>
<hr /> <hr />
<div asp-validation-summary="All" class="text-danger"></div> <div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group"> <div class="form-group">

@ -4,5 +4,5 @@
<h2>@ViewData["Title"].</h2> <h2>@ViewData["Title"].</h2>
<p> <p>
PleaseCheckYourEmail"] PleaseCheckYourEmail
</p> </p>

@ -9,7 +9,6 @@
<h4>Reset your password.</h4> <h4>Reset your password.</h4>
<hr /> <hr />
<div asp-validation-summary="All" class="text-danger"></div> <div asp-validation-summary="All" class="text-danger"></div>
<input asp-for="Code" type="hidden" />
<div class="form-group"> <div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label> <label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10"> <div class="col-md-10">

@ -34,7 +34,7 @@
<div class="col-md-offset-2 col-md-10"> <div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Change password</button> <button type="submit" class="btn btn-default">Change password</button>
<a asp-action="ForgotPassword" asp-controller="Account">Forgot your password?"]</a> <a asp-action="ForgotPassword" asp-controller="Account">Forgot your password?</a>
</div> </div>
</div> </div>
</form> </form>

@ -1,7 +1,7 @@
 
@using Yavsc.ViewModels.Account @using Yavsc.ViewModels.Account
@model SignInViewModel @model SignInModel
@{ @{
ViewData["Title"] = "Log in"; ViewData["Title"] = "Log in";
} }
@ -11,20 +11,19 @@
<hr/> <hr/>
<h2 class="lead text-left">Use a local account to log in</h2> <h2 class="lead text-left">Use a local account to log in</h2>
<form action="@Constants.LoginPath" method="post" class="form-horizontal" role="form"> <form asp-action="SignIn" class="form-horizontal" role="form">
<div asp-validation-summary="All" class="text-danger"></div> <div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group"> <div class="form-group">
<label for="UserName" class="col-md-2 control-label">UserName</label> <label for="EMail" class="col-md-2 control-label">EMail</label>
<div class="col-md-10"> <div class="col-md-10">
<input asp-for="UserName" class="form-control" /> <input asp-for="EMail" class="form-control" autocomplete="email" aria-required="true" placeholder="name@example.com" />
<span asp-validation-for="UserName" class="text-danger"></span> <span asp-validation-for="EMail" class="text-danger"></span>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="Password" class="col-md-2 control-label">Password</label> <label for="Password" class="col-md-2 control-label">Password</label>
<div class="col-md-10"> <div class="col-md-10">
<input asp-for="Password" class="form-control" /> <input asp-for="Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="password" />
<span asp-validation-for="Password" class="text-danger"></span> <span asp-validation-for="Password" class="text-danger"></span>
</div> </div>
</div> </div>
@ -45,7 +44,7 @@
<a asp-action="Register" asp-controller="Account">Register as a new user?</a> <a asp-action="Register" asp-controller="Account">Register as a new user?</a>
</p> </p>
<p> <p>
<a asp-action="ForgotPassword" asp-controller="Account">Forgot your password?"]</a> <a asp-action="ForgotPassword" asp-controller="Account">Forgot your password</a>
</p> </p>
<input type="hidden" name="Provider" value="LOCAL" /> <input type="hidden" name="Provider" value="LOCAL" />
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" /> <input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
@ -55,25 +54,5 @@
<hr/> <hr/>
<h2 class="lead text-left">Use another service to log in:</h2> <h2 class="lead text-left">Use another service to log in:</h2>
@if (Model.ExternalProviders==null || Model.ExternalProviders.Count() == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
@foreach (var description in Model.ExternalProviders) {
<form action="@Constants.LoginPath" method="post">
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
<button class="btn btn-lg btn-success" type="submit" name="Submit.Login">Connect using @description.DisplayName</button>
@Html.AntiForgeryToken()
</form>
}
}
</div> </div>

@ -1,54 +1,62 @@
@using System.Security.Claims @using System.Security.Claims
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@if (User.IsSignedIn()) <ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{ {
<li>
<a asp-controller="Manage" class="navbar-link" asp-action="Index" title="Manage">
<img src="/Avatars/@(User.GetUserName()).xs.png" asp-append-version="true" class="smalltofhol" />
</a>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Plateforme <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a asp-controller="Bug" asp-action="Index">Bugs</a></li>
<li><a asp-controller="HyperLink" asp-action="Index">HyperLink</a></li>
<li><a asp-controller="LiveFlow" asp-action="Index">LiveFlow</a></li>
<li><a asp-controller="Feature" asp-action="Index">Features</a></li>
</ul>
</li>
@if (User.IsInRole(Constants.AdminGroupName)) {
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Administration <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a asp-controller="Administration" asp-action="Index">Index</a></li>
<li><a asp-controller="Activity" asp-action="Index">Activités</a></li>
<li><a asp-controller="CommandForms" asp-action="Index">Formulaires</a></li>
<li><a asp-controller="Notifications" asp-action="Index">Notifications</a></li>
<li><a asp-controller="SIRENExceptions" asp-action="Index">Excéptions au numéro de SIREN</a></li>
<li><a asp-controller="Client" asp-action="Index">Accès API</a></li>
<li><a asp-controller="MailingTemplate" asp-action="Index">Emailing</a></li>
</ul>
</li>}
<ul class="nav navbar-nav navbar-right">
<li>
<a asp-controller="Manage" class="navbar-link" asp-action="Index" title="Manage">
<img src="/Avatars/@(User.GetUserName()).xs.png" asp-append-version="true" class="smalltofhol" />
</a>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Plateforme <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a asp-controller="Bug" asp-action="Index">Bugs</a></li>
<li><a asp-controller="HyperLink" asp-action="Index">HyperLink</a></li>
<li><a asp-controller="LiveFlow" asp-action="Index">LiveFlow</a></li>
<li><a asp-controller="Feature" asp-action="Index">Features</a></li>
</ul>
@if (User.IsInRole(Constants.AdminGroupName)) {
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Administration <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a asp-controller="Administration" asp-action="Index">Index</a></li>
<li><a asp-controller="Activity" asp-action="Index">Activités</a></li>
<li><a asp-controller="CommandForms" asp-action="Index">Formulaires</a></li>
<li><a asp-controller="Notifications" asp-action="Index">Notifications</a></li>
<li><a asp-controller="SIRENExceptions" asp-action="Index">Excéptions au numéro de SIREN</a></li>
<li><a asp-controller="Client" asp-action="Index">Accès API</a></li>
<li><a asp-controller="MailingTemplate" asp-action="Index">Emailing</a></li>
</ul>
</li>}
<li> <li class="nav-item">
<form asp-controller="Account" asp-action="LogOff" <a class="nav-link" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
method="post" id="logoutForm"> </li>
<button type="submit" class="btn navbar-btn" >Logout</button> <li class="nav-item">
<input type="hidden" name="ReturnUrl" value="/" /> <a class="nav-link" asp-controller="ApiKeys" asp-action="Index" title="Api Keys">Your API keys</a>
</form> </li>
</li> <li class="nav-item">
</ul> <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })">
<button type="submit" class="nav-link btn btn-link">Logout</button>
</form>
</li>
} }
else else
{ {
<ul class="nav navbar-nav navbar-right"> <li class="nav-item">
<li><a class="navbar-link" asp-controller="Account" asp-action="Register" asp-route-returnurl="@Url.Action()" >Register</a></li> <a class="nav-link" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li><a class="navbar-link" asp-controller="Account" asp-action="SignIn" asp-route-returnurl="@Url.Action()" >Login</a></li> <li class="nav-item">
</ul> <a class="nav-link" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
} }
</ul>

@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -18,7 +19,10 @@
<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.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.4" />
<PackageReference Include="Google.Apis.Compute.v1" Version="1.60.0.2987" /> <PackageReference Include="Google.Apis.Compute.v1" Version="1.60.0.2987" />
<PackageReference Include="MarkdownDeep-av.NET" Version="1.5.27" /> <PackageReference Include="MarkdownDeep-av.NET" Version="1.5.27" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
@ -27,10 +31,12 @@
<PackageReference Include="MimeKit" Version="3.6.0" /> <PackageReference Include="MimeKit" Version="3.6.0" />
<PackageReference Include="pazof.rules" Version="1.1.3" /> <PackageReference Include="pazof.rules" Version="1.1.3" />
<PackageReference Include="RazorEngine.NetCore" Version="3.1.0" /> <PackageReference Include="RazorEngine.NetCore" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.4" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.5" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.5" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="7.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.4" IncludeAssets="All" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -35,7 +35,7 @@
}, },
"DataProtection": { "DataProtection": {
"Keys": { "Keys": {
"Dir": "DataProtection-Keys" "Dir": "DataProtection"
}, },
"RSAParamFile": "RSA-Params.json", "RSAParamFile": "RSA-Params.json",
"ExpiresInHours": 168 "ExpiresInHours": 168

@ -458,7 +458,7 @@ namespace yavscTests
// before fixing the security protocol, let beleive our lib it's done with it. // before fixing the security protocol, let beleive our lib it's done with it.
//var cxmgr = PayPal.Manager.ConnectionManager.Instance; //var cxmgr = PayPal.Manager.ConnectionManager.Instance;
// then, fix it. // then, fix it.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)0xC00; // Tls12, required by PayPal // ServicePointManager.SecurityProtocol = (SecurityProtocolType)0xC00; // Tls12, required by PayPal
app.UseIISPlatformHandler(options => app.UseIISPlatformHandler(options =>
{ {

@ -1,19 +0,0 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"ansi-to-html": {
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.9.tgz",
"integrity": "sha512-hwNdg2DNgCzsrvaNc+LDqSxJkpxf9oEt4R7KE0IeURXhEOlontEqNpXNiGeFBpSes8TZF+ZZ9sjB85QzjPsI6A==",
"requires": {
"entities": "^1.1.1"
}
},
"entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
}
}
}
Loading…