예제 #1
0
    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);
    }
예제 #2
0
    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)));
        }
    }
예제 #4
0
    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);
            }
        }
    }
예제 #5
0
    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);
        };
    }
예제 #6
0
    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);
    }