Implemented OIDC
This commit is contained in:
parent
116dd93da2
commit
a9269ece30
|
@ -8,7 +8,7 @@ internal sealed class IdentityUserAccessor(
|
||||||
IdentityRedirectManager redirectManager) {
|
IdentityRedirectManager redirectManager) {
|
||||||
public async Task<ApplicationUser> GetRequiredUserAsync(HttpContext context) {
|
public async Task<ApplicationUser> GetRequiredUserAsync(HttpContext context) {
|
||||||
var user = await userManager.GetUserAsync(context.User);
|
var user = await userManager.GetUserAsync(context.User);
|
||||||
|
|
||||||
if (user is null) {
|
if (user is null) {
|
||||||
redirectManager.RedirectToWithStatus("Account/InvalidUser",
|
redirectManager.RedirectToWithStatus("Account/InvalidUser",
|
||||||
$"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context);
|
$"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context);
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
|
|
||||||
<BoardComponent CenterContent="true">
|
<BoardComponent CenterContent="true">
|
||||||
<BoardCardComponent Heading="@Localizer["Title"]">
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
<StatusMessage Message="@Message" />
|
<StatusMessage Message="@Message" />
|
||||||
|
<a class="btn btn-primary w-full mt-3" href="/Account/Login">@Localizer["Login_Label"]</a>
|
||||||
</BoardCardComponent>
|
</BoardCardComponent>
|
||||||
</BoardComponent>
|
</BoardComponent>
|
||||||
|
|
||||||
|
|
|
@ -4,192 +4,197 @@
|
||||||
@using System.Security.Claims
|
@using System.Security.Claims
|
||||||
@using System.Text
|
@using System.Text
|
||||||
@using System.Text.Encodings.Web
|
@using System.Text.Encodings.Web
|
||||||
|
@using Humanizer
|
||||||
@using Microsoft.AspNetCore.Identity
|
@using Microsoft.AspNetCore.Identity
|
||||||
@using Microsoft.AspNetCore.WebUtilities
|
@using Microsoft.AspNetCore.WebUtilities
|
||||||
@using Wave.Data
|
@using Wave.Data
|
||||||
|
|
||||||
@inject SignInManager<ApplicationUser> SignInManager
|
@inject SignInManager<ApplicationUser> SignInManager
|
||||||
@inject UserManager<ApplicationUser> UserManager
|
@inject UserManager<ApplicationUser> UserManager
|
||||||
|
@inject RoleManager<IdentityRole> RoleManager
|
||||||
@inject IUserStore<ApplicationUser> UserStore
|
@inject IUserStore<ApplicationUser> UserStore
|
||||||
@inject IEmailSender<ApplicationUser> EmailSender
|
@inject IEmailSender<ApplicationUser> EmailSender
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
@inject ILogger<ExternalLogin> Logger
|
@inject ILogger<ExternalLogin> Logger
|
||||||
|
@inject IStringLocalizer<ExternalLogin> Localizer
|
||||||
|
|
||||||
<PageTitle>Register</PageTitle>
|
<PageTitle>@Localizer["Title"]</PageTitle>
|
||||||
|
|
||||||
<StatusMessage Message="@message" />
|
<StatusMessage Message="@message" />
|
||||||
<h1>Register</h1>
|
|
||||||
<h2>Associate your @ProviderDisplayName account.</h2>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="alert alert-info">
|
<BoardComponent CenterContent="true">
|
||||||
You've successfully authenticated with <strong>@ProviderDisplayName</strong>.
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
Please enter an email address for this site below and click the Register button to finish
|
<Alert CanRemove="false" Type="Alert.MessageType.Information">
|
||||||
logging in.
|
<p>
|
||||||
</div>
|
@string.Format(Localizer["Message"], ProviderDisplayName)
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
<EditForm Model="Input" OnValidSubmit="OnValidSubmitAsync" FormName="confirmation" method="post">
|
||||||
|
<DataAnnotationsValidator/>
|
||||||
|
<InputLabelComponent LabelText="@Localizer["Email_Label"]" For="() => Input.Email">
|
||||||
|
<InputText @bind-Value="Input.Email" class="input input-bordered w-full"
|
||||||
|
autocomplete="email" placeholder="@Localizer["Email_Placeholder"]" />
|
||||||
|
</InputLabelComponent>
|
||||||
|
|
||||||
<div class="row">
|
<button type="submit" class="btn btn-primary w-full">
|
||||||
<div class="col-md-4">
|
@Localizer["Submit"]
|
||||||
<EditForm Model="Input" OnValidSubmit="OnValidSubmitAsync" FormName="confirmation" method="post">
|
</button>
|
||||||
<DataAnnotationsValidator />
|
</EditForm>
|
||||||
<ValidationSummary class="text-danger" role="alert" />
|
</BoardCardComponent>
|
||||||
<div class="form-floating mb-3">
|
</BoardComponent>
|
||||||
<InputText @bind-Value="Input.Email" class="form-control" autocomplete="email" placeholder="Please enter your email." />
|
|
||||||
<label for="email" class="form-label">Email</label>
|
|
||||||
<ValidationMessage For="() => Input.Email" />
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
|
|
||||||
</EditForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public const string LoginCallbackAction = "LoginCallback";
|
public const string LoginCallbackAction = "LoginCallback";
|
||||||
|
|
||||||
private string? message;
|
private string? message;
|
||||||
private ExternalLoginInfo externalLoginInfo = default!;
|
private ExternalLoginInfo externalLoginInfo = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
private HttpContext HttpContext { get; set; } = default!;
|
private HttpContext HttpContext { get; set; } = default!;
|
||||||
|
|
||||||
[SupplyParameterFromForm]
|
[SupplyParameterFromForm]
|
||||||
private InputModel Input { get; set; } = new();
|
private InputModel Input { get; set; } = new();
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery]
|
||||||
private string? RemoteError { get; set; }
|
private string? RemoteError { get; set; }
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery]
|
||||||
private string? ReturnUrl { get; set; }
|
private string? ReturnUrl { get; set; }
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery]
|
||||||
private string? Action { get; set; }
|
private string? Action { get; set; }
|
||||||
|
|
||||||
private string? ProviderDisplayName => externalLoginInfo.ProviderDisplayName;
|
private string? ProviderDisplayName => externalLoginInfo.ProviderDisplayName;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync() {
|
||||||
{
|
if (RemoteError is not null) {
|
||||||
if (RemoteError is not null)
|
RedirectManager.RedirectToWithStatus("Account/Login", $"Error from external provider: {RemoteError}", HttpContext);
|
||||||
{
|
}
|
||||||
RedirectManager.RedirectToWithStatus("Account/Login", $"Error from external provider: {RemoteError}", HttpContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
var info = await SignInManager.GetExternalLoginInfoAsync();
|
var info = await SignInManager.GetExternalLoginInfoAsync();
|
||||||
if (info is null)
|
if (info is null) {
|
||||||
{
|
RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext);
|
||||||
RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
externalLoginInfo = info;
|
externalLoginInfo = info;
|
||||||
|
|
||||||
if (HttpMethods.IsGet(HttpContext.Request.Method))
|
if (HttpMethods.IsGet(HttpContext.Request.Method)) {
|
||||||
{
|
if (Action == LoginCallbackAction) {
|
||||||
if (Action == LoginCallbackAction)
|
await OnLoginCallbackAsync();
|
||||||
{
|
return;
|
||||||
await OnLoginCallbackAsync();
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should only reach this page via the login callback, so redirect back to
|
// We should only reach this page via the login callback, so redirect back to
|
||||||
// the login page if we get here some other way.
|
// the login page if we get here some other way.
|
||||||
RedirectManager.RedirectTo("Account/Login");
|
RedirectManager.RedirectTo("Account/Login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnLoginCallbackAsync()
|
private async Task OnLoginCallbackAsync() {
|
||||||
{
|
// Sign in the user with this external login provider if the user already has a login.
|
||||||
// Sign in the user with this external login provider if the user already has a login.
|
var result = await SignInManager.ExternalLoginSignInAsync(
|
||||||
var result = await SignInManager.ExternalLoginSignInAsync(
|
externalLoginInfo.LoginProvider,
|
||||||
externalLoginInfo.LoginProvider,
|
externalLoginInfo.ProviderKey,
|
||||||
externalLoginInfo.ProviderKey,
|
isPersistent: false,
|
||||||
isPersistent: false,
|
bypassTwoFactor: true);
|
||||||
bypassTwoFactor: true);
|
|
||||||
|
|
||||||
if (result.Succeeded)
|
if (result.Succeeded) {
|
||||||
{
|
Logger.LogInformation(
|
||||||
Logger.LogInformation(
|
"{Name} logged in with {LoginProvider} provider.",
|
||||||
"{Name} logged in with {LoginProvider} provider.",
|
externalLoginInfo.Principal.Identity?.Name,
|
||||||
externalLoginInfo.Principal.Identity?.Name,
|
externalLoginInfo.LoginProvider);
|
||||||
externalLoginInfo.LoginProvider);
|
RedirectManager.RedirectTo(ReturnUrl);
|
||||||
RedirectManager.RedirectTo(ReturnUrl);
|
} else if (result.IsLockedOut) {
|
||||||
}
|
RedirectManager.RedirectTo("Account/Lockout");
|
||||||
else if (result.IsLockedOut)
|
}
|
||||||
{
|
|
||||||
RedirectManager.RedirectTo("Account/Lockout");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user does not have an account, then ask the user to create an account.
|
// If the user does not have an account, then ask the user to create an account.
|
||||||
if (externalLoginInfo.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
|
if (externalLoginInfo.Principal.Claims.FirstOrDefault(c => c.Type is ClaimTypes.Email or "email") is {} claim) {
|
||||||
{
|
Input.Email = claim.Value;
|
||||||
Input.Email = externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email) ?? "";
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnValidSubmitAsync()
|
private async Task OnValidSubmitAsync() {
|
||||||
{
|
var emailStore = GetEmailStore();
|
||||||
var emailStore = GetEmailStore();
|
var user = CreateUser();
|
||||||
var user = CreateUser();
|
|
||||||
|
|
||||||
await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
|
await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
|
||||||
await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
|
await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
|
||||||
|
|
||||||
var result = await UserManager.CreateAsync(user);
|
var info = await SignInManager.GetExternalLoginInfoAsync();
|
||||||
if (result.Succeeded)
|
if (info?.Principal.Claims.FirstOrDefault(c => c.Type is ClaimTypes.Name or ClaimTypes.GivenName or "name") is {} nameClaim) {
|
||||||
{
|
user.FullName = nameClaim.Value;
|
||||||
result = await UserManager.AddLoginAsync(user, externalLoginInfo);
|
}
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User created an account using {Name} provider.", externalLoginInfo.LoginProvider);
|
|
||||||
|
|
||||||
var userId = await UserManager.GetUserIdAsync(user);
|
var result = await UserManager.CreateAsync(user);
|
||||||
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
|
if (result.Succeeded) {
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
result = await UserManager.AddLoginAsync(user, externalLoginInfo);
|
||||||
|
if (result.Succeeded) {
|
||||||
|
Logger.LogInformation("User created an account using {Name} provider.", externalLoginInfo.LoginProvider);
|
||||||
|
|
||||||
var callbackUrl = NavigationManager.GetUriWithQueryParameters(
|
string userId = await UserManager.GetUserIdAsync(user);
|
||||||
NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
|
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code });
|
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
||||||
await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));
|
|
||||||
|
|
||||||
// If account confirmation is required, we need to show the link if we don't have a real email sender
|
string callbackUrl = NavigationManager.GetUriWithQueryParameters(
|
||||||
if (UserManager.Options.SignIn.RequireConfirmedAccount)
|
NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
|
||||||
{
|
new Dictionary<string, object?> {["userId"] = userId, ["code"] = code});
|
||||||
RedirectManager.RedirectTo("Account/RegisterConfirmation", new() { ["email"] = Input.Email });
|
await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));
|
||||||
}
|
|
||||||
|
|
||||||
await SignInManager.SignInAsync(user, isPersistent: false, externalLoginInfo.LoginProvider);
|
if (info?.Principal.Claims.FirstOrDefault(c => c.Type is ClaimTypes.Role or "roles") is { } roleClaim) {
|
||||||
RedirectManager.RedirectTo(ReturnUrl);
|
var roles = roleClaim.Value.Split(",").Select(s => s.Trim());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}";
|
foreach (string role in roles) {
|
||||||
}
|
try {
|
||||||
|
string r = role.Titleize();
|
||||||
|
if (r is "Author" or "Reviewer" or "Moderator" or "Admin" &&
|
||||||
|
!await RoleManager.RoleExistsAsync(r) &&
|
||||||
|
!(await RoleManager.CreateAsync(new IdentityRole(r))).Succeeded) {
|
||||||
|
Logger.LogError("Failed to create role {role}. Failed to assign it to user {name}.", r, user.UserName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
private ApplicationUser CreateUser()
|
await UserManager.AddToRoleAsync(user, r);
|
||||||
{
|
} catch (Exception ex) {
|
||||||
try
|
Logger.LogWarning(ex, "Failed to add newly created user {name} to role {role}.", user.UserName, role);
|
||||||
{
|
}
|
||||||
return Activator.CreateInstance<ApplicationUser>();
|
}
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
|
|
||||||
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IUserEmailStore<ApplicationUser> GetEmailStore()
|
// If account confirmation is required, we need to show the link if we don't have a real email sender
|
||||||
{
|
if (UserManager.Options.SignIn.RequireConfirmedAccount) {
|
||||||
if (!UserManager.SupportsUserEmail)
|
RedirectManager.RedirectTo("Account/RegisterConfirmation", new() { ["email"] = Input.Email });
|
||||||
{
|
}
|
||||||
throw new NotSupportedException("The default UI requires a user store with email support.");
|
|
||||||
}
|
|
||||||
return (IUserEmailStore<ApplicationUser>)UserStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class InputModel
|
await SignInManager.SignInAsync(user, isPersistent: false, externalLoginInfo.LoginProvider);
|
||||||
{
|
RedirectManager.RedirectTo(ReturnUrl);
|
||||||
[Required]
|
}
|
||||||
[EmailAddress]
|
}
|
||||||
public string Email { get; set; } = "";
|
|
||||||
}
|
message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ApplicationUser CreateUser() {
|
||||||
|
try {
|
||||||
|
return Activator.CreateInstance<ApplicationUser>();
|
||||||
|
} catch {
|
||||||
|
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
|
||||||
|
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IUserEmailStore<ApplicationUser> GetEmailStore() {
|
||||||
|
if (!UserManager.SupportsUserEmail) {
|
||||||
|
throw new NotSupportedException("The default UI requires a user store with email support.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IUserEmailStore<ApplicationUser>) UserStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class InputModel {
|
||||||
|
[Required] [EmailAddress]
|
||||||
|
public string Email { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,54 +20,49 @@
|
||||||
<StatusMessage Message="@_errorMessage" />
|
<StatusMessage Message="@_errorMessage" />
|
||||||
|
|
||||||
<BoardComponent CenterContent="true">
|
<BoardComponent CenterContent="true">
|
||||||
<BoardCardComponent Heading="@Localizer["Title"]">
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
<EditForm Model="Input" method="post" OnValidSubmit="LoginUser" FormName="login" class="w-full">
|
<EditForm Model="Input" method="post" OnValidSubmit="LoginUser" FormName="login" class="w-full">
|
||||||
<DataAnnotationsValidator />
|
<DataAnnotationsValidator />
|
||||||
|
|
||||||
<InputLabelComponent LabelText="@Localizer["Email_Label"]" For="() => Input.Email">
|
<InputLabelComponent LabelText="@Localizer["Email_Label"]" For="() => Input.Email">
|
||||||
<InputText @bind-Value="Input.Email" class="input input-bordered w-full" autocomplete="username"
|
<InputText @bind-Value="Input.Email" class="input input-bordered w-full" autocomplete="username"
|
||||||
required aria-required="true" placeholder="@Localizer["Email_Placeholder"]" />
|
required aria-required="true" placeholder="@Localizer["Email_Placeholder"]" />
|
||||||
</InputLabelComponent>
|
</InputLabelComponent>
|
||||||
<InputLabelComponent LabelText="@Localizer["Password_Label"]" For="() => Input.Password">
|
<InputLabelComponent LabelText="@Localizer["Password_Label"]" For="() => Input.Password">
|
||||||
<InputText @bind-Value="Input.Password" class="input input-bordered w-full" autocomplete="current-password" type="password"
|
<InputText @bind-Value="Input.Password" class="input input-bordered w-full" autocomplete="current-password" type="password"
|
||||||
required aria-required="true" placeholder="@Localizer["Password_Placeholder"]" />
|
required aria-required="true" placeholder="@Localizer["Password_Placeholder"]" />
|
||||||
</InputLabelComponent>
|
</InputLabelComponent>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">@Localizer["RememberMe_Label"]</span>
|
<span class="label-text">@Localizer["RememberMe_Label"]</span>
|
||||||
<InputCheckbox @bind-Value="Input.RememberMe" class="checkbox" />
|
<InputCheckbox @bind-Value="Input.RememberMe" class="checkbox" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary w-full">
|
<button type="submit" class="btn btn-primary w-full">
|
||||||
@Localizer["Submit"]
|
@Localizer["Submit"]
|
||||||
</button>
|
</button>
|
||||||
</EditForm>
|
</EditForm>
|
||||||
<ul class="mt-3 flex flex-col gap-1 text-center">
|
<ul class="mt-3 flex flex-col gap-1 text-center">
|
||||||
<li>
|
<li>
|
||||||
<a class="hover:link" href="Account/ForgotPassword">
|
<a class="hover:link" href="Account/ForgotPassword">
|
||||||
@Localizer["ResetPassword_Label"]
|
@Localizer["ResetPassword_Label"]
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="hover:link" href="@(NavigationManager.GetUriWithQueryParameters("Account/Register", new Dictionary<string, object?> { ["ReturnUrl"] = ReturnUrl }))">
|
<a class="hover:link" href="@(NavigationManager.GetUriWithQueryParameters("Account/Register", new Dictionary<string, object?> { ["ReturnUrl"] = ReturnUrl }))">
|
||||||
@Localizer["Register_Label"]
|
@Localizer["Register_Label"]
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="hover:link" href="Account/ResendEmailConfirmation">
|
<a class="hover:link" href="Account/ResendEmailConfirmation">
|
||||||
@Localizer["ResendMailConfirmation_Label"]
|
@Localizer["ResendMailConfirmation_Label"]
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</BoardCardComponent>
|
</BoardCardComponent>
|
||||||
<!--
|
|
||||||
<section class="w-80 max-w-xs">
|
<ExternalLoginPicker />
|
||||||
<h2 class="text-2xl lg:text-4xl mb-3">Use another service to log in.</h2>
|
|
||||||
<hr />
|
|
||||||
<ExternalLoginPicker />
|
|
||||||
</section>
|
|
||||||
-->
|
|
||||||
</BoardComponent>
|
</BoardComponent>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
@using System.ComponentModel.DataAnnotations
|
@using System.ComponentModel.DataAnnotations
|
||||||
@using Microsoft.AspNetCore.Identity
|
@using Microsoft.AspNetCore.Identity
|
||||||
@using Wave.Data
|
@using Wave.Data
|
||||||
|
@using Wave.Utilities
|
||||||
|
|
||||||
@inject UserManager<ApplicationUser> UserManager
|
@inject UserManager<ApplicationUser> UserManager
|
||||||
@inject SignInManager<ApplicationUser> SignInManager
|
@inject SignInManager<ApplicationUser> SignInManager
|
||||||
|
@ -10,66 +11,69 @@
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
@inject ILogger<DeletePersonalData> Logger
|
@inject ILogger<DeletePersonalData> Logger
|
||||||
@inject IStringLocalizer<DeletePersonalData> Localizer
|
@inject IStringLocalizer<DeletePersonalData> Localizer
|
||||||
|
@inject IMessageDisplay Message
|
||||||
|
|
||||||
<PageTitle>@Localizer["Title"]</PageTitle>
|
<PageTitle>@Localizer["Title"]</PageTitle>
|
||||||
|
|
||||||
<StatusMessage Message="@message" />
|
|
||||||
|
|
||||||
<BoardComponent>
|
<BoardComponent>
|
||||||
<BoardCardComponent Heading="@Localizer["Title"]">
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
<Alert Type="Alert.MessageType.Warning" CanRemove="false">
|
<Alert Type="Alert.MessageType.Warning" CanRemove="false">
|
||||||
<strong class="font-bold">@Localizer["Delete_FinalWarning"]</strong>
|
<strong class="font-bold">@Localizer["Delete_FinalWarning"]</strong>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<EditForm Model="Input" FormName="delete-user" OnValidSubmit="OnValidSubmitAsync" method="post" class="w-full">
|
<EditForm Model="Input" FormName="delete-user" OnValidSubmit="OnValidSubmitAsync" method="post" class="w-full mt-3">
|
||||||
<DataAnnotationsValidator />
|
<DataAnnotationsValidator/>
|
||||||
<ValidationSummary class="text-error" role="alert" />
|
@if (RequirePassword) {
|
||||||
@if (requirePassword) {
|
<InputLabelComponent LabelText="@Localizer["Delete_Password_Label"]" For="() => Input.Password">
|
||||||
<InputLabelComponent LabelText="@Localizer["Delete_Password_Label"]" For="() => Input.Password">
|
<InputText type="password" @bind-Value="Input.Password" class="input input-bordered w-full" required
|
||||||
<InputText type="password" @bind-Value="Input.Password" class="input input-bordered w-full" required
|
autocomplete="current-password" placeholder="@Localizer["Delete_Password_Placeholder"]"/>
|
||||||
autocomplete="current-password" placeholder="@Localizer["Delete_Password_Placeholder"]" />
|
</InputLabelComponent>
|
||||||
</InputLabelComponent>
|
} else {
|
||||||
}
|
<!-- our model binding fails without zero bound properties -->
|
||||||
<button class="btn btn-lg btn-error w-full" type="submit">@Localizer["Delete_FinalSubmit"]</button>
|
<InputText type="hidden" @bind-Value="Input.Password" />
|
||||||
</EditForm>
|
}
|
||||||
</BoardCardComponent>
|
<button class="btn btn-lg btn-error w-full" type="submit">@Localizer["Delete_FinalSubmit"]</button>
|
||||||
|
</EditForm>
|
||||||
|
</BoardCardComponent>
|
||||||
</BoardComponent>
|
</BoardComponent>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string? message;
|
private ApplicationUser User { get; set; } = default!;
|
||||||
private ApplicationUser user = default!;
|
private bool RequirePassword { get; set; }
|
||||||
private bool requirePassword;
|
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter] private HttpContext HttpContext { get; set; } = default!;
|
||||||
private HttpContext HttpContext { get; set; } = default!;
|
|
||||||
[SupplyParameterFromForm]
|
|
||||||
private InputModel Input { get; set; } = new();
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
[SupplyParameterFromForm(FormName = "delete-user")]
|
||||||
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
private InputModel Input { get; set; } = new();
|
||||||
requirePassword = await UserManager.HasPasswordAsync(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnValidSubmitAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
if (requirePassword && !await UserManager.CheckPasswordAsync(user, Input.Password)) {
|
User = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
||||||
message = Localizer["Delete_ErrorWrongPassword"];
|
RequirePassword = await UserManager.HasPasswordAsync(User);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var result = await UserManager.DeleteAsync(user);
|
private async Task OnValidSubmitAsync() {
|
||||||
if (!result.Succeeded) {
|
if (RequirePassword && !await UserManager.CheckPasswordAsync(User, Input.Password)) {
|
||||||
throw new InvalidOperationException(Localizer["Delete_ErrorUnknown"]);
|
Message.ShowError(Localizer["Delete_ErrorWrongPassword"]);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await SignInManager.SignOutAsync();
|
var result = await UserManager.DeleteAsync(User);
|
||||||
|
if (!result.Succeeded) {
|
||||||
|
throw new InvalidOperationException(Localizer["Delete_ErrorUnknown"]);
|
||||||
|
}
|
||||||
|
|
||||||
string userId = await UserManager.GetUserIdAsync(user);
|
await SignInManager.SignOutAsync();
|
||||||
Logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);
|
|
||||||
|
|
||||||
RedirectManager.RedirectToWithStatus("/", Localizer["Delete_Success"], HttpContext);
|
string userId = await UserManager.GetUserIdAsync(User);
|
||||||
}
|
Logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);
|
||||||
|
|
||||||
private sealed class InputModel {
|
Message.ShowSuccess(Localizer["Delete_Success"]);
|
||||||
[DataType(DataType.Password)] public string Password { get; set; } = "";
|
RedirectManager.RedirectTo("/");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private sealed class InputModel {
|
||||||
|
[DataType(DataType.Password)]
|
||||||
|
public string Password { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,132 +9,129 @@
|
||||||
@inject IdentityUserAccessor UserAccessor
|
@inject IdentityUserAccessor UserAccessor
|
||||||
@inject IUserStore<ApplicationUser> UserStore
|
@inject IUserStore<ApplicationUser> UserStore
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
|
@inject IStringLocalizer<ExternalLogin> Localizer
|
||||||
|
|
||||||
<PageTitle>Manage your external logins</PageTitle>
|
<PageTitle>@Localizer["Title"]</PageTitle>
|
||||||
|
|
||||||
<StatusMessage />
|
<StatusMessage/>
|
||||||
@if (currentLogins?.Count > 0)
|
|
||||||
{
|
@if (CurrentLogins?.Count > 0) {
|
||||||
<h3>Registered Logins</h3>
|
<BoardComponent>
|
||||||
<table class="table">
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
<tbody>
|
<div class="overflow-x-auto">
|
||||||
@foreach (var login in currentLogins)
|
<table class="table">
|
||||||
{
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>@login.ProviderDisplayName</td>
|
<th>Provider</th>
|
||||||
<td>
|
<th></th>
|
||||||
@if (showRemoveButton)
|
</tr>
|
||||||
{
|
</thead>
|
||||||
<form @formname="@($"remove-login-{login.LoginProvider}")" @onsubmit="OnSubmitAsync" method="post">
|
<tbody>
|
||||||
<AntiforgeryToken />
|
@foreach (var login in CurrentLogins) {
|
||||||
<div>
|
<tr>
|
||||||
<input type="hidden" name="@nameof(LoginProvider)" value="@login.LoginProvider" />
|
<td>@login.ProviderDisplayName</td>
|
||||||
<input type="hidden" name="@nameof(ProviderKey)" value="@login.ProviderKey" />
|
<td>
|
||||||
<button type="submit" class="btn btn-primary" title="Remove this @login.ProviderDisplayName login from your account">Remove</button>
|
@if (ShowRemoveButton) {
|
||||||
</div>
|
<form @formname="@($"remove-login-{login.LoginProvider}")" @onsubmit="OnSubmitAsync" method="post">
|
||||||
</form>
|
<AntiforgeryToken/>
|
||||||
}
|
<div>
|
||||||
else
|
<input type="hidden" name="@nameof(LoginProvider)" value="@login.LoginProvider"/>
|
||||||
{
|
<input type="hidden" name="@nameof(ProviderKey)" value="@login.ProviderKey"/>
|
||||||
@:
|
<button type="submit" class="btn btn-primary" title="Remove this @login.ProviderDisplayName login from your account">Remove</button>
|
||||||
}
|
</div>
|
||||||
</td>
|
</form>
|
||||||
</tr>
|
} else {
|
||||||
}
|
@:
|
||||||
</tbody>
|
}
|
||||||
</table>
|
</td>
|
||||||
}
|
</tr>
|
||||||
@if (otherLogins?.Count > 0)
|
}
|
||||||
{
|
</tbody>
|
||||||
<h4>Add another service to log in.</h4>
|
</table>
|
||||||
<hr />
|
</div>
|
||||||
<form class="form-horizontal" action="Account/Manage/LinkExternalLogin" method="post">
|
</BoardCardComponent>
|
||||||
<AntiforgeryToken />
|
@if (OtherLogins?.Count > 0) {
|
||||||
<div>
|
<BoardCardComponent Heading="Add another service to log in.">
|
||||||
<p>
|
<form class="form-horizontal" action="Account/Manage/LinkExternalLogin" method="post">
|
||||||
@foreach (var provider in otherLogins)
|
<AntiforgeryToken/>
|
||||||
{
|
<div>
|
||||||
<button type="submit" class="btn btn-primary" name="Provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">
|
<p>
|
||||||
@provider.DisplayName
|
@foreach (var provider in OtherLogins) {
|
||||||
</button>
|
<button type="submit" class="btn btn-primary" name="Provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">
|
||||||
}
|
@provider.DisplayName
|
||||||
</p>
|
</button>
|
||||||
</div>
|
}
|
||||||
</form>
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</BoardCardComponent>
|
||||||
|
}
|
||||||
|
</BoardComponent>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public const string LinkLoginCallbackAction = "LinkLoginCallback";
|
public const string LinkLoginCallbackAction = "LinkLoginCallback";
|
||||||
|
|
||||||
private ApplicationUser user = default!;
|
private ApplicationUser User { get; set; } = default!;
|
||||||
private IList<UserLoginInfo>? currentLogins;
|
private IList<UserLoginInfo>? CurrentLogins { get; set; }
|
||||||
private IList<AuthenticationScheme>? otherLogins;
|
private IList<AuthenticationScheme>? OtherLogins { get; set; }
|
||||||
private bool showRemoveButton;
|
private bool ShowRemoveButton { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
private HttpContext HttpContext { get; set; } = default!;
|
private HttpContext HttpContext { get; set; } = default!;
|
||||||
|
|
||||||
[SupplyParameterFromForm]
|
[SupplyParameterFromForm]
|
||||||
private string? LoginProvider { get; set; }
|
private string? LoginProvider { get; set; }
|
||||||
|
[SupplyParameterFromForm]
|
||||||
[SupplyParameterFromForm]
|
|
||||||
private string? ProviderKey { get; set; }
|
private string? ProviderKey { get; set; }
|
||||||
|
[SupplyParameterFromQuery]
|
||||||
[SupplyParameterFromQuery]
|
|
||||||
private string? Action { get; set; }
|
private string? Action { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync() {
|
||||||
{
|
User = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
||||||
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
CurrentLogins = await UserManager.GetLoginsAsync(User);
|
||||||
currentLogins = await UserManager.GetLoginsAsync(user);
|
OtherLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync())
|
||||||
otherLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync())
|
.Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider))
|
||||||
.Where(auth => currentLogins.All(ul => auth.Name != ul.LoginProvider))
|
.ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
string? passwordHash = null;
|
string? passwordHash = null;
|
||||||
if (UserStore is IUserPasswordStore<ApplicationUser> userPasswordStore)
|
if (UserStore is IUserPasswordStore<ApplicationUser> userPasswordStore) {
|
||||||
{
|
passwordHash = await userPasswordStore.GetPasswordHashAsync(User, HttpContext.RequestAborted);
|
||||||
passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
showRemoveButton = passwordHash is not null || currentLogins.Count > 1;
|
ShowRemoveButton = passwordHash is not null || CurrentLogins.Count > 1;
|
||||||
|
|
||||||
if (HttpMethods.IsGet(HttpContext.Request.Method) && Action == LinkLoginCallbackAction)
|
if (HttpMethods.IsGet(HttpContext.Request.Method) && Action == LinkLoginCallbackAction) {
|
||||||
{
|
await OnGetLinkLoginCallbackAsync();
|
||||||
await OnGetLinkLoginCallbackAsync();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnSubmitAsync()
|
private async Task OnSubmitAsync() {
|
||||||
{
|
var result = await UserManager.RemoveLoginAsync(User, LoginProvider!, ProviderKey!);
|
||||||
var result = await UserManager.RemoveLoginAsync(user, LoginProvider!, ProviderKey!);
|
if (!result.Succeeded) {
|
||||||
if (!result.Succeeded)
|
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not removed.", HttpContext);
|
||||||
{
|
}
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not removed.", HttpContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
await SignInManager.RefreshSignInAsync(user);
|
await SignInManager.RefreshSignInAsync(User);
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("The external login was removed.", HttpContext);
|
RedirectManager.RedirectToCurrentPageWithStatus("The external login was removed.", HttpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnGetLinkLoginCallbackAsync()
|
private async Task OnGetLinkLoginCallbackAsync() {
|
||||||
{
|
var userId = await UserManager.GetUserIdAsync(User);
|
||||||
var userId = await UserManager.GetUserIdAsync(user);
|
var info = await SignInManager.GetExternalLoginInfoAsync(userId);
|
||||||
var info = await SignInManager.GetExternalLoginInfoAsync(userId);
|
if (info is null) {
|
||||||
if (info is null)
|
RedirectManager.RedirectToCurrentPageWithStatus("Error: Could not load external login info.", HttpContext);
|
||||||
{
|
}
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("Error: Could not load external login info.", HttpContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await UserManager.AddLoginAsync(user, info);
|
var result = await UserManager.AddLoginAsync(User, info);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded) {
|
||||||
{
|
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not added. External logins can only be associated with one account.", HttpContext);
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not added. External logins can only be associated with one account.", HttpContext);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the existing external cookie to ensure a clean login process
|
// Clear the existing external cookie to ensure a clean login process
|
||||||
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
||||||
|
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("The external login was added.", HttpContext);
|
RedirectManager.RedirectToCurrentPageWithStatus("The external login was added.", HttpContext);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
|
@ -8,80 +8,72 @@
|
||||||
@inject SignInManager<ApplicationUser> SignInManager
|
@inject SignInManager<ApplicationUser> SignInManager
|
||||||
@inject IdentityUserAccessor UserAccessor
|
@inject IdentityUserAccessor UserAccessor
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
|
@inject IStringLocalizer<SetPassword> Localizer
|
||||||
|
|
||||||
<PageTitle>Set password</PageTitle>
|
<PageTitle>@Localizer["Title"]</PageTitle>
|
||||||
|
|
||||||
<h3>Set your password</h3>
|
<StatusMessage Message="@Message"/>
|
||||||
<StatusMessage Message="@message" />
|
<BoardComponent>
|
||||||
<p class="text-info">
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
You do not have a local username/password for this site. Add a local
|
<Alert CanRemove="false" Type="Alert.MessageType.Information">
|
||||||
account so you can log in without an external login.
|
<p>@Localizer["Message"]</p>
|
||||||
</p>
|
</Alert>
|
||||||
<div class="row">
|
<EditForm Model="Input" FormName="set-password" OnValidSubmit="OnValidSubmitAsync" method="post">
|
||||||
<div class="col-md-6">
|
<DataAnnotationsValidator/>
|
||||||
<EditForm Model="Input" FormName="set-password" OnValidSubmit="OnValidSubmitAsync" method="post">
|
<InputLabelComponent LabelText="@Localizer["NewPassword_Label"]" For="() => Input.NewPassword">
|
||||||
<DataAnnotationsValidator />
|
<InputText type="password" @bind-Value="Input.NewPassword" class="input input-bordered w-full" autocomplete="new-password"
|
||||||
<ValidationSummary class="text-danger" role="alert" />
|
required aria-required="true" placeholder="@Localizer["NewPassword_Placeholder"]"/>
|
||||||
<div class="form-floating mb-3">
|
</InputLabelComponent>
|
||||||
<InputText type="password" @bind-Value="Input.NewPassword" class="form-control" autocomplete="new-password" placeholder="Please enter your new password." />
|
<InputLabelComponent LabelText="@Localizer["ConfirmPassword_Label"]" For="() => Input.ConfirmPassword">
|
||||||
<label for="new-password" class="form-label">New password</label>
|
<InputText type="password" @bind-Value="Input.ConfirmPassword" class="input input-bordered w-full" autocomplete="new-password"
|
||||||
<ValidationMessage For="() => Input.NewPassword" class="text-danger" />
|
required aria-required="true" placeholder="@Localizer["ConfirmPassword_Placeholder"]"/>
|
||||||
</div>
|
</InputLabelComponent>
|
||||||
<div class="form-floating mb-3">
|
<button type="submit" class="btn btn-primary w-full">
|
||||||
<InputText type="password" @bind-Value="Input.ConfirmPassword" class="form-control" autocomplete="new-password" placeholder="Please confirm your new password." />
|
@Localizer["ChangePassword_Submit"]
|
||||||
<label for="confirm-password" class="form-label">Confirm password</label>
|
</button>
|
||||||
<ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
|
</EditForm>
|
||||||
</div>
|
</BoardCardComponent>
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Set password</button>
|
</BoardComponent>
|
||||||
</EditForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string? message;
|
private string? Message { get; set; }
|
||||||
private ApplicationUser user = default!;
|
private ApplicationUser User { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter] private HttpContext HttpContext { get; set; } = default!;
|
||||||
private HttpContext HttpContext { get; set; } = default!;
|
|
||||||
|
|
||||||
[SupplyParameterFromForm]
|
[SupplyParameterFromForm] private InputModel Input { get; set; } = new();
|
||||||
private InputModel Input { get; set; } = new();
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync() {
|
||||||
{
|
User = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
||||||
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
|
|
||||||
|
|
||||||
var hasPassword = await UserManager.HasPasswordAsync(user);
|
bool hasPassword = await UserManager.HasPasswordAsync(User);
|
||||||
if (hasPassword)
|
if (hasPassword) {
|
||||||
{
|
RedirectManager.RedirectTo("Account/Manage/ChangePassword");
|
||||||
RedirectManager.RedirectTo("Account/Manage/ChangePassword");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnValidSubmitAsync()
|
private async Task OnValidSubmitAsync() {
|
||||||
{
|
var addPasswordResult = await UserManager.AddPasswordAsync(User, Input.NewPassword!);
|
||||||
var addPasswordResult = await UserManager.AddPasswordAsync(user, Input.NewPassword!);
|
if (!addPasswordResult.Succeeded) {
|
||||||
if (!addPasswordResult.Succeeded)
|
Message = $"Error: {string.Join(",", addPasswordResult.Errors.Select(error => error.Description))}";
|
||||||
{
|
return;
|
||||||
message = $"Error: {string.Join(",", addPasswordResult.Errors.Select(error => error.Description))}";
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await SignInManager.RefreshSignInAsync(user);
|
await SignInManager.RefreshSignInAsync(User);
|
||||||
RedirectManager.RedirectToCurrentPageWithStatus("Your password has been set.", HttpContext);
|
RedirectManager.RedirectToCurrentPageWithStatus("Your password has been set.", HttpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class InputModel
|
private sealed class InputModel {
|
||||||
{
|
[Required]
|
||||||
[Required]
|
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
||||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
[DataType(DataType.Password)]
|
||||||
[DataType(DataType.Password)]
|
[Display(Name = "New password")]
|
||||||
[Display(Name = "New password")]
|
public string? NewPassword { get; set; }
|
||||||
public string? NewPassword { get; set; }
|
|
||||||
|
|
||||||
[DataType(DataType.Password)]
|
[DataType(DataType.Password)]
|
||||||
[Display(Name = "Confirm new password")]
|
[Display(Name = "Confirm new password")]
|
||||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
||||||
public string? ConfirmPassword { get; set; }
|
public string? ConfirmPassword { get; set; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
|
@ -9,64 +9,59 @@
|
||||||
@inject IEmailSender<ApplicationUser> EmailSender
|
@inject IEmailSender<ApplicationUser> EmailSender
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
|
@inject IStringLocalizer<RegisterConfirmation> Localizer
|
||||||
|
|
||||||
<HeadContent>
|
<HeadContent>
|
||||||
<meta name="robots" content="noindex,nofollow">
|
<meta name="robots" content="noindex,nofollow">
|
||||||
</HeadContent>
|
</HeadContent>
|
||||||
|
|
||||||
<PageTitle>Register confirmation</PageTitle>
|
<PageTitle>@Localizer["Title"] </PageTitle>
|
||||||
|
|
||||||
<h1>Register confirmation</h1>
|
<StatusMessage Message="@statusMessage"/>
|
||||||
|
|
||||||
<StatusMessage Message="@statusMessage" />
|
<BoardComponent CenterContent="true">
|
||||||
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
@if (emailConfirmationLink is not null)
|
<Alert CanRemove="false" Type="Alert.MessageType.Success">
|
||||||
{
|
@if (emailConfirmationLink is not null) {
|
||||||
<p>
|
<p>
|
||||||
This app does not currently have a real email sender registered, see <a href="https://aka.ms/aspaccountconf">these docs</a> for how to configure a real email sender.
|
This app does not currently have a real email sender registered, see <a href="https://aka.ms/aspaccountconf">these docs</a> for how to configure a real email sender.
|
||||||
Normally this would be emailed: <a href="@emailConfirmationLink">Click here to confirm your account</a>
|
Normally this would be emailed: <a href="@emailConfirmationLink">Click here to confirm your account</a>
|
||||||
</p>
|
</p>
|
||||||
}
|
} else {
|
||||||
else
|
<p>@Localizer["Message"]</p>
|
||||||
{
|
}
|
||||||
<p>Please check your email to confirm your account.</p>
|
</Alert>
|
||||||
}
|
</BoardCardComponent>
|
||||||
|
</BoardComponent>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string? emailConfirmationLink;
|
private string? emailConfirmationLink;
|
||||||
private string? statusMessage;
|
private string? statusMessage;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter] private HttpContext HttpContext { get; set; } = default!;
|
||||||
private HttpContext HttpContext { get; set; } = default!;
|
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery] private string? Email { get; set; }
|
||||||
private string? Email { get; set; }
|
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery] private string? ReturnUrl { get; set; }
|
||||||
private string? ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync() {
|
||||||
{
|
if (Email is null) {
|
||||||
if (Email is null)
|
RedirectManager.RedirectTo("");
|
||||||
{
|
}
|
||||||
RedirectManager.RedirectTo("");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await UserManager.FindByEmailAsync(Email);
|
var user = await UserManager.FindByEmailAsync(Email);
|
||||||
if (user is null)
|
if (user is null) {
|
||||||
{
|
HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
|
||||||
HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
|
statusMessage = "Error finding user for unspecified email";
|
||||||
statusMessage = "Error finding user for unspecified email";
|
} else if (EmailSender is IdentityNoOpEmailSender) {
|
||||||
}
|
// Once you add a real email sender, you should remove this code that lets you confirm the account
|
||||||
else if (EmailSender is IdentityNoOpEmailSender)
|
var userId = await UserManager.GetUserIdAsync(user);
|
||||||
{
|
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
// Once you add a real email sender, you should remove this code that lets you confirm the account
|
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
||||||
var userId = await UserManager.GetUserIdAsync(user);
|
emailConfirmationLink = NavigationManager.GetUriWithQueryParameters(
|
||||||
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
|
NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
new Dictionary<string, object?> {["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl});
|
||||||
emailConfirmationLink = NavigationManager.GetUriWithQueryParameters(
|
}
|
||||||
NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
|
}
|
||||||
new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl });
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,40 +4,42 @@
|
||||||
|
|
||||||
@inject SignInManager<ApplicationUser> SignInManager
|
@inject SignInManager<ApplicationUser> SignInManager
|
||||||
@inject IdentityRedirectManager RedirectManager
|
@inject IdentityRedirectManager RedirectManager
|
||||||
|
@inject IStringLocalizer<ExternalLoginPicker> Localizer
|
||||||
|
|
||||||
@if (externalLogins.Length == 0)
|
@if (externalLogins.Length > 0) {
|
||||||
{
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
||||||
<div>
|
<form class="form-horizontal" action="Account/PerformExternalLogin" method="post">
|
||||||
<p>
|
<div class="flex flex-col space-y-3">
|
||||||
There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">article
|
<AntiforgeryToken/>
|
||||||
about setting up this ASP.NET application to support logging in via external services</a>.
|
<input type="hidden" name="ReturnUrl" value="@ReturnUrl"/>
|
||||||
</p>
|
<p>
|
||||||
</div>
|
@foreach (var provider in externalLogins) {
|
||||||
}
|
if (provider.Name is "OpenIdConnect") {
|
||||||
else
|
<button type="submit" class="btn btn-wide btn-primary" name="provider" value="@provider.Name" title="@Localizer["OpenId_Tooltip"]">
|
||||||
{
|
@Localizer["OpenId_Label"]
|
||||||
<form class="form-horizontal" action="Account/PerformExternalLogin" method="post">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||||
<div>
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9" />
|
||||||
<AntiforgeryToken />
|
</svg>
|
||||||
<input type="hidden" name="ReturnUrl" value="@ReturnUrl" />
|
</button>
|
||||||
<p>
|
} else {
|
||||||
@foreach (var provider in externalLogins)
|
<button type="submit" class="btn btn-wide btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">
|
||||||
{
|
@provider.DisplayName
|
||||||
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
|
</button>
|
||||||
}
|
}
|
||||||
</p>
|
}
|
||||||
</div>
|
</p>
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
|
</BoardCardComponent>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private AuthenticationScheme[] externalLogins = [];
|
private AuthenticationScheme[] externalLogins = [];
|
||||||
|
|
||||||
[SupplyParameterFromQuery]
|
[SupplyParameterFromQuery] private string? ReturnUrl { get; set; }
|
||||||
private string? ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync() {
|
||||||
{
|
externalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToArray();
|
||||||
externalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToArray();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
7
Wave/Data/OidcConfiguration.cs
Normal file
7
Wave/Data/OidcConfiguration.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Wave.Data;
|
||||||
|
|
||||||
|
public class OidcConfiguration {
|
||||||
|
public string Authority { get; set; } = string.Empty;
|
||||||
|
public string ClientId { get; set; } = string.Empty;
|
||||||
|
public string ClientSecret { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ public class UserClaimsFactory(
|
||||||
: UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>(userManager, roleManager, options) {
|
: UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>(userManager, roleManager, options) {
|
||||||
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user) {
|
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user) {
|
||||||
var principal = await base.GenerateClaimsAsync(user);
|
var principal = await base.GenerateClaimsAsync(user);
|
||||||
principal.AddClaim(new Claim("Id", user.Id));
|
// principal.AddClaim(new Claim("Id", user.Id));
|
||||||
principal.AddClaim(new Claim("FullName", user.Name));
|
principal.AddClaim(new Claim("FullName", user.Name));
|
||||||
return principal;
|
return principal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
|
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
|
||||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
|
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
@ -19,6 +18,7 @@
|
||||||
using Wave.Data;
|
using Wave.Data;
|
||||||
using Wave.Services;
|
using Wave.Services;
|
||||||
using Wave.Utilities;
|
using Wave.Utilities;
|
||||||
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||||
|
|
||||||
string humanReadableVersion = Assembly.GetEntryAssembly()?
|
string humanReadableVersion = Assembly.GetEntryAssembly()?
|
||||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
.AddPolicy("ArticleEditOrReviewPermissions", p => p.RequireRole("Author", "Reviewer", "Admin"))
|
.AddPolicy("ArticleEditOrReviewPermissions", p => p.RequireRole("Author", "Reviewer", "Admin"))
|
||||||
|
|
||||||
.AddPolicy("EmailApi", p => p.RequireClaim("EmailApi")
|
.AddPolicy("EmailApi", p => p.RequireClaim("EmailApi")
|
||||||
.AddAuthenticationSchemes(ApiKeyDefaults.AuthenticationScheme));
|
.AddAuthenticationSchemes(ApiKeyDefaults.AuthenticationScheme));
|
||||||
builder.Services.AddAuthentication(options => {
|
builder.Services.AddAuthentication(options => {
|
||||||
options.DefaultScheme = IdentityConstants.ApplicationScheme;
|
options.DefaultScheme = IdentityConstants.ApplicationScheme;
|
||||||
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
|
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
|
||||||
|
@ -103,6 +103,30 @@
|
||||||
options.Realm = "Wave API";
|
options.Realm = "Wave API";
|
||||||
})
|
})
|
||||||
.AddIdentityCookies();
|
.AddIdentityCookies();
|
||||||
|
if (builder.Configuration.GetSection("Oidc").Get<OidcConfiguration>() is {} oidc && !string.IsNullOrWhiteSpace(oidc.Authority)) {
|
||||||
|
builder.Services.AddAuthentication(options => {
|
||||||
|
options.DefaultScheme = IdentityConstants.ApplicationScheme;
|
||||||
|
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
|
||||||
|
}).AddOpenIdConnect(options => {
|
||||||
|
options.SignInScheme = IdentityConstants.ExternalScheme;
|
||||||
|
|
||||||
|
options.Scope.Add(OpenIdConnectScope.OpenIdProfile);
|
||||||
|
options.Scope.Add(OpenIdConnectScope.OfflineAccess);
|
||||||
|
options.Authority = oidc.Authority;
|
||||||
|
|
||||||
|
options.ClientId = oidc.ClientId;
|
||||||
|
options.ClientSecret = oidc.ClientSecret;
|
||||||
|
options.ResponseType = OpenIdConnectResponseType.Code;
|
||||||
|
|
||||||
|
options.MapInboundClaims = false;
|
||||||
|
options.TokenValidationParameters.NameClaimType = "name";
|
||||||
|
options.TokenValidationParameters.RoleClaimType = "role";
|
||||||
|
|
||||||
|
options.CallbackPath = new PathString("/signin-oidc");
|
||||||
|
options.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
|
||||||
|
options.RemoteSignOutPath = new PathString("/signout-oidc");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -114,7 +138,10 @@
|
||||||
options.UseNpgsql(connectionString));
|
options.UseNpgsql(connectionString));
|
||||||
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
|
|
||||||
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
builder.Services.AddIdentityCore<ApplicationUser>(options => {
|
||||||
|
options.SignIn.RequireConfirmedAccount = true;
|
||||||
|
options.ClaimsIdentity.UserIdClaimType = "Id";
|
||||||
|
})
|
||||||
.AddRoles<IdentityRole>()
|
.AddRoles<IdentityRole>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||||
.AddSignInManager()
|
.AddSignInManager()
|
||||||
|
|
|
@ -110,4 +110,7 @@
|
||||||
<data name="Success" xml:space="preserve">
|
<data name="Success" xml:space="preserve">
|
||||||
<value>Vielen Dank fürs Bestätigen ihrer E-Mail Adresse.</value>
|
<value>Vielen Dank fürs Bestätigen ihrer E-Mail Adresse.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Login_Label" xml:space="preserve">
|
||||||
|
<value>Anmelden</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -110,4 +110,7 @@
|
||||||
<data name="Success" xml:space="preserve">
|
<data name="Success" xml:space="preserve">
|
||||||
<value>Thank you for confirming your email.</value>
|
<value>Thank you for confirming your email.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Login_Label" xml:space="preserve">
|
||||||
|
<value>Log In</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
117
Wave/Resources/Components/Account/Pages/ExternalLogin.de-DE.resx
Normal file
117
Wave/Resources/Components/Account/Pages/ExternalLogin.de-DE.resx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>Sie haben sich erfolgreich mit {0} angemeldet.
|
||||||
|
Bitte geben Sie nun eine E-Mail Addresse für diese Webseite ein.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Email_Label" xml:space="preserve">
|
||||||
|
<value>E-Mail</value>
|
||||||
|
</data>
|
||||||
|
<data name="Email_Placeholder" xml:space="preserve">
|
||||||
|
<value>name@example.de</value>
|
||||||
|
</data>
|
||||||
|
<data name="Submit" xml:space="preserve">
|
||||||
|
<value>Registrieren</value>
|
||||||
|
</data>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Benutzerkonto Erstellen</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
101
Wave/Resources/Components/Account/Pages/ExternalLogin.en-GB.resx
Normal file
101
Wave/Resources/Components/Account/Pages/ExternalLogin.en-GB.resx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
117
Wave/Resources/Components/Account/Pages/ExternalLogin.resx
Normal file
117
Wave/Resources/Components/Account/Pages/ExternalLogin.resx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Create Account</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>You've successfully authenticated with {0}.
|
||||||
|
Please enter an email address for this site below.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Email_Label" xml:space="preserve">
|
||||||
|
<value>Email</value>
|
||||||
|
</data>
|
||||||
|
<data name="Email_Placeholder" xml:space="preserve">
|
||||||
|
<value>name@example.com</value>
|
||||||
|
</data>
|
||||||
|
<data name="Submit" xml:space="preserve">
|
||||||
|
<value>Register</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,122 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Passwort Erstellen</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>Sie haben momentan kein lokales Benutzerkonto/Passwort für diese Seite. Fügen Sie ein lokales Konto hinzu um sich ohne externen Dienst anmelden zu können.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConfirmPassword_Label" xml:space="preserve">
|
||||||
|
<value>Neues Passwort wiederholen</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConfirmPassword_Placeholder" xml:space="preserve">
|
||||||
|
<value>Bestätigen Sie ihr neues Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewPassword_Label" xml:space="preserve">
|
||||||
|
<value>Neues Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewPassword_Placeholder" xml:space="preserve">
|
||||||
|
<value>Geben Sie ihr neues Passwort ein</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChangePassword_Submit" xml:space="preserve">
|
||||||
|
<value>Passwort Ändern</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
122
Wave/Resources/Components/Account/Pages/Manage/SetPassword.resx
Normal file
122
Wave/Resources/Components/Account/Pages/Manage/SetPassword.resx
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Create Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>You do not have a local username/password for this site. Add a local account, so you can log in without an external login.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewPassword_Label" xml:space="preserve">
|
||||||
|
<value>New password</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewPassword_Placeholder" xml:space="preserve">
|
||||||
|
<value>Enter your new password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConfirmPassword_Label" xml:space="preserve">
|
||||||
|
<value>Confirm new password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConfirmPassword_Placeholder" xml:space="preserve">
|
||||||
|
<value>Confirm your new Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChangePassword_Submit" xml:space="preserve">
|
||||||
|
<value>Change Password</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Registrierung Bestätigen</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>Bitte öffnen Sie Ihre E-Mails und bestätigen Sie ihr Benutzerkonto. Sie können sich nicht Anmelden bevor Ihr Konto bestätigt wurde.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Confirm Registration</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message" xml:space="preserve">
|
||||||
|
<value>Please check your email to confirm your account. You cannot log in before your account has been confirmed.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Anmelden über externen Dienst</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenId_Tooltip" xml:space="preserve">
|
||||||
|
<value>Melden Sie sich über ihren OpenID Connect Dienst an</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
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">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</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.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:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Title" xml:space="preserve">
|
||||||
|
<value>Log In using external service</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenId_Label" xml:space="preserve">
|
||||||
|
<value>OpenID Connect</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenId_Tooltip" xml:space="preserve">
|
||||||
|
<value>Log In using OpenID Connect provider</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -17,6 +17,7 @@
|
||||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
||||||
<PackageReference Include="MailKit" Version="4.3.0" />
|
<PackageReference Include="MailKit" Version="4.3.0" />
|
||||||
<PackageReference Include="Markdig" Version="0.34.0" />
|
<PackageReference Include="Markdig" Version="0.34.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
||||||
|
|
2
Wave/wwwroot/css/main.min.css
vendored
2
Wave/wwwroot/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue