14 Commits

Author SHA1 Message Date
96864eed93 Password reset
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 4s
Dotnet build and test / build (push) Failing after 0s
2025-09-07 22:37:33 +01:00
9c5ea692b0 Passwor re-init 2025-09-07 17:43:13 +01:00
111ada56f7 localisation 2025-08-31 18:27:53 +01:00
1f4b3980c7 restored templates
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 2s
2025-08-25 14:18:26 +01:00
7ac48c3bbf Drops the replaced Client table 2025-08-25 13:32:31 +01:00
c65de51f9c Dimiss the notification
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 1s
Dotnet build and test / build (push) Failing after 2s
2025-08-25 12:58:25 +01:00
c0f1866e9f mef 2025-08-24 16:50:52 +01:00
0ca4259451 Id Stores from db
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 2s
2025-08-24 16:07:53 +01:00
34e028e6d1 Get activities
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 2s
2025-08-23 12:29:56 +01:00
7a06ce1deb User list
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 1s
2025-08-19 21:32:17 +01:00
d691501d42 Client viewa restored
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 2s
2025-08-19 15:40:31 +01:00
1e568279ad Authorizations
Some checks failed
Dotnet build and test / log-the-inputs (push) Failing after 2s
Dotnet build and test / build (push) Failing after 2s
2025-08-18 11:27:13 +01:00
541b891c3b restores the activitiy setup pages 2025-08-18 11:19:30 +01:00
2615f65515 Gice a chance to import/export at failing migration 2025-08-18 09:30:22 +01:00
116 changed files with 9129 additions and 2564 deletions

1
.vscode/launch.json vendored
View File

@ -4,6 +4,7 @@
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "cli .NET Core Launch (console)", "name": "cli .NET Core Launch (console)",
"type": "coreclr", "type": "coreclr",

View File

@ -8,11 +8,15 @@
<PackageVersion Include="bootstrap" Version="5.3.7" /> <PackageVersion Include="bootstrap" Version="5.3.7" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" /> <PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.69.0.3746" /> <PackageVersion Include="Google.Apis.Calendar.v3" Version="1.69.0.3746" />
<PackageVersion Include="Google.Apis.Compute.v1" Version="1.70.0.3841" /> <PackageVersion Include="Google.Apis.Compute.v1" Version="1.70.0.3871" />
<PackageVersion Include="HigginsSoft.IdentityServer8" Version="8.0.5-preview-net9" /> <PackageVersion Include="HigginsSoft.IdentityServer8" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.AspNetIdentity" Version="8.0.5-preview-net9" /> <PackageVersion Include="HigginsSoft.IdentityServer8.AspNetIdentity" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.Storage" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework.Storage" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.Security" Version="8.0.5-preview-net9" />
<PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" /> <PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" />
<PackageVersion Include="MailKit" Version="4.13.0" /> <PackageVersion Include="MailKit" Version="4.8.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.0" /> <PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
@ -38,7 +42,7 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.53.0" /> <PackageVersion Include="Microsoft.Playwright" Version="1.53.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" /> <PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="MimeKit" Version="4.13.0" /> <PackageVersion Include="MimeKit" Version="4.8.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" /> <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" /> <PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" />

View File

@ -3,6 +3,9 @@ CONFIG=Debug
FRAMEWORK=net8.0 FRAMEWORK=net8.0
DESTDIR=/tmp/yavsc DESTDIR=/tmp/yavsc
all:
@dotnet build --nologo 2>/dev/null |grep error
clean: clean:
dotnet clean dotnet clean

View File

@ -33,7 +33,7 @@ namespace Yavsc.ApiControllers
public BillingController( public BillingController(
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IStringLocalizer<Yavsc.YavscLocalization> SR, IStringLocalizer<BillingController> SR,
ApplicationDbContext context, ApplicationDbContext context,
IOptions<GoogleAuthSettings> googleSettings, IOptions<GoogleAuthSettings> googleSettings,
IYavscMessageSender GCMSender, IYavscMessageSender GCMSender,

View File

@ -18,7 +18,7 @@ namespace Yavsc.Controllers
using Yavsc.Server.Helpers; using Yavsc.Server.Helpers;
[Produces("application/json")] [Produces("application/json")]
[Route("api/bookquery"), Authorize(Roles = "Performer,Administrator")] [Route("api/bookquery"), Authorize("Performer")]
public class BookQueryApiController : Controller public class BookQueryApiController : Controller
{ {
private ApplicationDbContext _context; private ApplicationDbContext _context;

View File

@ -28,7 +28,7 @@ namespace Yavsc.Controllers
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[Authorize(Roles="Performer"),HttpGet("{id}")] [Authorize("Performer"),HttpGet("{id}")]
public IActionResult Get(string id) public IActionResult Get(string id)
{ {
var pfr = dbContext.Performers.Include( var pfr = dbContext.Performers.Include(

View File

@ -12,7 +12,7 @@ using Yavsc.Server.Helpers;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
[Produces("application/json"),Authorize(Roles="Administrator")] [Produces("application/json"),Authorize("AdministratorOnly")]
[Route("api/users")] [Route("api/users")]
public class ApplicationUserApiController : Controller public class ApplicationUserApiController : Controller
{ {

View File

@ -34,7 +34,7 @@ namespace Yavsc.ApiControllers.accounting
public UserInfo[] GetUserHint(string name) public UserInfo[] GetUserHint(string name)
{ {
return _dbContext.Users.Where(u=>u.UserName.IndexOf(name)>0) return _dbContext.Users.Where(u=>u.UserName.IndexOf(name)>0)
.Select(u=>new UserInfo(u.Id, u.UserName, u.Avatar)) .Select(u=>new UserInfo(u.Id, u.UserName, u.Email, u.Avatar))
.Take(10).ToArray(); .Take(10).ToArray();
} }
} }

View File

@ -13,6 +13,7 @@
using IdentityModel; using IdentityModel;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Yavsc;
using Yavsc.Helpers; using Yavsc.Helpers;
using Yavsc.Interface; using Yavsc.Interface;
using Yavsc.Models; using Yavsc.Models;
@ -61,7 +62,7 @@ internal class Program
options.IncludeErrorDetails = true; options.IncludeErrorDetails = true;
options.Authority = "https://localhost:5001"; options.Authority = "https://localhost:5001";
options.TokenValidationParameters = options.TokenValidationParameters =
new() { ValidateAudience = false, RoleClaimType = JwtClaimTypes.Role }; new() { ValidateAudience = false, RoleClaimType = Constants.RoleClaimType };
options.MapInboundClaims = true; options.MapInboundClaims = true;
}); });

View File

@ -54,5 +54,7 @@ namespace Yavsc
public const string LivePath = "/live/cast"; public const string LivePath = "/live/cast";
public const string StreamingPath = "/api/stream/put"; public const string StreamingPath = "/api/stream/put";
public static string RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
} }
} }

View File

@ -7,15 +7,17 @@ namespace Yavsc.Abstract.Identity
} }
public UserInfo(string userId, string userName, string avatar) public UserInfo(string userId, string userName, string email, string avatar)
{ {
UserId = userId; UserId = userId;
UserName = userName; UserName = userName;
Email = email;
Avatar = avatar; Avatar = avatar;
} }
public string UserId { get; set; } public string UserId { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string Email { get; }
public string Avatar { get; set; } public string Avatar { get; set; }
} }
} }

View File

@ -43,13 +43,13 @@ public static class Config
new IdentityResources.Email() new IdentityResources.Email()
]; ];
public static IEnumerable<ApiScope> TestingApiScopes => public static IEnumerable<ApiScope> ApiScopes =>
[ [
new ApiScope("scope1",new string[] {"scope1"}), new ApiScope("scope1",new string[] {"scope1"}),
new ApiScope("scope2",new string[] {"scope2"}), new ApiScope("scope2",new string[] {"scope2"}),
]; ];
public static IEnumerable<Client> TestingClients => public static IEnumerable<Client> Clients =>
[ [
// m2m client credentials flow client // m2m client credentials flow client
new Client new Client

View File

@ -0,0 +1,18 @@
namespace Yavsc.Services
{
[Serializable]
internal class YavscInfrastructureException : Exception
{
public YavscInfrastructureException()
{
}
public YavscInfrastructureException(string? message) : base(message)
{
}
public YavscInfrastructureException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
}

View File

@ -56,10 +56,10 @@ namespace Yavsc
_localizer = stringLocalizerFactory.Create(typeof(ChatHub)); _localizer = stringLocalizerFactory.Create(typeof(ChatHub));
_cxManager = connexionManager; _cxManager = connexionManager;
_cxManager.SetErrorHandler ((context, error) => _cxManager.SetErrorHandler ((context, error) =>
{ {
NotifyUser(NotificationTypes.Error, context, error); NotifyUser(NotificationTypes.Error, context, error);
}); });
_logger = loggerFactory.CreateLogger<ChatHub>(); _logger = loggerFactory.CreateLogger<ChatHub>();
InputValidator = new HubInputValidator { NotifyUser = async (type, target, msg) => await this.NotifyUser(type, target, msg) }; InputValidator = new HubInputValidator { NotifyUser = async (type, target, msg) => await this.NotifyUser(type, target, msg) };
} }

View File

@ -91,8 +91,6 @@ namespace Yavsc.Models
optionsBuilder.UseNpgsql(envCxStr); optionsBuilder.UseNpgsql(envCxStr);
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
} }
public DbSet<Client> Applications { get; set; }
/// <summary> /// <summary>
/// Activities referenced on this site /// Activities referenced on this site
@ -278,6 +276,5 @@ namespace Yavsc.Models
public DbSet<Scope> Scopes { get; set; } public DbSet<Scope> Scopes { get; set; }
public DbSet<BlogSpotPublication> blogSpotPublications { get; set; } public DbSet<BlogSpotPublication> blogSpotPublications { get; set; }
public DbSet<Client> Client { get; set; }
} }
} }

View File

