/// <summary> /// Adds and configures a ClaimsStrategy to the application where the TenantClaimName configuration registered elsewhere. /// </summary> /// <remarks> /// The claims strategy does not rely on TenantContext. Therefore, it is not necessary to /// register the tenant context here. The only thing it relies on is a tenant claim name and this /// is registered via a TenantConfiguration object which is injected into the TenantConfigurations /// object. The TenantConfigurations object will handle duplicates in case app settings are also /// registered and have a tenant claim name value. /// </remarks> /// <param name="builder"></param> /// <returns></returns> public static FinbuckleMultiTenantBuilder WithClaimsStrategy(this FinbuckleMultiTenantBuilder builder) { // register the strategy with the built in finbuckly custom strategy builder.WithStrategy <ClaimsStrategy>(ServiceLifetime.Scoped); return(builder); }
/// <summary> /// Adds and configures a BasePathStrategy to the application. /// </summary> /// <returns>The same MultiTenantBuilder passed into the method.></returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithBasePathStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder, Action <BasePathStrategyOptions> configureOptions) where TTenantInfo : class, ITenantInfo, new() { builder.Services.Configure(configureOptions); builder.Services.Configure <MultiTenantOptions>(options => { var origOnTenantResolved = options.Events.OnTenantResolved; options.Events.OnTenantResolved = tenantResolvedContext => { var httpContext = tenantResolvedContext.Context as HttpContext ?? throw new MultiTenantException("BasePathStrategy expects HttpContext."); if (tenantResolvedContext.StrategyType == typeof(BasePathStrategy) && httpContext.RequestServices.GetRequiredService <IOptions <BasePathStrategyOptions> >().Value .RebaseAspNetCorePathBase) { httpContext.Request.Path.StartsWithSegments($"/{tenantResolvedContext.TenantInfo?.Identifier}", out var matched, out var newPath); httpContext.Request.PathBase = Path.Combine(httpContext.Request.PathBase, matched); httpContext.Request.Path = newPath; } return(origOnTenantResolved(tenantResolvedContext)); }; }); return(builder.WithStrategy <BasePathStrategy>(ServiceLifetime.Singleton)); }
/// <summary> /// Adds and configures a ClaimStrategy to the application. /// </summary> /// <param name="builder">MultiTenantBuilder instance.</param> /// <param name="tenantKey">Claim name for determining the tenant identifier.</param> /// <param name="authenticationScheme">The authentication scheme to check for claims.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithClaimStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder, string tenantKey, string authenticationScheme) where TTenantInfo : class, ITenantInfo, new() { BypassSessionPrincipalValidation(builder); return(builder.WithStrategy <ClaimStrategy>(ServiceLifetime.Singleton, tenantKey, authenticationScheme)); }
/// <summary> /// Adds and configures a ClaimsStrategy to the application where the TenantClaimName is registered via IConfigurationSection. /// </summary> /// <remarks> /// The claims strategy does not rely on TenantContext. Therefore, it is not necessary to /// register the tenant context here. The only thing it relies on is a tenant claim name and this /// is registered via a TenantConfiguration object which is injected into the TenantConfigurations /// object. The TenantConfigurations object will handle duplicates in case app settings are also /// registered and have a tenant claim name value. /// </remarks> /// <param name="builder"></param> /// <param name="configurationSection">The configuration section containing a value for <see cref="Constants.TenantClaimName"/>.</param> /// <returns></returns> public static FinbuckleMultiTenantBuilder WithClaimsStrategy(this FinbuckleMultiTenantBuilder builder, IConfigurationSection configurationSection) { // add the configuration section and configuration wrapper builder.Services.AddTenantConfigurations(configurationSection); // register the strategy with the built in finbuckly custom strategy builder.WithStrategy <ClaimsStrategy>(ServiceLifetime.Scoped); return(builder); }
/// <summary> /// Adds and configures a HostStrategy to the application. /// </summary> /// <param name="template">The template for determining the tenant identifier in the host.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithHostStrategy <TTenantInfo>(this FinbuckleMultiTenantBuilder <TTenantInfo> builder, string template) where TTenantInfo : class, ITenantInfo, new() { if (string.IsNullOrWhiteSpace(template)) { throw new ArgumentException("Invalid value for \"template\"", nameof(template)); } return(builder.WithStrategy <HostStrategy>(ServiceLifetime.Singleton, new object[] { template })); }
/// <summary> /// Adds and configures a StaticStrategy to the application. /// </summary> /// <param name="identifier">The tenant identifier to use for all tenant resolution.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder WithStaticStrategy(this FinbuckleMultiTenantBuilder builder, string identifier) { if (string.IsNullOrWhiteSpace(identifier)) { throw new ArgumentException("Invalid value for \"identifier\"", nameof(identifier)); } return(builder.WithStrategy <StaticStrategy>(ServiceLifetime.Singleton, new object[] { identifier }));; }
/// <summary> /// Adds and configures a DelegateStrategy to the application. /// </summary> /// <param name="doStrategy">The delegate implementing the strategy.</returns> public static FinbuckleMultiTenantBuilder WithDelegateStrategy(this FinbuckleMultiTenantBuilder builder, Func <object, Task <string> > doStrategy) { if (doStrategy == null) { throw new ArgumentNullException(nameof(doStrategy)); } return(builder.WithStrategy <DelegateStrategy>(ServiceLifetime.Singleton, new object[] { doStrategy })); }
/// <summary> /// Adds and configures a StaticStrategy to the application. /// </summary> /// <param name="builder">The builder instance.</param> /// <param name="identifier">The tenant identifier to use for all tenant resolution.</param> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithStaticStrategy <TTenantInfo>(this FinbuckleMultiTenantBuilder <TTenantInfo> builder, string identifier) where TTenantInfo : class, ITenantInfo, new() { if (string.IsNullOrWhiteSpace(identifier)) { throw new ArgumentNullException(nameof(identifier), "Invalid value for \"identifier\""); } return(builder.WithStrategy <StaticStrategy>(ServiceLifetime.Singleton, new object[] { identifier })); }
/// <summary> /// Adds and configures a DelegateStrategy to the application. /// </summary> /// <param name="builder">The builder instance.</param> /// <param name="doStrategy">The delegate implementing the strategy.</param> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithDelegateStrategy <TTenantInfo>(this FinbuckleMultiTenantBuilder <TTenantInfo> builder, Func <object, Task <string?> > doStrategy) where TTenantInfo : class, ITenantInfo, new() { if (doStrategy == null) { throw new ArgumentNullException(nameof(doStrategy)); } return(builder.WithStrategy <DelegateStrategy>(ServiceLifetime.Singleton, new object[] { doStrategy })); }
/// <summary> /// Adds and configures a FormStrategy to the application with a singleton configuration. /// </summary> /// <remarks> /// The form strategy does not rely on TenantContext. Therefore, it is not necessary to /// register the tenant context here. The only thing it relies on is a FormStrategyConfiguration /// object. This object is either added as a parameter or injected via IOptionsSnapshot. /// </remarks> /// <param name="builder"></param> /// <param name="formStrategyConfiguration">A static form strategy configuration</param> /// <returns></returns> public static FinbuckleMultiTenantBuilder WithFormStrategy(this FinbuckleMultiTenantBuilder builder, FormStrategyConfiguration formStrategyConfiguration) { // validate the configuration section ValidateFormStrategyConfiguration(formStrategyConfiguration); // wrap the configuration value in a IOptionsSnapshot object and register it builder.Services.AddSingleton <IOptionsSnapshot <FormStrategyConfiguration> >(new OptionSnapshotFormStrategyConfiguration(formStrategyConfiguration)); // register the strategy with the built in finbuckly custom strategy builder.WithStrategy <FormStrategy>(ServiceLifetime.Scoped); return(builder); }
/// <summary> /// Adds and configures a ClaimsStrategy to the application. /// </summary> /// <remarks> /// The claims strategy does not rely on TenantContext. Therefore, it is not necessary to /// register the tenant context here. The only thing it relies on is a tenant claim name and this /// is registered via a TenantConfiguration object which is injected into the TenantConfigurations /// object. The TenantConfigurations object will handle duplicates in case app settings are also /// registered and have a tenant claim name value. /// </remarks> /// <param name="builder"></param> /// <param name="tenantClaimName">The name of the claim holding the tenant id.</param> /// <returns></returns> public static FinbuckleMultiTenantBuilder WithClaimsStrategy(this FinbuckleMultiTenantBuilder builder, string tenantClaimName) { // add the claim name as a manual configuration builder.Services.AddSingleton <ITenantConfiguration>(new TenantConfiguration() { Key = Constants.TenantClaimName, Value = tenantClaimName }); // add the configuration wrapper builder.Services.AddTenantConfigurations(); // register the strategy with the built in finbuckly custom strategy builder.WithStrategy <ClaimsStrategy>(ServiceLifetime.Scoped); return(builder); }
/// <summary> /// Adds and configures a RouteStrategy to the application. /// </summary> /// <param name="tenantParam">The name of the route parameter used to determine the tenant identifier.</param> /// <param name="configRoutes">Delegate to configure the routes.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder WithRouteStrategy(this FinbuckleMultiTenantBuilder builder, string tenantParam, Action <IRouteBuilder> configRoutes) { if (string.IsNullOrWhiteSpace(tenantParam)) { throw new ArgumentException("Invalud value for \"tenantParam\"", nameof(tenantParam)); } if (configRoutes == null) { throw new ArgumentNullException(nameof(configRoutes)); } return(builder.WithStrategy <RouteStrategy>(ServiceLifetime.Singleton, new object[] { tenantParam, configRoutes })); }
/// <summary> /// Adds and configures a FormStrategy to the application with a configuration section configuration which reloads with changes. /// </summary> /// <remarks> /// The form strategy does not rely on TenantContext. Therefore, it is not necessary to /// register the tenant context here. The only thing it relies on is a FormStrategyConfiguration /// object. This object is either added as a parameter or injected via IOptionsSnapshot. /// </remarks> /// <param name="builder"></param> /// <param name="formStrategyConfiguration">The configuration section defining the form strategy configuration and resolved with IOptionsSnapshot<></param> /// <returns></returns> public static FinbuckleMultiTenantBuilder WithFormStrategy(this FinbuckleMultiTenantBuilder builder, IConfigurationSection configurationSection) { // validate the configuration section var formStrategyConfiguration = new FormStrategyConfiguration(); configurationSection.Bind(formStrategyConfiguration); ValidateFormStrategyConfiguration(formStrategyConfiguration); // register configuration so it will reload with changes builder.Services.Configure <FormStrategyConfiguration>(configurationSection); // register the strategy with the built in finbuckly custom strategy builder.WithStrategy <FormStrategy>(ServiceLifetime.Scoped); return(builder); }
/// <summary> /// Adds and configures a Header to the application. /// </summary> /// <param name="builder">MultiTenantBuilder instance.</param> /// <param name="tenantKey">The template for determining the tenant identifier in the host.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithHeaderStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder, string tenantKey) where TTenantInfo : class, ITenantInfo, new() { return(builder.WithStrategy <HeaderStrategy>(ServiceLifetime.Singleton, tenantKey)); }
/// <summary> /// Adds and configures a RemoteAuthenticationCallbackStrategy to the application. /// </summary> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithRemoteAuthenticationCallbackStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder) where TTenantInfo : class, ITenantInfo, new() { return(builder.WithStrategy <RemoteAuthenticationCallbackStrategy>(ServiceLifetime.Singleton)); }
/// <summary> /// Adds and configures a SessionStrategy to the application. /// </summary> /// <param name="builder">MultiTenantBuilder instance.</param> /// <param name="tenantKey">The session key to use.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithSessionStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder, string tenantKey) where TTenantInfo : class, ITenantInfo, new() => builder.WithStrategy <SessionStrategy>(ServiceLifetime.Singleton, tenantKey);
/// <summary> /// Adds and configures a SessionStrategy to the application. /// </summary> /// <param name="builder">MultiTenantBuilder instance.</param> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithSessionStrategy <TTenantInfo>( this FinbuckleMultiTenantBuilder <TTenantInfo> builder) where TTenantInfo : class, ITenantInfo, new() => builder.WithStrategy <SessionStrategy>(ServiceLifetime.Singleton, Constants.TenantToken);
/// <summary> /// Adds and configures a ClaimStrategy with tenantKey "__tenant__" to the application. /// </summary> /// <returns>The same MultiTenantBuilder passed into the method.</returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithClaimStrategy <TTenantInfo>(this FinbuckleMultiTenantBuilder <TTenantInfo> builder) where TTenantInfo : class, ITenantInfo, new() { return(builder.WithStrategy <ClaimStrategy>(ServiceLifetime.Singleton, Constants.TenantToken)); }
/// <summary> /// Adds and configures a BasePathStrategy to the application. /// </summary> /// <returns>The same MultiTenantBuilder passed into the method.></returns> public static FinbuckleMultiTenantBuilder <TTenantInfo> WithBasePathStrategy <TTenantInfo>(this FinbuckleMultiTenantBuilder <TTenantInfo> builder) where TTenantInfo : class, ITenantInfo, new() => builder.WithStrategy <BasePathStrategy>(ServiceLifetime.Singleton);
/// <summary> /// Adds and configures a BasePathStrategy to the application. /// </summary> /// <returns>The same MultiTenantBuilder passed into the method.></returns> public static FinbuckleMultiTenantBuilder WithBasePathStrategy(this FinbuckleMultiTenantBuilder builder) => builder.WithStrategy <BasePathStrategy>(ServiceLifetime.Singleton);