Add project files.

This commit is contained in:
Khwezi Mngoma
2026-06-05 22:07:25 +02:00
parent 59ea7de742
commit 437e8c5c08
978 changed files with 151911 additions and 0 deletions
@@ -0,0 +1,23 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class AccountOptions
{
public static bool AllowLocalLogin = true;
public static bool AllowRememberLogin = true;
public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);
public static bool ShowLogoutPrompt = true;
public static bool AutomaticRedirectAfterSignOut = false;
public static string InvalidCredentialsErrorMessage = "Invalid username or password";
public static string InvalidPasskeyErrorMessage = "Passkey sign-in failed";
}
}
@@ -0,0 +1,18 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class AdminConfiguration
{
public string PageTitle { get; set; }
public string HomePageLogoUri { get; set; }
public string FaviconUri { get; set; }
public string IdentityAdminBaseUrl { get; set; }
public string AdministrationRole { get; set; }
public string Theme { get; set; }
public string CustomThemeCss { get; set; }
}
}
@@ -0,0 +1,24 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace LiteCharmsSecurity.STS.Identity.Configuration.ApplicationParts
{
public class GenericControllerRouteConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.IsGenericType)
{
// this change is required because some of the controllers have generic parameters
// and require resolution that will remove arity from the type
// as well as remove the 'Controller' at the end of string
var name = controller.ControllerType.Name;
var nameWithoutArity = name.Substring(0, name.IndexOf('`'));
controller.ControllerName = nameWithoutArity.Substring(0, nameWithoutArity.LastIndexOf("Controller"));
}
}
}
}
@@ -0,0 +1,42 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
namespace LiteCharmsSecurity.STS.Identity.Configuration.ApplicationParts
{
public class GenericTypeControllerFeatureProvider<TUser, TKey> : IApplicationFeatureProvider<ControllerFeature>
where TUser : IdentityUser<TKey>
where TKey : IEquatable<TKey>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
var currentAssembly = typeof(GenericTypeControllerFeatureProvider<TUser, TKey>).Assembly;
var controllerTypes = currentAssembly.GetExportedTypes()
.Where(t => typeof(ControllerBase).IsAssignableFrom(t) && t.IsGenericTypeDefinition)
.Select(t => t.GetTypeInfo());
var type = GetType();
var genericType = type.GetGenericTypeDefinition().GetTypeInfo();
var parameters = genericType.GenericTypeParameters
.Select((p, i) => new { p.Name, Index = i })
.ToDictionary(a => a.Name, a => type.GenericTypeArguments[a.Index]);
foreach (var controllerType in controllerTypes)
{
var typeArguments = controllerType.GenericTypeParameters
.Select(p => parameters[p.Name])
.ToArray();
feature.Controllers.Add(controllerType.MakeGenericType(typeArguments).GetTypeInfo());
}
}
}
}
@@ -0,0 +1,18 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class ConsentOptions
{
public static bool EnableOfflineAccess = true;
public static string OfflineAccessDisplayName = "Offline Access";
public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline";
public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission";
public static readonly string InvalidSelectionErrorMessage = "Invalid selection";
}
}
@@ -0,0 +1,14 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration.Constants
{
public static class AddressClaimConstants
{
public static readonly string StreetAddress = "street_address";
public static readonly string Locality = "locality";
public static readonly string Region = "region";
public static readonly string PostalCode = "postal_code";
public static readonly string Country = "country";
}
}
@@ -0,0 +1,10 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration.Constants
{
public class AuthorizationConsts
{
public const string AdministrationPolicy = "RequireAdministratorRole";
}
}
@@ -0,0 +1,30 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration.Constants
{
public class ConfigurationConsts
{
public const string AdminConnectionStringKey = "AdminConnection";
public const string ConfigurationDbConnectionStringKey = "ConfigurationDbConnection";
public const string PersistedGrantDbConnectionStringKey = "PersistedGrantDbConnection";
public const string IdentityDbConnectionStringKey = "IdentityDbConnection";
public const string DataProtectionDbConnectionStringKey = "DataProtectionDbConnection";
public const string ResourcesPath = "Resources";
public const string AdminConfigurationKey = "AdminConfiguration";
public const string RegisterConfigurationKey = "RegisterConfiguration";
public const string AdvancedConfigurationKey = "AdvancedConfiguration";
public const string CspTrustedDomainsKey = "CspTrustedDomains";
public const string ForwardedHeadersConfigurationKey = "ForwardedHeadersConfiguration";
}
}
@@ -0,0 +1,16 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class CultureConfiguration
{
public static readonly string[] AvailableCultures = { "en", "fa", "fr", "ru", "sv", "zh", "es", "da", "de", "nl", "fi", "pt" };
public static readonly string DefaultRequestCulture = "en";
public List<string> Cultures { get; set; }
public string DefaultCulture { get; set; } = DefaultRequestCulture;
}
}
@@ -0,0 +1,21 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class ExternalProvidersConfiguration
{
public bool UseGitHubProvider { get; set; }
public string GitHubClientId { get; set; }
public string GitHubClientSecret { get; set; }
public string GitHubCallbackPath { get; set; }
public bool UseAzureAdProvider { get; set; }
public string AzureAdClientId { get; set; }
public string AzureAdSecret { get; set; }
public string AzureAdTenantId { get; set; }
public string AzureInstance { get; set; }
public string AzureAdCallbackPath { get; set; }
public string AzureDomain { get; set; }
}
}
@@ -0,0 +1,40 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class ForwardedHeadersConfiguration
{
/// <summary>
/// Enable forwarded headers middleware. Default: true
/// Set to false if running Kestrel directly without a reverse proxy
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// List of known proxy IP addresses or CIDR ranges (e.g., "10.0.0.1", "192.168.1.0/24")
/// Leave empty for development. For production, specify your proxy/load balancer IPs
/// </summary>
public List<string> KnownProxies { get; set; } = new List<string>();
/// <summary>
/// List of known network CIDR ranges (e.g., "10.0.0.0/8", "172.16.0.0/12")
/// Leave empty for development. For production, specify your internal network ranges
/// </summary>
public List<string> KnownNetworks { get; set; } = new List<string>();
/// <summary>
/// Forward limit - number of proxies to trust. Default: 1
/// Set to null for unlimited (not recommended for production)
/// </summary>
public int? ForwardLimit { get; set; } = 1;
/// <summary>
/// Allow all proxies and networks (insecure, only for development)
/// When true, clears KnownProxies and KnownNetworks allowing all sources
/// </summary>
public bool AllowAll { get; set; } = false;
}
}
@@ -0,0 +1,14 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
namespace LiteCharmsSecurity.STS.Identity.Configuration.Interfaces
{
public interface IRootConfiguration
{
AdminConfiguration AdminConfiguration { get; }
RegisterConfiguration RegisterConfiguration { get; }
}
}
@@ -0,0 +1,14 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
using LiteCharmsSecurity.STS.Identity.Configuration.Interfaces;
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class RootConfiguration : IRootConfiguration
{
public AdminConfiguration AdminConfiguration { get; } = new AdminConfiguration();
public RegisterConfiguration RegisterConfiguration { get; } = new RegisterConfiguration();
}
}
@@ -0,0 +1,12 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Configuration
{
public class ServerSideSessionsConfiguration
{
public const string SectionName = nameof(ServerSideSessionsConfiguration);
public bool Enabled { get; set; } = false;
}
}
@@ -0,0 +1,23 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using LiteCharmsSecurity.Admin.EntityFramework.Shared.DbContexts;
using LiteCharmsSecurity.STS.Identity.Helpers;
namespace LiteCharmsSecurity.STS.Identity.Configuration.Test
{
public class StartupTest : Startup
{
public StartupTest(IWebHostEnvironment environment, IConfiguration configuration) : base(environment, configuration)
{
}
public override void RegisterDbContexts(IServiceCollection services)
{
services.RegisterDbContextsStaging<AdminIdentityDbContext, IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, IdentityServerDataProtectionDbContext>();
}
}
}
@@ -0,0 +1,886 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Duende.IdentityServer;
using Duende.IdentityServer.Events;
using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Stores;
using IdentityModel;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
using LiteCharmsSecurity.STS.Identity.Configuration;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.Helpers.Localization;
using LiteCharmsSecurity.STS.Identity.ViewModels.Account;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
[SecurityHeaders]
[Authorize]
public class AccountController<TUser, TKey> : Controller
where TUser : IdentityUser<TKey>, new()
where TKey : IEquatable<TKey>
{
private readonly UserResolver<TUser> _userResolver;
private readonly UserManager<TUser> _userManager;
private readonly ApplicationSignInManager<TUser> _signInManager;
private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clientStore;
private readonly IAuthenticationSchemeProvider _schemeProvider;
private readonly IEventService _events;
private readonly IEmailSender _emailSender;
private readonly IGenericControllerLocalizer<AccountController<TUser, TKey>> _localizer;
private readonly LoginConfiguration _loginConfiguration;
private readonly RegisterConfiguration _registerConfiguration;
private readonly IdentityOptions _identityOptions;
private readonly ILogger<AccountController<TUser, TKey>> _logger;
private readonly IIdentityProviderStore _identityProviderStore;
public AccountController(
UserResolver<TUser> userResolver,
UserManager<TUser> userManager,
ApplicationSignInManager<TUser> signInManager,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events,
IEmailSender emailSender,
IGenericControllerLocalizer<AccountController<TUser, TKey>> localizer,
LoginConfiguration loginConfiguration,
RegisterConfiguration registerConfiguration,
IdentityOptions identityOptions,
ILogger<AccountController<TUser, TKey>> logger,
IIdentityProviderStore identityProviderStore)
{
_userResolver = userResolver;
_userManager = userManager;
_signInManager = signInManager;
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
_emailSender = emailSender;
_localizer = localizer;
_loginConfiguration = loginConfiguration;
_registerConfiguration = registerConfiguration;
_identityOptions = identityOptions;
_logger = logger;
_identityProviderStore = identityProviderStore;
}
/// <summary>
/// Entry point into the login workflow
/// </summary>
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl)
{
// build a model so we know what to show on the login page
var vm = await BuildLoginViewModelAsync(returnUrl);
if (vm.EnableLocalLogin == false && vm.ExternalProviders.Count() == 1)
{
// only one option for logging in
return ExternalLogin(vm.ExternalProviders.First().AuthenticationScheme, returnUrl);
}
return View(vm);
}
/// <summary>
/// Handle postback from username/password login or passkey login
/// </summary>
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model, string button)
{
// check if we are in the context of an authorization request
var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
var isPasskeySubmit = button == "__passkeySubmit";
var hasPasskeyPayload = !string.IsNullOrEmpty(model.Passkey?.CredentialJson) || !string.IsNullOrEmpty(model.Passkey?.Error);
if (!isPasskeySubmit && HttpContext.Request.HasFormContentType)
{
isPasskeySubmit = HttpContext.Request.Form.ContainsKey("__passkeySubmit");
}
isPasskeySubmit = isPasskeySubmit || hasPasskeyPayload;
// the user clicked the "cancel" button (but not the passkey submit button)
if (button != "login" && button != "__passkeySubmit" && button != null)
{
if (context != null)
{
// if the user cancels, send a result back into IdentityServer as if they
// denied the consent (even if this client does not require consent).
// this will send back an access denied OIDC error response to the client.
await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
if (context.IsNativeClient())
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage("Redirect", model.ReturnUrl);
}
return Redirect(model.ReturnUrl);
}
// since we don't have a valid context, then we just go back to the home page
return Redirect("~/");
}
Microsoft.AspNetCore.Identity.SignInResult result = null;
TUser user = null;
// Passkey submit: bypass username/password required validation
if (isPasskeySubmit)
{
ModelState.Clear();
// Browser returned a passkey flow error (including user cancel) - keep the login page without credential validation errors
if (!string.IsNullOrEmpty(model.Passkey?.Error))
{
var passkeyErrorVm = await BuildLoginViewModelAsync(model);
return View(passkeyErrorVm);
}
// User canceled the passkey picker - keep the login page without validation errors
if (string.IsNullOrEmpty(model.Passkey?.CredentialJson))
{
var passkeyVm = await BuildLoginViewModelAsync(model);
return View(passkeyVm);
}
try
{
(result, user) = await _signInManager.PasskeySignInWithUserAsync(model.Passkey.CredentialJson);
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Passkey sign-in failed because no passkey assertion was active or payload was invalid.");
result = Microsoft.AspNetCore.Identity.SignInResult.Failed;
}
}
else if (ModelState.IsValid)
{
user = await _userResolver.GetUserAsync(model.Username);
if (user != default(TUser))
{
var rememberLogin = AccountOptions.AllowRememberLogin && model.RememberLogin;
result = await _signInManager.PasswordSignInAsync(user.UserName, model.Password, rememberLogin, lockoutOnFailure: true);
}
}
if (result?.Succeeded == true && user != null)
{
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));
if (context != null)
{
if (context.IsNativeClient())
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage("Redirect", model.ReturnUrl);
}
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(model.ReturnUrl);
}
// request for a local page
if (Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
if (string.IsNullOrEmpty(model.ReturnUrl))
{
return Redirect("~/");
}
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
if (result?.RequiresTwoFactor == true)
{
return RedirectToAction(nameof(LoginWith2fa), new { model.ReturnUrl, RememberMe = model.RememberLogin });
}
if (result?.IsLockedOut == true)
{
return View("Lockout");
}
var loginFailureReason = isPasskeySubmit ? "invalid passkey" : "invalid credentials";
var loginFailureMessage = isPasskeySubmit ? AccountOptions.InvalidPasskeyErrorMessage : AccountOptions.InvalidCredentialsErrorMessage;
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, loginFailureReason, clientId: context?.Client.ClientId));
ModelState.AddModelError(string.Empty, loginFailureMessage);
// something went wrong, show form with error
var vm = await BuildLoginViewModelAsync(model);
return View(vm);
}
/// <summary>
/// Show logout page
/// </summary>
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Logout(string logoutId)
{
// build a model so the logout page knows what to display
var vm = await BuildLogoutViewModelAsync(logoutId);
if (vm.ShowLogoutPrompt == false)
{
// if the request for logout was properly authenticated from IdentityServer, then
// we don't need to show the prompt and can just log the user out directly.
return await Logout(vm);
}
return View(vm);
}
/// <summary>
/// Handle logout page postback
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutInputModel model)
{
// build a model so the logged out page knows what to display
var vm = await BuildLoggedOutViewModelAsync(model.LogoutId);
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await _signInManager.SignOutAsync();
// raise the logout event
await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
}
// check if we need to trigger sign-out at an upstream identity provider
if (vm.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
return View("LoggedOut", vm);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return View("Error");
}
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
var result = await _userManager.ConfirmEmailAsync(user, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPassword()
{
return View(new ForgotPasswordViewModel());
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
TUser user = null;
switch (model.Policy)
{
case LoginResolutionPolicy.Email:
try
{
user = await _userManager.FindByEmailAsync(model.Email);
}
catch (Exception ex)
{
// in case of multiple users with the same email this method would throw and reveal that the email is registered
_logger.LogError("Error retrieving user by email ({0}) for forgot password functionality: {1}", model.Email, ex.Message);
user = null;
}
break;
case LoginResolutionPolicy.Username:
try
{
user = await _userManager.FindByNameAsync(model.Username);
}
catch (Exception ex)
{
_logger.LogError("Error retrieving user by userName ({0}) for forgot password functionality: {1}", model.Username, ex.Message);
user = null;
}
break;
}
if (user == null || !await _userManager.IsEmailConfirmedAsync(user))
{
// Don't reveal that the user does not exist
return View("ForgotPasswordConfirmation");
}
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code }, HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(user.Email, _localizer["ResetPasswordTitle"], _localizer["ResetPasswordBody", HtmlEncoder.Default.Encode(callbackUrl)]);
return View("ForgotPasswordConfirmation");
}
return View(model);
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
return code == null ? View("Error") : View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(ResetPasswordConfirmation), "Account");
}
var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(model.Code));
var result = await _userManager.ResetPasswordAsync(user, code, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(ResetPasswordConfirmation), "Account");
}
AddErrors(result);
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPasswordConfirmation()
{
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPasswordConfirmation()
{
return View();
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, _localizer["ErrorExternalProvider", remoteError]);
return View(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(LoginWith2fa), new { ReturnUrl = returnUrl });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var userName = info.Principal.Identity.Name;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email, UserName = userName });
}
[HttpPost]
[HttpGet]
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return View("ExternalLoginFailure");
}
if (ModelState.IsValid)
{
var user = new TUser
{
UserName = model.UserName,
Email = model.Email
};
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewData["LoginProvider"] = info.LoginProvider;
ViewData["ReturnUrl"] = returnUrl;
return View(model);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> LoginWithRecoveryCode(string returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException(_localizer["Unable2FA"]);
}
var model = new LoginWithRecoveryCodeViewModel()
{
ReturnUrl = returnUrl
};
return View(model);
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> LoginWithRecoveryCode(LoginWithRecoveryCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException(_localizer["Unable2FA"]);
}
var recoveryCode = model.RecoveryCode.Replace(" ", string.Empty);
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
if (result.Succeeded)
{
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));
return LocalRedirect(string.IsNullOrEmpty(model.ReturnUrl) ? "~/" : model.ReturnUrl);
}
if (result.IsLockedOut)
{
return View("Lockout");
}
ModelState.AddModelError(string.Empty, _localizer["InvalidRecoveryCode"]);
return View(model);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> LoginWith2fa(bool rememberMe, string returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException(_localizer["Unable2FA"]);
}
var model = new LoginWith2faViewModel()
{
ReturnUrl = returnUrl,
RememberMe = rememberMe
};
return View(model);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LoginWith2fa(LoginWith2faViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException(_localizer["Unable2FA"]);
}
var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);
var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, model.RememberMe, model.RememberMachine);
if (result.Succeeded)
{
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));
return LocalRedirect(string.IsNullOrEmpty(model.ReturnUrl) ? "~/" : model.ReturnUrl);
}
if (result.IsLockedOut)
{
return View("Lockout");
}
ModelState.AddModelError(string.Empty, _localizer["InvalidAuthenticatorCode"]);
return View(model);
}
[HttpGet]
[AllowAnonymous]
public IActionResult Register(string returnUrl = null)
{
if (!_registerConfiguration.Enabled) return View("RegisterFailure");
ViewData["ReturnUrl"] = returnUrl;
return _loginConfiguration.ResolutionPolicy switch
{
LoginResolutionPolicy.Username => View(),
LoginResolutionPolicy.Email => View("RegisterWithoutUsername"),
_ => View("RegisterFailure")
};
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null, bool IsCalledFromRegisterWithoutUsername = false)
{
if (!_registerConfiguration.Enabled) return View("RegisterFailure");
returnUrl ??= Url.Content("~/");
ViewData["ReturnUrl"] = returnUrl;
if (!ModelState.IsValid) return View(model);
var user = new TUser
{
UserName = model.UserName,
Email = model.Email
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code }, HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, _localizer["ConfirmEmailTitle"], _localizer["ConfirmEmailBody", HtmlEncoder.Default.Encode(callbackUrl)]);
if (_identityOptions.SignIn.RequireConfirmedAccount)
{
return View("RegisterConfirmation");
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
AddErrors(result);
// If we got this far, something failed, redisplay form
if (IsCalledFromRegisterWithoutUsername)
{
var registerWithoutUsernameModel = new RegisterWithoutUsernameViewModel
{
Email = model.Email,
Password = model.Password,
ConfirmPassword = model.ConfirmPassword
};
return View("RegisterWithoutUsername", registerWithoutUsernameModel);
}
else
{
return View(model);
}
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RegisterWithoutUsername(RegisterWithoutUsernameViewModel model, string returnUrl = null)
{
var registerModel = new RegisterViewModel
{
UserName = model.Email,
Email = model.Email,
Password = model.Password,
ConfirmPassword = model.ConfirmPassword
};
return await Register(registerModel, returnUrl, true);
}
/*****************************************/
/* helper APIs for the AccountController */
/*****************************************/
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction(nameof(HomeController.Index), "Home");
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
private async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl)
{
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null)
{
var local = context.IdP == IdentityServerConstants.LocalIdentityProvider;
// this is meant to short circuit the UI and only trigger the one external IdP
var vm = new LoginViewModel
{
EnableLocalLogin = local,
ReturnUrl = returnUrl,
Username = context?.LoginHint,
};
if (!local)
{
vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } };
}
return vm;
}
var schemes = await _schemeProvider.GetAllSchemesAsync();
var providers = schemes
.Where(x => x.DisplayName != null)
.Select(x => new ExternalProvider
{
DisplayName = x.DisplayName ?? x.Name,
AuthenticationScheme = x.Name
}).ToList();
var dynamicSchemes = (await _identityProviderStore.GetAllSchemeNamesAsync())
.Where(x => x.Enabled)
.Select(x => new ExternalProvider
{
AuthenticationScheme = x.Scheme,
DisplayName = x.DisplayName
});
providers.AddRange(dynamicSchemes);
var allowLocal = true;
if (context?.Client.ClientId != null)
{
var client = await _clientStore.FindEnabledClientByIdAsync(context.Client.ClientId);
if (client != null)
{
allowLocal = client.EnableLocalLogin;
if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any())
{
providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList();
}
}
}
return new LoginViewModel
{
AllowRememberLogin = AccountOptions.AllowRememberLogin,
EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin,
ReturnUrl = returnUrl,
Username = context?.LoginHint,
ExternalProviders = providers.ToArray()
};
}
private async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model)
{
var vm = await BuildLoginViewModelAsync(model.ReturnUrl);
vm.Username = model.Username;
vm.RememberLogin = model.RememberLogin;
return vm;
}
private async Task<LogoutViewModel> BuildLogoutViewModelAsync(string logoutId)
{
var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt };
if (User?.Identity.IsAuthenticated != true)
{
// if the user is not authenticated, then just show logged out page
vm.ShowLogoutPrompt = false;
return vm;
}
var context = await _interaction.GetLogoutContextAsync(logoutId);
if (context?.ShowSignoutPrompt == false)
{
// it's safe to automatically sign-out
vm.ShowLogoutPrompt = false;
return vm;
}
// show the logout prompt. this prevents attacks where the user
// is automatically signed out by another malicious web page.
return vm;
}
private async Task<LoggedOutViewModel> BuildLoggedOutViewModelAsync(string logoutId)
{
// get context information (client name, post logout redirect URI and iframe for federated signout)
var logout = await _interaction.GetLogoutContextAsync(logoutId);
var vm = new LoggedOutViewModel
{
AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,
ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName,
SignOutIframeUrl = logout?.SignOutIFrameUrl,
LogoutId = logoutId
};
if (User?.Identity.IsAuthenticated == true)
{
var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider)
{
var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);
if (providerSupportsSignout)
{
if (vm.LogoutId == null)
{
// if there's no current logout context, we need to create one
// this captures necessary info from the current logged in user
// before we signout and redirect away to the external IdP for signout
vm.LogoutId = await _interaction.CreateLogoutContextAsync();
}
vm.ExternalAuthenticationScheme = idp;
}
}
}
return vm;
}
}
}
@@ -0,0 +1,267 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer.Events;
using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using LiteCharmsSecurity.STS.Identity.Configuration;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.ViewModels.Consent;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
/// <summary>
/// This controller processes the consent UI
/// </summary>
[SecurityHeaders]
[Authorize]
public class ConsentController : Controller
{
private readonly IIdentityServerInteractionService _interaction;
private readonly IEventService _events;
private readonly ILogger<ConsentController> _logger;
public ConsentController(
IIdentityServerInteractionService interaction,
IEventService events,
ILogger<ConsentController> logger)
{
_interaction = interaction;
_events = events;
_logger = logger;
}
/// <summary>
/// Shows the consent screen
/// </summary>
/// <param name="returnUrl"></param>
/// <returns></returns>
[HttpGet]
public async Task<IActionResult> Index(string returnUrl)
{
var vm = await BuildViewModelAsync(returnUrl);
if (vm != null)
{
return View("Index", vm);
}
return View("Error");
}
/// <summary>
/// Handles the consent screen postback
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(ConsentInputModel model)
{
var result = await ProcessConsent(model);
if (result.IsRedirect)
{
var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
if (context?.IsNativeClient() == true)
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage("Redirect", result.RedirectUri);
}
return Redirect(result.RedirectUri);
}
if (result.HasValidationError)
{
ModelState.AddModelError(string.Empty, result.ValidationError);
}
if (result.ShowView)
{
return View("Index", result.ViewModel);
}
return View("Error");
}
/*****************************************/
/* helper APIs for the ConsentController */
/*****************************************/
private async Task<ProcessConsentResult> ProcessConsent(ConsentInputModel model)
{
var result = new ProcessConsentResult();
// validate return url is still valid
var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
if (request == null) return result;
ConsentResponse grantedConsent = null;
// user clicked 'no' - send back the standard 'access_denied' response
if (model?.Button == "no")
{
grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };
// emit event
await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
}
// user clicked 'yes' - validate the data
else if (model?.Button == "yes")
{
// if the user consented to some scope, build the response model
if (model.ScopesConsented != null && model.ScopesConsented.Any())
{
var scopes = model.ScopesConsented;
if (ConsentOptions.EnableOfflineAccess == false)
{
scopes = scopes.Where(x => x != global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess);
}
grantedConsent = new ConsentResponse
{
RememberConsent = model.RememberConsent,
ScopesValuesConsented = scopes.ToArray(),
Description = model.Description
};
// emit event
await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
}
else
{
result.ValidationError = ConsentOptions.MustChooseOneErrorMessage;
}
}
else
{
result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage;
}
if (grantedConsent != null)
{
// communicate outcome of consent back to identityserver
await _interaction.GrantConsentAsync(request, grantedConsent);
// indicate that's it ok to redirect back to authorization endpoint
result.RedirectUri = model.ReturnUrl;
result.Client = request.Client;
}
else
{
// we need to redisplay the consent UI
result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model);
}
return result;
}
private async Task<ConsentViewModel> BuildViewModelAsync(string returnUrl, ConsentInputModel model = null)
{
var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (request != null)
{
return CreateConsentViewModel(model, returnUrl, request);
}
else
{
_logger.LogError("No consent request matching request: {0}", returnUrl);
}
return null;
}
private ConsentViewModel CreateConsentViewModel(
ConsentInputModel model, string returnUrl,
AuthorizationRequest request)
{
var vm = new ConsentViewModel
{
RememberConsent = model?.RememberConsent ?? true,
ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>(),
Description = model?.Description,
ReturnUrl = returnUrl,
ClientName = request.Client.ClientName ?? request.Client.ClientId,
ClientUrl = request.Client.ClientUri,
ClientLogoUrl = request.Client.LogoUri,
AllowRememberConsent = request.Client.AllowRememberConsent
};
vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray();
var apiScopes = new List<ScopeViewModel>();
foreach (var parsedScope in request.ValidatedResources.ParsedScopes)
{
var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);
if (apiScope != null)
{
var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null);
apiScopes.Add(scopeVm);
}
}
if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)
{
apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null));
}
vm.ApiScopes = apiScopes;
return vm;
}
private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
{
return new ScopeViewModel
{
Value = identity.Name,
DisplayName = identity.DisplayName ?? identity.Name,
Description = identity.Description,
Emphasize = identity.Emphasize,
Required = identity.Required,
Checked = check || identity.Required
};
}
public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)
{
var displayName = apiScope.DisplayName ?? apiScope.Name;
if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter))
{
displayName += ":" + parsedScopeValue.ParsedParameter;
}
return new ScopeViewModel
{
Value = parsedScopeValue.RawValue,
DisplayName = displayName,
Description = apiScope.Description,
Emphasize = apiScope.Emphasize,
Required = apiScope.Required,
Checked = check || apiScope.Required
};
}
private ScopeViewModel GetOfflineAccessScope(bool check)
{
return new ScopeViewModel
{
Value = global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess,
DisplayName = ConsentOptions.OfflineAccessDisplayName,
Description = ConsentOptions.OfflineAccessDescription,
Emphasize = true,
Checked = check
};
}
}
}
@@ -0,0 +1,238 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.Events;
using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using LiteCharmsSecurity.STS.Identity.Configuration;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.ViewModels.Consent;
using LiteCharmsSecurity.STS.Identity.ViewModels.Device;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
[Authorize]
[SecurityHeaders]
public class DeviceController : Controller
{
private readonly IDeviceFlowInteractionService _interaction;
private readonly IEventService _events;
private readonly IOptions<IdentityServerOptions> _options;
private readonly ILogger<DeviceController> _logger;
public DeviceController(
IDeviceFlowInteractionService interaction,
IEventService eventService,
IOptions<IdentityServerOptions> options,
ILogger<DeviceController> logger)
{
_interaction = interaction;
_events = eventService;
_options = options;
_logger = logger;
}
[HttpGet]
public async Task<IActionResult> Index()
{
string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter;
string userCode = Request.Query[userCodeParamName];
if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture");
var vm = await BuildViewModelAsync(userCode);
if (vm == null) return View("Error");
vm.ConfirmUserCode = true;
return View("UserCodeConfirmation", vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UserCodeCapture(string userCode)
{
var vm = await BuildViewModelAsync(userCode);
if (vm == null) return View("Error");
return View("UserCodeConfirmation", vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Callback(DeviceAuthorizationInputModel model)
{
if (model == null) throw new ArgumentNullException(nameof(model));
var result = await ProcessConsent(model);
if (result.HasValidationError) return View("Error");
return View("Success");
}
private async Task<ProcessConsentResult> ProcessConsent(DeviceAuthorizationInputModel model)
{
var result = new ProcessConsentResult();
var request = await _interaction.GetAuthorizationContextAsync(model.UserCode);
if (request == null) return result;
ConsentResponse grantedConsent = null;
// user clicked 'no' - send back the standard 'access_denied' response
if (model.Button == "no")
{
grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };
// emit event
await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
}
// user clicked 'yes' - validate the data
else if (model.Button == "yes")
{
// if the user consented to some scope, build the response model
if (model.ScopesConsented != null && model.ScopesConsented.Any())
{
var scopes = model.ScopesConsented;
if (ConsentOptions.EnableOfflineAccess == false)
{
scopes = scopes.Where(x => x != global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess);
}
grantedConsent = new ConsentResponse
{
RememberConsent = model.RememberConsent,
ScopesValuesConsented = scopes.ToArray(),
Description = model.Description
};
// emit event
await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
}
else
{
result.ValidationError = ConsentOptions.MustChooseOneErrorMessage;
}
}
else
{
result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage;
}
if (grantedConsent != null)
{
// communicate outcome of consent back to identityserver
await _interaction.HandleRequestAsync(model.UserCode, grantedConsent);
// indicate that's it ok to redirect back to authorization endpoint
result.RedirectUri = model.ReturnUrl;
result.Client = request.Client;
}
else
{
// we need to redisplay the consent UI
result.ViewModel = await BuildViewModelAsync(model.UserCode, model);
}
return result;
}
private async Task<DeviceAuthorizationViewModel> BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null)
{
var request = await _interaction.GetAuthorizationContextAsync(userCode);
if (request != null)
{
return CreateConsentViewModel(userCode, model, request);
}
return null;
}
private DeviceAuthorizationViewModel CreateConsentViewModel(string userCode, DeviceAuthorizationInputModel model, DeviceFlowAuthorizationRequest request)
{
var vm = new DeviceAuthorizationViewModel
{
UserCode = userCode,
Description = model?.Description,
RememberConsent = model?.RememberConsent ?? true,
ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>(),
ClientName = request.Client.ClientName ?? request.Client.ClientId,
ClientUrl = request.Client.ClientUri,
ClientLogoUrl = request.Client.LogoUri,
AllowRememberConsent = request.Client.AllowRememberConsent
};
vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray();
var apiScopes = new List<ScopeViewModel>();
foreach (var parsedScope in request.ValidatedResources.ParsedScopes)
{
var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);
if (apiScope != null)
{
var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null);
apiScopes.Add(scopeVm);
}
}
if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)
{
apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null));
}
vm.ApiScopes = apiScopes;
return vm;
}
private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
{
return new ScopeViewModel
{
Value = identity.Name,
DisplayName = identity.DisplayName ?? identity.Name,
Description = identity.Description,
Emphasize = identity.Emphasize,
Required = identity.Required,
Checked = check || identity.Required
};
}
public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)
{
return new ScopeViewModel
{
Value = parsedScopeValue.RawValue,
// todo: use the parsed scope value in the display?
DisplayName = apiScope.DisplayName ?? apiScope.Name,
Description = apiScope.Description,
Emphasize = apiScope.Emphasize,
Required = apiScope.Required,
Checked = check || apiScope.Required
};
}
private ScopeViewModel GetOfflineAccessScope(bool check)
{
return new ScopeViewModel
{
Value = global::Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess,
DisplayName = ConsentOptions.OfflineAccessDisplayName,
Description = ConsentOptions.OfflineAccessDescription,
Emphasize = true,
Checked = check
};
}
}
}
@@ -0,0 +1,33 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.ViewModels.Diagnostics;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
[SecurityHeaders]
[Authorize]
public class DiagnosticsController : Controller
{
public async Task<IActionResult> Index()
{
var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection?.LocalIpAddress?.ToString() };
if (!localAddresses.Contains(HttpContext.Connection?.RemoteIpAddress?.ToString()))
{
return NotFound();
}
var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync());
return View(model);
}
}
}
@@ -0,0 +1,101 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer.Events;
using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Stores;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.ViewModels.Grants;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
/// <summary>
/// This sample controller allows a user to revoke grants given to clients
/// </summary>
[SecurityHeaders]
[Authorize]
public class GrantsController : Controller
{
private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clients;
private readonly IResourceStore _resources;
private readonly IEventService _events;
public GrantsController(IIdentityServerInteractionService interaction,
IClientStore clients,
IResourceStore resources,
IEventService events)
{
_interaction = interaction;
_clients = clients;
_resources = resources;
_events = events;
}
/// <summary>
/// Show list of grants
/// </summary>
[HttpGet]
public async Task<IActionResult> Index()
{
return View("Index", await BuildViewModelAsync());
}
/// <summary>
/// Handle postback to revoke a client
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Revoke(string clientId)
{
await _interaction.RevokeUserConsentAsync(clientId);
await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId));
return RedirectToAction("Index");
}
private async Task<GrantsViewModel> BuildViewModelAsync()
{
var grants = await _interaction.GetAllUserGrantsAsync();
var list = new List<GrantViewModel>();
foreach (var grant in grants)
{
var client = await _clients.FindClientByIdAsync(grant.ClientId);
if (client != null)
{
var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes);
var item = new GrantViewModel()
{
ClientId = client.ClientId,
ClientName = client.ClientName ?? client.ClientId,
ClientLogoUrl = client.LogoUri,
ClientUrl = client.ClientUri,
Description = grant.Description,
Created = grant.CreationTime,
Expires = grant.Expiration,
IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(),
ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray()
};
list.Add(item);
}
}
return new GrantsViewModel
{
Grants = list
};
}
}
}
@@ -0,0 +1,76 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
using System.Threading.Tasks;
using Duende.IdentityServer.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Helpers;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.ViewModels.Home;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
[SecurityHeaders]
public class HomeController : Controller
{
private readonly IIdentityServerInteractionService _interaction;
public HomeController(IIdentityServerInteractionService interaction)
{
_interaction = interaction;
}
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SetLanguage(string culture, string returnUrl)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return LocalRedirect(returnUrl);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SelectTheme(string theme, string returnUrl)
{
Response.Cookies.Append(
ThemeHelpers.CookieThemeKey,
theme,
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return LocalRedirect(returnUrl);
}
/// <summary>
/// Shows the error page
/// </summary>
public async Task<IActionResult> Error(string errorId)
{
var vm = new ErrorViewModel();
// retrieve error details from identityserver
var message = await _interaction.GetErrorContextAsync(errorId);
if (message != null)
{
vm.Error = message;
}
return View("Error", vm);
}
}
}
@@ -0,0 +1,933 @@
using System;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using LiteCharmsSecurity.Admin.EntityFramework.Shared.DbContexts;
using LiteCharmsSecurity.Admin.EntityFramework.Shared.Entities.Identity;
using LiteCharmsSecurity.STS.Identity.Helpers;
using LiteCharmsSecurity.STS.Identity.Helpers.Localization;
using LiteCharmsSecurity.STS.Identity.ViewModels.Manage;
namespace LiteCharmsSecurity.STS.Identity.Controllers
{
[Authorize]
public class ManageController<TUser, TKey> : Controller
where TUser : IdentityUser<TKey>, new()
where TKey : IEquatable<TKey>
{
private readonly UserManager<TUser> _userManager;
private readonly SignInManager<TUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ILogger<ManageController<TUser, TKey>> _logger;
private readonly IGenericControllerLocalizer<ManageController<TUser, TKey>> _localizer;
private readonly UrlEncoder _urlEncoder;
private readonly AdminIdentityDbContext _identityDbContext;
private const string RecoveryCodesKey = nameof(RecoveryCodesKey);
private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6";
[TempData]
public string StatusMessage { get; set; }
public ManageController(UserManager<TUser> userManager, SignInManager<TUser> signInManager, IEmailSender emailSender, ILogger<ManageController<TUser, TKey>> logger, IGenericControllerLocalizer<ManageController<TUser, TKey>> localizer, UrlEncoder urlEncoder, AdminIdentityDbContext identityDbContext)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_logger = logger;
_localizer = localizer;
_urlEncoder = urlEncoder;
_identityDbContext = identityDbContext;
}
[HttpGet]
public async Task<IActionResult> Index()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var model = await BuildManageIndexViewModelAsync(user);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(IndexViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var email = user.Email;
if (model.Email != email)
{
var setEmailResult = await _userManager.SetEmailAsync(user, model.Email);
if (!setEmailResult.Succeeded)
{
throw new ApplicationException(_localizer["ErrorSettingEmail", user.Id]);
}
}
var phoneNumber = user.PhoneNumber;
if (model.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, model.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
throw new ApplicationException(_localizer["ErrorSettingPhone", user.Id]);
}
}
await UpdateUserClaimsAsync(model, user);
StatusMessage = _localizer["ProfileUpdated"];
return RedirectToAction(nameof(Index));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SendVerificationEmail(IndexViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code }, HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, _localizer["ConfirmEmailTitle"], _localizer["ConfirmEmailBody", HtmlEncoder.Default.Encode(callbackUrl)]);
StatusMessage = _localizer["VerificationSent"];
return RedirectToAction(nameof(Index));
}
[HttpGet]
public async Task<IActionResult> ChangePassword()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var hasPassword = await _userManager.HasPasswordAsync(user);
if (!hasPassword)
{
return RedirectToAction(nameof(SetPassword));
}
var model = new ChangePasswordViewModel { StatusMessage = StatusMessage };
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var changePasswordResult = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
if (!changePasswordResult.Succeeded)
{
AddErrors(changePasswordResult);
return View(model);
}
await _signInManager.RefreshSignInAsync(user);
_logger.LogInformation(_localizer["PasswordChangedLog", user.UserName]);
StatusMessage = _localizer["PasswordChanged"];
return RedirectToAction(nameof(ChangePassword));
}
[HttpGet]
public async Task<IActionResult> SetPassword()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var hasPassword = await _userManager.HasPasswordAsync(user);
if (hasPassword)
{
return RedirectToAction(nameof(ChangePassword));
}
var model = new SetPasswordViewModel { StatusMessage = StatusMessage };
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SetPassword(SetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var addPasswordResult = await _userManager.AddPasswordAsync(user, model.NewPassword);
if (!addPasswordResult.Succeeded)
{
AddErrors(addPasswordResult);
return View(model);
}
await _signInManager.RefreshSignInAsync(user);
StatusMessage = _localizer["PasswordSet"];
return RedirectToAction(nameof(SetPassword));
}
[HttpGet]
public async Task<IActionResult> PersonalData()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DownloadPersonalData()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
_logger.LogInformation(_localizer["AskForPersonalDataLog"], _userManager.GetUserId(User));
var personalDataProps = typeof(TUser).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute)));
var personalData = personalDataProps.ToDictionary(p => p.Name, p => p.GetValue(user)?.ToString() ?? "null");
Response.Headers.Append("Content-Disposition", "attachment; filename=PersonalData.json");
return new FileContentResult(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(personalData)), "text/json");
}
[HttpGet]
public async Task<IActionResult> DeletePersonalData()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var deletePersonalDataViewModel = new DeletePersonalDataViewModel
{
RequirePassword = await _userManager.HasPasswordAsync(user)
};
return View(deletePersonalDataViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeletePersonalData(DeletePersonalDataViewModel deletePersonalDataViewModel)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
deletePersonalDataViewModel.RequirePassword = await _userManager.HasPasswordAsync(user);
if (deletePersonalDataViewModel.RequirePassword)
{
if (!await _userManager.CheckPasswordAsync(user, deletePersonalDataViewModel.Password))
{
ModelState.AddModelError(string.Empty, _localizer["PasswordNotCorrect"]);
return View(deletePersonalDataViewModel);
}
}
var result = await _userManager.DeleteAsync(user);
var userId = await _userManager.GetUserIdAsync(user);
if (!result.Succeeded)
{
throw new InvalidOperationException(_localizer["ErrorDeletingUser", user.Id]);
}
await _signInManager.SignOutAsync();
_logger.LogInformation(_localizer["DeletePersonalData"], userId);
return Redirect("~/");
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel model)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var result = await _userManager.RemoveLoginAsync(user, model.LoginProvider, model.ProviderKey);
if (!result.Succeeded)
{
throw new ApplicationException(_localizer["ErrorRemovingExternalLogin", user.Id]);
}
await _signInManager.RefreshSignInAsync(user);
StatusMessage = _localizer["ExternalLoginRemoved"];
return RedirectToAction(nameof(ExternalLogins));
}
[HttpGet]
public async Task<IActionResult> LinkLoginCallback()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var info = await _signInManager.GetExternalLoginInfoAsync(user.Id.ToString());
if (info == null)
{
throw new ApplicationException(_localizer["ErrorLoadingExternalLogin", user.Id]);
}
var result = await _userManager.AddLoginAsync(user, info);
if (!result.Succeeded)
{
AddErrors(result);
return View("LinkLoginFailure");
}
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
StatusMessage = _localizer["ExternalLoginAdded"];
return RedirectToAction(nameof(ExternalLogins));
}
[HttpGet]
public async Task<IActionResult> ExternalLogins()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var model = new ExternalLoginsViewModel
{
CurrentLogins = await _userManager.GetLoginsAsync(user)
};
model.OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.Where(auth => model.CurrentLogins.All(ul => auth.Name != ul.LoginProvider))
.ToList();
model.ShowRemoveButton = await _userManager.HasPasswordAsync(user) || model.CurrentLogins.Count > 1;
model.StatusMessage = StatusMessage;
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LinkLogin(string provider)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action(nameof(LinkLoginCallback));
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
return new ChallengeResult(provider, properties);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> GenerateRecoveryCodes()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (!user.TwoFactorEnabled)
{
AddError(_localizer["ErrorGenerateCodesWithout2FA"]);
return View();
}
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
_logger.LogInformation(_localizer["UserGenerated2FACodes", user.Id]);
var model = new ShowRecoveryCodesViewModel { RecoveryCodes = recoveryCodes.ToArray() };
return View(nameof(ShowRecoveryCodes), model);
}
[HttpGet]
public IActionResult ShowRecoveryCodes()
{
var recoveryCodes = (string[])TempData[RecoveryCodesKey];
if (recoveryCodes == null)
{
return RedirectToAction(nameof(TwoFactorAuthentication));
}
var model = new ShowRecoveryCodesViewModel { RecoveryCodes = recoveryCodes };
return View(model);
}
[HttpGet]
public async Task<IActionResult> TwoFactorAuthentication()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var model = new TwoFactorAuthenticationViewModel
{
HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null,
Is2faEnabled = user.TwoFactorEnabled,
RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user),
IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user)
};
return View(model);
}
[HttpPost]
public async Task<IActionResult> ForgetTwoFactorClient()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
await _signInManager.ForgetTwoFactorClientAsync();
StatusMessage = _localizer["SuccessForgetBrowser2FA"];
return RedirectToAction(nameof(TwoFactorAuthentication));
}
[HttpGet]
public async Task<IActionResult> Disable2faWarning()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (!user.TwoFactorEnabled)
{
throw new ApplicationException(_localizer["ErrorDisable2FA", user.Id]);
}
return View(nameof(Disable2fa));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Disable2fa()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false);
if (!disable2faResult.Succeeded)
{
throw new ApplicationException(_localizer["ErrorDisable2FA", user.Id]);
}
_logger.LogInformation(_localizer["SuccessDisabled2FA", user.Id]);
return RedirectToAction(nameof(TwoFactorAuthentication));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetAuthenticator()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
await _userManager.SetTwoFactorEnabledAsync(user, false);
await _userManager.ResetAuthenticatorKeyAsync(user);
_logger.LogInformation(_localizer["SuccessResetAuthenticationKey", user.Id]);
return RedirectToAction(nameof(EnableAuthenticator));
}
[HttpGet]
public IActionResult ResetAuthenticatorWarning()
{
return View(nameof(ResetAuthenticator));
}
[HttpGet]
public async Task<IActionResult> EnableAuthenticator()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var model = new EnableAuthenticatorViewModel();
await LoadSharedKeyAndQrCodeUriAsync(user, model);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EnableAuthenticator(EnableAuthenticatorViewModel model)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (!ModelState.IsValid)
{
await LoadSharedKeyAndQrCodeUriAsync(user, model);
return View(model);
}
var verificationCode = model.Code.Replace(" ", string.Empty).Replace("-", string.Empty);
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
if (!is2faTokenValid)
{
ModelState.AddModelError(_localizer["ErrorCode"], _localizer["InvalidVerificationCode"]);
await LoadSharedKeyAndQrCodeUriAsync(user, model);
return View(model);
}
await _userManager.SetTwoFactorEnabledAsync(user, true);
var userId = await _userManager.GetUserIdAsync(user);
_logger.LogInformation(_localizer["SuccessUserEnabled2FA"], userId);
StatusMessage = _localizer["AuthenticatorVerified"];
if (await _userManager.CountRecoveryCodesAsync(user) == 0)
{
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
return RedirectToAction(nameof(ShowRecoveryCodes));
}
return RedirectToAction(nameof(TwoFactorAuthentication));
}
[HttpGet]
public async Task<IActionResult> GenerateRecoveryCodesWarning()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (!user.TwoFactorEnabled)
{
throw new ApplicationException(_localizer["Error2FANotEnabled", user.Id]);
}
return View(nameof(GenerateRecoveryCodes));
}
#region Passkey Management
[HttpGet]
public async Task<IActionResult> Passkeys()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
var passkeys = await _userManager.GetPasskeysAsync(user);
var model = new ViewModels.Manage.PasskeysViewModel
{
CurrentPasskeys = passkeys,
StatusMessage = StatusMessage
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdatePasskey(ViewModels.Manage.PasskeysInputModel input)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (string.IsNullOrEmpty(input?.CredentialId))
{
StatusMessage = _localizer["PasskeyNotFound"];
return RedirectToAction(nameof(Passkeys));
}
byte[] credentialId;
try
{
credentialId = System.Buffers.Text.Base64Url.DecodeFromChars(input.CredentialId);
}
catch (FormatException)
{
StatusMessage = _localizer["PasskeyInvalidFormat"];
return RedirectToAction(nameof(Passkeys));
}
switch (input.Action)
{
case "rename":
return RedirectToAction(nameof(RenamePasskey), new { id = input.CredentialId });
case "delete":
var deleteResult = await _userManager.RemovePasskeyAsync(user, credentialId);
if (deleteResult.Succeeded)
{
StatusMessage = _localizer["PasskeyDeleted"];
}
else
{
StatusMessage = _localizer["PasskeyDeleteFailed"];
}
break;
}
return RedirectToAction(nameof(Passkeys));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddPasskey(ViewModels.Manage.PasskeysInputModel input)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (!string.IsNullOrEmpty(input?.Passkey?.Error))
{
StatusMessage = string.Format(_localizer["PasskeyAddError"], input.Passkey.Error);
return RedirectToAction(nameof(Passkeys));
}
if (string.IsNullOrEmpty(input?.Passkey?.CredentialJson))
{
StatusMessage = _localizer["PasskeyNotProvided"];
return RedirectToAction(nameof(Passkeys));
}
var attestationResult = await _signInManager.PerformPasskeyAttestationAsync(input.Passkey.CredentialJson);
if (!attestationResult.Succeeded)
{
StatusMessage = string.Format(_localizer["PasskeyAddError"], attestationResult.Failure.Message);
return RedirectToAction(nameof(Passkeys));
}
var setPasskeyResult = await _userManager.AddOrUpdatePasskeyAsync(user, attestationResult.Passkey);
if (!setPasskeyResult.Succeeded)
{
StatusMessage = _localizer["PasskeyAddFailed"];
return RedirectToAction(nameof(Passkeys));
}
StatusMessage = _localizer["PasskeyAdded"];
return RedirectToAction(nameof(RenamePasskey), new { id = System.Buffers.Text.Base64Url.EncodeToString(attestationResult.Passkey.CredentialId) });
}
[HttpGet]
public async Task<IActionResult> RenamePasskey(string id)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
byte[] credentialId;
try
{
credentialId = System.Buffers.Text.Base64Url.DecodeFromChars(id);
}
catch (FormatException)
{
StatusMessage = _localizer["PasskeyInvalidFormat"];
return RedirectToAction(nameof(Passkeys));
}
var passkey = await _userManager.GetPasskeyAsync(user, credentialId);
if (passkey == null)
{
StatusMessage = _localizer["PasskeyNotFound"];
return RedirectToAction(nameof(Passkeys));
}
var model = new ViewModels.Manage.RenamePasskeyViewModel
{
CredentialId = id,
Name = passkey.Name,
StatusMessage = StatusMessage
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RenamePasskey(ViewModels.Manage.RenamePasskeyViewModel model)
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(_localizer["UserNotFound", _userManager.GetUserId(User)]);
}
if (string.IsNullOrEmpty(model?.CredentialId))
{
StatusMessage = _localizer["PasskeyNotFound"];
return RedirectToAction(nameof(Passkeys));
}
byte[] credentialId;
try
{
credentialId = System.Buffers.Text.Base64Url.DecodeFromChars(model.CredentialId);
}
catch (FormatException)
{
StatusMessage = _localizer["PasskeyInvalidFormat"];
return RedirectToAction(nameof(Passkeys));
}
var passkey = await _userManager.GetPasskeyAsync(user, credentialId);
if (passkey == null)
{
StatusMessage = _localizer["PasskeyNotFound"];
return RedirectToAction(nameof(Passkeys));
}
// Update the passkey name and save
passkey.Name = model.Name;
var result = await _userManager.AddOrUpdatePasskeyAsync(user, passkey);
if (!result.Succeeded)
{
StatusMessage = _localizer["PasskeyRenameFailed"];
return View(model);
}
// Identity passkey name updates are not persisted by all stores yet.
// Persist the name directly so rename is reliable across providers.
var userId = _userManager.GetUserId(User);
var passkeyEntity = await _identityDbContext.Set<UserIdentityPasskey>()
.SingleOrDefaultAsync(userPasskey => userPasskey.UserId == userId && userPasskey.CredentialId.SequenceEqual(credentialId));
if (passkeyEntity?.Data != null)
{
passkeyEntity.Data.Name = model.Name;
await _identityDbContext.SaveChangesAsync();
}
StatusMessage = _localizer["PasskeyRenamed"];
return RedirectToAction(nameof(Passkeys));
}
#endregion
private async Task LoadSharedKeyAndQrCodeUriAsync(TUser user, EnableAuthenticatorViewModel model)
{
var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
if (string.IsNullOrEmpty(unformattedKey))
{
await _userManager.ResetAuthenticatorKeyAsync(user);
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
}
model.SharedKey = FormatKey(unformattedKey);
model.AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey);
}
private async Task<IndexViewModel> BuildManageIndexViewModelAsync(TUser user)
{
var claims = await _userManager.GetClaimsAsync(user);
var profile = OpenIdClaimHelpers.ExtractProfileInfo(claims);
var model = new IndexViewModel
{
Username = user.UserName,
Email = user.Email,
PhoneNumber = user.PhoneNumber,
IsEmailConfirmed = user.EmailConfirmed,
StatusMessage = StatusMessage,
Name = profile.FullName,
Website = profile.Website,
Profile = profile.Profile,
Country = profile.Country,
Region = profile.Region,
PostalCode = profile.PostalCode,
Locality = profile.Locality,
StreetAddress = profile.StreetAddress
};
return model;
}
private async Task UpdateUserClaimsAsync(IndexViewModel model, TUser user)
{
var claims = await _userManager.GetClaimsAsync(user);
var oldProfile = OpenIdClaimHelpers.ExtractProfileInfo(claims);
var newProfile = new OpenIdProfile
{
Website = model.Website,
StreetAddress = model.StreetAddress,
Locality = model.Locality,
PostalCode = model.PostalCode,
Region = model.Region,
Country = model.Country,
FullName = model.Name,
Profile = model.Profile
};
var claimsToRemove = OpenIdClaimHelpers.ExtractClaimsToRemove(oldProfile, newProfile);
var claimsToAdd = OpenIdClaimHelpers.ExtractClaimsToAdd(oldProfile, newProfile);
var claimsToReplace = OpenIdClaimHelpers.ExtractClaimsToReplace(claims, newProfile);
await _userManager.RemoveClaimsAsync(user, claimsToRemove);
await _userManager.AddClaimsAsync(user, claimsToAdd);
foreach (var pair in claimsToReplace)
{
await _userManager.ReplaceClaimAsync(user, pair.Item1, pair.Item2);
}
}
private string FormatKey(string unformattedKey)
{
var result = new StringBuilder();
var currentPosition = 0;
while (currentPosition + 4 < unformattedKey.Length)
{
result.Append(unformattedKey.Substring(currentPosition, 4)).Append(" ");
currentPosition += 4;
}
if (currentPosition < unformattedKey.Length)
{
result.Append(unformattedKey.Substring(currentPosition));
}
return result.ToString().ToLowerInvariant();
}
private string GenerateQrCodeUri(string email, string unformattedKey)
{
return string.Format(
AuthenticatorUriFormat,
_urlEncoder.Encode("LiteCharmsSecurity.STS.Identity"),
_urlEncoder.Encode(email),
unformattedKey);
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
private void AddError(string description, string title = "")
{
ModelState.AddModelError(title, description);
}
}
}
@@ -0,0 +1,111 @@
#nullable enable
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer;
using Duende.IdentityServer.EntityFramework.Entities;
using Duende.IdentityServer.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using LiteCharmsSecurity.Admin.EntityFramework.Shared.DbContexts;
using LiteCharmsSecurity.STS.Identity.Configuration.Constants;
using LiteCharmsSecurity.STS.Identity.Models.ViewModels;
using LiteCharmsSecurity.STS.Identity.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
namespace LiteCharmsSecurity.STS.Identity.Controllers;
[Authorize(Policy = AuthorizationConsts.AdministrationPolicy)]
public class ServerSideSessionsController : Controller
{
private readonly IdentityServerPersistedGrantDbContext _persistedGrantDbContext;
private readonly ServerSideSessionsConfiguration _serverSideSessionsConfig;
private readonly ILogger<ServerSideSessionsController> _logger;
public ServerSideSessionsController(
IdentityServerPersistedGrantDbContext persistedGrantDbContext,
IOptions<ServerSideSessionsConfiguration> serverSideSessionsOptions,
ILogger<ServerSideSessionsController> logger)
{
_persistedGrantDbContext = persistedGrantDbContext;
_serverSideSessionsConfig = serverSideSessionsOptions.Value;
_logger = logger;
}
private bool IsServerSideSessionsEnabled()
{
return _serverSideSessionsConfig.Enabled;
}
public async Task<IActionResult> Index(string filter, int page = 1, int pageSize = 20)
{
if (!IsServerSideSessionsEnabled())
{
_logger.LogWarning("Server-side sessions feature is disabled. Enable it in configuration: {SectionName}:Enabled = true",
ServerSideSessionsConfiguration.SectionName);
return NotFound();
}
if (page < 1) page = 1;
var query = _persistedGrantDbContext.Set<ServerSideSession>().AsNoTracking();
if (!string.IsNullOrWhiteSpace(filter))
{
query = query.Where(s =>
s.SubjectId.Contains(filter) ||
s.SessionId.Contains(filter) ||
s.DisplayName.Contains(filter));
}
var total = await query.CountAsync();
var sessions = await query
.OrderByDescending(s => s.Created)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(s => new SessionItem
{
SubjectId = s.SubjectId,
SessionId = s.SessionId,
DisplayName = s.DisplayName,
Created = s.Created,
Expires = s.Expires,
Data = s.Data
})
.ToListAsync();
return View(new ServerSideSessionsViewModel
{
Sessions = sessions,
Filter = filter,
Page = page,
PageSize = pageSize,
TotalCount = total
});
}
[HttpPost]
public async Task<IActionResult> Delete(string sessionId, string filter, int page = 1, int pageSize = 20)
{
if (!IsServerSideSessionsEnabled())
{
_logger.LogWarning("Attempted to delete server-side session {SessionId} but feature is disabled. Enable it in configuration: {SectionName}:Enabled = true",
sessionId, ServerSideSessionsConfiguration.SectionName);
return NotFound();
}
var session = await _persistedGrantDbContext.Set<ServerSideSession>()
.FirstOrDefaultAsync(s => s.SessionId == sessionId);
if (session != null)
{
_persistedGrantDbContext.Set<ServerSideSession>().Remove(session);
await _persistedGrantDbContext.SaveChangesAsync();
}
return RedirectToAction(nameof(Index), new { filter, page, pageSize });
}
}
@@ -0,0 +1,24 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG TARGETARCH
WORKDIR /src
COPY ["src/LiteCharmsSecurity.STS.Identity/LiteCharmsSecurity.STS.Identity.csproj", "src/LiteCharmsSecurity.STS.Identity/"]
COPY ["src/LiteCharmsSecurity.Admin.EntityFramework.Shared/LiteCharmsSecurity.Admin.EntityFramework.Shared.csproj", "src/LiteCharmsSecurity.Admin.EntityFramework.Shared/"]
COPY ["src/LiteCharmsSecurity.Shared/LiteCharmsSecurity.Shared.csproj", "src/LiteCharmsSecurity.Shared/"]
RUN dotnet restore -a $TARGETARCH "src/LiteCharmsSecurity.STS.Identity/LiteCharmsSecurity.STS.Identity.csproj"
COPY . .
WORKDIR "/src/src/LiteCharmsSecurity.STS.Identity"
RUN dotnet build -a $TARGETARCH "LiteCharmsSecurity.STS.Identity.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -a $TARGETARCH "LiteCharmsSecurity.STS.Identity.csproj" -c Release --no-restore -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
ENTRYPOINT ["dotnet", "LiteCharmsSecurity.STS.Identity.dll"]
@@ -0,0 +1,90 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
// File: https://github.com/IdentityServer/IdentityServer4/blob/main/samples/Quickstarts/3_AspNetCoreAndApis/src/IdentityServer/Quickstart/Account/ExternalController.cs
// Modified by Jan Škoruba and J. Arturo
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public class ApplicationSignInManager<TUser> : SignInManager<TUser>
where TUser : class
{
private readonly IHttpContextAccessor _contextAccessor;
public ApplicationSignInManager(UserManager<TUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<TUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<TUser>> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<TUser> confirmation) : base(userManager, contextAccessor,
claimsFactory, optionsAccessor, logger, schemes, confirmation)
{
_contextAccessor = contextAccessor;
}
public override async Task SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable<Claim> additionalClaims)
{
var claims = additionalClaims.ToList();
var externalResult = await _contextAccessor.HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);
if (externalResult != null && externalResult.Succeeded)
{
var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
if (sid != null)
{
claims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
}
if (authenticationProperties != null)
{
// if the external provider issued an id_token, we'll keep it for sign out
var idToken = externalResult.Properties.GetTokenValue("id_token");
if (idToken != null)
{
authenticationProperties.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } });
}
}
var authenticationMethod = claims.FirstOrDefault(x => x.Type == ClaimTypes.AuthenticationMethod);
var idp = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.IdentityProvider);
if (authenticationMethod != null && idp == null)
{
claims.Add(new Claim(JwtClaimTypes.IdentityProvider, authenticationMethod.Value));
}
}
await base.SignInWithClaimsAsync(user, authenticationProperties, claims);
}
/// <summary>
/// Validates a passkey assertion and, if valid, signs the user in while also returning the signed-in user.
/// This is necessary because <see cref="PasskeySignInAsync"/> does not return the user object,
/// and the request principal is not updated after the auth cookie is issued in the same request.
/// </summary>
public async Task<(SignInResult Result, TUser User)> PasskeySignInWithUserAsync(string credentialJson)
{
var assertionResult = await PerformPasskeyAssertionAsync(credentialJson);
if (!assertionResult.Succeeded)
{
return (SignInResult.Failed, default);
}
var signInResult = await SignInOrTwoFactorAsync(assertionResult.User, isPersistent: false);
return (signInResult, assertionResult.User);
}
}
}
@@ -0,0 +1,43 @@
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Validation;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public class DelegationGrantValidator : IExtensionGrantValidator
{
private readonly ITokenValidator _validator;
public DelegationGrantValidator(ITokenValidator validator)
{
_validator = validator;
}
public string GrantType => "delegation";
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var userToken = context.Request.Raw.Get("token");
if (string.IsNullOrEmpty(userToken))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var result = await _validator.ValidateAccessTokenAsync(userToken);
if (result.IsError)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
// get user's identity
var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
context.Result = new GrantValidationResult(sub, GrantType);
return;
}
}
}
@@ -0,0 +1,48 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using System;
using System.Threading.Tasks;
using Duende.IdentityServer.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using LiteCharmsSecurity.STS.Identity.ViewModels.Account;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public static class Extensions
{
/// <summary>
/// Determines if the authentication scheme support signout.
/// </summary>
public static async Task<bool> GetSchemeSupportsSignOutAsync(this HttpContext context, string scheme)
{
var provider = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var handler = await provider.GetHandlerAsync(context, scheme);
return (handler is IAuthenticationSignOutHandler);
}
/// <summary>
/// Checks if the redirect URI is for a native client.
/// </summary>
/// <returns></returns>
public static bool IsNativeClient(this AuthorizationRequest context)
{
return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal)
&& !context.RedirectUri.StartsWith("http", StringComparison.Ordinal);
}
public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri)
{
controller.HttpContext.Response.StatusCode = 200;
controller.HttpContext.Response.Headers["Location"] = "";
return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri });
}
}
}
@@ -0,0 +1,6 @@
namespace LiteCharmsSecurity.STS.Identity.Helpers;
public class IdentityProvidersHelpers
{
public const string OpenIdConnect = "oidc";
}
@@ -0,0 +1,188 @@
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Common;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Helpers;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public static class IdentityServerBuilderExtensions
{
private const string CertificateNotFound = "Certificate not found";
private const string SigningCertificateThumbprintNotFound = "Signing certificate thumbprint not found";
private const string SigningCertificatePathIsNotSpecified = "Signing certificate file path is not specified";
private const string ValidationCertificateThumbprintNotFound = "Validation certificate thumbprint not found";
private const string ValidationCertificatePathIsNotSpecified = "Validation certificate file path is not specified";
/// <summary>
/// Add custom signing certificate from certification store according thumbprint or from file
/// </summary>
/// <param name="builder"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IIdentityServerBuilder AddCustomSigningCredential(this IIdentityServerBuilder builder, IConfiguration configuration)
{
var certificateConfiguration = configuration.GetSection(nameof(CertificateConfiguration)).Get<CertificateConfiguration>();
var azureKeyVaultConfiguration = configuration.GetSection(nameof(AzureKeyVaultConfiguration)).Get<AzureKeyVaultConfiguration>();
if (certificateConfiguration.UseSigningCertificateThumbprint)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.SigningCertificateThumbprint))
{
throw new Exception(SigningCertificateThumbprintNotFound);
}
StoreLocation storeLocation = StoreLocation.LocalMachine;
bool validOnly = certificateConfiguration.CertificateValidOnly;
// Parse the Certificate StoreLocation
string certStoreLocationLower = certificateConfiguration.CertificateStoreLocation.ToLower();
if (certStoreLocationLower == StoreLocation.CurrentUser.ToString().ToLower() ||
certificateConfiguration.CertificateStoreLocation == ((int)StoreLocation.CurrentUser).ToString())
{
storeLocation = StoreLocation.CurrentUser;
}
else if (certStoreLocationLower == StoreLocation.LocalMachine.ToString().ToLower() ||
certStoreLocationLower == ((int)StoreLocation.LocalMachine).ToString())
{
storeLocation = StoreLocation.LocalMachine;
}
else { storeLocation = StoreLocation.LocalMachine; validOnly = true; }
// Open Certificate
var certStore = new X509Store(StoreName.My, storeLocation);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certificateConfiguration.SigningCertificateThumbprint, validOnly);
if (certCollection.Count == 0)
{
throw new Exception(CertificateNotFound);
}
var certificate = certCollection[0];
builder.AddSigningCredential(certificate);
}
else if (certificateConfiguration.UseSigningCertificateForAzureKeyVault)
{
var x509Certificate2Certs = AzureKeyVaultHelpers.GetCertificates(azureKeyVaultConfiguration).GetAwaiter().GetResult();
builder.AddSigningCredential(x509Certificate2Certs.ActiveCertificate);
}
else if (certificateConfiguration.UseSigningCertificatePfxFile)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.SigningCertificatePfxFilePath))
{
throw new Exception(SigningCertificatePathIsNotSpecified);
}
if (File.Exists(certificateConfiguration.SigningCertificatePfxFilePath))
{
try
{
var bytes = File.ReadAllBytes(certificateConfiguration.SigningCertificatePfxFilePath);
var cert = X509CertificateLoader.LoadPkcs12(bytes, certificateConfiguration.SigningCertificatePfxFilePassword);
builder.AddSigningCredential(cert);
}
catch (Exception e)
{
throw new Exception("There was an error adding the key file - during the creation of the signing key", e);
}
}
else
{
throw new Exception($"Signing key file: {certificateConfiguration.SigningCertificatePfxFilePath} not found");
}
}
else if (certificateConfiguration.UseTemporarySigningKeyForDevelopment)
{
builder.AddDeveloperSigningCredential();
}
else
{
throw new Exception("Signing credential is not specified");
}
return builder;
}
/// <summary>
/// Add custom validation key for signing key rollover
/// http://docs.identityserver.io/en/latest/topics/crypto.html#signing-key-rollover
/// </summary>
/// <param name="builder"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IIdentityServerBuilder AddCustomValidationKey(this IIdentityServerBuilder builder, IConfiguration configuration)
{
var certificateConfiguration = configuration.GetSection(nameof(CertificateConfiguration)).Get<CertificateConfiguration>();
var azureKeyVaultConfiguration = configuration.GetSection(nameof(AzureKeyVaultConfiguration)).Get<AzureKeyVaultConfiguration>();
if (certificateConfiguration.UseValidationCertificateThumbprint)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.ValidationCertificateThumbprint))
{
throw new Exception(ValidationCertificateThumbprintNotFound);
}
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certificateConfiguration.ValidationCertificateThumbprint, false);
if (certCollection.Count == 0)
{
throw new Exception(CertificateNotFound);
}
var certificate = certCollection[0];
builder.AddValidationKey(certificate);
}
else if (certificateConfiguration.UseValidationCertificateForAzureKeyVault)
{
var x509Certificate2Certs = AzureKeyVaultHelpers.GetCertificates(azureKeyVaultConfiguration).GetAwaiter().GetResult();
if (x509Certificate2Certs.SecondaryCertificate != null)
{
builder.AddValidationKey(x509Certificate2Certs.SecondaryCertificate);
}
}
else if (certificateConfiguration.UseValidationCertificatePfxFile)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.ValidationCertificatePfxFilePath))
{
throw new Exception(ValidationCertificatePathIsNotSpecified);
}
if (File.Exists(certificateConfiguration.ValidationCertificatePfxFilePath))
{
try
{
var validationCertBytes = File.ReadAllBytes(certificateConfiguration.ValidationCertificatePfxFilePath);
var validationCertificate = X509CertificateLoader.LoadPkcs12(
validationCertBytes,
certificateConfiguration.ValidationCertificatePfxFilePassword);
builder.AddValidationKey(validationCertificate);
}
catch (Exception e)
{
throw new Exception("There was an error adding the key file - during the creation of the validation key", e);
}
}
else
{
throw new Exception($"Validation key file: {certificateConfiguration.ValidationCertificatePfxFilePath} not found");
}
}
return builder;
}
}
}
@@ -0,0 +1,12 @@
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public static class KeyValuePairExtensions
{
public static bool IsDefault<T>(this T value) where T : struct
{
var isDefault = value.Equals(default(T));
return isDefault;
}
}
}
@@ -0,0 +1,59 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// https://github.com/aspnet/Extensions/blob/master/src/Localization/Abstractions/src/StringLocalizerOfT.cs
// Modified by Jan Škoruba
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Extensions.Localization;
namespace LiteCharmsSecurity.STS.Identity.Helpers.Localization
{
public class GenericControllerLocalizer<TResourceSource> : IGenericControllerLocalizer<TResourceSource>
{
private IStringLocalizer _localizer;
/// <summary>
/// Creates a new <see cref="T:Microsoft.Extensions.Localization.StringLocalizer`1" />.
/// </summary>
/// <param name="factory">The <see cref="T:Microsoft.Extensions.Localization.IStringLocalizerFactory" /> to use.</param>
public GenericControllerLocalizer(IStringLocalizerFactory factory)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
var type = typeof(TResourceSource);
var assemblyName = type.GetTypeInfo().Assembly.GetName().Name;
var typeName = type.Name.Remove(type.Name.IndexOf('`'));
var baseName = (type.Namespace + "." + typeName).Substring(assemblyName.Length).Trim('.');
_localizer = factory.Create(baseName, assemblyName);
}
public virtual LocalizedString this[string name]
{
get
{
if (name == null)
throw new ArgumentNullException(nameof(name));
return _localizer[name];
}
}
public virtual LocalizedString this[string name, params object[] arguments]
{
get
{
if (name == null)
throw new ArgumentNullException(nameof(name));
return _localizer[name, arguments];
}
}
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{
return _localizer.GetAllStrings(includeParentCultures);
}
}
}
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Microsoft.Extensions.Localization;
namespace LiteCharmsSecurity.STS.Identity.Helpers.Localization
{
public interface IGenericControllerLocalizer<out T>
{
LocalizedString this[string name] { get; }
LocalizedString this[string name, params object[] arguments] { get; }
IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures);
}
}
@@ -0,0 +1,23 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
namespace LiteCharmsSecurity.STS.Identity.Helpers.Localization
{
public static class LoginPolicyResolutionLocalizer
{
public static string GetUserNameLocalizationKey(LoginResolutionPolicy policy)
{
switch (policy)
{
case LoginResolutionPolicy.Username:
return "Username";
case LoginResolutionPolicy.Email:
return "Email";
default:
return "Username";
}
}
}
}
@@ -0,0 +1,37 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System.Security.Cryptography;
using System.Text;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
/// <summary>
/// Helper-class to create Md5hashes from strings
/// </summary>
public static class Md5HashHelper
{
/// <summary>
/// Computes a Md5-hash of the submitted string and returns the corresponding hash
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string GetHash(string input)
{
using (var md5 = MD5.Create())
{
var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
var sBuilder = new StringBuilder();
foreach (var dataByte in bytes)
{
sBuilder.Append(dataByte.ToString("x2"));
}
return sBuilder.ToString();
}
}
}
}
@@ -0,0 +1,17 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public class OpenIdProfile
{
public string FullName { get; internal set; }
public string Website { get; internal set; }
public string Profile { get; internal set; }
public string StreetAddress { get; internal set; }
public string Locality { get; internal set; }
public string Region { get; internal set; }
public string PostalCode { get; internal set; }
public string Country { get; internal set; }
}
}
@@ -0,0 +1,231 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using IdentityModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using LiteCharmsSecurity.STS.Identity.Configuration.Constants;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public static class OpenIdClaimHelpers
{
public static Claim ExtractAddressClaim(OpenIdProfile profile)
{
var addressJson = new JObject();
if (!string.IsNullOrWhiteSpace(profile.StreetAddress))
{
addressJson[AddressClaimConstants.StreetAddress] = profile.StreetAddress;
}
if (!string.IsNullOrWhiteSpace(profile.Locality))
{
addressJson[AddressClaimConstants.Locality] = profile.Locality;
}
if (!string.IsNullOrWhiteSpace(profile.Region))
{
addressJson[AddressClaimConstants.Region] = profile.Region;
}
if (!string.IsNullOrWhiteSpace(profile.PostalCode))
{
addressJson[AddressClaimConstants.PostalCode] = profile.PostalCode;
}
if (!string.IsNullOrWhiteSpace(profile.Country))
{
addressJson[AddressClaimConstants.Country] = profile.Country;
}
return new Claim(JwtClaimTypes.Address, addressJson.Count != 0 ? addressJson.ToString() : string.Empty);
}
/// <summary>
/// Map claims to OpenId Profile
/// </summary>
/// <param name="claims"></param>
/// <returns></returns>
public static OpenIdProfile ExtractProfileInfo(IList<Claim> claims)
{
var profile = new OpenIdProfile
{
FullName = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value,
Website = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.WebSite)?.Value,
Profile = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Profile)?.Value
};
var address = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Address)?.Value;
if (address == null) return profile;
try
{
var addressJson = JObject.Parse(address);
if (addressJson.ContainsKey(AddressClaimConstants.StreetAddress))
{
profile.StreetAddress = addressJson[AddressClaimConstants.StreetAddress].ToString();
}
if (addressJson.ContainsKey(AddressClaimConstants.Locality))
{
profile.Locality = addressJson[AddressClaimConstants.Locality].ToString();
}
if (addressJson.ContainsKey(AddressClaimConstants.Region))
{
profile.Region = addressJson[AddressClaimConstants.Region].ToString();
}
if (addressJson.ContainsKey(AddressClaimConstants.PostalCode))
{
profile.PostalCode = addressJson[AddressClaimConstants.PostalCode].ToString();
}
if (addressJson.ContainsKey(AddressClaimConstants.Country))
{
profile.Country = addressJson[AddressClaimConstants.Country].ToString();
}
}
catch (JsonReaderException)
{
}
return profile;
}
/// <summary>
/// Get claims to remove
/// </summary>
/// <param name="oldProfile"></param>
/// <param name="newProfile"></param>
/// <returns></returns>
public static IList<Claim> ExtractClaimsToRemove(OpenIdProfile oldProfile, OpenIdProfile newProfile)
{
var claimsToRemove = new List<Claim>();
if (string.IsNullOrWhiteSpace(newProfile.FullName) && !string.IsNullOrWhiteSpace(oldProfile.FullName))
{
claimsToRemove.Add(new Claim(JwtClaimTypes.Name, oldProfile.FullName));
}
if (string.IsNullOrWhiteSpace(newProfile.Website) && !string.IsNullOrWhiteSpace(oldProfile.Website))
{
claimsToRemove.Add(new Claim(JwtClaimTypes.WebSite, oldProfile.Website));
}
if (string.IsNullOrWhiteSpace(newProfile.Profile) && !string.IsNullOrWhiteSpace(oldProfile.Profile))
{
claimsToRemove.Add(new Claim(JwtClaimTypes.Profile, oldProfile.Profile));
}
var oldAddressClaim = ExtractAddressClaim(oldProfile);
var newAddressClaim = ExtractAddressClaim(newProfile);
if (string.IsNullOrWhiteSpace(newAddressClaim.Value) && !string.IsNullOrWhiteSpace(oldAddressClaim.Value))
{
claimsToRemove.Add(oldAddressClaim);
}
return claimsToRemove;
}
/// <summary>
/// Get claims to add
/// </summary>
/// <param name="oldProfile"></param>
/// <param name="newProfile"></param>
/// <returns></returns>
public static IList<Claim> ExtractClaimsToAdd(OpenIdProfile oldProfile, OpenIdProfile newProfile)
{
var claimsToAdd = new List<Claim>();
if (!string.IsNullOrWhiteSpace(newProfile.FullName) && string.IsNullOrWhiteSpace(oldProfile.FullName))
{
claimsToAdd.Add(new Claim(JwtClaimTypes.Name, newProfile.FullName));
}
if (!string.IsNullOrWhiteSpace(newProfile.Website) && string.IsNullOrWhiteSpace(oldProfile.Website))
{
claimsToAdd.Add(new Claim(JwtClaimTypes.WebSite, newProfile.Website));
}
if (!string.IsNullOrWhiteSpace(newProfile.Profile) && string.IsNullOrWhiteSpace(oldProfile.Profile))
{
claimsToAdd.Add(new Claim(JwtClaimTypes.Profile, newProfile.Profile));
}
var oldAddressClaim = ExtractAddressClaim(oldProfile);
var newAddressClaim = ExtractAddressClaim(newProfile);
if (!string.IsNullOrWhiteSpace(newAddressClaim.Value) && string.IsNullOrWhiteSpace(oldAddressClaim.Value))
{
claimsToAdd.Add(newAddressClaim);
}
return claimsToAdd;
}
/// <summary>
/// Get claims to replace
/// </summary>
/// <param name="oldClaims"></param>
/// <param name="newProfile"></param>
/// <returns></returns>
public static IList<Tuple<Claim,Claim>> ExtractClaimsToReplace(IList<Claim> oldClaims, OpenIdProfile newProfile)
{
var oldProfile = ExtractProfileInfo(oldClaims);
var claimsToReplace = new List<Tuple<Claim, Claim>>();
if (!string.IsNullOrWhiteSpace(newProfile.FullName) && !string.IsNullOrWhiteSpace(oldProfile.FullName))
{
if (newProfile.FullName != oldProfile.FullName)
{
var oldClaim = oldClaims.First(x => x.Type == JwtClaimTypes.Name);
var newClaim = new Claim(JwtClaimTypes.Name, newProfile.FullName);
claimsToReplace.Add(new Tuple<Claim, Claim>(oldClaim, newClaim));
}
}
if (!string.IsNullOrWhiteSpace(newProfile.Website) && !string.IsNullOrWhiteSpace(oldProfile.Website))
{
if (newProfile.Website != oldProfile.Website)
{
var oldClaim = oldClaims.First(x => x.Type == JwtClaimTypes.WebSite);
var newClaim = new Claim(JwtClaimTypes.WebSite, newProfile.Website);
claimsToReplace.Add(new Tuple<Claim, Claim>(oldClaim, newClaim));
}
}
if (!string.IsNullOrWhiteSpace(newProfile.Profile) && !string.IsNullOrWhiteSpace(oldProfile.Profile))
{
if (newProfile.Profile != oldProfile.Profile)
{
var oldClaim = oldClaims.First(x => x.Type == JwtClaimTypes.Profile);
var newClaim = new Claim(JwtClaimTypes.Profile, newProfile.Profile);
claimsToReplace.Add(new Tuple<Claim, Claim>(oldClaim, newClaim));
}
}
var oldAddressClaim = ExtractAddressClaim(oldProfile);
var newAddressClaim = ExtractAddressClaim(newProfile);
if (!string.IsNullOrWhiteSpace(newAddressClaim.Value) && !string.IsNullOrWhiteSpace(oldAddressClaim.Value))
{
if (newAddressClaim.Value != oldAddressClaim.Value)
{
var oldClaim = oldClaims.First(x => x.Type == JwtClaimTypes.Address);
claimsToReplace.Add(new Tuple<Claim, Claim>(oldClaim, newAddressClaim));
}
}
return claimsToReplace;
}
}
}
@@ -0,0 +1,59 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
// Original file: https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI
// Modified by Jan Škoruba
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public class SecurityHeadersAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var result = context.Result;
if (result is ViewResult)
{
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options"))
{
context.HttpContext.Response.Headers.Append("X-Content-Type-Options", "nosniff");
}
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options"))
{
context.HttpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN");
}
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';";
// also consider adding upgrade-insecure-requests once you have HTTPS in place for production
//csp += "upgrade-insecure-requests;";
// also an example if you need client images to be displayed from twitter
// csp += "img-src 'self' https://pbs.twimg.com;";
// once for standards compliant browsers
if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy"))
{
context.HttpContext.Response.Headers.Append("Content-Security-Policy", csp);
}
// and once again for IE
if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy"))
{
context.HttpContext.Response.Headers.Append("X-Content-Security-Policy", csp);
}
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
var referrer_policy = "no-referrer";
if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy"))
{
context.HttpContext.Response.Headers.Append("Referrer-Policy", referrer_policy);
}
}
}
}
}
@@ -0,0 +1,579 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using NetIPNetwork = System.Net.IPNetwork;
using Duende.IdentityServer;
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.EntityFramework.Storage;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using IdentityModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Tokens;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Constants;
using System.IO;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.Configuration;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.PostgreSQL;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.SqlServer;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Helpers;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Interfaces;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Authentication;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
using LiteCharmsSecurity.STS.Identity.Configuration;
using LiteCharmsSecurity.STS.Identity.Configuration.ApplicationParts;
using LiteCharmsSecurity.STS.Identity.Configuration.Constants;
using LiteCharmsSecurity.STS.Identity.Configuration.Interfaces;
using Configuration = LiteCharmsSecurity.STS.Identity.Configuration;
using LiteCharmsSecurity.STS.Identity.Helpers.Localization;
using LiteCharmsSecurity.STS.Identity.Services;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public static class StartupHelpers
{
/// <summary>
/// Register services for MVC and localization including available languages
/// </summary>
/// <param name="services"></param>
public static IMvcBuilder AddMvcWithLocalization<TUser, TKey>(this IServiceCollection services, IConfiguration configuration)
where TUser : IdentityUser<TKey>
where TKey : IEquatable<TKey>
{
services.AddLocalization(opts => { opts.ResourcesPath = ConfigurationConsts.ResourcesPath; });
services.TryAddTransient(typeof(IGenericControllerLocalizer<>), typeof(GenericControllerLocalizer<>));
var mvcBuilder = services.AddControllersWithViews(o =>
{
o.Conventions.Add(new GenericControllerRouteConvention());
})
.AddViewLocalization(
LanguageViewLocationExpanderFormat.Suffix,
opts => { opts.ResourcesPath = ConfigurationConsts.ResourcesPath; })
.AddDataAnnotationsLocalization()
.ConfigureApplicationPartManager(m =>
{
m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider<TUser, TKey>());
});
var cultureConfiguration = configuration.GetSection(nameof(CultureConfiguration)).Get<CultureConfiguration>();
services.Configure<RequestLocalizationOptions>(
opts =>
{
// If cultures are specified in the configuration, use them (making sure they are among the available cultures),
// otherwise use all the available cultures
var supportedCultureCodes = (cultureConfiguration?.Cultures?.Count > 0 ?
cultureConfiguration.Cultures.Intersect(CultureConfiguration.AvailableCultures) :
CultureConfiguration.AvailableCultures).ToArray();
if (!supportedCultureCodes.Any()) supportedCultureCodes = CultureConfiguration.AvailableCultures;
var supportedCultures = supportedCultureCodes.Select(c => new CultureInfo(c)).ToList();
// If the default culture is specified use it, otherwise use CultureConfiguration.DefaultRequestCulture ("en")
var defaultCultureCode = string.IsNullOrEmpty(cultureConfiguration?.DefaultCulture) ?
CultureConfiguration.DefaultRequestCulture : cultureConfiguration?.DefaultCulture;
// If the default culture is not among the supported cultures, use the first supported culture as default
if (!supportedCultureCodes.Contains(defaultCultureCode)) defaultCultureCode = supportedCultureCodes.FirstOrDefault();
opts.DefaultRequestCulture = new RequestCulture(defaultCultureCode);
opts.SupportedCultures = supportedCultures;
opts.SupportedUICultures = supportedCultures;
});
return mvcBuilder;
}
/// <summary>
/// Using of Forwarded Headers and Referrer Policy
/// </summary>
/// <param name="app"></param>
/// <param name="configuration"></param>
public static void UseSecurityHeaders(this IApplicationBuilder app, IConfiguration configuration)
{
var forwardedHeadersConfig = configuration.GetSection(ConfigurationConsts.ForwardedHeadersConfigurationKey)
.Get<Configuration.ForwardedHeadersConfiguration>() ?? new Configuration.ForwardedHeadersConfiguration();
if (forwardedHeadersConfig.Enabled)
{
var forwardingOptions = new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.All,
ForwardLimit = forwardedHeadersConfig.ForwardLimit
};
if (forwardedHeadersConfig.AllowAll)
{
// Development mode: allow all proxies and networks (insecure)
forwardingOptions.KnownIPNetworks.Clear();
forwardingOptions.KnownProxies.Clear();
}
else
{
// Production mode: only trust configured proxies and networks
if (forwardedHeadersConfig.KnownProxies != null && forwardedHeadersConfig.KnownProxies.Count > 0)
{
forwardingOptions.KnownProxies.Clear();
foreach (var proxy in forwardedHeadersConfig.KnownProxies)
{
if (System.Net.IPAddress.TryParse(proxy, out var ipAddress))
{
forwardingOptions.KnownProxies.Add(ipAddress);
}
}
}
if (forwardedHeadersConfig.KnownNetworks != null && forwardedHeadersConfig.KnownNetworks.Count > 0)
{
forwardingOptions.KnownIPNetworks.Clear();
foreach (var network in forwardedHeadersConfig.KnownNetworks)
{
var parts = network.Split('/');
if (parts.Length == 2 &&
IPAddress.TryParse(parts[0], out var prefix) &&
int.TryParse(parts[1], out var prefixLength))
{
forwardingOptions.KnownIPNetworks.Add(new NetIPNetwork(prefix, prefixLength));
}
}
}
// If no proxies or networks configured, don't clear defaults (more secure)
// This means it will only trust the loopback by default
}
app.UseForwardedHeaders(forwardingOptions);
}
app.UseReferrerPolicy(options => options.NoReferrer());
// CSP Configuration to be able to use external resources
var cspTrustedDomains = new List<string>();
configuration.GetSection(ConfigurationConsts.CspTrustedDomainsKey).Bind(cspTrustedDomains);
if (cspTrustedDomains.Any())
{
app.UseCsp(csp =>
{
var imagesSources = new List<string> { "data:" };
imagesSources.AddRange(cspTrustedDomains);
csp.ImageSources(options =>
{
options.SelfSrc = true;
options.CustomSources = imagesSources;
options.Enabled = true;
});
csp.FontSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.ScriptSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.StyleSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
options.UnsafeInlineSrc = false;
});
csp.Sandbox(options =>
{
options.AllowForms()
.AllowSameOrigin()
.AllowScripts();
});
csp.FrameAncestors(option =>
{
option.NoneSrc = true;
option.Enabled = true;
});
csp.BaseUris(options =>
{
options.SelfSrc = true;
options.Enabled = true;
});
csp.ObjectSources(options =>
{
options.NoneSrc = true;
options.Enabled = true;
});
csp.DefaultSources(options =>
{
options.Enabled = true;
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
});
});
}
}
/// <summary>
/// Register DbContexts for IdentityServer ConfigurationStore, PersistedGrants, Identity and DataProtection
/// Configure the connection strings in AppSettings.json
/// </summary>
/// <typeparam name="TConfigurationDbContext"></typeparam>
/// <typeparam name="TPersistedGrantDbContext"></typeparam>
/// <typeparam name="TIdentityDbContext"></typeparam>
/// <typeparam name="TDataProtectionDbContext"></typeparam>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void RegisterDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(this IServiceCollection services, IConfiguration configuration)
where TIdentityDbContext : DbContext
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
{
var databaseProvider = configuration.GetSection(nameof(DatabaseProviderConfiguration)).Get<DatabaseProviderConfiguration>();
var identityConnectionString = configuration.GetConnectionString(ConfigurationConsts.IdentityDbConnectionStringKey);
var configurationConnectionString = configuration.GetConnectionString(ConfigurationConsts.ConfigurationDbConnectionStringKey);
var persistedGrantsConnectionString = configuration.GetConnectionString(ConfigurationConsts.PersistedGrantDbConnectionStringKey);
var dataProtectionConnectionString = configuration.GetConnectionString(ConfigurationConsts.DataProtectionDbConnectionStringKey);
switch (databaseProvider.ProviderType)
{
case DatabaseProviderType.SqlServer:
services.RegisterSqlServerDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(identityConnectionString, configurationConnectionString, persistedGrantsConnectionString, dataProtectionConnectionString);
break;
case DatabaseProviderType.PostgreSQL:
services.RegisterNpgSqlDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(identityConnectionString, configurationConnectionString, persistedGrantsConnectionString, dataProtectionConnectionString);
break;
default:
throw new ArgumentOutOfRangeException(nameof(databaseProvider.ProviderType), $@"The value needs to be one of {string.Join(", ", Enum.GetNames(typeof(DatabaseProviderType)))}.");
}
}
/// <summary>
/// Register InMemory DbContexts for IdentityServer ConfigurationStore, PersistedGrants, Identity and DataProtection
/// Configure the connection strings in AppSettings.json
/// </summary>
/// <typeparam name="TConfigurationDbContext"></typeparam>
/// <typeparam name="TPersistedGrantDbContext"></typeparam>
/// <typeparam name="TIdentityDbContext"></typeparam>
/// <param name="services"></param>
public static void RegisterDbContextsStaging<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(
this IServiceCollection services)
where TIdentityDbContext : DbContext
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
{
var identityDatabaseName = Guid.NewGuid().ToString();
services.AddDbContext<TIdentityDbContext>(optionsBuilder => optionsBuilder.UseInMemoryDatabase(identityDatabaseName));
var configurationDatabaseName = Guid.NewGuid().ToString();
var operationalDatabaseName = Guid.NewGuid().ToString();
var dataProtectionDatabaseName = Guid.NewGuid().ToString();
services.AddConfigurationDbContext<TConfigurationDbContext>(options =>
{
options.ConfigureDbContext = b => b.UseInMemoryDatabase(configurationDatabaseName);
});
services.AddOperationalDbContext<TPersistedGrantDbContext>(options =>
{
options.ConfigureDbContext = b => b.UseInMemoryDatabase(operationalDatabaseName);
});
services.AddDbContext<TDataProtectionDbContext>(options =>
{
options.UseInMemoryDatabase(dataProtectionDatabaseName);
});
}
/// <summary>
/// Add services for authentication, including Identity model, Duende IdentityServer and external providers
/// </summary>
/// <typeparam name="TIdentityDbContext">DbContext for Identity</typeparam>
/// <typeparam name="TUserIdentity">User Identity class</typeparam>
/// <typeparam name="TUserIdentityRole">User Identity Role class</typeparam>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddAuthenticationServices<TIdentityDbContext, TUserIdentity, TUserIdentityRole>(this IServiceCollection services, IConfiguration configuration) where TIdentityDbContext : DbContext
where TUserIdentity : class
where TUserIdentityRole : class
{
var loginConfiguration = GetLoginConfiguration(configuration);
var registrationConfiguration = GetRegistrationConfiguration(configuration);
var identityOptions = configuration.GetSection(nameof(IdentityOptions)).Get<IdentityOptions>();
services
.AddSingleton(registrationConfiguration)
.AddSingleton(loginConfiguration)
.AddSingleton(identityOptions)
.AddScoped<ApplicationSignInManager<TUserIdentity>>()
.AddScoped<UserResolver<TUserIdentity>>()
.AddIdentity<TUserIdentity, TUserIdentityRole>(options =>
{
configuration.GetSection(nameof(IdentityOptions)).Bind(options);
options.Stores.SchemaVersion = IdentityStoreDefaults.SchemaVersion;
options.Stores.MaxLengthForKeys = IdentityStoreDefaults.MaxLengthForKeys;
})
.AddEntityFrameworkStores<TIdentityDbContext>()
.AddDefaultTokenProviders();
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.Secure = CookieSecurePolicy.SameAsRequest;
options.OnAppendCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
var authenticationBuilder = services.AddAuthentication();
AddExternalProviders(authenticationBuilder, configuration);
}
/// <summary>
/// Get configuration for login
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
private static LoginConfiguration GetLoginConfiguration(IConfiguration configuration)
{
var loginConfiguration = configuration.GetSection(nameof(LoginConfiguration)).Get<LoginConfiguration>();
// Cannot load configuration - use default configuration values
if (loginConfiguration == null)
{
return new LoginConfiguration();
}
return loginConfiguration;
}
/// <summary>
/// Get configuration for registration
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
private static RegisterConfiguration GetRegistrationConfiguration(IConfiguration configuration)
{
var registerConfiguration = configuration.GetSection(nameof(RegisterConfiguration)).Get<RegisterConfiguration>();
// Cannot load configuration - use default configuration values
if (registerConfiguration == null)
{
return new RegisterConfiguration();
}
return registerConfiguration;
}
/// <summary>
/// Add configuration for Duende IdentityServer
/// </summary>
/// <typeparam name="TUserIdentity"></typeparam>
/// <typeparam name="TConfigurationDbContext"></typeparam>
/// <typeparam name="TPersistedGrantDbContext"></typeparam>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static IIdentityServerBuilder AddIdentityServer<TConfigurationDbContext, TPersistedGrantDbContext, TUserIdentity>(
this IServiceCollection services,
IConfiguration configuration)
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TUserIdentity : class
{
var configurationSection = configuration.GetSection(nameof(IdentityServerOptions));
var identityServerOptions = configurationSection.Get<IdentityServerOptions>();
var builder = services.AddIdentityServer(options =>
{
configurationSection.Bind(options);
options.DynamicProviders.SignInScheme = IdentityConstants.ExternalScheme;
options.DynamicProviders.SignOutScheme = IdentityConstants.ApplicationScheme;
})
.AddConfigurationStore<TConfigurationDbContext>()
.AddOperationalStore<TPersistedGrantDbContext>()
.AddAspNetIdentity<TUserIdentity>();
services.ConfigureOptions<OpenIdClaimsMappingConfig>();
if (!identityServerOptions.KeyManagement.Enabled)
{
builder.AddCustomSigningCredential(configuration);
builder.AddCustomValidationKey(configuration);
}
builder.AddExtensionGrantValidator<DelegationGrantValidator>();
// Check if server-side sessions should be enabled from configuration
var serverSideSessionsConfig = configuration.GetSection(Configuration.ServerSideSessionsConfiguration.SectionName).Get<Configuration.ServerSideSessionsConfiguration>() ?? new Configuration.ServerSideSessionsConfiguration();
var serverSideSessionsEnabled = serverSideSessionsConfig.Enabled;
if (serverSideSessionsEnabled)
{
builder.AddServerSideSessions();
services.Configure<IdentityServerOptions>(options =>
{
options.ServerSideSessions.UserDisplayNameClaimType = JwtClaimTypes.Name;
options.ServerSideSessions.RemoveExpiredSessions = true;
options.ServerSideSessions.ExpiredSessionsTriggerBackchannelLogout = true;
});
}
return builder;
}
/// <summary>
/// Add external providers
/// </summary>
/// <param name="authenticationBuilder"></param>
/// <param name="configuration"></param>
private static void AddExternalProviders(AuthenticationBuilder authenticationBuilder,
IConfiguration configuration)
{
var externalProviderConfiguration = configuration.GetSection(nameof(ExternalProvidersConfiguration)).Get<ExternalProvidersConfiguration>();
if (externalProviderConfiguration.UseGitHubProvider)
{
authenticationBuilder.AddGitHub(options =>
{
options.ClientId = externalProviderConfiguration.GitHubClientId;
options.ClientSecret = externalProviderConfiguration.GitHubClientSecret;
options.CallbackPath = externalProviderConfiguration.GitHubCallbackPath;
options.Scope.Add("user:email");
});
}
if (externalProviderConfiguration.UseAzureAdProvider)
{
authenticationBuilder.AddMicrosoftIdentityWebApp(options =>
{
options.ClientSecret = externalProviderConfiguration.AzureAdSecret;
options.ClientId = externalProviderConfiguration.AzureAdClientId;
options.TenantId = externalProviderConfiguration.AzureAdTenantId;
options.Instance = externalProviderConfiguration.AzureInstance;
options.Domain = externalProviderConfiguration.AzureDomain;
options.CallbackPath = externalProviderConfiguration.AzureAdCallbackPath;
}, cookieScheme: null);
}
}
/// <summary>
/// Register middleware for localization
/// </summary>
/// <param name="app"></param>
public static void UseMvcLocalizationServices(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
}
/// <summary>
/// Add authorization policies
/// </summary>
/// <param name="services"></param>
/// <param name="rootConfiguration"></param>
public static void AddAuthorizationPolicies(this IServiceCollection services,
IRootConfiguration rootConfiguration)
{
services.AddAuthorization(options =>
{
options.AddPolicy(AuthorizationConsts.AdministrationPolicy,
policy => policy.RequireRole(rootConfiguration.AdminConfiguration.AdministrationRole));
});
}
public static void AddIdSHealthChecks<TConfigurationDbContext, TPersistedGrantDbContext, TIdentityDbContext, TDataProtectionDbContext>(this IServiceCollection services, IConfiguration configuration)
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TIdentityDbContext : DbContext
where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
{
var configurationDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.ConfigurationDbConnectionStringKey);
var persistedGrantsDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.PersistedGrantDbConnectionStringKey);
var identityDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.IdentityDbConnectionStringKey);
var dataProtectionDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.DataProtectionDbConnectionStringKey);
var healthChecksBuilder = services.AddHealthChecks()
.AddDbContextCheck<TConfigurationDbContext>("ConfigurationDbContext")
.AddDbContextCheck<TPersistedGrantDbContext>("PersistedGrantsDbContext")
.AddDbContextCheck<TIdentityDbContext>("IdentityDbContext")
.AddDbContextCheck<TDataProtectionDbContext>("DataProtectionDbContext");
var serviceProvider = services.BuildServiceProvider();
var scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var configurationTableName = DbContextHelpers.GetEntityTable<TConfigurationDbContext>(scope.ServiceProvider);
var persistedGrantTableName = DbContextHelpers.GetEntityTable<TPersistedGrantDbContext>(scope.ServiceProvider);
var identityTableName = DbContextHelpers.GetEntityTable<TIdentityDbContext>(scope.ServiceProvider);
var dataProtectionTableName = DbContextHelpers.GetEntityTable<TDataProtectionDbContext>(scope.ServiceProvider);
var databaseProvider = configuration.GetSection(nameof(DatabaseProviderConfiguration)).Get<DatabaseProviderConfiguration>();
switch (databaseProvider.ProviderType)
{
case DatabaseProviderType.SqlServer:
healthChecksBuilder
.AddSqlServer(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{configurationTableName}]")
.AddSqlServer(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{persistedGrantTableName}]")
.AddSqlServer(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{identityTableName}]")
.AddSqlServer(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{dataProtectionTableName}]");
break;
case DatabaseProviderType.PostgreSQL:
healthChecksBuilder
.AddNpgSql(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT * FROM \"{configurationTableName}\" LIMIT 1")
.AddNpgSql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT * FROM \"{persistedGrantTableName}\" LIMIT 1")
.AddNpgSql(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT * FROM \"{identityTableName}\" LIMIT 1")
.AddNpgSql(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT * FROM \"{dataProtectionTableName}\" LIMIT 1");
break;
default:
throw new NotImplementedException($"Health checks not defined for database provider {databaseProvider.ProviderType}");
}
}
}
}
}
@@ -0,0 +1,52 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace LiteCharmsSecurity.STS.Identity.Helpers.TagHelpers
{
[HtmlTargetElement("img-gravatar")]
public class GravatarTagHelper : TagHelper
{
[HtmlAttributeName("email")]
public string Email { get; set; }
[HtmlAttributeName("alt")]
public string Alt { get; set; }
[HtmlAttributeName("class")]
public string Class { get; set; }
[HtmlAttributeName("size")]
public int Size { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!string.IsNullOrWhiteSpace(Email))
{
var hash = Md5HashHelper.GetHash(Email);
output.TagName = "img";
if (!string.IsNullOrWhiteSpace(Class))
{
output.Attributes.Add("class", Class);
}
if (!string.IsNullOrWhiteSpace(Alt))
{
output.Attributes.Add("alt", Alt);
}
output.Attributes.Add("src", GetAvatarUrl(hash, Size));
output.TagMode = TagMode.SelfClosing;
}
}
private static string GetAvatarUrl(string hash, int size)
{
var sizeArg = size > 0 ? $"?s={size}" : "";
return $"https://www.gravatar.com/avatar/{hash}{sizeArg}";
}
}
}
@@ -0,0 +1,63 @@
#nullable enable
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.FileProviders;
namespace LiteCharmsSecurity.STS.Identity.Helpers.TagHelpers
{
[HtmlTargetElement("lucideicon", TagStructure = TagStructure.WithoutEndTag)]
public class LucideIconTagHelper : TagHelper
{
private readonly IFileProvider _fileProvider;
public LucideIconTagHelper(IWebHostEnvironment env)
{
_fileProvider = env.WebRootFileProvider;
}
[HtmlAttributeName("name")]
public string Name { get; set; } = string.Empty;
[HtmlAttributeName("class")]
public string? Class { get; set; }
[HtmlAttributeName("size")]
public int? Size { get; set; }
[HtmlAttributeName("base-path")]
public string BasePath { get; set; } = "icons/lucide";
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = null;
if (string.IsNullOrWhiteSpace(Name))
{
output.Content.SetHtmlContent("<!-- missing icon name -->");
return;
}
var file = _fileProvider.GetFileInfo($"{BasePath}/{Name}.svg");
if (!file.Exists)
{
output.Content.SetHtmlContent($"<!-- icon not found: {Name} -->");
return;
}
string svg;
using (var stream = file.CreateReadStream())
using (var reader = new StreamReader(stream))
svg = reader.ReadToEnd();
if (!string.IsNullOrWhiteSpace(Class))
svg = svg.Replace("<svg", $"<svg class=\"{Class}\"", StringComparison.OrdinalIgnoreCase);
if (Size.HasValue)
svg = svg.Replace("<svg", $"<svg width=\"{Size}\" height=\"{Size}\"", StringComparison.OrdinalIgnoreCase);
output.Content.SetHtmlContent(svg);
}
}
}
@@ -0,0 +1,27 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace LiteCharmsSecurity.STS.Identity.Helpers.TagHelpers
{
[HtmlTargetElement("toggle-button")]
public class SwitchTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
var divSlider = new TagBuilder("div");
divSlider.AddCssClass("slider round bg-primary");
output.TagName = "label";
output.Attributes.Add("class", "switch");
output.Content.AppendHtml(childContent);
output.Content.AppendHtml(divSlider);
output.TagMode = TagMode.StartTagAndEndTag;
}
}
}
@@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace LiteCharmsSecurity.STS.Identity.Helpers.TagHelpers;
[HtmlTargetElement("label", Attributes = "asp-for,tw-validation", TagStructure = TagStructure.NormalOrSelfClosing)]
public class TwValidationLabelTagHelper : TagHelper
{
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; } = default!;
[HtmlAttributeName("tw-validation")]
public bool TwValidation { get; set; } = true;
[ViewContext]
public ViewContext ViewContext { get; set; } = default!;
public override int Order => 1000;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!TwValidation || ViewContext == null || For == null) return;
var key = For.Name;
var modelState = ViewContext.ViewData.ModelState;
if (modelState.TryGetValue(key, out var entry) && entry.Errors.Count > 0)
{
var existingClass = output.Attributes["class"]?.Value?.ToString() ?? string.Empty;
var mergedClass = string.IsNullOrWhiteSpace(existingClass)
? "form-label form-label-invalid"
: $"{existingClass} form-label-invalid";
output.Attributes.SetAttribute("class", mergedClass);
}
// odstraníme vlastní atribut, aby nešel do HTML
output.Attributes.RemoveAll("tw-validation");
}
}
@@ -0,0 +1,65 @@
#nullable enable
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace LiteCharmsSecurity.STS.Identity.Helpers.TagHelpers;
[HtmlTargetElement("input", Attributes = "asp-for,tw-validation")]
public class TwValidationTagHelper : TagHelper
{
public override int Order => 1000;
[HtmlAttributeName("asp-for")]
public ModelExpression AspFor { get; set; } = default!;
[HtmlAttributeName("tw-validation")]
public bool TwValidation { get; set; } = true;
[ViewContext, HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; } = default!;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.RemoveAll("tw-validation");
if (!TwValidation || AspFor == null || ViewContext == null)
return;
var fieldName = AspFor.Name;
var hasError = ViewContext.ViewData.ModelState.TryGetValue(fieldName, out var entry)
&& entry is { Errors.Count: > 0 };
if (!hasError)
return;
var existing = output.Attributes.TryGetAttribute("class", out var classAttr)
? AsPlainText(classAttr.Value)
: string.Empty;
var merged = string.IsNullOrWhiteSpace(existing)
? "input-invalid"
: $"{existing} input-invalid";
output.Attributes.SetAttribute("class", merged.Trim());
output.Attributes.SetAttribute("aria-invalid", "true");
}
private static string AsPlainText(object? value)
{
if (value is null) return string.Empty;
if (value is string s) return s;
if (value is IHtmlContent html)
{
using var sw = new StringWriter();
html.WriteTo(sw, HtmlEncoder.Default);
return sw.ToString();
}
return value.ToString() ?? string.Empty;
}
}
@@ -0,0 +1,34 @@
// Copyright (c) Jan Škoruba. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Configuration.Identity;
namespace LiteCharmsSecurity.STS.Identity.Helpers
{
public class UserResolver<TUser> where TUser : class
{
private readonly UserManager<TUser> _userManager;
private readonly LoginResolutionPolicy _policy;
public UserResolver(UserManager<TUser> userManager, LoginConfiguration configuration)
{
_userManager = userManager;
_policy = configuration.ResolutionPolicy;
}
public async Task<TUser> GetUserAsync(string login)
{
switch (_policy)
{
case LoginResolutionPolicy.Username:
return await _userManager.FindByNameAsync(login);
case LoginResolutionPolicy.Email:
return await _userManager.FindByEmailAsync(login);
default:
return null;
}
}
}
}
@@ -0,0 +1,135 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<UserSecretsId>9c91d295-54c5-4d09-9bd6-fa56fb74011b</UserSecretsId>
<DockerComposeProjectPath>..\..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="10.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="9.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageReference Include="KubernetesClient" Version="19.0.2" />
<PackageReference Include="IdentityModel" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.Identity.Web" Version="4.8.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.7" />
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="7.4.7" />
<PackageReference Include="Duende.IdentityServer.EntityFramework" Version="7.4.7" />
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="9.0.3" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="Skoruba.AuditLogging.EntityFramework" Version="3.0.0" />
<PackageReference Include="NWebsec.AspNetCore.Middleware" Version="3.0.0" />
<PackageReference Include="Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration" Version="3.0.0-rc4" />
<PackageReference Include="Skoruba.Duende.IdentityServer.Shared.Configuration" Version="3.0.0-rc4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LiteCharmsSecurity.Admin.EntityFramework.Shared\LiteCharmsSecurity.Admin.EntityFramework.Shared.csproj" />
<ProjectReference Include="..\LiteCharmsSecurity.Shared\LiteCharmsSecurity.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.ru.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.zh.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.sv.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.fi.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.fr.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.fa.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.es.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.de.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.da.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Views\Account\RegisterConfirmation.en.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\fontawesome-webfont.eot" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\fontawesome-webfont.svg" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\fontawesome-webfont.ttf" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\fontawesome-webfont.woff" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\fontawesome-webfont.woff2" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\FontAwesome.otf" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\open-iconic.eot" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\open-iconic.otf" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\open-iconic.svg" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\open-iconic.ttf" />
<_ContentIncludedByDefault Remove="wwwroot\dist\fonts\open-iconic.woff" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\bundle.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\cerulean\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\cosmo\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\cyborg\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\darkly\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\flatly\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\journal\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\litera\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\lumen\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\lux\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\materia\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\minty\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\pulse\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\sandstone\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\simplex\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\sketchy\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\slate\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\solar\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\spacelab\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\superhero\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\united\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\themes\yeti\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\web.css" />
<_ContentIncludedByDefault Remove="wwwroot\dist\css\web.min.css" />
</ItemGroup>
</Project>
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace LiteCharmsSecurity.STS.Identity.Models.ViewModels;
public class ServerSideSessionsViewModel
{
public IList<SessionItem> Sessions { get; set; } = new List<SessionItem>();
public string Filter { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages => PageSize == 0 ? 0 : (int)Math.Ceiling(TotalCount / (double)PageSize);
public bool HasPrevious => Page > 1;
public bool HasNext => Page < TotalPages;
}
public class SessionItem
{
public string SubjectId { get; set; }
public string SessionId { get; set; }
public string DisplayName { get; set; }
public DateTime Created { get; set; }
public DateTime? Expires { get; set; }
public string Data { get; set; }
}
@@ -0,0 +1,70 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// Modified by Jan Skoruba
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using LiteCharmsSecurity.STS.Identity.Helpers;
namespace LiteCharmsSecurity.STS.Identity.Passkeys
{
public static class PasskeyEndpointRouteBuilderExtensions
{
public static IEndpointConventionBuilder MapPasskeyEndpoints<TUser>(this IEndpointRouteBuilder endpoints)
where TUser : class
{
ArgumentNullException.ThrowIfNull(endpoints);
var accountGroup = endpoints.MapGroup("/Identity/Account").ExcludeFromDescription();
accountGroup.MapPost("/PasskeyCreationOptions", async (
HttpContext context,
[FromServices] UserManager<TUser> userManager,
[FromServices] SignInManager<TUser> signInManager,
[FromServices] IAntiforgery antiforgery) =>
{
await antiforgery.ValidateRequestAsync(context);
var user = await userManager.GetUserAsync(context.User);
if (user is null)
{
return Results.NotFound($"Unable to load user with ID '{userManager.GetUserId(context.User)}'.");
}
var userId = await userManager.GetUserIdAsync(user);
var userName = await userManager.GetUserNameAsync(user) ?? "User";
var optionsJson = await signInManager.MakePasskeyCreationOptionsAsync(new()
{
Id = userId,
Name = userName,
DisplayName = userName
});
return TypedResults.Content(optionsJson, contentType: "application/json");
});
accountGroup.MapPost("/PasskeyRequestOptions", async (
HttpContext context,
[FromServices] UserResolver<TUser> userResolver,
[FromServices] SignInManager<TUser> signInManager,
[FromServices] IAntiforgery antiforgery,
[FromQuery] string username) =>
{
await antiforgery.ValidateRequestAsync(context);
var user = string.IsNullOrWhiteSpace(username) ? null : await userResolver.GetUserAsync(username);
var optionsJson = await signInManager.MakePasskeyRequestOptionsAsync(user);
return TypedResults.Content(optionsJson, contentType: "application/json");
});
return accountGroup;
}
}
}
@@ -0,0 +1,12 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// Modified by Jan Skoruba
namespace LiteCharmsSecurity.STS.Identity.Passkeys
{
public enum PasskeyOperation
{
Create = 0,
Request = 1
}
}
@@ -0,0 +1,87 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// Modified by Jan Skoruba
#nullable enable
using System;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
namespace LiteCharmsSecurity.STS.Identity.Passkeys
{
[HtmlTargetElement("passkey-submit")]
public class PasskeySubmitTagHelper : TagHelper
{
private readonly IHttpContextAccessor _httpContextAccessor;
[HtmlAttributeName("operation")]
public PasskeyOperation Operation { get; set; }
[HtmlAttributeName("name")]
public string Name { get; set; } = null!;
[HtmlAttributeName("email-name")]
public string? EmailName { get; set; }
public PasskeySubmitTagHelper(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
// Get tokens and store the antiforgery cookie so that subsequent passkey fetch requests can be validated
var tokens = _httpContextAccessor.HttpContext?.RequestServices
.GetService<IAntiforgery>()?.GetAndStoreTokens(_httpContextAccessor.HttpContext);
// Button is the main element we want to create, capture all attributes etc.
var buttonAttributes = output.Attributes.Where(it => it.Name != "operation" && it.Name != "name" && it.Name != "email-name").ToList();
var buttonContent = (await output.GetChildContentAsync(NullHtmlEncoder.Default))
.GetContent(NullHtmlEncoder.Default);
// Create the button
using var htmlWriter = new StringWriter();
htmlWriter.Write("<button type=\"submit\" name=\"__passkeySubmit\" ");
foreach (var buttonAttribute in buttonAttributes)
{
buttonAttribute.WriteTo(htmlWriter, NullHtmlEncoder.Default);
htmlWriter.Write(" ");
}
htmlWriter.Write(">");
if (!string.IsNullOrEmpty(buttonContent))
{
htmlWriter.Write(buttonContent);
}
htmlWriter.Write("</button>");
htmlWriter.WriteLine();
// Create the passkey-submit web component element
htmlWriter.Write("<passkey-submit ");
htmlWriter.Write($"operation=\"{Operation}\" ");
htmlWriter.Write($"name=\"{Name}\" ");
htmlWriter.Write($"email-name=\"{EmailName ?? ""}\" ");
htmlWriter.Write($"request-token-name=\"{tokens?.HeaderName ?? ""}\" ");
htmlWriter.Write($"request-token-value=\"{tokens?.RequestToken ?? ""}\" ");
var pathBase = _httpContextAccessor.HttpContext?.Request.PathBase.Value ?? string.Empty;
htmlWriter.Write($"creation-options-url=\"{pathBase}/Identity/Account/PasskeyCreationOptions\" ");
htmlWriter.Write($"request-options-url=\"{pathBase}/Identity/Account/PasskeyRequestOptions\" ");
htmlWriter.Write(">");
htmlWriter.Write("</passkey-submit>");
// Emit the element
output.TagName = null;
output.Attributes.Clear();
output.Content.Clear();
output.Content.SetHtmlContent(htmlWriter.ToString());
await base.ProcessAsync(context, output);
}
}
}
@@ -0,0 +1,97 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using Skoruba.Duende.IdentityServer.Shared.Configuration.Helpers;
namespace LiteCharmsSecurity.STS.Identity
{
public class Program
{
public static void Main(string[] args)
{
var configuration = GetConfiguration(args);
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
DockerHelpers.ApplyDockerConfiguration(configuration);
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
private static IConfiguration GetConfiguration(string[] args)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var isDevelopment = environment == Environments.Development;
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
.AddJsonFile("serilog.json", optional: true, reloadOnChange: true)
.AddJsonFile($"serilog.{environment}.json", optional: true, reloadOnChange: true);
if (isDevelopment)
{
configurationBuilder.AddUserSecrets<Startup>(true);
}
var configuration = configurationBuilder.Build();
configuration.AddAzureKeyVaultConfiguration(configurationBuilder);
configurationBuilder.AddCommandLine(args);
configurationBuilder.AddEnvironmentVariables();
return configurationBuilder.Build();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, configApp) =>
{
var configurationRoot = configApp.Build();
configApp.AddJsonFile("serilog.json", optional: true, reloadOnChange: true);
var env = hostContext.HostingEnvironment;
configApp.AddJsonFile($"serilog.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
configApp.AddUserSecrets<Startup>(true);
}
configurationRoot.AddAzureKeyVaultConfiguration(configApp);
configApp.AddEnvironmentVariables();
configApp.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options => options.AddServerHeader = false);
webBuilder.UseStartup<Startup>();
})
.UseSerilog((hostContext, loggerConfig) =>
{
loggerConfig
.ReadFrom.Configuration(hostContext.Configuration)
.Enrich.WithProperty("ApplicationName", hostContext.HostingEnvironment.ApplicationName);
});
}
}
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44310",
"sslPort": 44310
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"LiteCharmsSecurity.AspNetIdentity": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44310"
}
}
}
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bekræft venligst din email konto ved at &lt;a href='{0}'&gt;klikke her&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bekræft din email konto</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>Brugeren eksisterer ikke eller er ikke bekræftet</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Fejl fra ekstern udbyder: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Ugyldig bekræftelseskode.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Ugyldig gendannelseskode.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Nulstil din adgangskode ved at &lt;a href='{0}'&gt;klikke her&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Nulstil adgangskode</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Kan ikke indlæse totrinsbekræftelse for denne bruger.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bitte den Account bestätigen indem Sie &lt;a href='{0}'&gt;hier klicken&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bestätigen Sie die Email</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>Der Benutzer existiert nicht oder wurde nicht bestätgt</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Fehler von externen Providern: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Ungültiger Authentifizierer-Code.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Ungültiger Wiederherstellungscode eingegeben.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Bitte setzen Sie Ihr Passwort zurück indem Sie &lt;a href='{0}'&gt;hier klicken&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Passwort zurücksetzten</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Benutzer mit Zwei-Faktor-Authentifizierung kann nicht geladen werden.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Please confirm your account by &lt;a href='{0}'&gt;clicking here&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirm your email</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>The user does not exist or is not confirmed</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Error from external provider: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Invalid authenticator code.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Invalid recovery code entered.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Please reset your password by &lt;a href='{0}'&gt;clicking here&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Reset Password</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Unable to load two-factor authentication user.</value>
</data>
</root>
@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Por favor, confirma tu cuenta haciento &lt;a href='{0}'&gt;clic aquí&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirma tu e-mail</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>El usuario no existe o no ha confirmado su cuenta</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Error de proveedor externo: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Código de autenticador invalido.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>El código de recuperación ingresado es invalido.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Por favor, cambia tu contraseña haciendo &lt;a href='{0}'&gt;clic aquí&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Restablecer contraseña</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Fue imposible cargar el usuario de autenticación en dos pasos.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>لطفا حساب خود را تایید کنید با &lt;a href='{0}'&gt;کلیک کردن اینجا&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>ایمیل خود را تایید کنید</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>کاربر وجود ندارد یا تایید نشده است</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>خطا از طرف ارائه دهنده خارجی: {0}}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>کد تایید هویت نامعتبر است.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>کد بازیابی وارد شده نامعتبر است.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>لطفا کلمه عبور خود را تنظیم مجدد کنید با &lt;a href='{0}'&gt;کلیک کردن اینجا&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>تنظیم مجدد کلمه عبور</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>بارگذاری احراز هویت دو-عاملی کاربر امکان پذیر نیست.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Vahvista tilisi napsauttamalla &lt;a href='{0}'&gt; napsauttamalla tätä &lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>vahvista sähköpostiosoitteesi</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>Käyttäjää ei ole tai sitä ei ole vahvistettu</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Ulkoisen palveluntarjoajan virhe: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Virheellinen todennuskoodi.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Annettu virheellinen palautuskoodi.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Palauta salasanasi napsauttamalla &lt;a href='{0}'&gt; napsauttamalla tätä &lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Nollaa salasana</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Kahden tekijän todennuksen käyttäjää ei voi ladata.</value>
</data>
</root>
@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Veuillez confirmer votre compte par &lt;a href='{0}'&gt;en cliquant ici&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirmez votre e-mail</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>L'utilisateur n'existe pas ou n'est pas valide</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Erreur de la part d'un fournisseur externe : {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Code d'authentification invalide.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Code de récupération invalide.</value>
<comment>Code de récupération saisi non valide.</comment>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Veuillez réinitialiser votre mot de passe &lt;a href='{0}'&gt;en cliquant ici&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Réinitialiser le mot de passe</value>
<comment>Réinitialiser Mot de passe</comment>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Impossible de charger l'utilisateur d'authentification à deux facteurs.</value>
</data>
</root>
@@ -0,0 +1,41 @@
<root>
<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.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bevestig a.u.b. uw account door &lt;a href='{0}'&gt;hier te klikken&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bevestig uw email</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>De user bestaat niet of is niet bevestigd</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Fout opgetreden bij externe provider: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Ongeldige authenticator code.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Ongeldige herstel code ingevoerd.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Reset uw wachtwoord a.u.b. door &lt;a href='{0}'&gt;hier te klikken&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Reset wachtwoord</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Kan two-factor authenticatie user niet laden.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Por favor, confirme sua conta &lt;a href='{0}'&gt; clicando aqui&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirme seu e-mail</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>O usuário não existe ou não está confirmado</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Erro do provedor externo: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Código de autenticador inválido.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Código digitado para recuperação é inválido.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Redefina sua senha com &lt;a href='{0}'&gt;clicking here&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Redefinir senha</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Não foi possível carregar o usuário de autenticação de dois fatores.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Пожалуйста, подтвердите вашу учетную запись нажатием &lt;a href='{0}'&gt;на ссылку&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Подтвердите ваш адрес электройнной почты</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>Пользователь не существует или не подтверждён</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Ошибка из внешнего источника: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Неверный код аутентификатора.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Введен неверный год восстановления.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Пожалуйста, сбросьте ваш пароль нажатием &lt;a href='{0}'&gt;на ссылку&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Сброс пароля</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Не удаётся загрузить двухфакторную аутентификацию пользователя.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Verifiera ditt konto genom att &lt;a href='{0}'&gt;klicka här&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Verifiera din e-postadress</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>Användaren finns inte eller så er denne inte verifierad</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>Fel från extern källa: {0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>Felaktig autentiseringskod.</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>Ogiltig återställningskod.</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>Återställ ditt lösenord genom att &lt;a href='{0}'&gt;klicka här&lt;/a&gt;.</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>Återställ lösenord</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>Kunde inte ladda användare via två faktorsautentiering.</value>
</data>
</root>
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>请通过&lt;a href='{0}'&gt;点击此处&lt;/a&gt;确认您的帐户。</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>确认您的电子邮件</value>
</data>
<data name="EmailNotFound" xml:space="preserve">
<value>用户不存在或未确认</value>
</data>
<data name="ErrorExternalProvider" xml:space="preserve">
<value>外部提供程序出错:{0}</value>
</data>
<data name="InvalidAuthenticatorCode" xml:space="preserve">
<value>验证码无效。</value>
</data>
<data name="InvalidRecoveryCode" xml:space="preserve">
<value>输入的恢复码无效。</value>
</data>
<data name="ResetPasswordBody" xml:space="preserve">
<value>请通过&lt;a href='{0}'&gt;点击此处&lt;/a&gt;重置密码。</value>
</data>
<data name="ResetPasswordTitle" xml:space="preserve">
<value>重置密码</value>
</data>
<data name="Unable2FA" xml:space="preserve">
<value>无法加载双因素身份验证用户。</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>Bruger med ID '{0}' har bedt om at få deres personlige data.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Din bekræftelses app er blevet bekræftet.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bekræft venligst din email konto ved at &lt;a href='{0}'&gt;klikke her&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bekræft din email konto</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>Bruger med ID '{0}' har slettet sin bruger.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Kan ikke generere gendannelseskoder til bruger med ID {0}, fordi de ikke har totrinsbekræftelse aktiveret.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Fejl kode</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Der opstod en uventet fejl ved sletning af bruger med ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Der opstod en uventet fejl, da der blev deaktiveret totrinsbekræftelse for bruger med ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Kan ikke generere gendannelseskoder for brugeren, da brugeren ikke har totrinsbekræftelse aktiveret.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Der opstod en uventet fejl ved indlæsning af eksterne login informationer for bruger med ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Der opstod en uventet fejl ved fjernelse af eksternt login til bruger med ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Der opstod en uventet fejl ved indstilling af email til bruger med ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Der opstod en uventet fejl ved indstilling af telefonnummer for bruger med ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Det eksterne login blev tilføjet.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Det eksterne login blev fjernet.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Bekræftelseskoden er ugyldig.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Din adgangskode er blevet ændret.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>Bruger {0} ændrede deres adgangskode succesfuldt.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Adgangskode er ikke korrekt.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Din adgangskode er gemt.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Din profil er blevet opdateret</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>Bruger med ID {0} har deaktiveret totrinsbekræftelse.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Den aktuelle browser er glemt. Når du logger ind igen fra denne browser, bliver du bedt om din bekræftelseskode.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>Bruger med id {0} har nulstillet deres bekræftelsesnøgle.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>Bruger med ID {0} har aktiveret totrinsbekræftelse med en totrinsbekræftelses app.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>Bruger med ID {0} har genereret nye totrinsbekræftelse gendannelseskoder.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Kan ikke indlæse bruger med ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Bekræftelses email er sendt. Tjek venligst din email.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>Benutzer mit ID '{0}' fragt nach persönlichen Daten.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Ihre Authentifizierungsapplikation wurde verifiziert.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bitte bestätigen Sie Ihren Account indem Sie &lt;a href='{0}'&gt;hier klicken&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bestätigen Sie die Email</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>Benutzer mit ID '{0}' hat sich selbst gelöscht.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Kann keine Wiederherstellungscodes für Benutzer mit ID {0} generieren, weil 2FA nicht aktiviert ist.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Code</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Unerwarteter Fehler beim Löschen von Benutzern mit ID {0} aufgetreten.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Unerwarteter Fehler beim abstellen von 2FA des Benutzers mit ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Kann keine Wiederherstellungscodes für Benutzer generieren, da 2FA aktiviert ist.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Unerwarteter Fehler beim Laden externer Anmeldeinformationen für Benutzer mit {0} aufgetreten.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Unerwarteter Fehler beim entfernen des externen Logins von Benutzer mit ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Unerwarteter Fehler beim Setzen der Email des Benutzers mit ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Unerwarteter Fehler beim Setzen der Email der Telefonnummer mit ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Der externe Login wurde hinzugefügt.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Der externe Login wurde entfernt.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Verifizierungscode ist ungültig.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Ihr Passwort wurde geändert.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>Benutzer {0} hat sein Passwort erfolgreich geändert.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Passwort nicht korrekt.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Ihr Passwort wurde gesetzt.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Ihr Profil wurde geupdatet</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>Benutzer mit ID {0} hat 2FA abgeschaltet.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Der aktuelle Browser wurde vergessen. Wenn Sie sich von diesem Browser aus wieder einloggen, werden Sie nach Ihrem 2FA-Code gefragt.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>Benutzer mit ID {0} hat ihren Authentifizierungs-App Key zurückgesetzt.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>Benutzer mit ID {0} hat 2FA mit einer Authentifizierungs-App aktiviert.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>Benutzer mit ID {0} hat neue 2FA Wiederherstellungscodes generiert.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Kann Benutzer mit ID {0} nicht laden.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Verifizierungs-E-Mail gesendet. Bitte überprüfen Sie Ihre E-Mail.</value>
</data>
</root>
@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>User with ID '{0}' asked for their personal data.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Your authenticator app has been verified.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Please confirm your account by &lt;a href='{0}'&gt;clicking here&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirm your email</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>User with ID '{0}' deleted themselves.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Cannot generate recovery codes for user with ID {0} because they do not have 2FA enabled.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Code</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Unexpected error occurred deleting user with ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Unexpected error occured disabling 2FA for user with ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Cannot generate recovery codes for user as they do not have 2FA enabled.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Unexpected error occurred loading external login info for user with ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Unexpected error occurred removing external login for user with ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Unexpected error occurred setting email for user with ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Unexpected error occurred setting phone number for user with ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>The external login was added.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>The external login was removed.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Verification code is invalid.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Your password has been changed.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>User {0} changed their password successfully.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Password not correct.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Your password has been set.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Your profile has been updated</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>User with ID {0} has disabled 2fa.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>User with id {0} has reset their authentication app key.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>User with ID {0} has enabled 2FA with an authenticator app.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>User with ID {0} has generated new 2FA recovery codes.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Unable to load user with ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Verification email sent. Please check your email.</value>
</data>
<data name="PasskeyNotFound" xml:space="preserve">
<value>Could not find the passkey.</value>
</data>
<data name="PasskeyInvalidFormat" xml:space="preserve">
<value>The specified passkey ID had an invalid format.</value>
</data>
<data name="PasskeyDeleted" xml:space="preserve">
<value>The passkey was deleted from your account.</value>
</data>
<data name="PasskeyDeleteFailed" xml:space="preserve">
<value>The passkey could not be deleted from your account.</value>
</data>
<data name="PasskeyAddError" xml:space="preserve">
<value>Could not add a passkey: {0}</value>
</data>
<data name="PasskeyNotProvided" xml:space="preserve">
<value>The browser did not provide a passkey.</value>
</data>
<data name="PasskeyAddFailed" xml:space="preserve">
<value>The passkey could not be added to your account.</value>
</data>
<data name="PasskeyAdded" xml:space="preserve">
<value>The passkey was added to your account. Give it an easy to remember name.</value>
</data>
<data name="PasskeyRenamed" xml:space="preserve">
<value>The passkey was renamed successfully.</value>
</data>
<data name="PasskeyRenameFailed" xml:space="preserve">
<value>The passkey could not be renamed.</value>
</data>
</root>
@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>El usuario con ID '{0}' pregunto por su información personal.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Tu aplicación autenticadora fue verificada.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Por favor, confirma tu cuenta haciendo &lt;a href='{0}'&gt;clic aquí&lt;/a&gt;
.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirma tu e-mail</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>El usuario con ID '{0}' se eliminó a si mismo.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>No se pueden generar los codigos de recuperación para el usuario con ID {0} porque no tienen la autenticación en dos pasos habilitada.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Código</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Ocurrio un error inesperado al tratar de eliminar el usuario con ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Ocurrio un error inesperado al tratar de deshabilitar autenticación en dos pasos para el usuario con ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>No se pudieron generar los codigos de recuperación para el usuario ya que no tiene la autenticación en dos pasos habilitada.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Ocurrio un error inesperado al cargar la información externa de inicio de sesión para el usuario con ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Ocurrio un error inesperado al remover el inicio de sesión externo para el usuario con ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Ocurrio un error inesperado al configurar el e-mail para el usuario con ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Ocurrio un error inesperado al configurar el número de telefono para el usuario con ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>El inicio de sesión externo fue agregado.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>El inicio de sesión externo fue quitado.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>El código de verificación es inválido.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Tu contraseña ha sido cambiada.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>El usuario {0} cambió su contraseña con éxito.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>La contraseña no es correcta.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Tu contraseña ha sido establecida.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Tu perfil ha sido actualizado.</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>El usuario con ID {0} ha desabilitado la autenticación en dos pasos.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>El navegador actual ha sido olvidado. Cuando te autentifiques denuevo desde este navegador se te preguntara con tu código de autenticación en dos pasos.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>El usuario con ID {0} ha restablecido su llave de app de autenticación.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>El usuario con ID {0} ha habilitado la autenticación en dos pasos con una app autenticadora.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>El usuario con ID {0} ha generado nuevos códigos de recuperación de autenticación en dos pasos.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>No es posible cargar el usuario con ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>E-mail de verificación enviado. Por favor, revisa tu bandeja de entrada.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>کاربر با شناسه "{0}" اطلاعات شخصی شان را درخواست کرده است.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>برنامه تایید هویت شما تایید شده است.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>لطفا حساب خود را تایید کنید با &lt;a href='{0}'&gt;کلیک کردن اینجا&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>ایمیل خود را تایید کنید</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>کاربر با شناسه '{0}' حذف شان کرده است.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>نمی توان کدهای بازیابی را برای کاربر با شناسه {0} ایجاد کرد بدلیل اینکه 2FA را فعال نکرده اند.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>کد</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>خطای غیرمنتظره در حذف کاربر با شناسه {0} رخ داده است.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>خطای غیرمنتظره در غیرفعال کردن 2FA برای کاربر با شناسه {0} رخ داده است.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>نمی توان کدهای بازیابی را برای کاربر ایجاد کرد بدلیل اینکه 2FA را فعال نکرده اند.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>در بارگذاری اطلاعات ورود خارجی برای کاربر با شناسه {0} خطای غیرمنتظره رخ داده است.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>در حذف ورود خارجی برای کاربر با شناسه {0} خطای غیرمنتظره رخ داده است.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>خطای غیرمنتظره در تنظیم ایمیل برای کاربر با شناسه {0} رخ داده است.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>خطای غیرمنتظره در تنظیم شماره تلفن برای کاربر با شناسه {0} رخ داده است.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>ورود خارجی اضافه شد.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>ورود خارجی حذف شد.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>کد تایید نامعتبر است.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>کلمه عبور شما تغییر کرده است.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>کاربر {0} کلمه عبور خود را با موفقیت تغییر داد.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>کلمه عبور صحیح نیست.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>کلمه عبور شما تنظیم شده است.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>مشخصات شما به روز شده است</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>کاربر با شناسه {0} 2fa را غیر فعال کرده است.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>مرورگر فعلی فراموش شده است. هنگامی که دوباره از این مرورگر وارد سیستم شوید، از شما کد 2fa خواسته خواهد شد.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>کاربر با شناسه {0} کلید برنامه تایید اعتبار خود را تنظیم مجدد کرده است.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>کاربر با شناسه {0} 2FA را با یک برنامه تایید هویت فعال کرده است.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>کاربر با شناسه {0} کد جدید بازیابی 2FA را ایجاد کرده است.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>بارگذاری کاربر با شناسه {0} امکان پذیر نیست.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>ایمیل تایید ارسال شد. لطفا ایمیل خود را چک کنید.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>Käyttäjä, jonka tunnus '{0}', pyysi henkilökohtaisia tietojaan.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Autentikaattorisovelluksesi on vahvistettu.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Vahvista tilisi napsauttamalla &lt;a href='{0}'&gt; napsauttamalla tätä &lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>vahvista sähköpostiosoitteesi</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>Käyttäjä, jonka tunnus '{0}', poisti itsensä.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Palautuskoodeja ei voi luoda käyttäjälle, jonka tunnus on {0}, koska heillä ei ole 2FA: ta käytössä.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Koodi</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Käyttäjän, jolla on tunnus {0}, poistamisessa tapahtui odottamaton virhe.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Odottamaton virhe tapahtui poistamalla 2FA käytöstä käyttäjälle, jolla on tunnus {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Palautuskoodeja ei voi luoda käyttäjälle, koska heillä ei ole 2FA: ta käytössä.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Odottamaton virhe ladattaessa ulkoista kirjautumistietoa käyttäjälle, jolla on tunnus {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Odottamaton virhe ulkoisen kirjautumisen poistamisessa käyttäjälle, jolla on tunnus {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Asettamalla odottamaton virhe sähköpostin asettamisessa käyttäjälle, jolla on tunnus {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Asettamalla odottamaton virhe puhelinnumeron asettamisessa käyttäjälle, jolla on tunnus {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Ulkoinen kirjautuminen lisättiin.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Ulkoinen sisäänkirjautuminen poistettiin.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Vahvistuskoodi on virheellinen.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Salasanasi on vaihdettu.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>Käyttäjä {0} vaihtoi salasanansa onnistuneesti.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Salasana ei ole oikea.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Salasanasi on asetettu.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Profiilisi on päivitetty</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>Käyttäjätunnuksella {0} on poistettu 2fa käytöstä.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Nykyinen selain on unohdettu. Kun kirjaudut sisään uudelleen tästä selaimesta, sinulta kysytään 2fa-koodiasi.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>Käyttäjä, jonka tunnus on {0}, on nollannut todennussovelluksen avaimen.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>Käyttäjä, jonka tunnus on {0}, on ottanut käyttöön 2FA: n todennussovelluksella.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>Käyttäjä, jonka tunnus on {0}, on luonut uusia 2FA-palautuskoodeja.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Käyttäjää, jolla on tunnus {0}, ei voi ladata.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Varmennusviesti lähetetty. Ole hyvä ja tarkista sähköpostisi.</value>
</data>
</root>
@@ -0,0 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>L'utilisateur avec l'ID '{0}' a demandé ses données personnelles.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Votre application d'authentification a été vérifiée.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Veuillez confirmer votre compte &lt;a href='{0}'&gt;en cliquant ici&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirmez votre e-mail</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>L'utilisateur avec l'ID '{0}' s'est supprimé.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Impossible de générer des codes de récupération pour l'utilisateur avec l'ID {0} car A2F n'est pas activé.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Code</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Une erreur inattendue s'est produite lors de la suppression de l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Une erreur inattendue s'est produite en désactivant A2F pour l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Impossible de générer des codes de récupération pour l'utilisateur car A2F n'est pas activé.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Une erreur inattendue s'est produite lors du chargement des informations de connexion externe de l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Une erreur inattendue s'est produite en supprimant la connexion externe pour l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Une erreur inattendue s'est produite lors du paramétrage de l'e-mail pour l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Une erreur inattendue s'est produite lors du réglage du numéro de téléphone de l'utilisateur avec l'ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Le login externe a été ajouté.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Le login externe a été supprimé.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Le code de vérification n'est pas valide.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Votre mot de passe a été modifié.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>L'utilisateur {0} a modifié son mot de passe avec succès.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Mot de passe incorrect.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Votre mot de passe a été défini.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Votre profil a été mis à jour</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>L'utilisateur avec l'ID {0} a désactivé A2F.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Le navigateur actuel a été oublié. Lorsque vous vous reconnectez à partir de ce navigateur, vous serez invité à entrer votre code A2F.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>L'utilisateur avec l'ID {0} a réinitialisé sa clé d'application d'authentification.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>L'utilisateur avec ID {0} a activé A2F avec une application d'authentification.</value>
<comment>L'utilisateur avec l'ID {0} a activé A2F avec une application d'authentification.</comment>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>L'utilisateur avec ID {0} a généré de nouveaux codes de récupération A2F.</value>
<comment>L'utilisateur avec l'ID {0} a généré de nouveaux codes de récupération A2F.</comment>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Impossible de charger l'utilisateur avec ID {0}.</value>
<comment>Impossible de charger l'utilisateur avec l'ID {0}.</comment>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Envoi d'un e-mail de vérification. Veuillez vérifier vos courriels.</value>
</data>
</root>
@@ -0,0 +1,101 @@
<root>
<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.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>User met ID '{0}' vraagt om zijn persoonlijke data.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Uw authenticator app is geverifieerd.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Bevestig a.u.b. uw account door &lt;a href='{0}'&gt;hier te klikken&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Bevestig uw email</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>User met ID '{0}' heeft zichzelf verwijderd.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Kan geen herstelcodes genereren for user met ID {0} omdat 2FA voor deze user niet geactiveerd is.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Code</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens het verwijderen van user met ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens deactiveren van 2FA voor user met ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Kan geen herstelcodes genereren for user omdat 2FA voor deze user niet geactiveerd is.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens het laden van externe login info voor user met ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens het verwijderen van externe login voor user met ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens het instellen van het emailadres voor user met ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Onverwachte fout opgetreden tijdens het instellen van het telefoonnummer voor user met ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>De externe login is toegevoegd</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>De externe login is verwijderd</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Verificatiecode is ongeldig.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Uw wachtwoord is gewijzigd</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>User {0} heeft zijn wachtwoord succesvol gewijzigd </value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Wachtwoord onjuist</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Uw wachtwoord is ingesteld</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Uw profiel is geupdate</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>User met ID {0} heeft 2FA gedeactiveerd.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>De huidige browser wordt vergeten. Wanneer u opnieuw inlogd met de huidige browser wordt u gevraagd om uw 2FA code.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>User met id {0} heeft zijn authentication app key gereset.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>User met id {0} heeft 2FA geactiveerd met een authenticator app.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>User met ID {0} nieuwe 2FA herstelcodes gegenereerd.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>User met ID {0} kan niet worden geladen.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Bevestigings email verzonden. Controleer a.u.b. uw email.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>O usuário com o ID '{0}' solicitou seus dados pessoais.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Seu aplicativo autenticador foi verificado.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Por favor, confirme sua conta com &lt;a href='{0}'&gt;clicando aqui&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Confirme seu e-mail</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>O usuário com ID'{0}' se excluiu.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Não é possível gerar códigos de recuperação para usuário com ID {0} porque eles não têm 2FA ativado.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Código</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Ocorreu um erro inesperado ao excluir o usuário com ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Ocorreu um erro inesperado ao desativar o 2FA para o usuário com ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Não é possível gerar códigos de recuperação para o usuário, pois eles não têm 2FA ativado.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Ocorreu um erro inesperado ao carregar informações de login externas para o usuário com ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Ocorreu um erro inesperado ao remover o login externo do usuário com ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Ocorreu um erro inesperado ao configurar o e-mail para o usuário com ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Ocorreu um erro inesperado ao configurar o número de telefone do usuário com ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>O login externo foi adicionado.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>O login externo foi removido.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>O código de verificação é inválido.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Sua senha foi alterada.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>O usuário {0} alterou sua senha com sucesso.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Senha incorreta.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Sua senha foi definida.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Seu perfil foi atualizado</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>O usuário com ID {0} desativou 2fa.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>O navegador foi esquecido. Você será solicitado a fornecer seu código 2fa ao fazer login novamente neste navegador.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>O usuário com ID {0} redefiniu a chave do aplicativo de autenticação.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>O usuário com ID {0} ativou o 2fa com um aplicativo autenticador.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>O usuário com ID {0} gerou novos códigos de recuperação 2fa.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Não foi possível carregar o usuário com ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>E-mail de verificação enviado. Por favor, verifique seu e-mail.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>Пользователь с ID '{0}' запросил свою личную информацию.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Приложение аутентификатора проверено.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Пожалуйста, подтвердите вашу учетную запись нажатием &lt;a href='{0}'&gt;на ссылку&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Подтвердите ваш адрес электронной почты</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>Пользователь с ID '{0}' удалился.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Не удается создать коды восстановления для пользователя с ID {0} потому что у них активирована двухфакторная аутентификация.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Код</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Непредвиденная ошибка при удалении пользователя с ID {0}.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Непредвиденная ошибка при отключении двухфакторной аутентификации для пользователя с ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Не удается создать коды восстановления для пользователя потому что двухфакторная аутентификация отключена.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Непредвиденная ошибка при загрузке внешних данных для входа пользователя с ID {0}.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Непредвиденная ошибка при удалении внешнего входа для пользователя с ID {0}.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Произошла непредвиденная ошибка при настройке электронной почты для пользователя с ID {0}.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Произошла непредвиденная ошибка при установке номера телефона для пользователя с ID {0}.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Внешний вход был добавлен.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Внешний вход был удалён.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Неверный проверочный код.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Ваш пароль был изменён.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>Пользователь {0} успешно сменил пароль.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Пароль неверный.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Ваш пароль установлен.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Ваш профиль был обновлён.</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>Пользователь с ID {0} отключил двухфакторную аутентификацию.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Текущий браузер был забыт. При повторном входе в систему из этого браузера вам будет предложено ввести код двухфакторной аутентификации.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>Пользователь с ID {0} сбросил ключ приложения аутентификации.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>Пользоваетль с ID {0} влкючил двухфакторную аутентификацию с приложением проверки подлинности.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>Пользователь с ID {0} сгенерировал новые коды восстановления с двухфакторной аутентификацией.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Невозможно загрузить данные пользователя с ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Подтверждение по электронной почте отправлено. Пожалуйста,проверьте электронную почту.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>Användaren med id '{0}' har efterfrågat sina personuppgifter.</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>Din autentiserings applikation har verifierats.</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>Verifiera ditt konto genom att &lt;a href='{0}'&gt;klicka här&lt;/a&gt;.</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>Verifiera din e-postadress</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>Användaren med id '{0}' har raderat sitt konto.</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>Kan inte generera återställningskoder till användaren med ID {0} för att de inte aktiverat tvåfaktorsautentisering.</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>Felkod</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>Oväntat fel inträffade när användaren med id {0} skulle raderas.</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>Oväntat fel inträffade när tvåfaktorsautentisering skulle inaktiveras för användare med ID {0}.</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>Kan inte generera återställningskoder för att användaren inte har tvåfaktorsautentisering aktiverat.</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>Oväntatfel inträffade när information om den externa inloggningen till användaren med ID {0} skulle laddas.</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>Oväntat fel inträffade när den externa inloggningen till användar med ID {0} skulle tas bort.</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>Oväntat fel inträffade när e-post addressen till användare med ID {0} skulle sparas.</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>Oväntat fel inträffade när telefonnummer till användare med ID {0} skulle sparas.</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>Den extarna inloggningen har lagts till.</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>Den externa inloggningen har tagitsbort.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Verifieringskoden är felaktig.</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>Ditt lösenord har ändrats.</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>Användaren {0} har ändrat sitt lösenord.</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>Lösenordet är felaktigt.</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>Ditt lösenord har sparats.</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>Din profil har uppdaterats</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>Användaren med ID {0} har inaktiverat tvåfaktorsautnetisering.</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>Denna webbläsaren är nu bort glömd. Nästa gång du loggar in med denna webbläsare är du tvungen att logga in med tvåfaktorsautentisering igen.</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>Användare med ID {0} har resetat sig authentiseringapp nyckel.</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>Användare med ID {0} har aktiverat tvåfaktorsautentisering via en autentiseringsapp.</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>Användare med ID {0} har genererat nya tvåfaktorsautentiseringsåterställningskoder.</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>Kunde inte ladda använare med ID {0}.</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>Verifierings p-post har skickats. Vänligen kontrollera din e-post.</value>
</data>
</root>
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AskForPersonalDataLog" xml:space="preserve">
<value>ID 为 '{0}' 的用户询问了他的个人数据。</value>
</data>
<data name="AuthenticatorVerified" xml:space="preserve">
<value>您的身份验证器应用已经过验证。</value>
</data>
<data name="ConfirmEmailBody" xml:space="preserve">
<value>请通过&lt;a href='{0}'&gt;点击此处&lt;/a&gt;确认您的帐户。</value>
</data>
<data name="ConfirmEmailTitle" xml:space="preserve">
<value>确认您的电子邮件</value>
</data>
<data name="DeletePersonalData" xml:space="preserve">
<value>ID 为 '{0}' 的用户自行删除。</value>
</data>
<data name="Error2FANotEnabled" xml:space="preserve">
<value>无法为 ID 为 {0} 的用户生成恢复码,因为他没有启用2FA。</value>
</data>
<data name="ErrorCode" xml:space="preserve">
<value>代码</value>
</data>
<data name="ErrorDeletingUser" xml:space="preserve">
<value>删除 ID 为 {0} 的用户时发生意外错误。</value>
</data>
<data name="ErrorDisable2FA" xml:space="preserve">
<value>禁用 ID 为 {0} 的用户 2FA 时发生意外错误。</value>
</data>
<data name="ErrorGenerateCodesWithout2FA" xml:space="preserve">
<value>无法为用户生成恢复代码,因为他没有启用 2FA。</value>
</data>
<data name="ErrorLoadingExternalLogin" xml:space="preserve">
<value>为 ID 为 {0} 的用户加载外部登录信息时发生意外错误。</value>
</data>
<data name="ErrorRemovingExternalLogin" xml:space="preserve">
<value>删除 ID 为 {0} 的用户的外部登录时发生意外错误。</value>
</data>
<data name="ErrorSettingEmail" xml:space="preserve">
<value>为 ID 为 {0} 的用户设置电子邮件时发生意外错误。</value>
</data>
<data name="ErrorSettingPhone" xml:space="preserve">
<value>为 ID 为 {0} 的用户设置电话号码时发生意外错误。</value>
</data>
<data name="ExternalLoginAdded" xml:space="preserve">
<value>外部登录已添加。</value>
</data>
<data name="ExternalLoginRemoved" xml:space="preserve">
<value>外部登录已删除。</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>验证码无效。</value>
</data>
<data name="PasswordChanged" xml:space="preserve">
<value>您的密码已被更改。</value>
</data>
<data name="PasswordChangedLog" xml:space="preserve">
<value>用户 {0} 已成功更改其密码。</value>
</data>
<data name="PasswordNotCorrect" xml:space="preserve">
<value>密码不正确。</value>
</data>
<data name="PasswordSet" xml:space="preserve">
<value>您的密码已设置。</value>
</data>
<data name="ProfileUpdated" xml:space="preserve">
<value>你的个人资料已经更新</value>
</data>
<data name="SuccessDisabled2FA" xml:space="preserve">
<value>ID 为 {0} 的用户已禁用 2fa。</value>
</data>
<data name="SuccessForgetBrowser2FA" xml:space="preserve">
<value>目前的浏览器已被遗忘。 当您从此浏览器再次登录时,系统将提示您输入 2fa 代码。</value>
</data>
<data name="SuccessResetAuthenticationKey" xml:space="preserve">
<value>ID 为 {0} 的用户已重置其身份验证应用密钥。</value>
</data>
<data name="SuccessUserEnabled2FA" xml:space="preserve">
<value>ID 为 {0} 的用户已使用身份验证器应用启用了 2FA。</value>
</data>
<data name="UserGenerated2FACodes" xml:space="preserve">
<value>ID 为 {0} 的用户已生成新的 FA 恢复代码。</value>
</data>
<data name="UserNotFound" xml:space="preserve">
<value>无法加载 ID 为 {0} 的用户。</value>
</data>
<data name="VerificationSent" xml:space="preserve">
<value>已发送验证邮件。 请检查您的电子邮件。</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Tak for bekræftelsen af ​​din email.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Bekræft email</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Danke für das bestätigen Ihrer Email.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Email bestätigen</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Thank you for confirming your email.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Confirm email</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Gracias por confirmar tu e-mail.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Confirmar e-mail</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>از تایید ایمیل خود متشکریم.</value>
</data>
<data name="Title" xml:space="preserve">
<value>ایمیل تایید</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Kiitos sähköpostiviestisi vahvistamisesta.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Vahvista sähköposti</value>
</data>
</root>
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Merci d'avoir confirmé votre e-mail.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Confirmation e-mail</value>
<comment>Confirmer l'e-mail</comment>
</data>
</root>
@@ -0,0 +1,20 @@
<root>
<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.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Dank u voor het bevestigen van uw email.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Bevestig email</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Obrigado por confirmar seu e-mail.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Confirmar e-mail</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Спасибо за подтверждение вашей электронной почты.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Подтвердить электронную почту</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>Tack för att du verifierat din e-postaddress.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Verifiera e-postadress</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConfirmMessage" xml:space="preserve">
<value>感谢您确认电子邮件。</value>
</data>
<data name="Title" xml:space="preserve">
<value>确认邮件</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>Du har godkendt med {0}.
Indtast en email adresse for dette websted nedenfor og klik på knappen Registrer for at afslutte
log ind.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Registrer</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Tilknyt din {0} konto.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Registrer</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Brugernavn</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>Sie haben sich erfolgreich mit {0} authentifiziert.
Bitte geben Sie unten eine E-Mail-Adresse für diese Website ein und klicken Sie auf die Schaltfläche Registrieren, um den Vorgang abzuschließen
Einloggen.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Registrieren</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Verknüpfen Sie Ihr {0} Account.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Registrieren</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Benutzername</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>You've successfully authenticated with {0}.
Please enter an email address for this site below and click the Register button to finish
logging in.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Register</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Associate your {0} account.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Register</value>
</data>
<data name="UserName" xml:space="preserve">
<value>UserName</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>Te has autentificado de manera exitosa con {0}.
Por favor, ingresa una dirección de correo electrónico para este sitio debajo y has clic en el boton Register para terminar de
iniciar sesión.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Regístrate</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Asocia tu {0} cuenta.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Regístrate</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Nombre de usuario</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>You've successfully authenticated with {0}.
Please enter an email address for this site below and click the Register button to finish
logging in.</value>
</data>
<data name="Register" xml:space="preserve">
<value>ثبت نام</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>{0} حساب شما متصل کنید.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Register</value>
</data>
<data name="UserName" xml:space="preserve">
<value>شناسه کاربری</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Sähköposti</value>
</data>
<data name="Info" xml:space="preserve">
<value>Olet todennut {0} onnistuneesti.
        Kirjoita tämän sivuston sähköpostiosoite alle ja napsauta Rekisteröi-painiketta viimeistelläksesi
        Kirjaudu sisään.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Rekisteröidy</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Yhdistä {0} -tilisi.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Rekisteröidy</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Käyttäjänimi</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>E-mail</value>
</data>
<data name="Info" xml:space="preserve">
<value>Vous avez réussi à vous authentifier avec {0}.
Veuillez entrer une adresse e-mail pour ce site ci-dessous et cliquez sur le bouton S'inscrire pour terminer
de vous connecter.</value>
</data>
<data name="Register" xml:space="preserve">
<value>S'inscrire</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Associez votre compte {0}.</value>
</data>
<data name="Title" xml:space="preserve">
<value>S'inscrire</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Nom d'utilisateur</value>
</data>
</root>
@@ -0,0 +1,34 @@
<root>
<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.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>Je bent succesvol geautenticeerd met {0}.
Voer uw email-adres in voor de site hieronder en klik de Registreer button om af te ronden
aan het inloggen.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Registreer</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Associeer uw {0} account.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Registreer</value>
</data>
<data name="UserName" xml:space="preserve">
<value>UserName</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>E-mail</value>
</data>
<data name="Info" xml:space="preserve">
<value>Você foi autenticado com sucesso {0}.
Por favor, insira um endereço de e-mail para este site abaixo e clique no botão Registrar para finalizar
logging in.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Registro</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Associe sua {0} conta.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Registro</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Nome de usuário</value>
</data>
</root>
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Адрес электронной почты</value>
</data>
<data name="Info" xml:space="preserve">
<value>Вы успешно прошли аутентификацию {0}.
Пожалуйста, введите адрес электронной почты для этого сайта ниже и нажмите на кнопку Регистрация для завершения входа в систему.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Регистрация</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Привязка вашей учетной записи {0}.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Регистрация</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Имя пользователя</value>
</data>
</root>
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>E-post</value>
</data>
<data name="Info" xml:space="preserve">
<value>Du har lyckats autensiera dig med {0}.
Vänligen ange en e-postadress för sajten nedan och klicka sedan på Registrera knappen för att avsluta
inloggningen.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Registrera</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>Associera ditt {0} konto.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Registrera</value>
</data>
<data name="UserName" xml:space="preserve">
<value>Användarnamn</value>
</data>
</root>
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Email" xml:space="preserve">
<value>Email</value>
</data>
<data name="Info" xml:space="preserve">
<value>您已使用 {0} 成功通过身份验证。
请在下面输入此站点的电子邮件地址,然后单击“注册”按钮完成登录。</value>
</data>
<data name="Register" xml:space="preserve">
<value>注册</value>
</data>
<data name="SubTitle" xml:space="preserve">
<value>关联您的 {0} 帐户。</value>
</data>
<data name="Title" xml:space="preserve">
<value>注册</value>
</data>
<data name="UserName" xml:space="preserve">
<value>用户名</value>
</data>
</root>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Error" xml:space="preserve">
<value>Mislykket login med service.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Login fejl</value>
</data>
</root>

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