@ -1,29 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Yavsc.Models.Auth
{
public class Client
{
[Key][Required][DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
[Required]
[MaxLength(128)]
public string DisplayName { get; set; }
[MaxLength(512)]
public string? RedirectUri { get; set; }
[MaxLength(512)]
public string? LogoutRedirectUri { get; set; }
[MaxLength(512)]
public string Secret { get; set; }
public ApplicationTypes Type { get; set; }
public bool Active { get; set; }
public int RefreshTokenLifeTime { get; set; }
public int AccessTokenLifetime { get; set; }
}
}

View File

@ -13,7 +13,7 @@ namespace Yavsc.Models.Billing
using Yavsc.Abstract.Workflow; using Yavsc.Abstract.Workflow;
using Yavsc.Services; using Yavsc.Services;
public abstract class NominativeServiceCommand : IDecidableQuery, IIdentified<long> public abstract class NominativeServiceCommand : IDecidableQuery, IIdentified<long>, IBillable
{ {
public string GetInvoiceId() { return GetType().Name + "/" + Id; } public string GetInvoiceId() { return GetType().Name + "/" + Id; }

View File

@ -24,16 +24,7 @@ namespace Yavsc.Models.Haircut
string _description = null; string _description = null;
public override string Description public override string Description
{ {
get get; set;
{
string type = ResourcesHelpers.GlobalLocalizer[this.GetType().Name];
string gender = ResourcesHelpers.GlobalLocalizer[this.Prestation.Gender.ToString()];
return $"{_description} {type} ({gender})";
}
set
{
_description = value;
}
} }

View File

@ -30,7 +30,7 @@ namespace Yavsc.Models.Haircut.Views
public class HaircutQueryProviderInfo : HaircutQueryComonInfo { public class HaircutQueryProviderInfo : HaircutQueryComonInfo {
public HaircutQueryProviderInfo(HairCutQuery query) : base (query) public HaircutQueryProviderInfo(HairCutQuery query) : base (query)
{ {
ClientInfo = new UserInfo(query.Client.Id, query.Client.UserName, query.Client.Avatar); ClientInfo = new UserInfo(query.Client.Id, query.Client.UserName, query.Client.Email, query.Client.Avatar);
} }
public UserInfo ClientInfo { get; set; } public UserInfo ClientInfo { get; set; }
@ -39,7 +39,7 @@ namespace Yavsc.Models.Haircut.Views
public HaircutQueryClientInfo(HairCutQuery query) : base (query) public HaircutQueryClientInfo(HairCutQuery query) : base (query)
{ {
var user = query.PerformerProfile.Performer; var user = query.PerformerProfile.Performer;
ProviderInfo = new UserInfo(user.Id, user.UserName, user.Avatar); ProviderInfo = new UserInfo(user.Id, user.UserName, user.Email, user.Avatar);
} }
public UserInfo ProviderInfo { get; set; } public UserInfo ProviderInfo { get; set; }

View File

@ -453,7 +453,6 @@
<data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data> <data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data>
<data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data> <data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data>
<data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data> <data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data>
<data name="ConfirmYourAccountTitle"><value>S'il vous plait, confirmez votre addresse e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0}, <data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer. mais votre adresse e-mail reste à confirmer.
Pour ce faire, suivez le lien suivant : &lt;{1}&gt;. Pour ce faire, suivez le lien suivant : &lt;{1}&gt;.

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="HairCutQueryValidation"><value>Une demande (de {0}) en coiffure à domicile vient d'être validée</value></data>
</root>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,788 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="About">
<value>About</value>
</data>
<data name="About_BookAStar">
<value>About BookAStar</value>
</data>
<data name="About_Message">
<value>Welcome by your stars.</value>
</data>
<data name="access_denied">
<value>Access denied</value>
</data>
<data name="AccountBalance">
<value>Account Balance</value>
</data>
<data name="Activity">
<value>Activity</value>
</data>
<data name="Activities">
<value>Activities</value>
</data>
<data name="additionally">
<value>additionally</value>
</data>
<data name="Allow my geolocatisation, nearby my clients">
<value>Allow my geolocatisation, nearby my clients</value>
</data>
<data name="AnIMessageHasbeenSent">
<value>An instant message has been sent to {0}, showing to him your query. You should be contacted very soon.</value>
</data>
<data name="aprestation">
<value>a prestation</value>
</data>
<data name="AskForAnEstimate">
<value>Ask for an estimate</value>
</data>
<data name="AttachedFiles">
<value>Attached files</value>
</data>
<data name="AuthenticatedOnly">
<value>You must be authenticated in order to access this information</value>
</data>
<data name="Author">
<value>Author</value>
</data>
<data name="available">
<value>available</value>
</data>
<data name="Basket">
<value>Basket</value>
</data>
<data name="Bill_edition">
<value>Bill edition</value>
</data>
<data name="Bill_removal">
<value>Bill removal</value>
</data>
<data name="BillAccessControl">
<value>Bill access control</value>
</data>
<data name="BillCreated">
<value>Bill created</value>
</data>
<data name="BillSourceCode">
<value>Bill source code</value>
</data>
<data name="BillUpdated">
<value>Bill updated</value>
</data>
<data name="body">
<value>body</value>
</data>
<data name="Book A Star">
<value>Book an artist</value>
</data>
<data name="Book IT">
<value>Book a performer in information technology</value>
</data>
<data name="BookingTitleArtiste">
<value>Book an artiste</value>
</data>
<data name="BookingTitle6829C">
<value>Book a software editor</value>
</data>
<data name="Catalog">
<value>Catalog</value>
</data>
<data name="Change user name form">
<value>Change user name form</value>
</data>
<data name="Change your account settings">
<value>Change your account settings</value>
</data>
<data name="ChooseADescription">
<value>Please, choose a description</value>
</data>
<data name="ChooseATitle">
<value>Please, choose a title</value>
</data>
<data name="ChooseADateInTheFutur">
<value>Please, Choose A Date In The Futur</value>
</data>
<data name="ChooseAnEventDate">
<value>Please, choose a date for this event </value>
</data>
<data name="Ciffer">
<value>Ciffer</value>
</data>
<data name="Circles">
<value>Circles</value>
</data>
<data name="Click action">
<value>Click action</value>
</data>
<data name="Color">
<value>Color</value>
</data>
<data name="Comment">
<value>Comment</value>
</data>
<data name="Consultant">
<value>Consultant</value>
</data>
<data name="ContactAPerformer">
<value>Contact a performer</value>
</data>
<data name="CouldNotConvertVToDouble">
<value>Could not convert '{0}' to double.</value>
</data>
<data name="Count">
<value>Count</value>
</data>
<data name="Create">
<value>Créer</value>
</data>
<data name="Credits">
<value>Credits</value>
</data>
<data name="Date_search">
<value>Date search</value>
</data>
<data name="DB">
<value>Data base</value>
</data>
<data name="Description">
<value>Description</value>
</data>
<data name="Disable">
<value>Disable</value>
</data>
<data name="DisplayName">
<value>Display Name</value>
</data>
<data name="DoAnEstimate">
<value>Do an estimate</value>
</data>
<data name="DoComment">
<value>Commenter</value>
</data>
<data name="DocTemplateException">
<value>Une erreur est survenue à la génération de votre document</value>
</data>
<data name="DoNotPublishMyActivity">
<value>Ne pas publier mon activité</value>
</data>
<data name="DoPost">
<value>Do post</value>
</data>
<data name="DoSpecifyCircles">
<value>S'il vous plait, spécifiez ceux de vos cercles à qui est destiné ce contenu</value>
</data>
<data name="DoTag">
<value>Tagger</value>
</data>
<data name="DuplicateEmail">
<value>This email adress is already used ({0}).</value>
</data>
<data name="DuplicateUserName">
<value>This user name is already used ({0}).</value>
</data>
<data name="Edit">
<value>Edit</value>
</data>
<data name="Edited">
<value>Edited</value>
</data>
<data name="EditRelatedSkills">
<value>Edit related skills</value>
</data>
<data name="EndDate">
<value>Date de fin</value>
</data>
<data name="EndHour">
<value>Heure de fin</value>
</data>
<data name="email">
<value>e-mail</value>
</data>
<data name="EMailToPerformerFooter">
<value> Generated e-mail from {0}, because of your perfomer profile publication, and your email usage agreement. Visit {1} to modify your profile, unsubscribe or unregister.</value>
</data>
<data name="entries">
<value>entries</value>
</data>
<data name="Estimate not found">
<value>Estimate not found</value>
</data>
<data name="EstimateWanted">
<value>Estimate wanted</value>
</data>
<data name="EventWebPage">
<value>Event Web page</value>
</data>
<data name="ExistantDB">
<value>Existant data base</value>
</data>
<data name="External Logins">
<value>External Logins</value>
</data>
<data name="FillInAFutureDate">
<value>Please, use a date in the future as starting date.</value>
</data>
<data name="Forbidden">
<value>Restricted area</value>
</data>
<data name="from">
<value>from</value>
</data>
<data name="GiveAnExplicitReason">
<value>Tell more, below, about your query</value>
</data>
<data name="GoogleDidntGeoLocalized">
<value>Google could'nt identify this place</value>
</data>
<data name="Google calendar">
<value>Google calendar</value>
</data>
<data name="Google error">
<value>Google error : {0}</value>
</data>
<data name="Google registration id">
<value>Google registration id</value>
</data>
<data name="Home">
<value>Home</value>
</data>
<data name="Hide">
<value>Hide</value>
</data>
<data name="hidden">
<value>hidden</value>
</data>
<data name="Hide source">
<value>Hide the bill source text</value>
</data>
<data name="I understood">
<value>I understood</value>
</data>
<data name="Icons made by">
<value>Icons made by</value>
</data>
<data name="ImgLocator">
<value>Image URI</value>
</data>
<data name="ImportException">
<value>Exception at importing</value>
</data>
<data name="InternalServerError">
<value>Internal Server Error</value>
</data>
<data name="is licensed by">
<value>is licensed by</value>
</data>
<data name="Item added to basket">
<value>Item added to basket</value>
</data>
<data name="Location">
<value>Location</value>
</data>
<data name="Login">
<value>Login</value>
</data>
<data name="Logout">
<value>Logout</value>
</data>
<data name="MainActivity">
<value>Main activity</value>
</data>
<data name="Manage">
<value>Manage</value>
</data>
<data name="ManagedSiteSkills">
<value>Site skills</value>
</data>
<data name="MaxDate">
<value>Maximal date for the rendez-vous</value>
</data>
<data name="MEACode">
<value>Mainly Exerted Activity code</value>
</data>
<data name="Manage your account">
<value>Manage your account</value>
</data>
<data name="Members">
<value>Members</value>
</data>
<data name="Message sent">
<value>Your message has been sent.</value>
</data>
<data name="MinDate">
<value>Minimal date for the rendez-vous</value>
</data>
<data name="Modify">
<value>Modify</value>
</data>
<data name="My Estimates">
<value>My estimates</value>
</data>
<data name="Name">
<value>Name</value>
</data>
<data name="Needs">
<value>Needs</value>
</data>
<data name="Need">
<value>Need</value>
</data>
<data name="nouvel instrument">
<value>new instrument</value>
</data>
<data name="UserName">
<value>Display name</value>
</data>
<data name="New user name">
<value>New display name</value>
</data>
<data name="New Tag">
<value>New Tag</value>
</data>
<data name="NewPasswordMessageSent">
<value>A message had been sent, containing a link to follow in order to update your password.</value>
</data>
<data name="no content">
<value>no content</value>
</data>
<data name="NoSkillforthisactivity">
<value>No skill was informed by any performer for this activity</value>
</data>
<data name="none">
<value>none</value>
</data>
<data name="Non existent user">
<value>Non existent user</value>
</data>
<data name="Not Approuved">
<value>Not Approuved</value>
</data>
<data name="No calendar for this user">
<value>No calendar was associated to this user.</value>
</data>
<data name="Offline">
<value>Offline</value>
</data>
<data name="Online">
<value>Online</value>
</data>
<data name="OnlyAuthorizedMayContact">
<value>Only authorized users may contact a performer by mail.</value>
</data>
<data name="Pdf version">
<value>Pdf version</value>
</data>
<data name="PerformanceDate">
<value>Performance date</value>
</data>
<data name="PerformancePlace">
<value>Performance place</value>
</data>
<data name="Performers">
<value>Performers</value>
</data>
<data name="Performer">
<value>Performer</value>
</data>
<data name="Person">
<value>Person</value>
</data>
<data name="Photo">
<value>Photo</value>
</data>
<data name="PhotoUpdated">
<value>Photo updated</value>
</data>
<data name="PleaseCheckYourEmail">
<value>Please check your email to reset your password.</value>
</data>
<data name="PleaseConfirmYourNewPassword">
<value>Please confirm your new password</value>
</data>
<data name="PleaseFillInABody">
<value>Please fill in a body</value>
</data>
<data name="PleaseFillInAReason">
<value>Please, fill in a reason</value>
</data>
<data name="Posted">
<value>Posted</value>
</data>
<data name="PreferedDate">
<value>Prefered date</value>
</data>
<data name="prestation">
<value>prestation</value>
</data>
<data name="PresationLocation">
<value>Presation location:{0}.\n</value>
</data>
<data name="Preview">
<value>Preview</value>
<comment>comment on preview</comment>
</data>
<data name="Profile edition">
<value>Profile edition</value>
</data>
<data name="Private circle">
<value>Private circle</value>
</data>
<data name="ProviderId">
<value>Provider identifier</value>
</data>
<data name="ProviderName">
<value>Provider name</value>
</data>
<data name="Product reference">
<value>Product_reference</value>
</data>
<data name="ReadMore">
<value>Read more ...</value>
</data>
<data name="reason">
<value>reason</value>
</data>
<data name="Register">
<value>Register</value>
</data>
<data name="RegistrationUnexpectedError">
<value>Registration: unexpected error occured: "{0}". Please forgive for troubles</value>
</data>
<data name="Remember me">
<value>Remember me</value>
</data>
<data name="Remove">
<value>Remove</value>
</data>
<data name="ResetPassword">
<value>Reset your password</value>
</data>
<data name="Role">
<value>Role</value>
</data>
<data name="role created">
<value>role created</value>
</data>
<data name="RoleName">
<value>Role name</value>
</data>
<data name="Save these settings">
<value>Save these settings</value>
</data>
<data name="Search">
<value>Search</value>
</data>
<data name="SiteSkills">
<value>Talents/Compétences/Spécialités gérés sur ce site</value>
</data>
<data name="Skill">
<value>Skill</value>
</data>
<data name="Skills">
<value>Skills</value>
</data>
<data name="Specifyavalidlatitude">
<value>Please, specify a valid latitude</value>
</data>
<data name="Specifyavalidlongitude">
<value>Please, specify a valid longitude</value>
</data>
<data name="SpecifyLatitude">
<value>Specify a latitude</value>
</data>
<data name="SpecifyLongitude">
<value>Specify a longitude</value>
</data>
<data name="SpecifyPlace">
<value>Please, specify a place</value>
</data>
<data name="SomeoneAskingYouForAnEstimate">
<value>{0} would want you to establish an estimate concerning {1}</value>
</data>
<data name="Sound">
<value>Sound</value>
</data>
<data name="StartDate">
<value>Start date</value>
</data>
<data name="StartDateAfterEndDate">
<value>The ending date must be later than the starting one.</value>
</data>
<data name="StartHour">
<value>Start hour</value>
</data>
<data name="Submit">
<value>Submit</value>
</data>
<data name="SubmitChanges">
<value>Submit changes</value>
</data>
<data name="Tag">
<value>Tag</value>
</data>
<data name="Tag name">
<value>Tag name</value>
</data>
<data name="Tex version">
<value>LaTeX version</value>
</data>
<data name="ThisSiteUsesCookies">
<value>This site uses cookies</value>
</data>
<data name="ThisPerformerGivesAccessToHisCalendarAndSeemsToBeAvailableThis">
<value>ThisPerformer Gives access to his calendar and seems to be available this</value>
</data>
<data name="ThisPerformerGivesAccessToHisCalendarAndItAppearsHeShouldNotBeAvailableThis">
<value>This performer gives access to his calendar and it appears he should not be available this</value>
</data>
<data name="ThisPerformerDoesntGiveAccessToHisCalendar">
<value>ThisPerformerDoesntGiveAccessToHisCalendar</value>
</data>
<data name="Title">
<value>Title</value>
</data>
<data name="to">
<value>to</value>
</data>
<data name="TwoFactorAuthentication">
<value>Two-Factor authentication</value>
</data>
<data name="Unitary_cost">
<value>Unitary_cost</value>
</data>
<data name="Unregister">
<value>Unregister</value>
</data>
<data name="User List">
<value>User List</value>
</data>
<data name="User name">
<value>User name</value>
</data>
<data name="UsersInRole">
<value>List of users assuming the role "{0}"</value>
</data>
<data name="UserNotInThisRole">
<value>This user is not in this role</value>
</data>
<data name="UserSkills">
<value>User skills</value>
</data>
<data name="View source">
<value>View source</value>
</data>
<data name="was added to_the_role">
<value>was added to the role</value>
</data>
<data name="was_added_to_the_empty_role">
<value>There was no user in the "{1}" role. You ({0}) was just added as firt user in the "{1}" role.</value>
</data>
<data name="Welcome">
<value>Welcome</value>
<comment></comment>
</data>
<data name="XHasBeenNotified">
<value>{0} has been notified of your query, you should be fast contacted</value>
</data>
<data name="Xshouldbeavailable">
<value>regarding his calendar, {0} should be available for this booking</value>
</data>
<data name="Yavsc.Models.Musical.Profiles.Instrumentation">
<value>Paramètres musicien (l'instrument)</value>
</data>
<data name="Yavsc.Models.Musical.Profiles.DjSettings">
<value>Paramètres Dj (le compte SoundCloud.com)</value>
</data>
<data name="Yavsc.Models.Musical.Profiles.FormationSettings">
<value>Paramètres formation (les partenaires)</value>
</data>
<data name="Yavsc.Models.Musical.Profiles.GeneralSettings">
<value>Paramètres généraux: une couleur musicale</value>
</data>
<data name="YouNeedToBeAuthenticatedIOToContact">
<value>You need to be authenticated in order to contact a performer</value>
</data>
<data name="younotadmin">
<value>You're not administrator</value>
</data>
<data name="YourEstimates">
<value>Your estimates</value>
</data>
<data name="YourMEACode">
<value>Your activity</value>
</data>
<data name="YourNeed">
<value>Your need</value>
</data>
<data name="yourquerytransmitted">
<value>your query has been transmitted</value>
</data>
<data name="YourSkills">
<value>Your skills, your special fields, the scope of your activities</value>
</data>
<data name="YourPosts">
<value>You posts</value>
</data>
<data name="YourProfile">
<value>Your profile</value>
</data>
<data name="YourMessageHasBeenSent">
<value>Your message has been sent</value>
</data>
<data name="Longueur de cheveux">
<value>Hair Length</value>
</data>
<data name="Français">
<value>French</value>
</data>
<data name="Anglais">
<value>English</value>
</data>
<data name="Portugais"><value>Portugese</value></data>
<data name="RequiredField">
<value>This field is required.</value>
</data>
<data name="PasswordTooShort">
<value>Passwords must be at least {0} characters.</value>
</data>
<data name="PasswordRequiresNonLetterAndDigit">
<value>Passwords must have at least one non letter and non digit character.</value>
</data>
<data name="PasswordRequiresDigit">
<value>Passwords must have at least one digit ('0'-'9').</value>
</data>
<data name="PasswordRequiresUpper">
<value>Passwords must have at least one uppercase ('A'-'Z').</value>
</data>
<data name="PassAndConfirmDontMach">
<value>Passwords and confirmation are not the same.</value>
</data>
<data name="PasswordConfirm">
<value>Password confirmation</value>
</data>
<data name="InvalidUserName">
<value>Invalid user name.
Valid caracters are: underscore '_', '-', 'a' - 'z', 'A' - 'Z', '0' - '9', the single quote ('), the space and the dot.</value>
</data>
<data name="EmailSentForConfirm">
<value>An email has been sent to confirm your addresse.</value>
</data>
<data name="ConfirmYourAccountBody"><value>You successfully created your {0} account,
but your e-mail address is not yet confirmed.
Please, in order to validate it, follow this link &lt;{1}&gt;.
Thanks.
--
{0} - {2} &lt;https://{3}&gt;</value>
</data>
<data name="Instrumentation"><value>Instrumentation</value></data>
<data name="Partenariat"><value>Co-working</value></data>
</root>

View File

@ -437,7 +437,6 @@
<data name="ConfirmPassword"><value>Confirme sua senha</value></data> <data name="ConfirmPassword"><value>Confirme sua senha</value></data>
<data name="ErrorSendingEmailForConfirm"><value>O envio de e-mail para confirmação do endereço de e-mail falhou.</value></data> <data name="ErrorSendingEmailForConfirm"><value>O envio de e-mail para confirmação do endereço de e-mail falhou.</value></data>
<data name="EmailSentForConfirm"><value>Um e-mail foi enviado para confirmação do endereço de e-mail.</value></data> <data name="EmailSentForConfirm"><value>Um e-mail foi enviado para confirmação do endereço de e-mail.</value></data>
<data name="ConfirmYourAccountTitle"><value>Por favor, confirme seu endereço de e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Você criou sua conta {0} com sucesso, <data name="ConfirmYourAccountBody"><value>Você criou sua conta {0} com sucesso,
mas o seu endereço de e-mail tem que ser confirmado. mas o seu endereço de e-mail tem que ser confirmado.
Para fazer isso, siga o seguinte link : &lt;{1}&gt;. Para fazer isso, siga o seguinte link : &lt;{1}&gt;.

View File

@ -0,0 +1,282 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="role created"><value>Rôle créé</value></data>
<data name="RoleName"><value>Nom du rôle </value></data>
<data name="Save these settings"><value>Enregistrer ces paramètres</value></data>
<data name="Search"><value>Chercher</value></data>
<data name="Select a Google calendar"><value>Selectioner un calendrier Google</value></data>
<data name="Send"><value>Envoyer</value></data>
<data name="Send a private message"><value>Envoyer un message privé</value></data>
<data name="Send a public message"><value>Envoyer un message publique</value></data>
<data name="Set"><value>Positioner</value></data>
<data name="SettingsClass"><value>Classe du paramétrage</value></data>
<data name="Short"><value>court</value></data>
<data name="Son blog"><value>Son blog</value></data>
<data name="Your performer profile"><value>Votre profil professionel</value></data>
<data name="Setup below your activity parameters"><value>Positionnez ci-après vos les paramêtre de votre activité</value></data>
<data name="SiteSkills"><value>Talents/Compétences/Spécialités gérés sur ce site</value></data>
<data name="Skill"><value>Compétence</value></data>
<data name="Skills"><value>Talents/Compétences/Spécialités</value></data>
<data name="SomeoneAskingYouForAnEstimate"><value>{0} désirerait un devis concernant {1}</value></data>
<data name="Sound"><value>Son</value></data>
<data name="SpecifyLatitude"><value>Specify a latitude</value></data>
<data name="SpecifyLongitude"><value>Specify a longitude</value></data>
<data name="SpecifyPlace"><value>L'endroit ainsi renseigné ne semble pas convenir ...</value></data>
<data name="Specifyavalidlatitude"><value>Please, specify a valid latitude.</value></data>
<data name="StartDate"><value>Date de début</value></data>
<data name="StartDateAfterEndDate"><value>La date de fin doit être postérieure à la date de début.</value></data>
<data name="StartHour"><value>Heure de début</value></data>
<data name="Submit"><value>Soumettre</value></data>
<data name="SubmitChanges"><value>Envoyer les modifications</value></data>
<data name="Tag"><value>Tag</value></data>
<data name="Tag name"><value>Nom du tag</value></data>
<data name="Tex version"><value>Version LaTeX</value></data>
<data name="ThisSiteUsesCookies"><value>Ce site utilise les cookies</value></data>
<data name="ThisPerformerGivesAccessToHisCalendarAndSeemsToBeAvailableThis"><value>Selon son calendier Google, ce perstataire est disponbile ce</value></data>
<data name="ThisPerformerGivesAccessToHisCalendarAndItAppearsHeShouldNotBeAvailableThis"><value>Selon son calendier Google, ce perstataire pourrait ne pas être disponible ce</value></data>
<data name="ThisPerformerDoesntGiveAccessToHisCalendar"><value>Ce prestataire n'a pas mis de calendrier à disposition.</value></data>
<data name="Title"><value>Titre</value></data>
<data name="Feature"><value>Fonctionalité</value></data>
<data name="FeatureId"><value>Identifiant de fonctionalité</value></data>
<data name="to"><value>à</value></data>
<data name="TwoFactorAuthentication"><value>Double identification</value></data>
<data name="Unitary_cost"><value>Coût unitaire</value></data>
<data name="Unregister"><value>Se désinscrire</value></data>
<data name="Use a local account to log in"><value>Utiliser un compte local pour se connecter</value></data>
<data name="Use another service to log in"><value>Utiliser un autre service pour se connecter</value></data>
<data name="UseGeoLocalizationToReduceDistanceWithClients"><value>Utiliser ma position pour avoir des clients plus proches</value></data>
<data name="User"><value>Utilisateur</value><comment></comment></data>
<data name="User List"><value>Liste des utilisateurs</value><comment></comment></data>
<data name="UserName"><value>Nom d'utilisateur</value></data>
<data name="UsersInRole"><value>Liste des utilisateurs assumant le rôle "{0}"</value></data>
<data name="UserSkills"><value>Talents/compétences/spécialités utilisateur</value></data>
<data name="UserNotInThisRole"><value>Le rôle demandé n'est pas assumé par ce préstataire</value></data>
<data name="ValidationDate"><value>Date de validation</value></data>
<data name="View_source"><value>Voir le texte source de l'article</value></data>
<data name="was_added_to_the_role"><value>a été ajouté au rôle</value></data>
<data name="was_added_to_the_empty_role"><value>Il n'y avait pas d'utilisateur dans le rôle "{1}". Vous ({0}) avez été ajouté au rôle "{1}".</value></data>
<data name="WebSite"><value>Site Web</value><comment></comment></data>
<data name="Welcome"><value>Bienvenue</value><comment></comment></data>
<data name="Women"><value>Femme</value><comment></comment></data>
<data name="XHasBeenNotified"><value>{0} à été notifié de votre demande, vous devriez être contacté rapidement</value></data>
<data name="Xshouldbeavailable"><value>Au vu de son calendrier,
{0} devrait être disponible pour ce rendez-vous</value></data>
<data name="Yavsc.Models.Musical.Profiles.Instrumentation"><value>Paramètres musicien (l'instrument)</value></data>
<data name="Yavsc.Models.Musical.Profiles.DjSettings"><value>Paramètres Dj (le compte SoundCloud.com)</value></data>
<data name="Yavsc.Models.Workflow.Profiles.FormationSettings"><value>Paramètres formation (les partenaires)</value></data>
<data name="Yavsc.Models.Musical.Profiles.GeneralSettings"><value>Paramètres généraux (visibilité et présentation)</value></data>
<data name="Yavsc.Models.Haircut.BrusherProfile"><value>Paramètres coiffeur: tarifs, disponibilité</value></data>
<data name="Yes"><value>Oui</value></data>
<data name="YouNeedToBeAuthenticatedIOToContact"><value>Vous devez vous authentifier pour pouvoir demander un devis
à un préstataire.</value></data>
<data name="younotadmin"><value>Vous n'êtes pas administrateur</value></data>
<data name="Your account settings"><value>Les paramètres de votre compte</value></data>
<data name="Your book query"><value>Votre demande de rendez-vous</value></data>
<data name="Your password has been reset."><value>Votre mote de passe a été mis à jour.</value></data>
<data name="YourEstimates"><value>Vos Devis</value></data>
<data name="YourMEACode"><value>Votre activité</value></data>
<data name="YourNeed"><value>Votre besoin</value></data>
<data name="yourquerytransmitted"><value>Votre demande a été transmise</value></data>
<data name="YourSkills"><value>Vos talents, vos spécialités, le domaine de vos activités</value></data>
<data name="Your posts"><value>Vos publications</value></data>
<data name="Your profile"><value>Votre profil</value></data>
<data name="YourMessageHasBeenSent"><value>Votre messge a été envoyé</value></data>
<data name="Tell more, below, about your query"><value>Dites en plus, ci àprès, à propos de cet évennement</value></data>
<data name="UnsetActivity"><value>Supprimer mon profil professionel</value></data>
<data name="Français"><value>Français</value></data>
<data name="Anglais"><value>Anglais</value></data>
<data name="Portugais"><value>Portugais</value></data>
<data name="InvalidUserName"><value>Nom d'utilisateur invalide.
Les caratères valides sont: le souligné (_), le petit titret (-), l'apostrohe ('), les minuscules et majuscules de a à z, les chiffres de 0 à 9, l'espace et le point.</value></data>
<data name="RequiredField"><value>Ce champ est obligatoire.</value></data>
<data name="validationError"><value>Champ invalide ...</value></data>
<data name="PasswordTooShort"><value>Le Mot de passe doit contenir au moins 6 caractères.</value></data>
<data name="PasswordRequiresNonLetterAndDigit"><value>Mot de passe doit contenir au moins un caractère spécial (ni un chiffre, ni une lettre).</value></data>
<data name="PasswordRequiresDigit"><value>Les mots de passe doivent contenir au moins un chiffre ('0' à '9').</value></data>
<data name="PasswordRequiresUpper"><value>Les mots de passe doivent contenir au moins une lettre majuscule ('A' à 'Z').</value></data>
<data name="PassAndConfirmDontMach"><value>Le mot de passe et sa confirmation ne sont pas les mêmes.</value></data>
<data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data>
<data name="ConfirmPassword"><value>Confirmation du mot de passe</value></data>
<data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data>
<data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data>
<data name="AccountEmailFactorTitle"><value>Le second facteur de votre identification</value></data>
<data name="AccountEmailFactorBody"><value>Votre compte est endurci d'une requisition d'un second facteur d'identification.
Une nouvelle connection depuis un navigateur web nécéssite votre authorisation.
Vous pouvez l'accorder en suivant le lien suivant : &lt;{1}&gt;.
Votre code dáctivation est : {4}
Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur.
{0} - {2} &lt;{3}&gt;</value></data>
<data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer.
Pour ce faire, veuillez, s'il vous plait, suivre le lien suivant
dans votre navigateur favori : &lt;{1}&gt;.
--
{0} - {2} &lt;{3}&gt;</value></data>
<data name="BadStringLength"><value>Taille maximale: {0} caractère.</value></data>
<data name="DetailledMinMaxStringLength"><value>Ce champ est
d'au moins {0} et d'au plus {1} caractère(s) (manquent {2}) ou ({3} en trop).</value></data>
<data name="DetailledMaxStringLength"><value>Ce champ est
d'au plus {0} caractère(s) ({1} en excès). </value></data>
<data name="EmailSentToPerformer"><value>Un message éléctronique a été envoyé à {0}.</value></data>
<data name="QueryValidatedNonReg"><value>Un client vient de valider une demande de prestation à votre encontre:
Prestation: {0}
Client : {1}
Date: {2},
Adresse: {3}
-----
{4}
Facture prévue (non réglée): {5}</value></data>
<data name="QueryValidatedRegular"><value>Un client vient de valider une demande de prestation à votre encontre:
Prestation: {0}
Client : {1}
Date: {2},
Adresse: {3}
-----
{4}
Facture réglée: {5}</value></data>
<data name="AllowMonthlyEmail"><value>Recevoir la lettre mensuelle d'information</value></data>
<data name="Join"><value>joindre</value></data>
<data name="Enroll"><value>Enrôler</value></data>
<data name="Fire"><value>Licencier</value></data>
<data name="LiveFlow"><value>Flux live</value></data>
<data name="Instrumentation"><value>Instrumentation</value></data>
<data name="Partenariat"><value>Partenariat</value></data>
<data name="IconWebUploadSpecification"><value>
Le format png pourrait être supporté ici,
le format Gif, peut-être aussi, et même, mais là, moins souvent, le surnommé Jpg.
</value></data>
</root>

View File

@ -14,16 +14,17 @@ using System.Web;
namespace Yavsc.Services namespace Yavsc.Services
{ {
public class MailSender : IEmailSender<ApplicationUser>, IEmailSender, ITrueEmailSender public class MailSender : IEmailSender<ApplicationUser>, IEmailSender, ITrueEmailSender
{ {
private readonly IStringLocalizer<YavscLocalization> localizer; private readonly IStringLocalizer<MailSender> localizer;
readonly SiteSettings siteSettings; readonly SiteSettings siteSettings;
readonly SmtpSettings smtpSettings; readonly SmtpSettings smtpSettings;
private readonly ILogger logger; private readonly ILogger logger;
public MailSender( public MailSender(
IOptions<SiteSettings> sitesOptions, IOptions<SiteSettings> sitesOptions,
IOptions<SmtpSettings> smtpOptions, IOptions<SmtpSettings> smtpOptions,
ILoggerFactory loggerFactory ILoggerFactory loggerFactory,
IStringLocalizer<MailSender> localizer
) )
{ {
this.localizer = localizer; this.localizer = localizer;
@ -46,17 +47,15 @@ namespace Yavsc.Services
/// <returns>a MessageWithPayloadResponse, /// <returns>a MessageWithPayloadResponse,
/// <c>bool somethingsent = (response.failure == 0 &amp;&amp; response.success > 0)</c> /// <c>bool somethingsent = (response.failure == 0 &amp;&amp; response.success > 0)</c>
/// </returns> /// </returns>
public async Task SendEmailAsync(string email, string subject, string htmlMessage) public async Task SendEmailAsync(string email, string subject, string htmlMessage)
{ {
await SendEmailAsync("", email, subject, htmlMessage); await SendEmailAsync("", email, subject, htmlMessage);
} }
public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage) public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage)
{ {
logger.LogInformation($"SendEmail for {email} : {subject}"); logger.LogInformation($"SendEmail for {email} : {subject}");
MimeMessage msg = new (); MimeMessage msg = new();
msg.From.Add(new MailboxAddress(siteSettings.Owner.Name, msg.From.Add(new MailboxAddress(siteSettings.Owner.Name,
siteSettings.Owner.EMail)); siteSettings.Owner.EMail));
msg.To.Add(new MailboxAddress(name, email)); msg.To.Add(new MailboxAddress(name, email));
@ -68,20 +67,22 @@ namespace Yavsc.Services
msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId( msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId(
siteSettings.Authority siteSettings.Authority
); );
using (SmtpClient sc = new ()) using (SmtpClient sc = new())
{ {
sc.Connect( sc.Connect(
smtpSettings.Server, smtpSettings.Server,
smtpSettings.Port, smtpSettings.Port,
SecureSocketOptions.Auto); SecureSocketOptions.Auto
);
if (smtpSettings.UserName!=null) { if (smtpSettings.UserName != null)
NetworkCredential creds = new ( {
smtpSettings.UserName, smtpSettings.Password); sc.Authenticate(smtpSettings.UserName, smtpSettings.Password);
await sc.AuthenticateAsync(System.Text.Encoding.UTF8, creds, System.Threading.CancellationToken.None);
} }
await sc.SendAsync(msg); await sc.SendAsync(msg);
logger.LogInformation($"Sent : {msg.MessageId}"); logger.LogInformation($"Sent : {msg.MessageId}");
sc.Disconnect(true);
} }
return msg.MessageId; return msg.MessageId;
} }
@ -105,10 +106,10 @@ namespace Yavsc.Services
public async Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink) public async Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink)
{ {
await SendEmailAsync(user.UserName, user.Email, await SendEmailAsync(user.UserName, user.Email,
localizer["Reset Password"], localizer["Reset Password"],
localizer["Please reset your password by "] + " <a href=\"" + localizer["Please reset your password by "] + " <a href=\"" +
resetLink + "\" >following this link</a>"); resetLink + "\" >following this link</a>");
} }
} }
} }

View File

@ -43,7 +43,7 @@ namespace Yavsc.Services
claimAdds.Remove("profile"); claimAdds.Remove("profile");
claimAdds.Add(JwtClaimTypes.Name); claimAdds.Add(JwtClaimTypes.Name);
claimAdds.Add(JwtClaimTypes.Email); claimAdds.Add(JwtClaimTypes.Email);
claimAdds.Add(JwtClaimTypes.Role); claimAdds.Add(Constants.RoleClaimType);
} }
if (claimAdds.Contains(JwtClaimTypes.Name)) if (claimAdds.Contains(JwtClaimTypes.Name))
@ -52,12 +52,12 @@ namespace Yavsc.Services
if (claimAdds.Contains(JwtClaimTypes.Email)) if (claimAdds.Contains(JwtClaimTypes.Email))
claims.Add(new Claim(JwtClaimTypes.Email, user.Email)); claims.Add(new Claim(JwtClaimTypes.Email, user.Email));
if (claimAdds.Contains(JwtClaimTypes.Role)) if (claimAdds.Contains(Constants.RoleClaimType))
{ {
var roles = await this._userManager.GetRolesAsync(user); var roles = await this._userManager.GetRolesAsync(user);
if (roles.Count()>0) if (roles.Count()>0)
{ {
claims.AddRange(roles.Select(r => new Claim(JwtClaimTypes.Role, r))); claims.AddRange(roles.Select(r => new Claim(Constants.RoleClaimType, r)));
} }
} }
return claims; return claims;

View File

@ -14,14 +14,17 @@ namespace Yavsc
public string FavIcon { get; set; } = "favicon.ico"; public string FavIcon { get; set; } = "favicon.ico";
public string Logo { get; set; } = "logo.png"; public string Logo { get; set; } = "logo.png";
/// <summary> /// <summary>
/// Conceptually,
/// This authorisation server only has this present site as unique audience.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public string Audience { get; set; } = "lua.pschneider.fr"; public string Audience { get; set; } = "lua.pschneider.fr";
/// <summary> /// <summary>
/// it's a very small company, with one domaine name only, /// External Url
/// so let it be the same as in the Audience field. /// </summary>
/// <value></value>
public string ExternalUrl { get; set; } = "http://lua.pschneider.fr";
/// <summary>
/// Must be a fqdn.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public string Authority { get; set; } = "lua.pschneider.fr"; public string Authority { get; set; } = "lua.pschneider.fr";

View File

@ -5,10 +5,10 @@ namespace Yavsc.ViewModels.Account
{ {
public class UnregisterViewModel public class UnregisterViewModel
{ {
[YaRequired] [Required]
public string UserId { get; set; } public string UserId { get; set; }
public string ReturnUrl { get; set; } public string? ReturnUrl { get; set; }
} }
} }

View File

@ -28,6 +28,7 @@ using System.Security.Cryptography;
using System.Text.Unicode; using System.Text.Unicode;
using System.Text; using System.Text;
using Yavsc.Server.Helpers; using Yavsc.Server.Helpers;
using System.Reflection;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
@ -66,7 +67,7 @@ namespace Yavsc.Controllers
ITrueEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
ILoggerFactory loggerFactory, IOptions<TwilioSettings> twilioSettings, ILoggerFactory loggerFactory, IOptions<TwilioSettings> twilioSettings,
IStringLocalizer<Yavsc.YavscLocalization> localizer, IStringLocalizerFactory localizerFactory,
ApplicationDbContext dbContext) ApplicationDbContext dbContext)
{ {
_interaction = interaction; _interaction = interaction;
@ -81,8 +82,9 @@ namespace Yavsc.Controllers
_siteSettings = siteSettings.Value; _siteSettings = siteSettings.Value;
_twilioSettings = twilioSettings.Value; _twilioSettings = twilioSettings.Value;
_logger = loggerFactory.CreateLogger<AccountController>(); _logger = loggerFactory.CreateLogger<AccountController>();
_localizer = localizer;
_dbContext = dbContext; _dbContext = dbContext;
_localizer = localizerFactory.Create(typeof(AccountController));
} }
@ -403,7 +405,7 @@ namespace Yavsc.Controllers
} }
[Authorize(Roles = Constants.AdminGroupName)] [Authorize("AdministratorOnly")]
public IActionResult Index() public IActionResult Index()
{ {
IViewComponentHelper h; IViewComponentHelper h;
@ -411,9 +413,9 @@ namespace Yavsc.Controllers
return View(); return View();
} }
[Authorize(Roles = Constants.AdminGroupName)] [Authorize("AdministratorOnly")]
[Route("Account/UserList/{pageNum}/{len?}")] [Route("Account/UserList/{pageNum?}/{len?}")]
public async Task<IActionResult> UserList(int pageNum, int pageLen = defaultLen) public async Task<IActionResult> UserList(int pageNum=0, int pageLen = 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;
@ -423,8 +425,6 @@ namespace Yavsc.Controllers
ViewBag.hasNext = users.Count() > (toShow.Count() + shown); ViewBag.hasNext = users.Count() > (toShow.Count() + shown);
ViewBag.nextpage = pageNum+1; ViewBag.nextpage = pageNum+1;
ViewBag.pageLen = pageLen; ViewBag.pageLen = pageLen;
// ApplicationUser user;
// user.EmailConfirmed
return View(toShow.ToArray()); return View(toShow.ToArray());
} }
@ -863,11 +863,13 @@ namespace Yavsc.Controllers
{ {
ApplicationUser user; ApplicationUser user;
// Username should not contain any '@' // Username should not contain any '@'
if (model.LoginOrEmail.Contains('@')) { if (model.LoginOrEmail.Contains('@'))
{
user = await _userManager.FindByEmailAsync(model.LoginOrEmail); user = await _userManager.FindByEmailAsync(model.LoginOrEmail);
} }
else { else
user = await _dbContext.Users.FirstOrDefaultAsync( u => u.UserName == model.LoginOrEmail); {
user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == model.LoginOrEmail);
} }
// Don't reveal that the user does not exist or is not confirmed // Don't reveal that the user does not exist or is not confirmed
@ -890,13 +892,16 @@ 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 = _siteSettings.Audience + "/Account/ResetPassword/" + var f = this.HttpContext.Features;
HttpUtility.UrlEncode(user.Id) + "/" + HttpUtility.UrlEncode(code); var callbackUrl = _siteSettings.ExternalUrl + "/Account/ResetPassword/" +
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 "] + " <a href=\"" + _localizer["Please reset your password by "] + " <a href=\"" +
callbackUrl + "\" >following this link</a>"); callbackUrl + "\" >following this link</a>");
return View("ForgotPasswordConfirmation", sent); return View("ForgotPasswordConfirmation", sent);
} }
// If we got this far, something failed, redisplay form // If we got this far, something failed, redisplay form
@ -920,8 +925,15 @@ namespace Yavsc.Controllers
var user = await _userManager.FindByIdAsync(id); var user = await _userManager.FindByIdAsync(id);
if (user==null) return new BadRequestResult(); if (user==null) return new BadRequestResult();
if (!await _userManager.VerifyUserTokenAsync(user,
_userManager.Options.Tokens.PasswordResetTokenProvider,
"ResetPassword", code.Replace("%2f","/")))
{
return BadRequest("code");
}
// We just serve the form to reset here. // We just serve the form to reset here.
return View(new ResetPasswordViewModel { return View(new ResetPasswordViewModel
{
Id = id, Id = id,
Code = code, Code = code,
Email = user.Email Email = user.Email
@ -946,9 +958,11 @@ 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");
} }
// code : "CfDJ8DmPlC3R8%2fNMqGlHZHZMwbjaXxgD3GW3H75Ubt+4Sbw%2fn%2fdg9X8Bll+CLIh%2fquI+Z96XEkx7bfrZiB+wpPb+b5%2ffgzgy+cQnKfX9J7%2fLNro+F3uE5JkXSlUc1WqVW2mVQrpWHjx1Dbn2n77TTGym3ttQoECsTR%2foo27dW9U11pmRJuTiwPBJZBOt0ffIRmgDDHh2f0VySTQEwjfRiLdCwctL%2fmh21ympJMKJl5PZnTVs"
if (user.Id != id) return BadRequest("userid");
var result = await _userManager.ResetPasswordAsync(user, var result = await _userManager.ResetPasswordAsync(user,
HttpUtility.UrlDecode(code), model.Password); code.Replace("%2f","/"), model.Password);
if (result.Succeeded) if (result.Succeeded)
{ {
@ -1086,11 +1100,23 @@ namespace Yavsc.Controllers
} }
[HttpGet, Authorize("AdministratorOnly")] [HttpGet, Authorize("AdministratorOnly")]
public IActionResult AdminDelete(string id) public IActionResult AdminDelete(string id, string? returnUrl=null)
{ {
return View(new UnregisterViewModel { UserId = id }); return View(new UnregisterViewModel { UserId = id, ReturnUrl = returnUrl });
} }
[HttpPost, Authorize("AdministratorOnly")]
public async Task<IActionResult> AdminDelete(UnregisterViewModel model)
{
var result = await DeleteUser(model.UserId);
if (!result.Succeeded)
{
AddErrors(result);
return new BadRequestObjectResult(ModelState);
}
return View();
}
[HttpPost, Authorize] [HttpPost, Authorize]
public async Task<IActionResult> Delete(UnregisterViewModel model) public async Task<IActionResult> Delete(UnregisterViewModel model)
{ {
@ -1118,21 +1144,6 @@ namespace Yavsc.Controllers
return await _userManager.DeleteAsync(user); return await _userManager.DeleteAsync(user);
} }
[HttpPost, Authorize("AdministratorOnly")]
public async Task<IActionResult> AdminDelete(UnregisterViewModel model)
{
var result = await DeleteUser(model.UserId);
if (!result.Succeeded)
{
AddErrors(result);
return new BadRequestObjectResult(ModelState);
}
return View();
}
#region Helpers
private void AddErrors(IdentityResult result) private void AddErrors(IdentityResult result)
{ {
foreach (var error in result.Errors) foreach (var error in result.Errors)
@ -1141,15 +1152,5 @@ namespace Yavsc.Controllers
} }
} }
private async Task<ApplicationUser> GetCurrentUserAsync()
{
return await GetCurrentUserAsync(HttpContext.User.GetUserId());
}
private async Task<ApplicationUser> GetCurrentUserAsync(string id)
{
return await _userManager.FindByIdAsync(id);
}
#endregion
} }
} }

