public async Task Run( [TimerTrigger("0 */5 * * * *", RunOnStartup = true)] TimerInfo timer, [Queue(CommandHandler.ProcessorQueue)] IAsyncCollector <ICommand> commandQueue, ILogger log) { if (timer is null) { throw new ArgumentNullException(nameof(timer)); } var utcNow = DateTime.UtcNow; if (timer.IsPastDue) { log.LogInformation("Timer is running late!"); } log.LogInformation($"Schedule Poller Timer trigger function executed at: {DateTime.Now}"); var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var orgs = await organizationRepository .ListAsync(tenantId.ToString()) .ToListAsync() .ConfigureAwait(false); var projectsTasks = orgs.Select(o => GetProjects(o.Id)); var projects = await Task.WhenAll(projectsTasks) .ConfigureAwait(false); var scheduleTasks = projects.SelectMany(p => p.Select(pp => GetSchedules(pp.Id, (DayOfWeek)utcNow.DayOfWeek, utcNow.Hour, utcNow.Minute, 5)) ); var schedules = await Task.WhenAll(scheduleTasks) .ConfigureAwait(false); var userIds = schedules.SelectMany(st => st.Select(sst => (org: sst.Organization, user: sst.Creator)) ).Distinct(); var usersTasks = userIds.Select(u => userRepository.GetAsync(u.org, u.user)); var users = await Task.WhenAll(usersTasks) .ConfigureAwait(false); var commandQueueTasks = schedules.SelectMany(st => st.Select(sst => commandQueue.AddAsync(new ScheduleRunCommand(users.FirstOrDefault(u => u.Id == sst.Creator), sst))) ); await Task.WhenAll(commandQueueTasks) .ConfigureAwait(false); }
public override async Task <ICommandResult> HandleAsync(ProjectCreateCommand command, IAsyncCollector <ICommand> commandQueue, IDurableOrchestrationContext orchestrationContext, ILogger log) { if (command is null) { throw new ArgumentNullException(nameof(command)); } if (commandQueue is null) { throw new ArgumentNullException(nameof(commandQueue)); } var commandResult = command.CreateResult(); try { commandResult.Result = await projectRepository .AddAsync(command.Payload) .ConfigureAwait(false); await userRepository .AddProjectMembershipAsync(command.User, commandResult.Result.Id, ProjectUserRole.Owner, new Dictionary <string, string>()) .ConfigureAwait(false); await commandQueue .AddAsync(new ProjectDeployCommand(command.User, command.Payload)) .ConfigureAwait(false); var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var message = NotificationMessage.Create <WelcomeMessage>(command.User); message.Merge(new WelcomeMessageData() { Organization = await organizationRepository.GetAsync(tenantId.ToString(), commandResult.Result.Organization, expand: true).ConfigureAwait(false), Project = commandResult.Result, User = await userRepository.ExpandAsync(command.User).ConfigureAwait(false), PortalUrl = endpointOptions.Portal }); await commandQueue .AddAsync(new NotificationSendMailCommand <WelcomeMessage>(command.User, message)) .ConfigureAwait(false); commandResult.RuntimeStatus = CommandRuntimeStatus.Completed; } catch (Exception exc) { commandResult.Errors.Add(exc); } return(commandResult); }
private async Task SendWelcomeMessageAsync(ICommand command, IAsyncCollector <ICommand> commandQueue, User userOld) { if (command.Payload is User userNew) { var projects = await userNew.ProjectMemberships .Select(pm => pm.ProjectId) .Except(userOld?.ProjectMemberships.Select(pm => pm.ProjectId) ?? Enumerable.Empty <string>(), StringComparer.OrdinalIgnoreCase) .Select(pid => projectRepository.GetAsync(userNew.Organization, pid, true)) .WhenAll() .ConfigureAwait(false); if (projects.Any()) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var organization = await organizationRepository .GetAsync(tenantId.ToString(), userNew.Organization, expand : true) .ConfigureAwait(false); userNew = await userRepository .ExpandAsync(userNew) .ConfigureAwait(false); await projects .Select(project => SendWelcomeMessageAsync(command.User, organization, project, userNew)) .WhenAll() .ConfigureAwait(false); } } Task SendWelcomeMessageAsync(User sender, Organization organization, Project project, User user) { var message = NotificationMessage.Create <WelcomeMessage>(user); message.Merge(new WelcomeMessageData() { Organization = organization, Project = project, User = user, PortalUrl = endpointOptions.Portal }); return(commandQueue.AddAsync(new NotificationSendMailCommand <WelcomeMessage>(sender, message))); } }
private async Task SendAlternateIdentityMessageAsync(ICommand command, IAsyncCollector <ICommand> commandQueue, User userOld) { if (command.Payload is User userNew) { var alternateIdentities = userNew.AlternateIdentities.Keys .Except(userOld?.AlternateIdentities.Keys ?? Enumerable.Empty <DeploymentScopeType>()) .Select(deploymentScopeType => deploymentScopeType.ToString(prettyPrint: true)); if (alternateIdentities.Any()) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var organization = await organizationRepository .GetAsync(tenantId.ToString(), userNew.Organization, expand : true) .ConfigureAwait(false); userNew = await userRepository .ExpandAsync(userNew) .ConfigureAwait(false); var message = NotificationMessage.Create <AlternateIdentityMessage>(userNew); message.Merge(new AlternateIdentityMessageData() { Organization = organization, Services = alternateIdentities.ToArray(), User = userNew, PortalUrl = endpointOptions.Portal }); await commandQueue .AddAsync(new NotificationSendMailCommand <AlternateIdentityMessage>(command.User, message)) .ConfigureAwait(false); } } }
protected override async Task InitializeEventsAsync() { await base .InitializeEventsAsync() .ConfigureAwait(false); Events.OnValidatePrincipal = async(context) => { if (context.Request.Query.TryGetValue(AdapterAuthenticationDefaults.QueryParam, out var queryValue)) { var match = context.Principal.Claims .Any(c => c.Type == AdapterAuthenticationDefaults.ClaimType && c.Value == queryValue.ToString()); if (!match) { context.RejectPrincipal(); } } else { var newPrincipal = new ClaimsPrincipal(); foreach (var identity in context.Principal.Identities) { if (identity.AuthenticationType.Equals(AdapterAuthenticationDefaults.AuthenticationType)) { var newIdentity = new ClaimsIdentity(identity.Claims.Where(c => !c.Type.Equals(ClaimTypes.Role)), AdapterAuthenticationDefaults.AuthenticationType); var userId = identity.Claims.FirstOrDefault(c => c.Type.Equals(ObjectIdClaimType))?.Value; if (!string.IsNullOrEmpty(userId)) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); newIdentity.AddClaims(await Context .ResolveClaimsAsync(tenantId.ToString(), userId) .ConfigureAwait(false)); } newPrincipal.AddIdentity(newIdentity); } else { newPrincipal.AddIdentity(identity); } } if (newPrincipal.Identity is null) { context.RejectPrincipal(); } else { context.ShouldRenew = true; context.ReplacePrincipal(newPrincipal); } } }; Events.OnRedirectToAccessDenied = (context) => { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; return(context.Response.CompleteAsync()); }; Events.OnRedirectToLogin = async(context) => { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; if (Request.Query.TryGetValue(AdapterAuthenticationDefaults.QueryParam, out var queryValue)) { var oneTimeTokenEntity = await oneTimeTokenService .InvalidateTokenAsync(queryValue.ToString()) .ConfigureAwait(false); if (oneTimeTokenEntity is not null) { var user = await userRepository .GetAsync(oneTimeTokenEntity.OrganizationId.ToString(), oneTimeTokenEntity.UserId.ToString(), expand : true) .ConfigureAwait(false); var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var claims = (await Context .ResolveClaimsAsync(tenantId.ToString(), oneTimeTokenEntity.UserId.ToString()) .ConfigureAwait(false)).ToList(); claims.Add(new Claim(ClaimTypes.Name, user.DisplayName)); claims.Add(new Claim(ObjectIdClaimType, oneTimeTokenEntity.UserId.ToString())); claims.Add(new Claim(TenantIdClaimType, tenantId.ToString())); claims.Add(new Claim(AdapterAuthenticationDefaults.ClaimType, oneTimeTokenEntity.Token)); var claimsIdentity = new ClaimsIdentity(claims, AdapterAuthenticationDefaults.AuthenticationType); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); await SignInAsync(claimsPrincipal, context.Properties).ConfigureAwait(false); context.Response.Redirect(OriginalPath); } } await context.Response .CompleteAsync() .ConfigureAwait(false); }; }
public virtual async Task <AzureServicePrincipal> GetServiceIdentityAsync(DeploymentScope deploymentScope, bool withPassword = false) { if (this is IAdapterIdentity) { var servicePrincipalKey = Guid.Parse(deploymentScope.Organization) .Combine(Guid.Parse(deploymentScope.Id)); var servicePrincipalName = $"{this.GetType().Name}/{servicePrincipalKey}"; var servicePrincipal = await graphService .GetServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); if (servicePrincipal is null) { // there is no service principal for the current deployment scope // create a new one that we can use to create/update the corresponding // service endpoint in the current team project servicePrincipal = await graphService .CreateServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); } else if (servicePrincipal.ExpiresOn.GetValueOrDefault(DateTime.MinValue) < DateTime.UtcNow) { // a service principal exists, but its secret is expired. lets refresh // the service principal (create a new secret) so we can move on // creating/updating the corresponding service endpoint. servicePrincipal = await graphService .RefreshServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); } if (!string.IsNullOrEmpty(servicePrincipal.Password)) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var organization = await organizationRepository .GetAsync(tenantId.ToString(), deploymentScope.Organization) .ConfigureAwait(false); var secretsStore = await secretsStoreProvider .GetSecretsStoreAsync(organization) .ConfigureAwait(false); servicePrincipal = await secretsStore .SetSecretAsync(servicePrincipal.Id.ToString(), servicePrincipal) .ConfigureAwait(false); } else if (withPassword) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var organization = await organizationRepository .GetAsync(tenantId.ToString(), deploymentScope.Organization) .ConfigureAwait(false); var secretsStore = await secretsStoreProvider .GetSecretsStoreAsync(organization) .ConfigureAwait(false); servicePrincipal = (await secretsStore .GetSecretAsync <AzureServicePrincipal>(servicePrincipal.Id.ToString()) .ConfigureAwait(false)) ?? servicePrincipal; } return(servicePrincipal); } return(null); }