/// <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;
 }
Exemplo n.º 3
0
        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>();
        }
Exemplo n.º 4
0
        /// <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));
        }
Exemplo n.º 7
0
 /// <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);
 }
Exemplo n.º 8
0
 /// <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);
 }
Exemplo n.º 9
0
 /// <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));
 }
Exemplo n.º 11
0
 /// <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;
 }
Exemplo n.º 12
0
        /// <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;
        }
Exemplo n.º 13
0
 /// <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);
        }
Exemplo n.º 17
0
 /// <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);
 }
Exemplo n.º 19
0
 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");
     }
 }
Exemplo n.º 20
0
 /// <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;
 }
Exemplo n.º 21
0
 public RedactedRootTenant(IPropertyBagFactory propertyBagFactory)
 {
     this.Properties = propertyBagFactory.Create(PropertyBagValues.Empty);
 }