View File

@ -51,7 +51,7 @@ namespace Yavsc.Controllers
IOptions<GoogleAuthSettings> googleSettings, IOptions<GoogleAuthSettings> googleSettings,
IOptions<PayPalSettings> paypalSettings, IOptions<PayPalSettings> paypalSettings,
IOptions<CompanyInfoSettings> cinfoSettings, IOptions<CompanyInfoSettings> cinfoSettings,
IStringLocalizer<Yavsc.YavscLocalization> SR, IStringLocalizer<ManageController> SR,
ICalendarManager calendarManager, ICalendarManager calendarManager,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {

View File

@ -30,7 +30,22 @@ namespace Yavsc.Controllers
this._dbContext = context; this._dbContext = context;
} }
private async Task<bool> EnsureRoleList () { public async Task<IActionResult> Role(string id)
{
var role = await _roleManager.FindByIdAsync(id);
if (role == null) return NotFound();
RoleUserCollection roleUserCollection = new RoleUserCollection
{
Id = id,
Name = role.Name,
Users = (await this._userManager.GetUsersInRoleAsync(role.Name))
.Select(u => new UserInfo (id, u.UserName, u.Email, u.Avatar)).ToArray()
};
return View(roleUserCollection);
}
private async Task<bool> EnsureRoleList()
{
// ensure all roles existence // ensure all roles existence
foreach (string roleName in new string[] { foreach (string roleName in new string[] {
Constants.AdminGroupName, Constants.AdminGroupName,
@ -50,7 +65,7 @@ namespace Yavsc.Controllers
return false; return false;
} }
} }
return true; return true;
} }
/// <summary> /// <summary>
@ -78,7 +93,8 @@ namespace Yavsc.Controllers
var user = await _userManager.FindByIdAsync(User.GetUserId()); var user = await _userManager.FindByIdAsync(User.GetUserId());
// check all user groups exist // check all user groups exist
if (!await EnsureRoleList()) { if (!await EnsureRoleList())
{
ModelState.AddModelError(null, "Could not ensure role list existence. aborting."); ModelState.AddModelError(null, "Could not ensure role list existence. aborting.");
return new BadRequestObjectResult(ModelState); return new BadRequestObjectResult(ModelState);
} }
@ -93,7 +109,7 @@ namespace Yavsc.Controllers
return Ok(new { message = "you owned it." }); return Ok(new { message = "you owned it." });
} }
[Authorize(Roles = Constants.AdminGroupName)] [Authorize("AdministratorOnly")]
[Produces("application/json")] [Produces("application/json")]
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
@ -104,10 +120,11 @@ namespace Yavsc.Controllers
await _userManager.FindByIdAsync(User.GetUserId()), await _userManager.FindByIdAsync(User.GetUserId()),
Constants.AdminGroupName); Constants.AdminGroupName);
var roles = await _roleManager.Roles.Select(x => new RoleInfo { var roles = await _roleManager.Roles.Select(x => new RoleInfo
{
Id = x.Id, Id = x.Id,
Name = x.Name Name = x.Name
}).ToArrayAsync(); }).ToArrayAsync();
foreach (var role in roles) foreach (var role in roles)
{ {
var uinrole = await _userManager.GetUsersInRoleAsync(role.Name); var uinrole = await _userManager.GetUsersInRoleAsync(role.Name);
@ -115,9 +132,9 @@ namespace Yavsc.Controllers
role.UserCount = uinrole.Count(); role.UserCount = uinrole.Count();
} }
var assembly = GetType().Assembly; var assembly = GetType().Assembly;
ViewBag.ThisAssembly = assembly.FullName; ViewBag.ThisAssembly = assembly.FullName;
ViewBag.RunTimeVersion = assembly.ImageRuntimeVersion; ViewBag.RunTimeVersion = assembly.ImageRuntimeVersion;
var rolesArray = roles.ToArray(); var rolesArray = roles.ToArray();
return View(new AdminViewModel return View(new AdminViewModel
{ {
Roles = rolesArray, Roles = rolesArray,
@ -131,7 +148,7 @@ namespace Yavsc.Controllers
public IActionResult Enroll(string roleName) public IActionResult Enroll(string roleName)
{ {
ViewBag.UserId = new SelectList(_dbContext.Users, "Id", "UserName"); ViewBag.UserId = new SelectList(_dbContext.Users, "Id", "UserName");
return View(new EnrolerViewModel{ RoleName = roleName }); return View(new EnrolerViewModel { RoleName = roleName });
} }
[Authorize("AdministratorOnly")] [Authorize("AdministratorOnly")]
@ -140,8 +157,8 @@ namespace Yavsc.Controllers
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var newAdmin = await _dbContext.Users.FirstOrDefaultAsync(u=>u.Id==model.EnroledUserId); var newAdmin = await _dbContext.Users.FirstOrDefaultAsync(u => u.Id == model.EnroledUserId);
if (newAdmin==null) return NotFound(); if (newAdmin == null) return NotFound();
var addToRoleResult = await _userManager.AddToRoleAsync(newAdmin, model.RoleName); var addToRoleResult = await _userManager.AddToRoleAsync(newAdmin, model.RoleName);
if (addToRoleResult.Succeeded) if (addToRoleResult.Succeeded)
{ {
@ -156,10 +173,10 @@ namespace Yavsc.Controllers
[Authorize("AdministratorOnly")] [Authorize("AdministratorOnly")]
public async Task<IActionResult> Fire(string roleName, string userId) public async Task<IActionResult> Fire(string roleName, string userId)
{ {
var user = await _dbContext.Users.FirstOrDefaultAsync(u=>u.Id==userId); var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
if (user == null) return NotFound(); if (user == null) return NotFound();
return View(new FireViewModel{ RoleName = roleName, EnroledUserId = userId, EnroledUserName = user.UserName }); return View(new FireViewModel { RoleName = roleName, EnroledUserId = userId, EnroledUserName = user.UserName });
} }
[Authorize("AdministratorOnly")] [Authorize("AdministratorOnly")]
@ -168,8 +185,8 @@ namespace Yavsc.Controllers
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var oldEnroled = await _dbContext.Users.FirstOrDefaultAsync(u=>u.Id==model.EnroledUserId); var oldEnroled = await _dbContext.Users.FirstOrDefaultAsync(u => u.Id == model.EnroledUserId);
if (oldEnroled==null) return NotFound(); if (oldEnroled == null) return NotFound();
var removeFromRole = await _userManager.RemoveFromRoleAsync(oldEnroled, model.RoleName); var removeFromRole = await _userManager.RemoveFromRoleAsync(oldEnroled, model.RoleName);
if (removeFromRole.Succeeded) if (removeFromRole.Succeeded)
{ {

View File

@ -1,3 +1,6 @@
using IdentityServer8.EntityFramework.DbContexts;
using IdentityServer8.EntityFramework.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -8,11 +11,12 @@ using Yavsc.Server.Helpers;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
[Authorize("AdministratorOnly")]
public class ClientController : Controller public class ClientController : Controller
{ {
private readonly ApplicationDbContext _context; private readonly ConfigurationDbContext _context;
public ClientController(ApplicationDbContext context) public ClientController(ConfigurationDbContext context)
{ {
_context = context; _context = context;
} }
@ -20,7 +24,8 @@ namespace Yavsc.Controllers
// GET: Client // GET: Client
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
return View(await _context.Applications.ToListAsync()); return View(await _context.Clients.Include(c=>c.AllowedGrantTypes)
.Include(c=>c.RedirectUris).ToListAsync());
} }
// GET: Client/Details/5 // GET: Client/Details/5
@ -31,7 +36,11 @@ namespace Yavsc.Controllers
return NotFound(); return NotFound();
} }
Client client = await _context.Applications.SingleAsync(m => m.Id == id); Client client = await _context.Clients.Include(
c => c.ClientSecrets
).Include(c=>c.AllowedGrantTypes)
.Include(c=>c.RedirectUris)
.SingleAsync(m => m.ClientId == id);
if (client == null) if (client == null)
{ {
return NotFound(); return NotFound();
@ -53,9 +62,10 @@ namespace Yavsc.Controllers
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
client.Id = Guid.NewGuid().ToString(); if (string.IsNullOrWhiteSpace(client.ClientId))
_context.Applications.Add(client); client.ClientId = Guid.NewGuid().ToString();
await _context.SaveChangesAsync(User.GetUserId()); _context.Clients.Add(client);
await _context.SaveChangesAsync();
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
SetAppTypesInputValues(); SetAppTypesInputValues();
@ -63,7 +73,7 @@ namespace Yavsc.Controllers
} }
private void SetAppTypesInputValues() private void SetAppTypesInputValues()
{ {
IEnumerable<SelectListItem> types = new SelectListItem[] { IEnumerable<SelectListItem> types = new SelectListItem[] {
new SelectListItem { new SelectListItem {
Text = ApplicationTypes.JavaScript.ToString(), Text = ApplicationTypes.JavaScript.ToString(),
Value = ((int) ApplicationTypes.JavaScript).ToString() }, Value = ((int) ApplicationTypes.JavaScript).ToString() },
@ -72,7 +82,7 @@ namespace Yavsc.Controllers
Value = ((int) ApplicationTypes.NativeConfidential).ToString() Value = ((int) ApplicationTypes.NativeConfidential).ToString()
} }
}; };
ViewData["Type"] = types; ViewData["AccessTokenType"] = types;
} }
// GET: Client/Edit/5 // GET: Client/Edit/5
public async Task<IActionResult> Edit(string id) public async Task<IActionResult> Edit(string id)
@ -82,7 +92,7 @@ namespace Yavsc.Controllers
return NotFound(); return NotFound();
} }
Client client = await _context.Applications.SingleAsync(m => m.Id == id); Client client = await _context.Clients.SingleAsync(m => m.ClientId == id);
if (client == null) if (client == null)
{ {
return NotFound(); return NotFound();
@ -99,7 +109,7 @@ namespace Yavsc.Controllers
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
_context.Update(client); _context.Update(client);
await _context.SaveChangesAsync(User.GetUserId()); await _context.SaveChangesAsync();
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
return View(client); return View(client);
@ -114,7 +124,7 @@ namespace Yavsc.Controllers
return NotFound(); return NotFound();
} }
Client client = await _context.Applications.SingleAsync(m => m.Id == id); Client client = await _context.Clients.SingleAsync(m => m.ClientId == id);
if (client == null) if (client == null)
{ {
return NotFound(); return NotFound();
@ -128,9 +138,9 @@ namespace Yavsc.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(string id) public async Task<IActionResult> DeleteConfirmed(string id)
{ {
Client client = await _context.Applications.SingleAsync(m => m.Id == id); Client client = await _context.Clients.SingleAsync(m => m.ClientId == id);
_context.Applications.Remove(client); _context.Clients.Remove(client);
await _context.SaveChangesAsync(User.GetUserId()); await _context.SaveChangesAsync();
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
} }

View File

@ -1,11 +1,9 @@
using System.IO.Compression;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json; using Newtonsoft.Json;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Blog;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
@ -24,42 +22,44 @@ namespace Yavsc.Controllers
public IActionResult GetBlog() public IActionResult GetBlog()
{ {
var data = applicationDbContext.BlogSpot.ToArray(); return ReturnDbSet(applicationDbContext.BlogSpot);
return Ok(JsonConvert.SerializeObject(data, Formatting.None));
} }
public IActionResult GetUsers() public IActionResult GetUsers()
{ {
var data = applicationDbContext.Users.ToArray(); return ReturnDbSet(applicationDbContext.Users);
return Ok(JsonConvert.SerializeObject(data, Formatting.None)); }
public IActionResult GeActivities()
{
return ReturnDbSet(applicationDbContext.Activities);
} }
public IActionResult ImportUsers(String usersJson) public IActionResult ImportUsers(String usersJson)
{
return DBSetImportFromJson(applicationDbContext.Users, usersJson);
}
public IActionResult ImportBlog(String blogJson)
{
return DBSetImportFromJson(applicationDbContext.BlogSpot, blogJson);
}
IActionResult ReturnDbSet<T>(DbSet<T> dbSet) where T : class
{
var data = dbSet.ToArray();
return Ok(data);
}
private IActionResult DBSetImportFromJson<T>(DbSet<T> dbSet, string usersJson) where T : class
{ {
int failures = 0; int failures = 0;
var input = JsonConvert.DeserializeObject<ApplicationUser[]>(usersJson); var input = JsonConvert.DeserializeObject<T[]>(usersJson);
foreach (var user in input) foreach (var user in input)
{ {
try try
{ {
applicationDbContext.Users.Add(user); dbSet.Add(user);
}
catch (Exception ex)
{
failures++;
}
}
return Ok(failures);
}
public IActionResult ImportBlog(String blogJson)
{
int failures = 0;
var input = JsonConvert.DeserializeObject<BlogPost[]>(blogJson);
foreach (var post in input)
{
try
{
applicationDbContext.BlogSpot.Add(post);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -15,11 +15,11 @@ namespace Yavsc.Controllers
public class ActivityController : Controller public class ActivityController : Controller
{ {
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
readonly IStringLocalizer<Yavsc.YavscLocalization> SR; readonly IStringLocalizer<ActivityController> SR;
readonly ILogger logger; readonly ILogger logger;
public ActivityController(ApplicationDbContext context, public ActivityController(ApplicationDbContext context,
IStringLocalizer<Yavsc.YavscLocalization> SR, IStringLocalizer<ActivityController> SR,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {
_context = context; _context = context;
@ -50,9 +50,8 @@ namespace Yavsc.Controllers
private List<SelectListItem> GetEligibleParent(string code) private List<SelectListItem> GetEligibleParent(string code)
{ {
// eligibles are those // eligibles are those
// who are not in descendants // who are not in descendence
//
var acts = _context.Activities.Where( var acts = _context.Activities.Where(
a => a.Code != code a => a.Code != code
).Select(a => new SelectListItem ).Select(a => new SelectListItem
@ -68,13 +67,13 @@ namespace Yavsc.Controllers
var pi = acts.FirstOrDefault(i => i.Value == existing.ParentCode); var pi = acts.FirstOrDefault(i => i.Value == existing.ParentCode);
if (pi!=null) pi.Selected = true; if (pi!=null) pi.Selected = true;
else nullItem.Selected = true; else nullItem.Selected = true;
RecFilterChild(acts, existing); RecursivelyFilterChild(acts, existing);
return acts; return acts;
} }
/// <summary> /// <summary>
/// Filters a activity selection list /// Filters a activity selection list
/// in order to exculde any descendant /// in order to exclude any descendant
/// from the eligible list at the <c>Parent</c> property. /// from the eligible list at the <c>Parent</c> property.
/// WARN! results in a infinite loop when /// WARN! results in a infinite loop when
/// data is corrupted and there is a circularity /// data is corrupted and there is a circularity
@ -82,22 +81,19 @@ namespace Yavsc.Controllers
/// </summary> /// </summary>
/// <param name="list"></param> /// <param name="list"></param>
/// <param name="activity"></param> /// <param name="activity"></param>
private static void RecFilterChild(List<SelectListItem> list, Activity activity) private static void RecursivelyFilterChild(List<SelectListItem> list, Activity activity)
{ {
if (activity == null) return; if (activity == null) return;
if (activity.Children == null) return; if (activity.Children == null) return;
if (list.Count == 0) return; if (list.Count == 0) return;
foreach (var child in activity.Children) foreach (var child in activity.Children)
{ {
RecFilterChild(list, child); RecursivelyFilterChild(list, child);
var rem = list.FirstOrDefault(i => i.Value == child.Code); var rem = list.FirstOrDefault(i => i.Value == child.Code);
if (rem != null) list.Remove(rem); if (rem != null) list.Remove(rem);
} }
} }
// GET: Activity/Details/5 // GET: Activity/Details/5
public IActionResult Details(string id) public IActionResult Details(string id)
{ {

View File

@ -16,6 +16,8 @@ namespace Yavsc.Controllers
using Models.Workflow; using Models.Workflow;
using Services; using Services;
using Yavsc.Interface; using Yavsc.Interface;
using Yavsc.Models.Billing;
using Yavsc.Models.Haircut;
using Yavsc.Server.Helpers; using Yavsc.Server.Helpers;
using Yavsc.Settings; using Yavsc.Settings;
@ -26,7 +28,7 @@ namespace Yavsc.Controllers
protected GoogleAuthSettings _googleSettings; protected GoogleAuthSettings _googleSettings;
protected IYavscMessageSender _MessageSender; protected IYavscMessageSender _MessageSender;
protected ITrueEmailSender _emailSender; protected ITrueEmailSender _emailSender;
protected IStringLocalizer _localizer; protected IStringLocalizer<CommandController> _localizer;
protected SiteSettings _siteSettings; protected SiteSettings _siteSettings;
protected SmtpSettings _smtpSettings; protected SmtpSettings _smtpSettings;
protected ICalendarManager _calendarManager; protected ICalendarManager _calendarManager;
@ -36,7 +38,7 @@ namespace Yavsc.Controllers
IYavscMessageSender messageSender, IYavscMessageSender messageSender,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
ICalendarManager calendarManager, ICalendarManager calendarManager,
IStringLocalizer<YavscLocalization> localizer, IStringLocalizer<CommandController> localizer,
ITrueEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SmtpSettings> smtpSettings, IOptions<SmtpSettings> smtpSettings,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,

View File

@ -25,7 +25,7 @@ namespace Yavsc.Controllers
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
IBillingService billing, IBillingService billing,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IStringLocalizer<Yavsc.YavscLocalization> SR) IStringLocalizer<FrontOfficeController> SR)
{ {
_context = context; _context = context;
_userManager = userManager; _userManager = userManager;

View File

@ -7,7 +7,7 @@ using Yavsc.Server.Helpers;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
[Authorize(Roles="Administrator")] [Authorize("AdministratorOnly")]
public class SIRENExceptionsController : Controller public class SIRENExceptionsController : Controller
{ {
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;

View File

@ -0,0 +1,175 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Messaging;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
[Produces("application/json")]
[Route("api/dimiss")]
public class DimissClicksApiController : Controller
{
private readonly ApplicationDbContext _context;
public DimissClicksApiController(ApplicationDbContext context)
{
_context = context;
}
// GET: api/DimissClicksApi
[HttpGet]
public IEnumerable<DismissClicked> GetDismissClicked()
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
return _context.DismissClicked.Where(d=>d.UserId == uid);
}
[HttpGet("click/{noteid}"),AllowAnonymous]
public async Task<IActionResult> Click(long noteid )
{
if (User.IsSignedIn())
return await PostDismissClicked(new DismissClicked { NotificationId= noteid, UserId = User.GetUserId()});
await HttpContext.Session.LoadAsync();
var clicked = HttpContext.Session.GetString("clicked");
if (clicked == null) {
HttpContext.Session.SetString("clicked",noteid.ToString());
} else HttpContext.Session.SetString("clicked",$"{clicked}:{noteid}");
await HttpContext.Session.CommitAsync();
return Ok();
}
// GET: api/DimissClicksApi/5
[HttpGet("{id}", Name = "GetDismissClicked")]
public async Task<IActionResult> GetDismissClicked([FromRoute] string id)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != id) return new ChallengeResult();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
DismissClicked DismissClicked = await _context.DismissClicked.SingleAsync(m => m.UserId == id);
if (DismissClicked == null)
{
return NotFound();
}
return Ok(DismissClicked);
}
// PUT: api/DimissClicksApi/5
[HttpPut("{id}")]
public async Task<IActionResult> PutDismissClicked([FromRoute] string id, [FromBody] DismissClicked DismissClicked)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != id || uid != DismissClicked.UserId) return new ChallengeResult();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != DismissClicked.UserId)
{
return BadRequest();
}
_context.Entry(DismissClicked).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync(User.GetUserId());
}
catch (DbUpdateConcurrencyException)
{
if (!DismissClickedExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return new StatusCodeResult(StatusCodes.Status204NoContent);
}
// POST: api/DimissClicksApi
[HttpPost]
public async Task<IActionResult> PostDismissClicked([FromBody] DismissClicked DismissClicked)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != DismissClicked.UserId) return new ChallengeResult();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.DismissClicked.Add(DismissClicked);
try
{
await _context.SaveChangesAsync(User.GetUserId());
}
catch (DbUpdateException)
{
if (DismissClickedExists(DismissClicked.UserId))
{
return new StatusCodeResult(StatusCodes.Status409Conflict);
}
else
{
throw;
}
}
return CreatedAtRoute("GetDismissClicked", new { id = DismissClicked.UserId }, DismissClicked);
}
// DELETE: api/DimissClicksApi/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteDismissClicked([FromRoute] string id)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (!User.IsInRole("Administrator"))
if (uid != id) return new ChallengeResult();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
DismissClicked DismissClicked = await _context.DismissClicked.SingleAsync(m => m.UserId == id);
if (DismissClicked == null)
{
return NotFound();
}
_context.DismissClicked.Remove(DismissClicked);
await _context.SaveChangesAsync(User.GetUserId());
return Ok(DismissClicked);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
base.Dispose(disposing);
}
private bool DismissClickedExists(string id)
{
return _context.DismissClicked.Count(e => e.UserId == id) > 0;
}
}
}

View File

@ -5,7 +5,7 @@ using Yavsc.Controllers.Generic;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
[Authorize(Roles="Performer")] [Authorize("Performer")]
public class BrusherProfileController : SettingsController<BrusherProfile> public class BrusherProfileController : SettingsController<BrusherProfile>
{ {
public BrusherProfileController(ApplicationDbContext context) : base(context) public BrusherProfileController(ApplicationDbContext context) : base(context)

View File

@ -18,11 +18,9 @@ namespace Yavsc.Controllers
using System.Globalization; using System.Globalization;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic; using System.Collections.Generic;
using Yavsc.Models.Messaging;
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.Interface;
using Yavsc.Settings; using Yavsc.Settings;
using Yavsc.Abstract.Models.Messaging; using Yavsc.Abstract.Models.Messaging;
@ -31,12 +29,15 @@ namespace Yavsc.Controllers
public class HairCutCommandController : CommandController public class HairCutCommandController : CommandController
{ {
readonly PayPalSettings payPalSettings; readonly PayPalSettings payPalSettings;
private readonly IStringLocalizer<HairCutQuery> haircutLocalizer;
public HairCutCommandController(ApplicationDbContext context, public HairCutCommandController(ApplicationDbContext context,
IOptions<PayPalSettings> payPalSettings, IOptions<PayPalSettings> payPalSettings,
IOptions<GoogleAuthSettings> googleSettings, IOptions<GoogleAuthSettings> googleSettings,
IYavscMessageSender GCMSender, IYavscMessageSender GCMSender,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
IStringLocalizer<Yavsc.YavscLocalization> localizer, IStringLocalizer<HairCutQuery> haircutLocalizer,
IStringLocalizer<CommandController> localizer,
ITrueEmailSender emailSender, ITrueEmailSender emailSender,
IOptions<SmtpSettings> smtpSettings, IOptions<SmtpSettings> smtpSettings,
IOptions<SiteSettings> siteSettings, IOptions<SiteSettings> siteSettings,
@ -45,6 +46,7 @@ namespace Yavsc.Controllers
calManager, localizer, emailSender, smtpSettings, siteSettings, loggerFactory) calManager, localizer, emailSender, smtpSettings, siteSettings, loggerFactory)
{ {
this.payPalSettings = payPalSettings.Value; this.payPalSettings = payPalSettings.Value;
this.haircutLocalizer = haircutLocalizer;
} }
@ -263,7 +265,7 @@ namespace Yavsc.Controllers
model.SelectedProfile = brusherProfile; model.SelectedProfile = brusherProfile;
model.Client = await _userManager.FindByIdAsync(uid); model.Client = await _userManager.FindByIdAsync(uid);
_logger.LogInformation(JsonConvert.SerializeObject(model)); _logger.LogInformation(JsonConvert.SerializeObject(model));
var yaev = model.CreateNewHairCutQueryEvent(_localizer); var yaev = model.CreateNewHairCutQueryEvent(this.haircutLocalizer);
if (pro.AcceptPublicContact) if (pro.AcceptPublicContact)
{ {

View File

@ -16,11 +16,11 @@ namespace Yavsc.Controllers
public class ProjectController : Controller public class ProjectController : Controller
{ {
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
readonly IStringLocalizer<Yavsc.YavscLocalization> _localizer; readonly IStringLocalizer<ProjectController> _localizer;
readonly IStringLocalizer<BugController> _bugLocalizer; readonly IStringLocalizer<BugController> _bugLocalizer;
public ProjectController(ApplicationDbContext context, public ProjectController(ApplicationDbContext context,
IStringLocalizer<Yavsc.YavscLocalization> localizer, IStringLocalizer<ProjectController> localizer,
IStringLocalizer<BugController> bugLocalizer IStringLocalizer<BugController> bugLocalizer
) )
{ {

View File

@ -2,6 +2,11 @@ using System.Diagnostics;
using System.Globalization; using System.Globalization;
using Google.Apis.Util.Store; using Google.Apis.Util.Store;
using IdentityServer8; using IdentityServer8;
using Microsoft.Extensions.DependencyInjection;
using IdentityServer8.Stores;
using IdentityServer8.EntityFramework;
using IdentityServer8.Extensions;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
@ -29,6 +34,9 @@ using IdentityModel;
using Yavsc.Interfaces; using Yavsc.Interfaces;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Npgsql; using Npgsql;
using System.Reflection;
using IdentityServer8.EntityFramework.DbContexts;
using IdentityServer8.EntityFramework.Mappers;
namespace Yavsc.Extensions; namespace Yavsc.Extensions;
@ -121,18 +129,22 @@ public static class HostingExtensions
{ {
IServiceCollection services = builder.Services; IServiceCollection services = builder.Services;
services.AddDbContext<ApplicationDbContext>(options => services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); {
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"),
options => options.MigrationsAssembly("Yavsc")
);
}
);
return services.AddIdentity<ApplicationUser, IdentityRole>( return services.AddIdentity<ApplicationUser, IdentityRole>(
options => options =>
{ {
options.SignIn.RequireConfirmedAccount = true; options.SignIn.RequireConfirmedAccount = true;
options.ClaimsIdentity.UserNameClaimType = JwtClaimTypes.PreferredUserName; options.ClaimsIdentity.UserNameClaimType = JwtClaimTypes.PreferredUserName;
options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role; options.ClaimsIdentity.RoleClaimType = Constants.RoleClaimType;
} }
) )
.AddEntityFrameworkStores<ApplicationDbContext>(); .AddEntityFrameworkStores<ApplicationDbContext>();
} }
private static void AddYavscPolicies(IServiceCollection services) private static void AddYavscPolicies(IServiceCollection services)
@ -144,17 +156,20 @@ public static class HostingExtensions
policy.RequireAuthenticatedUser() policy.RequireAuthenticatedUser()
.RequireClaim("scope", "scope2"); .RequireClaim("scope", "scope2");
}); });
options.AddPolicy("Performer", policy => options.AddPolicy("Performer", policy =>
{ {
policy policy
.RequireAuthenticatedUser() .RequireAuthenticatedUser()
.RequireClaim(JwtClaimTypes.Role, "Performer"); .RequireClaim(Constants.RoleClaimType,
new string[] { Constants.PerformerGroupName, Constants.AdminGroupName })
;
}); });
options.AddPolicy("AdministratorOnly", policy => options.AddPolicy("AdministratorOnly", policy =>
{ {
_ = policy _ = policy
.RequireAuthenticatedUser() .RequireAuthenticatedUser()
.RequireClaim(JwtClaimTypes.Role, Constants.AdminGroupName); .RequireClaim(Constants.RoleClaimType, Constants.AdminGroupName);
}); });
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName)); options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
@ -224,6 +239,9 @@ public static class HostingExtensions
} }
private static IIdentityServerBuilder AddIdentityServer(WebApplicationBuilder builder) private static IIdentityServerBuilder AddIdentityServer(WebApplicationBuilder builder)
{ {
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
var identityServerBuilder = builder.Services.AddIdentityServer(options => var identityServerBuilder = builder.Services.AddIdentityServer(options =>
{ {
options.Events.RaiseErrorEvents = true; options.Events.RaiseErrorEvents = true;
@ -235,13 +253,27 @@ public static class HostingExtensions
options.EmitStaticAudienceClaim = true; options.EmitStaticAudienceClaim = true;
}) })
.AddInMemoryIdentityResources(Config.IdentityResources) //.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryClients(Config.TestingClients) //.AddInMemoryClients(Config.TestingClients)
.AddClientStore<ClientStore>() //.AddInMemoryApiScopes(Config.TestingApiScopes)
.AddInMemoryApiScopes(Config.TestingApiScopes) .AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddAspNetIdentity<ApplicationUser>(); .AddAspNetIdentity<ApplicationUser>();
builder.Services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserIdClaimType = JwtClaimTypes.Subject;
options.ClaimsIdentity.UserNameClaimType = JwtClaimTypes.Name;
options.ClaimsIdentity.RoleClaimType = Constants.RoleClaimType;
});
if (builder.Environment.IsDevelopment()) if (builder.Environment.IsDevelopment())
{ {
@ -303,6 +335,8 @@ public static class HostingExtensions
public async static Task<WebApplication> ConfigurePipeline(this WebApplication app) public async static Task<WebApplication> ConfigurePipeline(this WebApplication app)
{ {
ILoggerFactory loggerFactory = app.Services.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
@ -311,10 +345,17 @@ public static class HostingExtensions
else else
{ {
app.UseExceptionHandler("/Home/Error"); app.UseExceptionHandler("/Home/Error");
using (var scope = app.Services.CreateScope()) try
{ {
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); using (var scope = app.Services.CreateScope())
await db.Database.MigrateAsync(); {
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
await db.Database.MigrateAsync();
}
}
catch (Exception ex)
{
logger.LogError("Error migrating the database : {0}", ex);
} }
} }
@ -345,19 +386,65 @@ public static class HostingExtensions
WorkflowHelpers.ConfigureBillingService(); WorkflowHelpers.ConfigureBillingService();
var services = app.Services; var services = app.Services;
ILoggerFactory loggerFactory = services.GetRequiredService<ILoggerFactory>();
var siteSettings = services.GetRequiredService<IOptions<SiteSettings>>(); var siteSettings = services.GetRequiredService<IOptions<SiteSettings>>();
var smtpSettings = services.GetRequiredService<IOptions<SmtpSettings>>(); var smtpSettings = services.GetRequiredService<IOptions<SmtpSettings>>();
var payPalSettings = services.GetRequiredService<IOptions<PayPalSettings>>(); var payPalSettings = services.GetRequiredService<IOptions<PayPalSettings>>();
var googleAuthSettings = services.GetRequiredService<IOptions<GoogleAuthSettings>>(); var googleAuthSettings = services.GetRequiredService<IOptions<GoogleAuthSettings>>();
var localization = services.GetRequiredService<IStringLocalizer<YavscLocalization>>(); var localization = services.GetRequiredService<IStringLocalizer<Startup>>();
Startup.Configure(app, siteSettings, smtpSettings, Startup.Configure(app, siteSettings, smtpSettings,
payPalSettings, googleAuthSettings, localization, loggerFactory, payPalSettings, googleAuthSettings, localization, loggerFactory,
app.Environment.EnvironmentName); app.Environment.EnvironmentName);
app.ConfigureFileServerApp(); app.ConfigureFileServerApp();
app.InitializeDatabase();
return app; return app;
} }
private static void InitializeDatabase(this IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
try
{
context.Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.Clients)
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.IdentityResources)
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
foreach (var resource in Config.ApiScopes)
{
context.ApiScopes.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
catch (InvalidOperationException ex)
{
app.Properties["DegradedDBContext"] = ex.Message;
}
}
}
static void LoadGoogleConfig(IConfigurationRoot configuration) static void LoadGoogleConfig(IConfigurationRoot configuration)
{ {

View File

@ -34,7 +34,7 @@ namespace Yavsc.Helpers
public static HairCutQueryEvent CreateNewHairCutQueryEvent(this HairCutQuery query, public static HairCutQueryEvent CreateNewHairCutQueryEvent(this HairCutQuery query,
IStringLocalizer SR) IStringLocalizer<HairCutQuery> SR)
{ {
string evdate = query.EventDate?.ToString("dddd dd/MM/yyyy à hh:mm")??"[pas de date spécifiée]"; string evdate = query.EventDate?.ToString("dddd dd/MM/yyyy à hh:mm")??"[pas de date spécifiée]";
string address = query.Location?.Address??"[pas de lieu spécifié]"; string address = query.Location?.Address??"[pas de lieu spécifié]";
@ -42,7 +42,7 @@ namespace Yavsc.Helpers
string strprestation = query.Description; string strprestation = query.Description;
var yaev = query.CreateEvent("NewHairCutQuery", var yaev = query.CreateEvent("NewHairCutQuery",
string.Format(ResourcesHelpers.GlobalLocalizer["HairCutQueryValidation"],query.Client.UserName), string.Format(SR["HairCutQueryValidation"],query.Client.UserName),
$"{query.Client.Id}"); $"{query.Client.Id}");

View File

@ -4,7 +4,7 @@ USER_AND_GROUP=www-data:www-data
SERVICE_PROD=yavsc SERVICE_PROD=yavsc
DOTNET_FRAMEWORK=net9.0 DOTNET_FRAMEWORK=net9.0
all: all: css js
dotnet build dotnet build
showConfig: showConfig:
@ -35,4 +35,6 @@ pushInProd: publish
%.min.css: %.css %.min.css: %.css
jsmin < $^ > $@ jsmin < $^ > $@
css: wwwroot/css/site.css css: wwwroot/css/site.min.css
js: wwwroot/js/site.min.js

View File

@ -9,10 +9,10 @@ using Yavsc.Models;
#nullable disable #nullable disable
namespace Yavsc.Server.Migrations namespace Yavsc.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("20250814102318_init")] [Migration("20250824130510_init")]
partial class init partial class init
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -702,7 +702,6 @@ namespace Yavsc.Server.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("AuthorId") b.Property<string>("AuthorId")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("Content") b.Property<string>("Content")
@ -2663,9 +2662,7 @@ namespace Yavsc.Server.Migrations
{ {
b.HasOne("Yavsc.Models.ApplicationUser", "Author") b.HasOne("Yavsc.Models.ApplicationUser", "Author")
.WithMany("Posts") .WithMany("Posts")
.HasForeignKey("AuthorId") .HasForeignKey("AuthorId");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author"); b.Navigation("Author");
}); });

View File

@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable #nullable disable
namespace Yavsc.Server.Migrations namespace Yavsc.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class init : Migration public partial class init : Migration
@ -800,7 +800,7 @@ namespace Yavsc.Server.Migrations
{ {
Id = table.Column<long>(type: "bigint", nullable: false) Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
AuthorId = table.Column<string>(type: "text", nullable: false), AuthorId = table.Column<string>(type: "text", nullable: true),
DateCreated = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), DateCreated = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UserCreated = table.Column<string>(type: "text", nullable: true), UserCreated = table.Column<string>(type: "text", nullable: true),
DateModified = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), DateModified = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
@ -816,8 +816,7 @@ namespace Yavsc.Server.Migrations
name: "FK_BlogSpot_AspNetUsers_AuthorId", name: "FK_BlogSpot_AspNetUsers_AuthorId",
column: x => x.AuthorId, column: x => x.AuthorId,
principalTable: "AspNetUsers", principalTable: "AspNetUsers",
principalColumn: "Id", principalColumn: "Id");
onDelete: ReferentialAction.Cascade);
}); });
migrationBuilder.CreateTable( migrationBuilder.CreateTable(

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class pending : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Client");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Client",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
AccessTokenLifetime = table.Column<int>(type: "integer", nullable: false),
Active = table.Column<bool>(type: "boolean", nullable: false),
DisplayName = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
LogoutRedirectUri = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
RedirectUri = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
RefreshTokenLifeTime = table.Column<int>(type: "integer", nullable: false),
Secret = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
Type = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Client", x => x.Id);
});
}
}
}

View File

@ -8,7 +8,7 @@ using Yavsc.Models;
#nullable disable #nullable disable
namespace Yavsc.Server.Migrations namespace Yavsc.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot partial class ApplicationDbContextModelSnapshot : ModelSnapshot
@ -429,47 +429,6 @@ namespace Yavsc.Server.Migrations
b.ToTable("AspNetUsers", (string)null); b.ToTable("AspNetUsers", (string)null);
}); });
modelBuilder.Entity("Yavsc.Models.Auth.Client", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("text");
b.Property<int>("AccessTokenLifetime")
.HasColumnType("integer");
b.Property<bool>("Active")
.HasColumnType("boolean");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("LogoutRedirectUri")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("RedirectUri")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<int>("RefreshTokenLifeTime")
.HasColumnType("integer");
b.Property<string>("Secret")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<int>("Type")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Client");
});
modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => modelBuilder.Entity("Yavsc.Models.Auth.Scope", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
@ -699,7 +658,6 @@ namespace Yavsc.Server.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("AuthorId") b.Property<string>("AuthorId")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("Content") b.Property<string>("Content")
@ -2660,9 +2618,7 @@ namespace Yavsc.Server.Migrations
{ {
b.HasOne("Yavsc.Models.ApplicationUser", "Author") b.HasOne("Yavsc.Models.ApplicationUser", "Author")
.WithMany("Posts") .WithMany("Posts")
.HasForeignKey("AuthorId") .HasForeignKey("AuthorId");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author"); b.Navigation("Author");
}); });

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,663 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Yavsc.Migrations.ConfigurationDb
{
/// <inheritdoc />
public partial class init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApiResources",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Enabled = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
AllowedAccessTokenSigningAlgorithms = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
ShowInDiscoveryDocument = table.Column<bool>(type: "boolean", nullable: false),
Created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Updated = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
LastAccessed = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
NonEditable = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiResources", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ApiScopes",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Enabled = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
Required = table.Column<bool>(type: "boolean", nullable: false),
Emphasize = table.Column<bool>(type: "boolean", nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiScopes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Clients",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Enabled = table.Column<bool>(type: "boolean", nullable: false),
ClientId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
ProtocolType = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
RequireClientSecret = table.Column<bool>(type: "boolean", nullable: false),
ClientName = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
ClientUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
LogoUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
RequireConsent = table.Column<bool>(type: "boolean", nullable: false),
AllowRememberConsent = table.Column<bool>(type: "boolean", nullable: false),
AlwaysIncludeUserClaimsInIdToken = table.Column<bool>(type: "boolean", nullable: false),
RequirePkce = table.Column<bool>(type: "boolean", nullable: false),
AllowPlainTextPkce = table.Column<bool>(type: "boolean", nullable: false),
RequireRequestObject = table.Column<bool>(type: "boolean", nullable: false),
AllowAccessTokensViaBrowser = table.Column<bool>(type: "boolean", nullable: false),
FrontChannelLogoutUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
FrontChannelLogoutSessionRequired = table.Column<bool>(type: "boolean", nullable: false),
BackChannelLogoutUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
BackChannelLogoutSessionRequired = table.Column<bool>(type: "boolean", nullable: false),
AllowOfflineAccess = table.Column<bool>(type: "boolean", nullable: false),
IdentityTokenLifetime = table.Column<int>(type: "integer", nullable: false),
AllowedIdentityTokenSigningAlgorithms = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
AccessTokenLifetime = table.Column<int>(type: "integer", nullable: false),
AuthorizationCodeLifetime = table.Column<int>(type: "integer", nullable: false),
ConsentLifetime = table.Column<int>(type: "integer", nullable: true),
AbsoluteRefreshTokenLifetime = table.Column<int>(type: "integer", nullable: false),
SlidingRefreshTokenLifetime = table.Column<int>(type: "integer", nullable: false),
RefreshTokenUsage = table.Column<int>(type: "integer", nullable: false),
UpdateAccessTokenClaimsOnRefresh = table.Column<bool>(type: "boolean", nullable: false),
RefreshTokenExpiration = table.Column<int>(type: "integer", nullable: false),
AccessTokenType = table.Column<int>(type: "integer", nullable: false),
EnableLocalLogin = table.Column<bool>(type: "boolean", nullable: false),
IncludeJwtId = table.Column<bool>(type: "boolean", nullable: false),
AlwaysSendClientClaims = table.Column<bool>(type: "boolean", nullable: false),
ClientClaimsPrefix = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
PairWiseSubjectSalt = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
Created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Updated = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
LastAccessed = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
UserSsoLifetime = table.Column<int>(type: "integer", nullable: true),
UserCodeType = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
DeviceCodeLifetime = table.Column<int>(type: "integer", nullable: false),
NonEditable = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Clients", x => x.Id);
});
migrationBuilder.CreateTable(
name: "IdentityResources",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Enabled = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
Required = table.Column<bool>(type: "boolean", nullable: false),
Emphasize = table.Column<bool>(type: "boolean", nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(type: "boolean", nullable: false),
Created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Updated = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
NonEditable = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IdentityResources", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ApiResourceClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ApiResourceId = table.Column<int>(type: "integer", nullable: false),
Type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiResourceClaims", x => x.Id);
table.ForeignKey(
name: "FK_ApiResourceClaims_ApiResources_ApiResourceId",
column: x => x.ApiResourceId,
principalTable: "ApiResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ApiResourceProperties",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ApiResourceId = table.Column<int>(type: "integer", nullable: false),
Key = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiResourceProperties", x => x.Id);
table.ForeignKey(
name: "FK_ApiResourceProperties_ApiResources_ApiResourceId",
column: x => x.ApiResourceId,
principalTable: "ApiResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ApiResourceScopes",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Scope = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
ApiResourceId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiResourceScopes", x => x.Id);
table.ForeignKey(
name: "FK_ApiResourceScopes_ApiResources_ApiResourceId",
column: x => x.ApiResourceId,
principalTable: "ApiResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ApiResourceSecrets",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ApiResourceId = table.Column<int>(type: "integer", nullable: false),
Description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
Value = table.Column<string>(type: "character varying(4000)", maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
Type = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id);
table.ForeignKey(
name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId",
column: x => x.ApiResourceId,
principalTable: "ApiResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ApiScopeClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ScopeId = table.Column<int>(type: "integer", nullable: false),
Type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiScopeClaims", x => x.Id);
table.ForeignKey(
name: "FK_ApiScopeClaims_ApiScopes_ScopeId",
column: x => x.ScopeId,
principalTable: "ApiScopes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ApiScopeProperties",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ScopeId = table.Column<int>(type: "integer", nullable: false),
Key = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiScopeProperties", x => x.Id);
table.ForeignKey(
name: "FK_ApiScopeProperties_ApiScopes_ScopeId",
column: x => x.ScopeId,
principalTable: "ApiScopes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Type = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientClaims", x => x.Id);
table.ForeignKey(
name: "FK_ClientClaims_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientCorsOrigins",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Origin = table.Column<string>(type: "character varying(150)", maxLength: 150, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id);
table.ForeignKey(
name: "FK_ClientCorsOrigins_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientGrantTypes",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GrantType = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientGrantTypes", x => x.Id);
table.ForeignKey(
name: "FK_ClientGrantTypes_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientIdPRestrictions",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Provider = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id);
table.ForeignKey(
name: "FK_ClientIdPRestrictions_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientPostLogoutRedirectUris",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
PostLogoutRedirectUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id);
table.ForeignKey(
name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientProperties",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ClientId = table.Column<int>(type: "integer", nullable: false),
Key = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientProperties", x => x.Id);
table.ForeignKey(
name: "FK_ClientProperties_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientRedirectUris",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
RedirectUri = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientRedirectUris", x => x.Id);
table.ForeignKey(
name: "FK_ClientRedirectUris_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientScopes",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Scope = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientScopes", x => x.Id);
table.ForeignKey(
name: "FK_ClientScopes_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ClientSecrets",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ClientId = table.Column<int>(type: "integer", nullable: false),
Description = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
Value = table.Column<string>(type: "character varying(4000)", maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
Type = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClientSecrets", x => x.Id);
table.ForeignKey(
name: "FK_ClientSecrets_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "IdentityResourceClaims",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
IdentityResourceId = table.Column<int>(type: "integer", nullable: false),
Type = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id);
table.ForeignKey(
name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId",
column: x => x.IdentityResourceId,
principalTable: "IdentityResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "IdentityResourceProperties",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
IdentityResourceId = table.Column<int>(type: "integer", nullable: false),
Key = table.Column<string>(type: "character varying(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IdentityResourceProperties", x => x.Id);
table.ForeignKey(
name: "FK_IdentityResourceProperties_IdentityResources_IdentityResour~",
column: x => x.IdentityResourceId,
principalTable: "IdentityResources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ApiResourceClaims_ApiResourceId",
table: "ApiResourceClaims",
column: "ApiResourceId");
migrationBuilder.CreateIndex(
name: "IX_ApiResourceProperties_ApiResourceId",
table: "ApiResourceProperties",
column: "ApiResourceId");
migrationBuilder.CreateIndex(
name: "IX_ApiResources_Name",
table: "ApiResources",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ApiResourceScopes_ApiResourceId",
table: "ApiResourceScopes",
column: "ApiResourceId");
migrationBuilder.CreateIndex(
name: "IX_ApiResourceSecrets_ApiResourceId",
table: "ApiResourceSecrets",
column: "ApiResourceId");
migrationBuilder.CreateIndex(
name: "IX_ApiScopeClaims_ScopeId",
table: "ApiScopeClaims",
column: "ScopeId");
migrationBuilder.CreateIndex(
name: "IX_ApiScopeProperties_ScopeId",
table: "ApiScopeProperties",
column: "ScopeId");
migrationBuilder.CreateIndex(
name: "IX_ApiScopes_Name",
table: "ApiScopes",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ClientClaims_ClientId",
table: "ClientClaims",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientCorsOrigins_ClientId",
table: "ClientCorsOrigins",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientGrantTypes_ClientId",
table: "ClientGrantTypes",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientIdPRestrictions_ClientId",
table: "ClientIdPRestrictions",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientPostLogoutRedirectUris_ClientId",
table: "ClientPostLogoutRedirectUris",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientProperties_ClientId",
table: "ClientProperties",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientRedirectUris_ClientId",
table: "ClientRedirectUris",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Clients_ClientId",
table: "Clients",
column: "ClientId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ClientScopes_ClientId",
table: "ClientScopes",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_ClientSecrets_ClientId",
table: "ClientSecrets",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_IdentityResourceClaims_IdentityResourceId",
table: "IdentityResourceClaims",
column: "IdentityResourceId");
migrationBuilder.CreateIndex(
name: "IX_IdentityResourceProperties_IdentityResourceId",
table: "IdentityResourceProperties",
column: "IdentityResourceId");
migrationBuilder.CreateIndex(
name: "IX_IdentityResources_Name",
table: "IdentityResources",
column: "Name",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ApiResourceClaims");
migrationBuilder.DropTable(
name: "ApiResourceProperties");
migrationBuilder.DropTable(
name: "ApiResourceScopes");
migrationBuilder.DropTable(
name: "ApiResourceSecrets");
migrationBuilder.DropTable(
name: "ApiScopeClaims");
migrationBuilder.DropTable(
name: "ApiScopeProperties");
migrationBuilder.DropTable(
name: "ClientClaims");
migrationBuilder.DropTable(
name: "ClientCorsOrigins");
migrationBuilder.DropTable(
name: "ClientGrantTypes");
migrationBuilder.DropTable(
name: "ClientIdPRestrictions");
migrationBuilder.DropTable(
name: "ClientPostLogoutRedirectUris");
migrationBuilder.DropTable(
name: "ClientProperties");
migrationBuilder.DropTable(
name: "ClientRedirectUris");
migrationBuilder.DropTable(
name: "ClientScopes");
migrationBuilder.DropTable(
name: "ClientSecrets");
migrationBuilder.DropTable(
name: "IdentityResourceClaims");
migrationBuilder.DropTable(
name: "IdentityResourceProperties");
migrationBuilder.DropTable(
name: "ApiResources");
migrationBuilder.DropTable(
name: "ApiScopes");
migrationBuilder.DropTable(
name: "Clients");
migrationBuilder.DropTable(
name: "IdentityResources");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmYourAccountBody">
<value>You successfully created your {0} account,
but your e-mail address is not yet confirmed.
Please, in order to validate it, follow this link &lt;{1}&gt;.
Thanks.
--
{0} - {2} &lt;https://{3}&gt;</value>
</data>
<data name="EmailSentForConfirm">
<value>An email has been sent to confirm your addresse.</value>
</data>
<data name="ConfirmYourAccountTitle">
<value>Please, confirm your e-mail</value>
</data>
<data name="ConfirmYourAccountBody">
<value>Ypu've successfully created an account {0},
but you still need to confirm your email.
Without this confirmation, you won't be able to login.
Please, follow this link to confirm your account : &lt;{1}&gt;.
--
{0} - {2} &lt;{3}&gt;</value>
</data>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root>

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root>

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmYourAccountBody">
<value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer.
Pour ce faire, veuillez, s'il vous plait, suivre le lien suivant
dans votre navigateur favori : &lt;{1}&gt;.
--
{0} - {2} &lt;{3}&gt;</value>
</data>
<data name="ConfirmYourAccountTitle">
<value>S'il vous plait, confirmez votre addresse e-mail</value>
</data>
<data name="AccountEmailFactorBody">
<value>Votre compte est endurci d'une requisition d'un second facteur d'identification.
Une nouvelle connection depuis un navigateur web nécéssite votre autorisation.
Vous pouvez l'accorder en suivant le lien suivant : &lt;{1}&gt;.
Votre code dáctivation est : {4}
Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette autorisation pour ce navigateur.
{0} - {2} &lt;{3}&gt;</value>
</data>
<data name="EmailSentForConfirm">
<value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value>
</data>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root>

View File

@ -772,18 +772,7 @@
<value>Invalid user name. <value>Invalid user name.
Valid caracters are: underscore '_', '-', 'a' - 'z', 'A' - 'Z', '0' - '9', the single quote ('), the space and the dot.</value> Valid caracters are: underscore '_', '-', 'a' - 'z', 'A' - 'Z', '0' - '9', the single quote ('), the space and the dot.</value>
</data> </data>
<data name="EmailSentForConfirm">
<value>An email has been sent to confirm your addresse.</value>
</data>
<data name="ConfirmYourAccountTitle"><value>Please, confirm your e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>You successfully created your {0} account,
but your e-mail address is not yet confirmed.
Please, in order to validate it, follow this link &lt;{1}&gt;.
Thanks.
--
{0} - {2} &lt;https://{3}&gt;</value>
</data>
<data name="Instrumentation"><value>Instrumentation</value></data> <data name="Instrumentation"><value>Instrumentation</value></data>
<data name="Partenariat"><value>Co-working</value></data> <data name="Partenariat"><value>Co-working</value></data>
</root> </root>

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Please reset your password by following this link:"><value>Por favor use o seguinte link para redefinir sua senha:</value></data>
<data name="Reset Password"><value>Redefinir sua senha</value></data>
</root>

View File

@ -251,7 +251,6 @@
<data name="HalfLong"><value>mi-long</value></data> <data name="HalfLong"><value>mi-long</value></data>
<data name="MobileHairCut"><value>Coiffure à domicile</value></data> <data name="MobileHairCut"><value>Coiffure à domicile</value></data>
<data name="HairCutQuery"><value>Préstation en coiffure à domicile</value></data> <data name="HairCutQuery"><value>Préstation en coiffure à domicile</value></data>
<data name="HairCutQueryValidation"><value>Une demande (de {0}) en coiffure à domicile vient d'être validée</value></data>
<data name="Hide source"><value>Cacher le texte source de l'article</value></data> <data name="Hide source"><value>Cacher le texte source de l'article</value></data>
<data name="Home"><value>Accueil</value></data> <data name="Home"><value>Accueil</value></data>
<data name="Hide"><value>Cacher</value></data> <data name="Hide"><value>Cacher</value></data>
@ -462,7 +461,6 @@
<data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data> <data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data>
<data name="ConfirmPassword"><value>Confirmation du mot de passe</value></data> <data name="ConfirmPassword"><value>Confirmation du mot de passe</value></data>
<data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data> <data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data>
<data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data>
<data name="AccountEmailFactorTitle"><value>Le second facteur de votre identification</value></data> <data name="AccountEmailFactorTitle"><value>Le second facteur de votre identification</value></data>
<data name="AccountEmailFactorBody"><value>Votre compte est endurci d'une requisition d'un second facteur d'identification. <data name="AccountEmailFactorBody"><value>Votre compte est endurci d'une requisition d'un second facteur d'identification.
@ -473,15 +471,7 @@ Votre code dáctivation est : {4}
Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur. Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur.
{0} - {2} &lt;{3}&gt;</value></data> {0} - {2} &lt;{3}&gt;</value></data>
<data name="ConfirmYourAccountTitle"><value>S'il vous plait, confirmez votre addresse e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer.
Pour ce faire, veuillez, s'il vous plait, suivre le lien suivant
dans votre navigateur favori : &lt;{1}&gt;.
--
{0} - {2} &lt;{3}&gt;</value></data>
<data name="BadStringLength"><value>Taille maximale: {0} caractère.</value></data> <data name="BadStringLength"><value>Taille maximale: {0} caractère.</value></data>
<data name="DetailledMinMaxStringLength"><value>Ce champ est <data name="DetailledMinMaxStringLength"><value>Ce champ est
d'au moins {0} et d'au plus {1} caractère(s) (manquent {2}) ou ({3} en trop).</value></data> d'au moins {0} et d'au plus {1} caractère(s) (manquent {2}) ou ({3} en trop).</value></data>

View File

@ -22,7 +22,7 @@ namespace Yavsc.Services
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private Action<string, string> _errorHandler; private Action<string, string>? _errorHandler;
/// <summary> /// <summary>
/// by cx id /// by cx id

View File

@ -1,37 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using IdentityServer8.Stores;
using IdentityServer8.Models;
namespace Yavsc.Services;
public class ClientStore : IClientStore
{
public ClientStore(ApplicationDbContext applicationDbContext)
{
ApplicationDbContext = applicationDbContext;
}
public ApplicationDbContext ApplicationDbContext { get; }
public async Task<Client> FindClientByIdAsync(string clientId)
{
var clientFromDb = await ApplicationDbContext.Client.FirstOrDefaultAsync(c => c.Id == clientId);
if (clientFromDb == null) return null;
return new Client
{
ClientId = clientFromDb.Id,
ClientName = clientFromDb.DisplayName,
ClientSecrets = { new Secret(clientFromDb.Secret.Sha256()) },
AllowedGrantTypes =
[
GrantType.AuthorizationCode,
GrantType.DeviceFlow,
GrantType.ClientCredentials
],
AllowedScopes = ["openid", "profile", "scope1"],
AbsoluteRefreshTokenLifetime = clientFromDb.RefreshTokenLifeTime,
AccessTokenLifetime = clientFromDb.AccessTokenLifetime
};
}
}

View File

@ -13,7 +13,7 @@ public class Startup
IOptions<SmtpSettings> smtpSettings, IOptions<SmtpSettings> smtpSettings,
IOptions<PayPalSettings> payPalSettings, IOptions<PayPalSettings> payPalSettings,
IOptions<GoogleAuthSettings> googleSettings, IOptions<GoogleAuthSettings> googleSettings,
IStringLocalizer<YavscLocalization> localizer, IStringLocalizer<Startup> localizer,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
string environmentName) string environmentName)
{ {

View File

@ -16,10 +16,10 @@ namespace Yavsc.ViewComponents
{ {
readonly ApplicationDbContext dbContext; readonly ApplicationDbContext dbContext;
readonly IBillingService billing; readonly IBillingService billing;
readonly IStringLocalizer<Yavsc.YavscLocalization> localizer; readonly IStringLocalizer<BillViewComponent> localizer;
public BillViewComponent(ApplicationDbContext dbContext, public BillViewComponent(ApplicationDbContext dbContext,
IStringLocalizer<Yavsc.YavscLocalization> localizer, IStringLocalizer<BillViewComponent> localizer,
IBillingService billing) IBillingService billing)
{ {
this.billing = billing; this.billing = billing;

View File

@ -5,13 +5,11 @@ namespace Yavsc.ViewModels
{ {
public partial class EnrolerViewModel { public partial class EnrolerViewModel {
[Display(Name="EnroledLabel", ResourceType=typeof(EnrolerViewModel))] [Required]
[YaRequired]
public string EnroledUserId { get; set; } public string EnroledUserId { get; set; }
[Display(Name="RoleNameLabel", ResourceType=typeof(EnrolerViewModel))] [Required]
[YaRequired]
public string RoleName { get; set; } public string RoleName { get; set; }
} }
} }

View File

@ -0,0 +1,10 @@
@{
ViewData["Title"] = "Account creation success";
}
<h1>@ViewData["Title"]</h1>
Your account has successfully been created.
<a asp-action="Index" asp-controller="Home">Return to home</a>

View File

@ -0,0 +1,14 @@
@model UnregisterViewModel
@{
ViewData["Title"] = "Unregister";
}
<h2>@ViewData["Title"].</h2>
<form asp-controller="Account" asp-action="AdminDelete" method="post" class="form-horizontal" role="form">
@Html.Hidden("UserId")
@Html.Hidden("ReturnUrl")
<input type="submit" value="Unregister" class="btn btn-primary" />
</form>

View File

@ -0,0 +1,12 @@
@model Yavsc.Abstract.Manage.EmailSentViewModel
@{
ViewData["Title"] = "S'il vous plait, veuillez confirmer votre adresse e-mail";
}
<h2>@ViewData["Title"].</h2>
<div>
<p>
Un message vient d'être envoyé à l'adresse e-mail ( @Model.EMail , id:@Model.MessageId ).
</p>
</div>

View File

@ -1,7 +1,9 @@
@model ResetPasswordViewModel @model ResetPasswordViewModel
<form asp-route-id="@Model.Id" asp-route-code="@Model.Code"> <form asp-route-id="@Model.Id" asp-route-code="@Model.Code">
<p>@Model.Email</p> <p>Your email : <code>@Model.Email</code></p>
<input type="hidden" name="Email" value="@Model.Email" />
@Html.ValidationSummary()
<div class="form-group"> <div class="form-group">
<label asp-for="Password"></label> <label asp-for="Password"></label>
<input class="form-control" placeholder="Password" asp-for="Password" autofocus> <input class="form-control" placeholder="Password" asp-for="Password" autofocus>
@ -10,6 +12,7 @@
<label asp-for="ConfirmPassword"></label> <label asp-for="ConfirmPassword"></label>
<input class="form-control" placeholder="ConfirmPassword" asp-for="ConfirmPassword" autofocus> <input class="form-control" placeholder="ConfirmPassword" asp-for="ConfirmPassword" autofocus>
</div> </div>
<button class="btn btn-primary" name="button" value="Reset">Reset Password</button> <button class="btn btn-primary" name="button" value="Reset">Reset Password</button>
</form> </form>

View File

@ -0,0 +1,7 @@
@{
ViewData["Title"] = "Reset password confirmation";
}
<h1>@ViewData["Title"].</h1>
<p>Votre mot de passe a été ré-initialisé.
<a href="~/signin">Cliquez ici pour vous connecter</a>.</p>

View File

@ -0,0 +1,8 @@
@{
ViewData["Title"] = "Reset password confirmation";
}
<h1>@ViewData["Title"].</h1>
<p>
Your password has been reset. Please <a href="~/signin">Click here to log in</a>.
</p>

View File

@ -0,0 +1,70 @@
@model ApplicationUser[]
@{
ViewData["Title"] = "Liste des utilisateurs";
}
<h2>@ViewData["Title"].</h2>
<table >
<thead>
<th>
@SR["Public info"]
</th>
<th>
@SR["AdminOnly"]
</th>
</thead>
@foreach (var user in Model)
{
<tr style="border-width:2px;">
<td>
@Html.DisplayFor(m=>user)
</td>
<td>
<dl>
<dt>
@SR["UserName"]
</dt>
<dd>
@Html.DisplayFor(m=>user.UserName)
</dd>
</dl>
<dl>
<dt>
@SR["FullName"]
</dt>
<dd>
@Html.DisplayFor(m=>user.FullName)
</dd>
</dl>
<dl>
<dt>
@SR["PostalAddress"]
</dt>
<dd>
@Html.DisplayFor(m=>user.PostalAddress)
</dd>
</dl>
<dl>
<dt>
@SR["Email"]
</dt>
<dd>
@Html.DisplayFor(m=>user.Email)
@if (!user.EmailConfirmed) {
<a class="btn btn-primary"
asp-action="AdminSendConfirationEmail" asp-route-id="@user.Id" >Envoyer une demande de confirmation</a>
}
<a asp-action="AdminDelete" asp-route-id="@user.Id"
class="btn btn-secondary">Supprimer</a>
</dd>
</dl>
</td>
</tr>
}
</table>
@if (ViewBag.hasNext)
{
<a asp-route-page="@ViewBag.nextpage" asp-route-len="@ViewBag.pageLen">Next page</a>
}

View File

@ -0,0 +1,83 @@
@model Activity
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<form asp-action="Create">
<div class="form-horizontal">
<h4>Activity</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Code" class="col-md-2 control-label">Code</label>
<div class="col-md-10">
<input asp-for="Code" class="form-control" />
<span asp-validation-for="Code" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Name" class="col-md-2 control-label">
Name"]</label>
<div class="col-md-10">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Parent" class="col-md-2 control-label">
Parent"]</label>
<div class="col-md-10">
<select asp-for="ParentCode" asp-items=@ViewBag.ParentCode class="form-control" >
</select>
<span asp-validation-for="ParentCode" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Description" class="col-md-2 control-label">
Description"]</label>
<div class="col-md-10">
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Photo" class="col-md-2 control-label">
Photo"]
</label>
<div class="col-md-10">
<input asp-for="Photo" class="form-control" />
<span asp-validation-for="Photo" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="SettingsClassName" class="col-md-2 control-label">
SettingsClass"]
</label>
<div class="col-md-10">
<select asp-for="SettingsClassName" class="form-control" asp-items="@ViewBag.SettingsClassName">
</select>
<span asp-validation-for="SettingsClassName" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create"]" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

View File

@ -0,0 +1,40 @@
@model Activity
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>AreYourSureYouWantToDeleteThis</h3>
<div>
<h4>Activity</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Description)
</dt>
<dd>
@Html.DisplayFor(model => model.Description)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Photo)
</dt>
<dd>
@Html.DisplayFor(model => model.Photo)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger" />
<a asp-action="Index" class="btn btn-link">Back to List</a>
</div>
</form>
</div>

View File

@ -0,0 +1,37 @@
@model Activity
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Activity</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Description)
</dt>
<dd>
@Html.DisplayFor(model => model.Description)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Photo)
</dt>
<dd>
@Html.DisplayFor(model => model.Photo)
<img src="@Model.Photo" style="max-width:100%"/>
</dd>
</dl>
</div>
<p>
<a asp-action="Edit" asp-route-id="@Model.Code">Edit</a> |
<a asp-action="Index">Back to List</a>
</p>

View File

@ -0,0 +1,86 @@
@model Activity
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Activity @Model.Code</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Code" />
<div class="form-group">
<label asp-for="Name" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Parent" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="ParentCode" asp-items=@ViewBag.ParentCode class="form-control" >
</select>
<span asp-validation-for="ParentCode" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="Description" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger" >
</span>
</div>
</div>
<div class="form-group">
<label asp-for="Photo" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Photo" class="form-control" />
<span asp-validation-for="Photo" class="text-danger">
</span>
</div>
</div>
<div class="form-group">
<label asp-for="SettingsClassName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="SettingsClassName" class="form-control" asp-items="@ViewBag.SettingsClassName">
</select>
<span asp-validation-for="SettingsClassName" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="Hidden" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Hidden" class="form-control" />
<span asp-validation-for="Hidden" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Rate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Rate" class="form-control" />
<span asp-validation-for="Rate" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

View File

@ -0,0 +1,89 @@
@model IEnumerable<Activity>
@{
ViewData["Title"] = "Index";
}
@section scripts {
<script>
$(document).ready(function(){
$("tr[data-hidden=True]").css('background-color','grey')
})
</script>
}
<h2>@ViewData["Title"]</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Code)
</th>
<th>
@Html.DisplayNameFor(model => model.Description)
</th>
<th>
@Html.DisplayNameFor(model => model.Photo)
</th>
<th>
@Html.DisplayNameFor(model => model.Parent)
</th>
<th>
@Html.DisplayNameFor(model => model.SettingsClassName)
</th>
<th>
@Html.DisplayNameFor(model => model.Children)
</th>
<th>
@Html.DisplayNameFor(model => model.Rate)
</th>
</tr>
@foreach (var item in Model) {
<tr data-hidden="@item.Hidden">
<td>
<a name="@item.Code" class="btn btn-link"></a> @Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Code)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>@if (item.Photo!=null) {
<img src="@item.Photo" style="max-height: 4em;" />
}
</td>
<td>
@if (item.Parent!=null) {
<text>
<a href="#@item.ParentCode">@Html.DisplayFor(modelItem => item.Parent)</a>
</text>
}
</td>
<td>
@if (item.SettingsClassName!=null) {
<text>
@item.SettingsClassName
</text>
}
</td>
<td>
@Html.DisplayFor(modelItem => item.Children)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Code" class="btn btn-default">Edit</a>
<a asp-action="Details" asp-route-id="@item.Code" class="btn btn-success">Details</a>
<a asp-action="Delete" asp-route-id="@item.Code" class="btn btn-danger">Delete</a>
</td>
</tr>
}
</table>

View File

@ -12,7 +12,7 @@
<table class="table"> <table class="table">
<tr> <tr>
<th> <th>
User"] User
</th> </th>
<th> <th>
</th> </th>
@ -22,7 +22,7 @@
<tr> <tr>
<td> <td>
<img src="~/avatars/@(user.UserName).xs.png" alt="avatar"/> <img src="~/avatars/@(user.UserName).xs.png" alt="avatar"/>
<span> @user.UserName </span> <span> @user.UserName &lt;@(user.Email)&gt; </span>
</td> </td>
<td> <td>
<a asp-action="Fire" asp-route-RoleName="@Model.Name" asp-route-UserId="@user.UserId" class="btn btn-success" > <a asp-action="Fire" asp-route-RoleName="@Model.Name" asp-route-UserId="@user.UserId" class="btn btn-success" >

View File

@ -0,0 +1,83 @@
@model Client
@{
ViewData["Title"] = @SR["Create"];
}
<h2>@SR["Create"]</h2>
<form asp-action="Create">
<div class="form-horizontal">
<h4>Client</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ClientId" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ClientId" class="form-control" />
<span asp-validation-for="ClientId" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<input asp-for="Enabled" />
<label asp-for="Enabled"></label>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="ClientName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ClientName" class="form-control" />
<span asp-validation-for="ClientName" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="FrontChannelLogoutUri" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="FrontChannelLogoutUri" class="form-control"></span>
<span asp-validation-for="FrontChannelLogoutUri" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="RedirectUris" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="RedirectUris" class="form-control" />
<span asp-validation-for="RedirectUris" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="AbsoluteRefreshTokenLifetime" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="AbsoluteRefreshTokenLifetime" class="form-control" ></span>
<span asp-validation-for="AbsoluteRefreshTokenLifetime" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="ClientSecrets" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ClientSecrets" class="form-control" />
<span asp-validation-for="ClientSecrets" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="AccessTokenType" class="col-md-2 control-label"></label>
<div class="col-md-10">
@Html.DropDownList("AccessTokenType")
<span asp-validation-for="AccessTokenType" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">@SR["Back to List"]</a>
</div>

View File

@ -0,0 +1,70 @@
@model Client
@{
ViewData["Title"] = @SR["Delete"];
}
<h2>@SR["Delete"]</h2>
<h3>@SR["AreYourSureYouWantToDeleteThis"]</h3>
<div>
<h4>Client</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.ClientId)
</dt>
<dt>
@Html.DisplayNameFor(model => model.ClientId)
</dt>
<dt>
@Html.DisplayNameFor(model => model.Enabled)
</dt>
<dt>
@Html.DisplayNameFor(model => model.Enabled)
</dt>
<dt>
@Html.DisplayNameFor(model => model.ClientName)
</dt>
<dd>
@Html.DisplayFor(model => model.ClientName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.FrontChannelLogoutUri)
</dt>
<dd>
@Html.DisplayFor(model => model.FrontChannelLogoutUri)
</dd>
<dt>
@Html.DisplayNameFor(model => model.RedirectUris)
</dt>
<dd>
@Html.DisplayFor(model => model.RedirectUris)
</dd>
<dt>
@Html.DisplayNameFor(model => model.AbsoluteRefreshTokenLifetime)
</dt>
<dd>
@Html.DisplayFor(model => model.AbsoluteRefreshTokenLifetime)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ClientSecrets)
</dt>
<dd>
@Html.DisplayFor(model => model.ClientSecrets)
</dd>
<dt>
@Html.DisplayNameFor(model => model.AccessTokenType)
</dt>
<dd>
@Html.DisplayFor(model => model.AccessTokenType)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">@SR["Back to List"]</a>
</div>
</form>
</div>

View File

@ -0,0 +1,68 @@
@model Client
@{
ViewData["Title"] = @SR["Details"];
}
<h2>@SR["Details"]</h2>
<div>
<h4>Client</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.ClientId)
</dt>
<dd>
@Html.DisplayFor(model => model.ClientId)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Enabled)
</dt>
<dd>
@Html.DisplayFor(model => model.Enabled)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ClientName)
</dt>
<dd>
@Html.DisplayFor(model => model.ClientName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.FrontChannelLogoutUri)
</dt>
<dd>
@Html.DisplayFor(model => model.FrontChannelLogoutUri)
</dd>
<dt>
@Html.DisplayNameFor(model => model.RedirectUris)
</dt>
<dd>
<ul>
@foreach (var uri in Model.RedirectUris)
{ <li>@uri.RedirectUri</li> }
</ul>
</dd>
<dt>
@Html.DisplayNameFor(model => model.AbsoluteRefreshTokenLifetime)
</dt>
<dd>
@Html.DisplayFor(model => model.AbsoluteRefreshTokenLifetime)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ClientSecrets)
</dt>
<dd>Count : @Model.ClientSecrets.Count</dd>
<dt>
@Html.DisplayNameFor(model => model.AccessTokenType)
</dt>
<dd>
@Html.DisplayFor(model => model.AccessTokenType)
</dd>
</dl>
</div>
<p>
<a asp-action="Edit" asp-route-id="@Model.Id">@SR["Edit"]</a> |
<a asp-action="Index">@SR["Back to List"]</a>
</p>

View File

@ -0,0 +1,83 @@
@model Client
@{
ViewData["Title"] = "Edit";
}
<h2>@SR["Edit"]</h2>
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Client</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ClientId" />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<input asp-for="Enabled" />
<label asp-for="Enabled"></label>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="ClientName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ClientName" class="form-control" />
<span asp-validation-for="ClientName" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="FrontChannelLogoutUri" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="FrontChannelLogoutUri" class="form-control" />
<span asp-validation-for="FrontChannelLogoutUri" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="RedirectUris" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="RedirectUris" class="form-control" />
<span asp-validation-for="RedirectUris" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="IdentityTokenLifetime" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="IdentityTokenLifetime" class="form-control" />
<span asp-validation-for="IdentityTokenLifetime" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="AbsoluteRefreshTokenLifetime" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="AbsoluteRefreshTokenLifetime" class="form-control" />
<span asp-validation-for="AbsoluteRefreshTokenLifetime" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="ClientSecrets" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ClientSecrets" class="form-control" />
<span asp-validation-for="ClientSecrets" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<label asp-for="AccessTokenType" class="col-md-2 control-label"></label>
<div class="col-md-10">
@Html.DropDownList("Type")
<span asp-validation-for="AccessTokenType" class="text-danger" ></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">@SR["Back to List"]</a>
</div>

View File

@ -0,0 +1,82 @@
@using IdentityServer8.Models
@model IEnumerable<IdentityServer8.EntityFramework.Entities.Client>
@{
ViewData["Title"] = @SR["Index"];
}
<h2>@SR["Index"]</h2>
<p>
<a asp-action="Create">@SR["Create New"]</a>
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.ClientId)
</th>
<th>
@Html.DisplayNameFor(model => model.Enabled)
</th>
<th>
@Html.DisplayNameFor(model => model.ClientName)
</th>
<th>
@Html.DisplayNameFor(model => model.FrontChannelLogoutUri)
</th>
<th>
@Html.DisplayNameFor(model => model.RedirectUris)
</th>
<th>
@Html.DisplayNameFor(model => model.AbsoluteRefreshTokenLifetime)
</th>
<th>
@Html.DisplayNameFor(model => model.AllowedGrantTypes)
</th>
<th>
@Html.DisplayNameFor(model => model.AccessTokenType)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ClientId)
</td>
<td>
@Html.DisplayFor(modelItem => item.Enabled)
</td>
<td>
@Html.DisplayFor(modelItem => item.ClientName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FrontChannelLogoutUri)
</td>
<td>
<ul>
@foreach (var uri in item.RedirectUris)
{ <li>@uri.RedirectUri</li> }
</ul>
</td>
<td>
@Html.DisplayFor(modelItem => item.AbsoluteRefreshTokenLifetime)
</td>
<td>
<ul>
@foreach (var t in item.AllowedGrantTypes)
{ <li>@t.GrantType</li> }
</ul>
</td>
<td>
@Enum.GetName(typeof(AccessTokenType), item.AccessTokenType)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ClientId">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ClientId">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ClientId">Delete</a>
</td>
</tr>
}
</table>

View File

@ -13,7 +13,7 @@
asp-route-activityCode="@ViewBag.Activity.Code" asp-route-activityCode="@ViewBag.Activity.Code"
asp-route-performerId="@profile.PerformerId" asp-route-performerId="@profile.PerformerId"
class="btn btn-success"> class="btn btn-success">
Proposer un rendez-vous à"] @profile.UserName Proposer un rendez-vous à @profile.UserName
</a> </a>
} }

Some files were not shown because too many files have changed in this diff Show More