/// <summary> /// Adds the root tenant to the collection, using the <see cref="ITenancyService"/>. /// </summary> /// <param name="services">The service collection to which to add the root tenant.</param> /// <returns>The configured service collection.</returns> public static IServiceCollection AddTenantServiceClientRootTenant(this IServiceCollection services) { if (services.Any(s => typeof(RootTenant).IsAssignableFrom(s.ServiceType))) { return(services); } services.AddContent(contentFactory => contentFactory.RegisterTransientContent <Tenant>()); // Construct a root tenant from the tenant retrieved from the service, using the // root tenant ID. services.AddSingleton(s => { ITenancyService tenancyService = s.GetRequiredService <ITenancyService>(); ITenantMapper tenantMapper = s.GetRequiredService <ITenantMapper>(); IPropertyBagFactory propertyBagFactory = s.GetRequiredService <IPropertyBagFactory>(); ITenant fetchedRootTenant = tenantMapper.MapTenant(tenancyService.GetTenant(RootTenant.RootTenantId)); var localRootTenant = new RootTenant(propertyBagFactory); IReadOnlyDictionary <string, object> propertiesToSetOrAdd = fetchedRootTenant.Properties.AsDictionary(); localRootTenant.UpdateProperties(propertiesToSetOrAdd); return(localRootTenant); }); return(services); }
/// <summary> /// Initializes a new instance of the <see cref="TriggerExecutionOrchestrator"/> class. /// </summary> /// <param name="propertyBagFactory">The property bag factory.</param> /// <param name="serializerSettingsProvider">The serialization settings provider.</param> public TriggerExecutionOrchestrator( IPropertyBagFactory propertyBagFactory, IJsonSerializerSettingsProvider serializerSettingsProvider) { this.serializerSettingsProvider = serializerSettingsProvider; this.propertyBagFactory = propertyBagFactory; }
public ClaimsBenchmarksBase() { IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true); IConfiguration configuration = configurationBuilder.Build(); this.ClientTenantId = configuration["ClientTenantId"]; this.AdministratorPrincipalObjectId = configuration["AdministratorPrincipalObjectId"]; ServiceProvider serviceProvider = new ServiceCollection() .AddClaimsClient(sp => configuration.GetSection("ClaimsClient").Get <ClaimsClientOptions>()) .AddSingleton(sp => configuration.GetSection("TenancyClient").Get <TenancyClientOptions>()) .AddTenancyClient(enableResponseCaching: true) .AddJsonNetPropertyBag() .AddBlobContainerV2ToV3Transition() .AddAzureBlobStorageClientSourceFromDynamicConfiguration() .AddServiceIdentityAzureTokenCredentialSourceFromLegacyConnectionString(configuration["AzureServicesAuthConnectionString"]) .AddMicrosoftRestAdapterForServiceIdentityAccessTokenSource() .BuildServiceProvider(); this.ClaimsService = serviceProvider.GetRequiredService <IClaimsService>(); this.TenancyService = serviceProvider.GetRequiredService <ITenancyService>(); this.TenantBlobContainerClientFactory = serviceProvider.GetRequiredService <IBlobContainerSourceWithTenantLegacyTransition>(); this.PropertyBagFactory = serviceProvider.GetRequiredService <IPropertyBagFactory>(); }
/// <summary> /// Adds services an Azure Blob storage-based implementation of <see cref="ITenantProvider"/>. /// </summary> /// <param name="services">The service collection.</param> /// <param name="getRootTenantStorageConfiguration"> /// A function that returns the <see cref="BlobStorageConfiguration"/> that will be used for the root tenant to /// determine where to store its children. /// </param> /// <returns>The modified service collection.</returns> public static IServiceCollection AddTenantProviderBlobStore( this IServiceCollection services, Func <IServiceProvider, BlobStorageConfiguration> getRootTenantStorageConfiguration) { if (services.Any(s => typeof(ITenantProvider).IsAssignableFrom(s.ServiceType))) { return(services); } services.AddRequiredTenancyServices(); services.AddSingleton(sp => { BlobStorageConfiguration rootTenantStorageConfig = getRootTenantStorageConfiguration(sp); IPropertyBagFactory propertyBagFactory = sp.GetRequiredService <IPropertyBagFactory>(); var rootTenant = new RootTenant(propertyBagFactory); rootTenant.UpdateProperties( values => values.AddBlobStorageConfiguration( TenantProviderBlobStore.ContainerDefinition, rootTenantStorageConfig)); ITenantCloudBlobContainerFactory tenantCloudBlobContainerFactory = sp.GetRequiredService <ITenantCloudBlobContainerFactory>(); IJsonSerializerSettingsProvider serializerSettingsProvider = sp.GetRequiredService <IJsonSerializerSettingsProvider>(); return(new TenantProviderBlobStore(rootTenant, propertyBagFactory, tenantCloudBlobContainerFactory, serializerSettingsProvider)); }); services.AddSingleton <ITenantStore>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); services.AddSingleton <ITenantProvider>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); return(services); }
public Task GivenIHaveCreatedAndStoredNotificationsWithTimestampsAtSecondIntervalsForTheUserWithId(int notificationCount, int interval, string userId) { IUserNotificationStore store = this.serviceProvider.GetRequiredService <IUserNotificationStore>(); IPropertyBagFactory propertyBagFactory = this.serviceProvider.GetRequiredService <IPropertyBagFactory>(); DateTimeOffset timestamp = DateTimeOffset.UtcNow; var offset = TimeSpan.FromSeconds(interval); var tasks = new List <Task>(); var propertiesDictionary = new Dictionary <string, object> { { "prop1", "val1" }, { "prop2", 2 }, { "prop3", DateTime.Now }, }; IPropertyBag properties = propertyBagFactory.Create(propertiesDictionary); for (int i = 0; i < notificationCount; i++) { string[] correlationIds = Enumerable.Range(0, 3).Select(_ => Guid.NewGuid().ToString()).ToArray(); var metadata = new UserNotificationMetadata(correlationIds, null); tasks.Add(store.StoreAsync(new UserNotification(null, "marain.usernotifications.test", userId, timestamp, properties, metadata))); timestamp -= offset; } return(Task.WhenAll(tasks)); }
/// <summary> /// Creates a property bag from a callback that produces a collection of key pair values. /// </summary> /// <param name="propertyBagFactory">The property bag factory.</param> /// <param name="builder">A function that builds the property collection.</param> /// <returns>A new property bag.</returns> /// <remarks> /// <para> /// This supports property builders designed to be chained together, e.g.: /// </para> /// <code><![CDATA[ /// IPropertyBag childProperties = this.propertyBagFactory.Create(start => /// start.AddBlobStorageConfiguration(ContainerDefinition, tenancyStorageConfiguration)); /// ]]></code> /// <para> /// It calls <see cref="IPropertyBagFactory.Create(IEnumerable{KeyValuePair{string, object}})"/> /// with the resulting properties. /// </para> /// </remarks> public static IPropertyBag Create( this IPropertyBagFactory propertyBagFactory, Func <IEnumerable <KeyValuePair <string, object> >, IEnumerable <KeyValuePair <string, object> > > builder) { IEnumerable <KeyValuePair <string, object> > values = builder(PropertyBagValues.Empty); return(propertyBagFactory.Create(values)); }
/// <summary> /// Sets the workflow instance Id to process. /// </summary> /// <param name="data">The envelope to add the value to.</param> /// <param name="propertyBagFactory">The property bag factory.</param> /// <param name="workflowInstanceId">The workflow instance id.</param> public static void SetWorkflowInstanceId( this WorkflowMessageEnvelope data, IPropertyBagFactory propertyBagFactory, string workflowInstanceId) { data.Properties = propertyBagFactory.CreateModified( data.Properties, new KeyValuePair <string, object>[] { new KeyValuePair <string, object>("WorkflowInstanceId", workflowInstanceId) }, null); }
/// <summary> /// Sets the workflow instances page number. /// </summary> /// <param name="data">The envelope to add the value to.</param> /// <param name="propertyBagFactory">The property bag factory.</param> /// <param name="pageNumber">The page number.</param> public static void SetWorkflowInstancesPageNumber( this WorkflowMessageEnvelope data, IPropertyBagFactory propertyBagFactory, int pageNumber) { data.Properties = propertyBagFactory.CreateModified( data.Properties, new KeyValuePair <string, object>[] { new KeyValuePair <string, object>("GetWorkflowInstancesPageNumber", pageNumber) }, null); }
/// <summary> /// Initializes a new instance of the <see cref="MessageIngestionService" /> class. /// </summary> /// <param name="serializerSettingsProvider">Serialization settings provider.</param> /// <param name="propertyBagFactory">Factory to use when creating initial IPropertyBag instances for workflow message envelopes.</param> /// <param name="operationsControl">Allows definition and control of long-running operations.</param> /// <param name="marainServicesTenancy">Marain tenancy services.</param> public MessageIngestionService( IJsonSerializerSettingsProvider serializerSettingsProvider, IPropertyBagFactory propertyBagFactory, IMarainOperationsControl operationsControl, IMarainServicesTenancy marainServicesTenancy) { this.marainServicesTenancy = marainServicesTenancy; this.operationsControl = operationsControl; this.serializerSettingsProvider = serializerSettingsProvider; this.propertyBagFactory = propertyBagFactory; }
/// <summary> /// Creates a new <see cref="IPropertyBag"/> based on an existing bag, but with some /// properties either added, updated, or removed, using a callback that produces a /// collection of key pair values to describe the properties to add or change. /// </summary> /// <param name="propertyBagFactory">The property bag factory.</param> /// <param name="input">The property bag on which to base the new one.</param> /// <param name="builder">A function that builds the collection describing the properties to add.</param> /// <param name="propertiesToRemove">Optional list of properties to remove.</param> /// <returns>A collection of key pair values.</returns> /// <remarks> /// <para> /// Similar to /// <see cref="Create(IPropertyBagFactory, Func{IEnumerable{KeyValuePair{string, object}}, IEnumerable{KeyValuePair{string, object}}})"/>, /// this supports property builders designed to be chained together. Whereas that method /// is for creating a new property bag from scratch, this invokes /// <see cref="IPropertyBagFactory.CreateModified(IPropertyBag, IEnumerable{KeyValuePair{string, object}}?, IEnumerable{string}?)"/>. /// For example: /// </para> /// <code><![CDATA[ /// IPropertyBag childProperties = propertyBagFactory.CreateModified( /// existingPropertyBag, /// values => values.AddBlobStorageConfiguration(ContainerDefinition, tenancyStorageConfiguration)); /// ]]></code> /// </remarks> public static IPropertyBag CreateModified( this IPropertyBagFactory propertyBagFactory, IPropertyBag input, Func <IEnumerable <KeyValuePair <string, object> >, IEnumerable <KeyValuePair <string, object> > > builder, IEnumerable <string>?propertiesToRemove = null) { return(propertyBagFactory.CreateModified( input, builder(PropertyBagValues.Empty), propertiesToRemove)); }
/// <summary> /// Initializes a new instance of the <see cref="InMemoryWorkflowMessageQueue" /> class. /// </summary> /// <param name="workflowEngineFactory"> /// The workflow engine factory to create the engine to which to hand off the triggers. /// </param> /// <param name="workflowInstanceStoreFactory"> /// The workflow instance store factory to use to access underlying instance storage. /// </param> /// <param name="tenantProvider"> /// The tenant provider that will be used when accessing storage. /// </param> /// <param name="propertyBagFactory"> /// The <see cref="IPropertyBagFactory"/> that will be used when creating new /// <see cref="WorkflowMessageEnvelope"/> instances. /// </param> /// <param name="logger"> /// Logger to use to write diagnostic messages. /// </param> /// <remarks> /// <para> /// The queue will be created in the "Stopped" state. To begin processing, /// call the <see cref="StartProcessing" /> method. /// </para> /// </remarks> public InMemoryWorkflowMessageQueue( ITenantedWorkflowEngineFactory workflowEngineFactory, ITenantedWorkflowInstanceStoreFactory workflowInstanceStoreFactory, ITenantProvider tenantProvider, IPropertyBagFactory propertyBagFactory, ILogger <InMemoryWorkflowMessageQueue> logger) { this.logger = logger; this.tenantProvider = tenantProvider; this.workflowEngineFactory = workflowEngineFactory; this.queue = new ConcurrentQueue <WorkflowMessageEnvelope>(); this.workflowInstanceStoreFactory = workflowInstanceStoreFactory; this.propertyBagFactory = propertyBagFactory; }
/// <summary> /// Initializes a new instance of the <see cref="TenantProviderBlobStore"/> class. /// </summary> /// <param name="tenant">The root tenant (registered as a singleton in the container).</param> /// <param name="propertyBagFactory"> /// Enables creation of <see cref="IPropertyBag"/> instances when no existing serialized /// representation exists (i.e., when creating a new tenant), and building of modified property /// bags. /// </param> /// <param name="tenantCloudBlobContainerFactory">The tenanted cloud blob container factory.</param> /// <param name="serializerSettingsProvider">The serializer settings provider for tenant serialization.</param> public TenantProviderBlobStore( RootTenant tenant, IPropertyBagFactory propertyBagFactory, ITenantCloudBlobContainerFactory tenantCloudBlobContainerFactory, IJsonSerializerSettingsProvider serializerSettingsProvider) { ArgumentNullException.ThrowIfNull(tenant); ArgumentNullException.ThrowIfNull(propertyBagFactory); ArgumentNullException.ThrowIfNull(tenantCloudBlobContainerFactory); ArgumentNullException.ThrowIfNull(serializerSettingsProvider); this.Root = tenant; this.tenantCloudBlobContainerFactory = tenantCloudBlobContainerFactory; this.serializerSettings = serializerSettingsProvider.Instance; this.propertyBagFactory = propertyBagFactory; }
/// <summary> /// Initializes a new instance of the <see cref="TenancyService"/> class. /// </summary> /// <param name="tenantStore">The tenant store.</param> /// <param name="propertyBagFactory">Provides property bag initialization and modification services.</param> /// <param name="tenantMapper">The mapper from tenants to tenant resources.</param> /// <param name="tenantCollectionResultMapper">The mapper from tenant collection results to the result resource.</param> /// <param name="linkResolver">The link resolver.</param> /// <param name="cacheConfiguration">Cache configuration.</param> /// <param name="logger">The logger for the service.</param> public TenancyService( ITenantStore tenantStore, IPropertyBagFactory propertyBagFactory, TenantMapper tenantMapper, TenantCollectionResultMapper tenantCollectionResultMapper, IOpenApiWebLinkResolver linkResolver, TenantCacheConfiguration cacheConfiguration, ILogger <TenancyService> logger) { this.tenantStore = tenantStore ?? throw new ArgumentNullException(nameof(tenantStore)); this.tenantMapper = tenantMapper ?? throw new ArgumentNullException(nameof(tenantMapper)); this.tenantCollectionResultMapper = tenantCollectionResultMapper ?? throw new ArgumentNullException(nameof(tenantCollectionResultMapper)); this.linkResolver = linkResolver ?? throw new ArgumentNullException(nameof(linkResolver)); this.cacheConfiguration = cacheConfiguration ?? throw new ArgumentNullException(nameof(cacheConfiguration)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.propertyBagFactory = propertyBagFactory; }
/// <summary> /// Adds the in-memory tenant provider to the service collection. /// </summary> /// <param name="serviceCollection">The service collection to add to.</param> /// <returns>The service collection, for chaining.</returns> public static IServiceCollection AddInMemoryTenantProvider(this IServiceCollection serviceCollection) { // Add directly and via the interface - some testing code may wish to work with the provider directly because // it provides some helpful methods to shortcut tenant lookup. serviceCollection.AddRequiredTenancyServices(); serviceCollection.AddSingleton <InMemoryTenantProvider>(); serviceCollection.AddSingleton( sp => { IPropertyBagFactory propertyBagFactory = sp.GetRequiredService <IPropertyBagFactory>(); return(new RootTenant(propertyBagFactory)); }); serviceCollection.AddSingleton <ITenantStore>(sp => sp.GetRequiredService <InMemoryTenantProvider>()); serviceCollection.AddSingleton <ITenantProvider>(sp => sp.GetRequiredService <InMemoryTenantProvider>()); return(serviceCollection); }
/// <summary> /// Creates a <see cref="AzureBlobStorageTenantStore"/>. /// </summary> /// <param name="configuration">Configuration settings.</param> /// <param name="containerSource">Provides access to tenanted blob storage.</param> /// <param name="serializerSettingsProvider">Settings for tenant serialization.</param> /// <param name="propertyBagFactory">Property bag services.</param> public AzureBlobStorageTenantStore( AzureBlobStorageTenantStoreConfiguration configuration, IBlobContainerSourceWithTenantLegacyTransition containerSource, IJsonSerializerSettingsProvider serializerSettingsProvider, IPropertyBagFactory propertyBagFactory) { this.containerSource = containerSource; this.propertyBagFactory = propertyBagFactory; this.jsonSerializer = JsonSerializer.Create(serializerSettingsProvider.Instance); this.propagateRootStorageConfigAsV2 = configuration.PropagateRootTenancyStorageConfigAsV2; // The root tenant is necessarily synthetic because we can't get access to storage // without it. And regardless of what stage of v2 to v3 transition we're in with // the store, we always configure the root tenant in v3 mode. this.Root = new RootTenant(propertyBagFactory); this.Root.UpdateProperties(values => values.Append(new KeyValuePair <string, object>( TenancyV3ConfigKey, configuration.RootStorageConfiguration))); }
public async Task GivenIHaveCreatedAndStoredNotificationsInTheCurrentTransientTenantWithTimestampsAtSecondIntervalsForTheUserWithId(int notificationCount, int interval, string userId) { ITenantedUserNotificationStoreFactory storeFactory = this.serviceProvider.GetRequiredService <ITenantedUserNotificationStoreFactory>(); IUserNotificationStore store = await storeFactory.GetUserNotificationStoreForTenantAsync(this.featureContext.GetTransientTenant()).ConfigureAwait(false); IPropertyBagFactory propertyBagFactory = this.serviceProvider.GetRequiredService <IPropertyBagFactory>(); var offset = TimeSpan.FromSeconds(interval); DateTimeOffset timestamp = DateTimeOffset.UtcNow - offset; var tasks = new List <Task <UserNotification> >(); var propertiesDictionary = new Dictionary <string, object> { { "prop1", "val1" }, { "prop2", 2 }, { "prop3", DateTime.Now }, }; IPropertyBag properties = propertyBagFactory.Create(propertiesDictionary); for (int i = 0; i < notificationCount; i++) { string[] correlationIds = Enumerable.Range(0, 3).Select(_ => Guid.NewGuid().ToString()).ToArray(); var metadata = new UserNotificationMetadata(correlationIds, null); tasks.Add(store.StoreAsync(new UserNotification(null, "marain.usernotifications.test", userId, timestamp, properties, metadata))); timestamp -= offset; } UserNotification[] newlyCreatedNotifications = await Task.WhenAll(tasks).ConfigureAwait(false); // Store the notifications in session state if (!this.scenarioContext.TryGetValue(CreatedNotificationsKey, out List <UserNotification> createdNotifications)) { createdNotifications = new List <UserNotification>(); this.scenarioContext.Set(createdNotifications, CreatedNotificationsKey); } createdNotifications.AddRange(newlyCreatedNotifications); }
/// <summary> /// Initializes a new instance of the <see cref="TenantMapper"/> class. /// </summary> /// <param name="propertyBagFactory">Enables property bag building.</param> public TenantMapper( IPropertyBagFactory propertyBagFactory) { this.propertyBagFactory = propertyBagFactory ?? throw new ArgumentNullException(nameof(propertyBagFactory)); }
public FakeTenantProvider(IPropertyBagFactory propertyBagFactory) { this.Root = new RootTenant(propertyBagFactory); }
internal AcrPropertyBag(PersistablePropertyBag propertyBag, AcrProfile profile, StoreObjectId itemId, IPropertyBagFactory propertyBagFactory, byte[] openChangeKey) { this.propertyBag = propertyBag; base.PrefetchPropertyArray = this.propertyBag.PrefetchPropertyArray; this.profile = profile; this.itemId = itemId; this.propertyBagFactory = propertyBagFactory; this.openChangeKey = openChangeKey; if (propertyBag.DisposeTracker != null) { propertyBag.DisposeTracker.AddExtraDataWithStackTrace("AcrPropertyBag owns PersistablePropertyBag propertyBag at"); } }
/// <summary> /// Initializes a new instance of the <see cref="RootTenant"/> class. /// </summary> /// <param name="propertyBagFactory">Enables property bag creation and update.</param> public RootTenant(IPropertyBagFactory propertyBagFactory) : base(RootTenantId, RootTenantName, propertyBagFactory.Create(PropertyBagValues.Empty)) { this.propertyBagFactory = propertyBagFactory; }
public RedactedRootTenant(IPropertyBagFactory propertyBagFactory) { this.Properties = propertyBagFactory.Create(PropertyBagValues.Empty); }