/// <summary> /// Retrieves the delegated tenant for the specified client and service. /// </summary> /// <param name="tenantStore">The <see cref="ITenantStore"/>.</param> /// <param name="clientTenantId">The Id of the client tenant.</param> /// <param name="serviceTenantId"> /// The Id of the service tenant representing the service that needs to make use of the delegated tenant. /// </param> /// <returns>The client tenant.</returns> /// <exception cref="TenantNotFoundException">There is no tenant with the specified client or service tenant Id.</exception> /// <exception cref="ArgumentException">There is no delegated tenant for the specified client and service.</exception> /// <exception cref="InvalidMarainTenantTypeException">The tenant Ids provided do not match the correct types of tenant.</exception> public static async Task <ITenant> GetDelegatedTenantAsync( this ITenantStore tenantStore, string clientTenantId, string serviceTenantId) { // Whilst we're saying "client tenant", the client here could itself be a delegated tenant: ITenant client = await tenantStore.GetTenantOfTypeAsync( clientTenantId, MarainTenantType.Client, MarainTenantType.Delegated).ConfigureAwait(false); // This method will throw if there is no delegated tenant. string delegatedTenantId = client.GetDelegatedTenantIdForServiceId(serviceTenantId); return(await tenantStore.GetDelegatedTenantAsync(delegatedTenantId).ConfigureAwait(false)); }
public void ThenTheTenantCalledShouldHaveTheIdOfTheTenantCalledSetAsTheOn_Behalf_Of_TenantForTheServiceCalled( string enrolledTenantName, string onBehalfOfTenantName, string serviceTenantName) { InMemoryTenantProvider tenantProvider = ContainerBindings.GetServiceProvider(this.scenarioContext).GetRequiredService <InMemoryTenantProvider>(); ITenant enrolledTenant = tenantProvider.GetTenantByName(enrolledTenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{enrolledTenantName}'"); ITenant onBehalfOfTenant = tenantProvider.GetTenantByName(onBehalfOfTenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{onBehalfOfTenantName}'"); ITenant serviceTenant = tenantProvider.GetTenantByName(serviceTenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{serviceTenantName}'"); Assert.AreEqual(onBehalfOfTenant.Id, enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id)); }
public void ThenTheTenantCalledShouldNotHaveADelegatedTenantForTheServiceCalled( string enrolledTenantName, string serviceTenantName) { InMemoryTenantProvider tenantProvider = ContainerBindings.GetServiceProvider(this.scenarioContext).GetRequiredService <InMemoryTenantProvider>(); ITenant enrolledTenant = tenantProvider.GetTenantByName(enrolledTenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{enrolledTenantName}'"); ITenant serviceTenant = tenantProvider.GetTenantByName(serviceTenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{serviceTenantName}'"); try { enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id); Assert.Fail($"Did not expect tenant with name '{enrolledTenant}' to have a delegated tenant for service '{serviceTenantName}', but one exists."); } catch (ArgumentException) { } }
/// <inheritdoc/> public async Task <string> GetDelegatedTenantIdForRequestingTenantAsync(string tenantId) { ITenant tenant = await this.GetTenantAsync(tenantId).ConfigureAwait(false); return(tenant.GetDelegatedTenantIdForServiceId(this.serviceConfiguration.ServiceTenantId)); }
/// <summary> /// Unenrolls the specified tenant from the service. /// </summary> /// <param name="tenantStore">The tenant store.</param> /// <param name="enrolledTenant">The tenant that is currently enrolled.</param> /// <param name="serviceTenant">The service they need to be unenrolled from.</param> /// <param name="logger">Optional logger.</param> /// <returns>A task which completes when the unenrollment has finished.</returns> public static async Task UnenrollFromServiceAsync( this ITenantStore tenantStore, ITenant enrolledTenant, ITenant serviceTenant, ILogger?logger = null) { if (!enrolledTenant.IsEnrolledForService(serviceTenant.Id)) { throw new InvalidOperationException( $"Cannot unenroll tenant '{enrolledTenant.Name}' with Id '{enrolledTenant.Id}' from service with Id '{serviceTenant.Id}' because it is not currently enrolled"); } logger?.LogDebug( "Unenrolling tenant '{enrolledTenantName}' with Id '{enrolledTenantId}' from service '{serviceTenantName}' with Id '{serviceTenantId}'", enrolledTenant.Name, enrolledTenant.Id, serviceTenant.Name, serviceTenant.Id); var propertiesToRemove = new List <string>(); ServiceManifest manifest = serviceTenant.GetServiceManifest(); // If there are dependencies, we first need to unenroll from each of those and then remove the delegated tenant. if (manifest.DependsOnServiceTenants.Count > 0) { logger?.LogDebug( "Service '{serviceTenantName}' has dependencies. Retrieving delegated tenant for unenrollment.", serviceTenant.Name); string delegatedTenantId = enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id); logger?.LogDebug( "Retrieved delegated tenant with Id '{delegatedTenantId}. Unenrolling from dependencies.", delegatedTenantId); foreach (ServiceDependency current in manifest.DependsOnServiceTenants) { await tenantStore.UnenrollFromServiceAsync(delegatedTenantId, current.Id).ConfigureAwait(false); } // Now delete the delegated tenant. logger?.LogDebug( "Deleting delegated tenant with Id '{delegatedTenantId}'.", delegatedTenantId); await tenantStore.DeleteTenantAsync(delegatedTenantId).ConfigureAwait(false); propertiesToRemove.AddRange(enrolledTenant.GetPropertiesToRemoveDelegatedTenantForService(serviceTenant)); } if (manifest.RequiredConfigurationEntries.Count > 0) { // Now remove any config for the service that's being unenrolled from. logger?.LogDebug( "Removing configuration for service '{serviceTenantName}' from '{enrolledTenantName}'", serviceTenant.Name, enrolledTenant.Name); foreach (ServiceManifestRequiredConfigurationEntry current in manifest.RequiredConfigurationEntries) { logger?.LogDebug( "Removing configuration item '{requiredConfigurationEntryKey}' for service '{serviceTenantName}' from '{enrolledTenantName}'", current.Key, serviceTenant.Name, enrolledTenant.Name); propertiesToRemove.AddRange(current.GetPropertiesToRemoveFromTenant(enrolledTenant)); } } // Finally, remove the enrollment entry for the service. logger?.LogDebug( "Removing enrollment entry for service '{serviceTenantName}' from '{enrolledTenantName}'", serviceTenant.Name, enrolledTenant.Name); IEnumerable <KeyValuePair <string, object> > propertiesToChange = enrolledTenant.GetPropertyUpdatesToRemoveServiceEnrollment(serviceTenant.Id); logger?.LogDebug( "Updating tenant '{enrolledTenantName}'", enrolledTenant.Name); await tenantStore.UpdateTenantAsync( enrolledTenant.Id, propertiesToSetOrAdd : propertiesToChange, propertiesToRemove : propertiesToRemove).ConfigureAwait(false); logger?.LogInformation( "Successfully unenrolled tenant '{enrolledTenantName}' with Id '{enrolledTenantId}' from service '{serviceTenantName}' with Id '{serviceTenantId}'", enrolledTenant.Name, enrolledTenant.Id, serviceTenant.Name, serviceTenant.Id); }