mirror of
https://github.com/bitwarden/server.git
synced 2025-02-16 01:51:21 +01:00
Added PreValidate endpoint on Account controller (#896)
* Added PreValidate endpoint on Account controller * Fixed IHttpClientFactory implementation * Core localization and org sproc fix * Pass culture, fixed sso middleware bug
This commit is contained in:
parent
303b9a7875
commit
db7d05b52f
@ -110,6 +110,7 @@ namespace Bit.Api
|
||||
// Services
|
||||
services.AddBaseServices();
|
||||
services.AddDefaultServices(globalSettings);
|
||||
services.AddCoreLocalizationServices();
|
||||
|
||||
// MVC
|
||||
services.AddMvc(config =>
|
||||
@ -162,6 +163,9 @@ namespace Bit.Api
|
||||
app.UseForwardedHeaders(globalSettings);
|
||||
}
|
||||
|
||||
// Add localization
|
||||
app.UseCoreLocalization();
|
||||
|
||||
// Add static files to the request pipeline.
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
@ -60,4 +60,8 @@
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
5
src/Core/Properties/AssemblyInfo.cs
Normal file
5
src/Core/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,5 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
[assembly: ResourceLocation("Resources")]
|
||||
[assembly: RootNamespace("Bit.Core")]
|
@ -26,6 +26,7 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
{
|
||||
var results = await connection.QueryAsync<Organization>(
|
||||
"[dbo].[Organization_ReadByIdentifier]",
|
||||
new { Identifier = identifier },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results.SingleOrDefault();
|
||||
|
8
src/Core/Resources/SharedResources.cs
Normal file
8
src/Core/Resources/SharedResources.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.Core.Resources
|
||||
{
|
||||
public class SharedResources
|
||||
{
|
||||
}
|
||||
}
|
415
src/Core/Resources/SharedResources.en.resx
Normal file
415
src/Core/Resources/SharedResources.en.resx
Normal file
@ -0,0 +1,415 @@
|
||||
<?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="Home" xml:space="preserve">
|
||||
<value>Home</value>
|
||||
<comment>Home page</comment>
|
||||
</data>
|
||||
<data name="Policies" xml:space="preserve">
|
||||
<value>Policies</value>
|
||||
</data>
|
||||
<data name="Enabled" xml:space="preserve">
|
||||
<value>Enabled</value>
|
||||
</data>
|
||||
<data name="TwoStepLogin" xml:space="preserve">
|
||||
<value>Two-step Login</value>
|
||||
</data>
|
||||
<data name="TwoStepLoginDescription" xml:space="preserve">
|
||||
<value>Require users to set up two-step login on their personal accounts.</value>
|
||||
</data>
|
||||
<data name="MasterPassword" xml:space="preserve">
|
||||
<value>Master Password</value>
|
||||
</data>
|
||||
<data name="MasterPasswordDescription" xml:space="preserve">
|
||||
<value>Set minimum requirements for master password strength.</value>
|
||||
</data>
|
||||
<data name="PasswordGenerator" xml:space="preserve">
|
||||
<value>Password Generator</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorDescription" xml:space="preserve">
|
||||
<value>Set minimum requirements for password generator configuration.</value>
|
||||
</data>
|
||||
<data name="EditPolicy" xml:space="preserve">
|
||||
<value>Edit Policy - {0}</value>
|
||||
</data>
|
||||
<data name="EditPolicyTwoStepLoginWarning" xml:space="preserve">
|
||||
<value>Organization members who do not have two-step login enabled for their personal account will be removed from the organization and will receive an email notifying them about the change.</value>
|
||||
</data>
|
||||
<data name="Save" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="MinimumComplexityScore" xml:space="preserve">
|
||||
<value>Minimum Complexity Score</value>
|
||||
</data>
|
||||
<data name="MinimumLength" xml:space="preserve">
|
||||
<value>Minimum Length</value>
|
||||
</data>
|
||||
<data name="Weak" xml:space="preserve">
|
||||
<value>Weak</value>
|
||||
</data>
|
||||
<data name="Good" xml:space="preserve">
|
||||
<value>Good</value>
|
||||
</data>
|
||||
<data name="Strong" xml:space="preserve">
|
||||
<value>Strong</value>
|
||||
</data>
|
||||
<data name="DefaultType" xml:space="preserve">
|
||||
<value>Default Type</value>
|
||||
</data>
|
||||
<data name="UserPreference" xml:space="preserve">
|
||||
<value>User Preference</value>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="Passphrase" xml:space="preserve">
|
||||
<value>Passphrase</value>
|
||||
</data>
|
||||
<data name="MinimumSpecial" xml:space="preserve">
|
||||
<value>Minimum Special</value>
|
||||
</data>
|
||||
<data name="MinimumNumbers" xml:space="preserve">
|
||||
<value>Minimum Numbers</value>
|
||||
</data>
|
||||
<data name="MinimumNumberOfWords" xml:space="preserve">
|
||||
<value>Minimum Number of Words</value>
|
||||
</data>
|
||||
<data name="Capitalize" xml:space="preserve">
|
||||
<value>Capitalize</value>
|
||||
</data>
|
||||
<data name="IncludeNumber" xml:space="preserve">
|
||||
<value>Include Number</value>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="UppercaseAZ" xml:space="preserve">
|
||||
<value>A-Z</value>
|
||||
</data>
|
||||
<data name="LowercaseAZ" xml:space="preserve">
|
||||
<value>a-z</value>
|
||||
</data>
|
||||
<data name="Numbers09" xml:space="preserve">
|
||||
<value>0-9</value>
|
||||
</data>
|
||||
<data name="SpecialCharacters" xml:space="preserve">
|
||||
<value>!@#$%^&*</value>
|
||||
</data>
|
||||
<data name="Select" xml:space="preserve">
|
||||
<value>Select</value>
|
||||
</data>
|
||||
<data name="MasterPasswordMinLengthError" xml:space="preserve">
|
||||
<value>The field {0} must be greater than or equal to {1}.</value>
|
||||
</data>
|
||||
<data name="SingleSignOn" xml:space="preserve">
|
||||
<value>Single Sign-On</value>
|
||||
</data>
|
||||
<data name="EditSsoConfig" xml:space="preserve">
|
||||
<value>Edit SSO Configuration</value>
|
||||
</data>
|
||||
<data name="ConfigType" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="OpenIdConnect" xml:space="preserve">
|
||||
<value>OpenID Connect</value>
|
||||
</data>
|
||||
<data name="Saml2" xml:space="preserve">
|
||||
<value>SAML 2.0</value>
|
||||
</data>
|
||||
<data name="SsoConfig" xml:space="preserve">
|
||||
<value>SSO Configuration</value>
|
||||
</data>
|
||||
<data name="OpenIdConnectConfig" xml:space="preserve">
|
||||
<value>OpenID Connect Configuration</value>
|
||||
</data>
|
||||
<data name="Authority" xml:space="preserve">
|
||||
<value>Authority</value>
|
||||
</data>
|
||||
<data name="ClientId" xml:space="preserve">
|
||||
<value>Client ID</value>
|
||||
</data>
|
||||
<data name="ClientSecret" xml:space="preserve">
|
||||
<value>Client Secret</value>
|
||||
</data>
|
||||
<data name="CallbackPath" xml:space="preserve">
|
||||
<value>Callback Path</value>
|
||||
</data>
|
||||
<data name="SignedOutCallbackPath" xml:space="preserve">
|
||||
<value>Signed Out Callback Path</value>
|
||||
</data>
|
||||
<data name="SamlSpConfig" xml:space="preserve">
|
||||
<value>SAML Service Provider Configuration</value>
|
||||
</data>
|
||||
<data name="EntityId" xml:space="preserve">
|
||||
<value>Entity ID</value>
|
||||
</data>
|
||||
<data name="SpEntityId" xml:space="preserve">
|
||||
<value>SP Entity ID</value>
|
||||
</data>
|
||||
<data name="NameIdFormat" xml:space="preserve">
|
||||
<value>Name ID Format</value>
|
||||
</data>
|
||||
<data name="NotConfigured" xml:space="preserve">
|
||||
<value>Not Configured</value>
|
||||
</data>
|
||||
<data name="Unspecified" xml:space="preserve">
|
||||
<value>Unspecified</value>
|
||||
</data>
|
||||
<data name="EmailAddress" xml:space="preserve">
|
||||
<value>Email Address</value>
|
||||
</data>
|
||||
<data name="X509SubjectName" xml:space="preserve">
|
||||
<value>X.509 Subject Name</value>
|
||||
</data>
|
||||
<data name="WindowsDomainQualifiedName" xml:space="preserve">
|
||||
<value>Windows Domain Qualified Name</value>
|
||||
</data>
|
||||
<data name="KerberosPrincipalName" xml:space="preserve">
|
||||
<value>Kerberos Principal Name</value>
|
||||
</data>
|
||||
<data name="EntityIdentifier" xml:space="preserve">
|
||||
<value>Entity Identifier</value>
|
||||
</data>
|
||||
<data name="Persistent" xml:space="preserve">
|
||||
<value>Persistent</value>
|
||||
</data>
|
||||
<data name="Transient" xml:space="preserve">
|
||||
<value>Transient</value>
|
||||
</data>
|
||||
<data name="PrivateKey" xml:space="preserve">
|
||||
<value>Private Key</value>
|
||||
</data>
|
||||
<data name="SamlIdpConfig" xml:space="preserve">
|
||||
<value>SAML Identity Provider Configuration</value>
|
||||
</data>
|
||||
<data name="SingleSignOnServiceUrl" xml:space="preserve">
|
||||
<value>Single Sign On Service URL</value>
|
||||
</data>
|
||||
<data name="SingleLogoutServiceUrl" xml:space="preserve">
|
||||
<value>Single Log Out Service URL</value>
|
||||
</data>
|
||||
<data name="PublicKey" xml:space="preserve">
|
||||
<value>Public Key</value>
|
||||
</data>
|
||||
<data name="SpWantAssertionsSigned" xml:space="preserve">
|
||||
<value>Sign Assertions</value>
|
||||
</data>
|
||||
<data name="SigningAlgorithm" xml:space="preserve">
|
||||
<value>Signing Algorithm</value>
|
||||
</data>
|
||||
<data name="SigningBehavior" xml:space="preserve">
|
||||
<value>Signing Behavior</value>
|
||||
</data>
|
||||
<data name="BindingType" xml:space="preserve">
|
||||
<value>Binding Type</value>
|
||||
</data>
|
||||
<data name="ArtifactResolutionServiceUrl" xml:space="preserve">
|
||||
<value>Artifact Resolution Service URL</value>
|
||||
</data>
|
||||
<data name="X509PublicCert" xml:space="preserve">
|
||||
<value>X509 Public Certificate</value>
|
||||
</data>
|
||||
<data name="OutboundSigningAlgorithm" xml:space="preserve">
|
||||
<value>Outbound Signing Algorithm</value>
|
||||
</data>
|
||||
<data name="AllowUnsolicitedAuthnResponse" xml:space="preserve">
|
||||
<value>Allow Unsolicited Authentication Response</value>
|
||||
</data>
|
||||
<data name="DisableOutboundLogoutRequests" xml:space="preserve">
|
||||
<value>Disable Outbound Logout Requests</value>
|
||||
</data>
|
||||
<data name="WantAuthnRequestsSigned" xml:space="preserve">
|
||||
<value>Want Authentication Requests Signed</value>
|
||||
</data>
|
||||
<data name="MetadataAddress" xml:space="preserve">
|
||||
<value>Metadata Address</value>
|
||||
</data>
|
||||
<data name="GetClaimsFromUserInfoEndpoint" xml:space="preserve">
|
||||
<value>Get Claims From User Info Endpoint</value>
|
||||
</data>
|
||||
<data name="AuthorityValidationError" xml:space="preserve">
|
||||
<value>The Authority field is required on a Open ID Connect configuration.</value>
|
||||
</data>
|
||||
<data name="ClientIdValidationError" xml:space="preserve">
|
||||
<value>The Client ID field is required on a Open ID Connect configuration.</value>
|
||||
</data>
|
||||
<data name="ClientSecretValidationError" xml:space="preserve">
|
||||
<value>The Client Secret field is required on a Open ID Connect configuration.</value>
|
||||
</data>
|
||||
<data name="CallbackPathValidationError" xml:space="preserve">
|
||||
<value>The Callback Path field is required on a Open ID Connect configuration.</value>
|
||||
</data>
|
||||
<data name="SpEntityIdValidationError" xml:space="preserve">
|
||||
<value>The Service Provider Configuration Entity Id field is required on a SAML configuration.</value>
|
||||
</data>
|
||||
<data name="IdpEntityIdValidationError" xml:space="preserve">
|
||||
<value>The Identity Provider Configuration Entity Id field is required on a SAML configuration.</value>
|
||||
</data>
|
||||
<data name="Saml2SigningBehaviorValidationError" xml:space="preserve">
|
||||
<value>If SAML Signing Behavior is set to never, public and private service provider keys are required.</value>
|
||||
</data>
|
||||
<data name="Saml2BindingTypeValidationError" xml:space="preserve">
|
||||
<value>If SAML Binding Type is set to artifact, identity provider resolution service URL is required.</value>
|
||||
</data>
|
||||
<data name="IdpSingleSignOnServiceUrlValidationError" xml:space="preserve">
|
||||
<value>If Identity Provider Entity ID is not a URL, single sign on service URL is required.</value>
|
||||
</data>
|
||||
<data name="InvalidSchemeConfigurationError" xml:space="preserve">
|
||||
<value>The configured authentication scheme is not valid: "{0}"</value>
|
||||
</data>
|
||||
<data name="NoSchemeOrHandlerForSsoConfigurationFoundError" xml:space="preserve">
|
||||
<value>No scheme or handler for this SSO configuration found.</value>
|
||||
</data>
|
||||
<data name="SsoNotEnabledForOrganizationError" xml:space="preserve">
|
||||
<value>SSO is not yet enabled for this organization.</value>
|
||||
</data>
|
||||
<data name="SsoConfigurationNotFoundForOrganizationError" xml:space="preserve">
|
||||
<value>No SSO configuration exists for this organization.</value>
|
||||
</data>
|
||||
<data name="SsoNotAllowedForOrganizationError" xml:space="preserve">
|
||||
<value>SSO is not allowed for this organization.</value>
|
||||
</data>
|
||||
<data name="OrganizationNotFoundByIdentifierError" xml:space="preserve">
|
||||
<value>Organization not found from identifier.</value>
|
||||
</data>
|
||||
<data name="NoOrganizationIdentifierProvidedError" xml:space="preserve">
|
||||
<value>No organization identifier provided.</value>
|
||||
</data>
|
||||
<data name="InvalidAuthenticationOptionsForSaml2SchemeError" xml:space="preserve">
|
||||
<value>Invalid authentication options provided to SAML2 scheme.</value>
|
||||
</data>
|
||||
<data name="InvalidAuthenticationOptionsForOidcSchemeError" xml:space="preserve">
|
||||
<value>Invalid authentication options provided to OpenID Connect scheme.</value>
|
||||
</data>
|
||||
<data name="PostConfigurationNotExecutedError" xml:space="preserve">
|
||||
<value>Post configuration not executed against OpenID Connect scheme.</value>
|
||||
</data>
|
||||
<data name="ReadingOpenIdConnectMetadataFailedError" xml:space="preserve">
|
||||
<value>Reading OpenID Connect metadata failed.</value>
|
||||
</data>
|
||||
<data name="NoOpenIdConnectMetadataError" xml:space="preserve">
|
||||
<value>No OpenID Connect metadata could be found or loaded.</value>
|
||||
</data>
|
||||
<data name="PreValidationError" xml:space="preserve">
|
||||
<value>Error performing pre validation.</value>
|
||||
</data>
|
||||
</root>
|
@ -5,6 +5,7 @@ namespace Bit.Core.Services
|
||||
public interface II18nService
|
||||
{
|
||||
LocalizedString GetLocalizedHtmlString(string key);
|
||||
LocalizedString GetLocalizedHtmlString(string key, params object[] args);
|
||||
string Translate(string key, params object[] args);
|
||||
string T(string key, params object[] args);
|
||||
}
|
||||
|
38
src/Core/Services/Implementations/I18nService.cs
Normal file
38
src/Core/Services/Implementations/I18nService.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Bit.Core.Resources;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class I18nService : II18nService
|
||||
{
|
||||
private readonly IStringLocalizer _localizer;
|
||||
|
||||
public I18nService(IStringLocalizerFactory factory)
|
||||
{
|
||||
var assemblyName = new AssemblyName(typeof(SharedResources).GetTypeInfo().Assembly.FullName);
|
||||
_localizer = factory.Create("SharedResources", assemblyName.Name);
|
||||
}
|
||||
|
||||
public LocalizedString GetLocalizedHtmlString(string key)
|
||||
{
|
||||
return _localizer[key];
|
||||
}
|
||||
|
||||
public LocalizedString GetLocalizedHtmlString(string key, params object[] args)
|
||||
{
|
||||
return _localizer[key, args];
|
||||
}
|
||||
|
||||
public string Translate(string key, params object[] args)
|
||||
{
|
||||
return string.Format(GetLocalizedHtmlString(key).ToString(), args);
|
||||
}
|
||||
|
||||
public string T(string key, params object[] args)
|
||||
{
|
||||
return Translate(key, args);
|
||||
}
|
||||
}
|
||||
}
|
37
src/Core/Services/Implementations/I18nViewLocalizer.cs
Normal file
37
src/Core/Services/Implementations/I18nViewLocalizer.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Bit.Core.Resources;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class I18nViewLocalizer : IViewLocalizer
|
||||
{
|
||||
private readonly IStringLocalizer _stringLocalizer;
|
||||
private readonly IHtmlLocalizer _htmlLocalizer;
|
||||
|
||||
public I18nViewLocalizer(IStringLocalizerFactory stringFactory,
|
||||
IHtmlLocalizerFactory htmlFactory)
|
||||
{
|
||||
var assemblyName = new AssemblyName(typeof(SharedResources).GetTypeInfo().Assembly.FullName);
|
||||
_stringLocalizer = stringFactory.Create("SharedResources", assemblyName.Name);
|
||||
_htmlLocalizer = htmlFactory.Create("SharedResources", assemblyName.Name);
|
||||
}
|
||||
|
||||
public LocalizedHtmlString this[string name] => _htmlLocalizer[name];
|
||||
public LocalizedHtmlString this[string name, params object[] args] => _htmlLocalizer[name, args];
|
||||
|
||||
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) =>
|
||||
_stringLocalizer.GetAllStrings(includeParentCultures);
|
||||
|
||||
public LocalizedString GetString(string name) => _stringLocalizer[name];
|
||||
public LocalizedString GetString(string name, params object[] arguments) =>
|
||||
_stringLocalizer[name, arguments];
|
||||
|
||||
[Obsolete("This method is obsolete. Use `CurrentCulture` and `CurrentUICulture` instead.")]
|
||||
public IHtmlLocalizer WithCulture(CultureInfo culture) => _htmlLocalizer.WithCulture(culture);
|
||||
}
|
||||
}
|
@ -32,6 +32,9 @@ using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Azure.Storage;
|
||||
using System.Reflection;
|
||||
using Bit.Core.Resources;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
|
||||
namespace Bit.Core.Utilities
|
||||
{
|
||||
@ -453,5 +456,32 @@ namespace Bit.Core.Utilities
|
||||
}
|
||||
app.UseForwardedHeaders(options);
|
||||
}
|
||||
|
||||
public static void AddCoreLocalizationServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<II18nService, I18nService>();
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseCoreLocalization(this IApplicationBuilder app)
|
||||
{
|
||||
var supportedCultures = new[] { "en" };
|
||||
return app.UseRequestLocalization(options => options
|
||||
.SetDefaultCulture(supportedCultures[0])
|
||||
.AddSupportedCultures(supportedCultures)
|
||||
.AddSupportedUICultures(supportedCultures));
|
||||
}
|
||||
|
||||
public static IMvcBuilder AddViewAndDataAnnotationLocalization(this IMvcBuilder mvc)
|
||||
{
|
||||
mvc.Services.AddTransient<IViewLocalizer, I18nViewLocalizer>();
|
||||
return mvc.AddViewLocalization(options => options.ResourcesPath = "Resources")
|
||||
.AddDataAnnotationsLocalization(options =>
|
||||
options.DataAnnotationLocalizerProvider = (type, factory) =>
|
||||
{
|
||||
var assemblyName = new AssemblyName(typeof(SharedResources).GetTypeInfo().Assembly.FullName);
|
||||
return factory.Create("SharedResources", assemblyName.Name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Identity.Models;
|
||||
@ -7,13 +8,15 @@ using IdentityServer4;
|
||||
using IdentityServer4.Services;
|
||||
using IdentityServer4.Stores;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -26,21 +29,63 @@ namespace Bit.Identity.Controllers
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
private readonly ISsoConfigRepository _ssoConfigRepository;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly IHttpClientFactory _clientFactory;
|
||||
|
||||
public AccountController(
|
||||
IClientStore clientStore,
|
||||
IIdentityServerInteractionService interaction,
|
||||
ILogger<AccountController> logger,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
ISsoConfigRepository ssoConfigRepository,
|
||||
IUserRepository userRepository,
|
||||
IUserService userService)
|
||||
IOrganizationRepository organizationRepository,
|
||||
IHttpClientFactory clientFactory)
|
||||
{
|
||||
_clientStore = clientStore;
|
||||
_interaction = interaction;
|
||||
_logger = logger;
|
||||
_ssoConfigRepository = ssoConfigRepository;
|
||||
_userRepository = userRepository;
|
||||
_organizationRepository = organizationRepository;
|
||||
_clientFactory = clientFactory;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> PreValidate(string domainHint)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(domainHint))
|
||||
{
|
||||
Response.StatusCode = 400;
|
||||
return Json(new ErrorResponseModel("No domain hint was provided"));
|
||||
}
|
||||
try
|
||||
{
|
||||
// Calls Sso Pre-Validate, assumes baseUri set
|
||||
var requestCultureFeature = Request.HttpContext.Features.Get<IRequestCultureFeature>();
|
||||
var culture = requestCultureFeature.RequestCulture.Culture.Name;
|
||||
var requestPath = $"/Account/PreValidate?domainHint={domainHint}&culture={culture}";
|
||||
var httpClient = _clientFactory.CreateClient("InternalSso");
|
||||
using var responseMessage = await httpClient.GetAsync(requestPath);
|
||||
if (responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
// All is good!
|
||||
return new EmptyResult();
|
||||
}
|
||||
Response.StatusCode = (int)responseMessage.StatusCode;
|
||||
var responseJson = await responseMessage.Content.ReadAsStringAsync();
|
||||
return Content(responseJson, "application/json");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error pre-validating against SSO service");
|
||||
Response.StatusCode = 500;
|
||||
return Json(new ErrorResponseModel("Error pre-validating SSO authentication")
|
||||
{
|
||||
ExceptionMessage = ex.Message,
|
||||
ExceptionStackTrace = ex.StackTrace,
|
||||
InnerExceptionMessage = ex.InnerException?.Message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
@ -100,7 +100,10 @@ namespace Bit.Identity
|
||||
{
|
||||
// Pass domain_hint onto the sso idp
|
||||
context.ProtocolMessage.DomainHint = context.Properties.Items["domain_hint"];
|
||||
context.ProtocolMessage.SessionState = context.Properties.Items["user_identifier"];
|
||||
if (context.Properties.Items.ContainsKey("user_identifier"))
|
||||
{
|
||||
context.ProtocolMessage.SessionState = context.Properties.Items["user_identifier"];
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
@ -115,12 +118,19 @@ namespace Bit.Identity
|
||||
// Services
|
||||
services.AddBaseServices();
|
||||
services.AddDefaultServices(globalSettings);
|
||||
services.AddCoreLocalizationServices();
|
||||
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.ServiceBus.ConnectionString) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.ServiceBus.ApplicationCacheTopicName))
|
||||
{
|
||||
services.AddHostedService<Core.HostedServices.ApplicationCacheHostedService>();
|
||||
}
|
||||
|
||||
// HttpClients
|
||||
services.AddHttpClient("InternalSso", client =>
|
||||
{
|
||||
client.BaseAddress = new Uri(globalSettings.BaseServiceUri.InternalSso);
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
@ -153,6 +163,9 @@ namespace Bit.Identity
|
||||
app.UseCookiePolicy();
|
||||
}
|
||||
|
||||
// Add localization
|
||||
app.UseCoreLocalization();
|
||||
|
||||
// Add static files to the request pipeline.
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
CREATE PROCEDURE [dbo].[Organization_ReadByIdentifier]
|
||||
@Identifier UNIQUEIDENTIFIER
|
||||
@Identifier NVARCHAR(50)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -10,4 +10,4 @@ BEGIN
|
||||
[dbo].[OrganizationView]
|
||||
WHERE
|
||||
[Identifier] = @Identifier
|
||||
END
|
||||
END
|
||||
|
@ -5,7 +5,7 @@ END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [dbo].[Organization_ReadByIdentifier]
|
||||
@Identifier UNIQUEIDENTIFIER
|
||||
@Identifier NVARCHAR(50)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
20
util/Migrator/DbScripts/2020-08-28_00_OrgByIdentifierFix.sql
Normal file
20
util/Migrator/DbScripts/2020-08-28_00_OrgByIdentifierFix.sql
Normal file
@ -0,0 +1,20 @@
|
||||
IF OBJECT_ID('[dbo].[Organization_ReadByIdentifier]') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE [dbo].[Organization_ReadByIdentifier]
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [dbo].[Organization_ReadByIdentifier]
|
||||
@Identifier NVARCHAR(50)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
[dbo].[OrganizationView]
|
||||
WHERE
|
||||
[Identifier] = @Identifier
|
||||
END
|
||||
GO
|
Loading…
Reference in New Issue
Block a user