예제 #1
0
        public async Task <IActionResult> Post([FromBody] UserDefinition userDefinition)
        {
            if (userDefinition is null)
            {
                throw new ArgumentNullException(nameof(userDefinition));
            }

            var validation = new UserDefinitionValidator().Validate(userDefinition);

            if (!validation.IsValid)
            {
                return(ErrorResult
                       .BadRequest(validation)
                       .ActionResult());
            }

            var teamCloudInstance = await teamCloudRepository
                                    .GetAsync()
                                    .ConfigureAwait(false);

            if (teamCloudInstance is null)
            {
                return(ErrorResult
                       .NotFound($"No TeamCloud Instance was found.")
                       .ActionResult());
            }

            var newUser = await userService
                          .GetUserAsync(userDefinition)
                          .ConfigureAwait(false);

            if (newUser is null)
            {
                return(ErrorResult
                       .NotFound($"A User with the Email '{userDefinition.Email}' could not be found.")
                       .ActionResult());
            }

            if (teamCloudInstance.Users.Contains(newUser))
            {
                return(ErrorResult
                       .Conflict($"A User with the Email '{userDefinition.Email}' already exists on this TeamCloud Instance. Please try your request again with a unique email or call PUT to update the existing User.")
                       .ActionResult());
            }

            var command = new OrchestratorTeamCloudUserCreateCommand(CurrentUser, newUser);

            var commandResult = await orchestrator
                                .InvokeAsync(command)
                                .ConfigureAwait(false);

            if (commandResult.Links.TryGetValue("status", out var statusUrl))
            {
                return(StatusResult
                       .Accepted(commandResult.CommandId.ToString(), statusUrl, commandResult.RuntimeStatus.ToString(), commandResult.CustomStatus)
                       .ActionResult());
            }

            throw new Exception("This shouldn't happen, but we need to decide to do when it does.");
        }
        public async Task <IActionResult> Post([FromBody] UserDefinition userDefinition)
        {
            if (userDefinition is null)
            {
                throw new ArgumentNullException(nameof(userDefinition));
            }

            var validation = new UserDefinitionTeamCloudAdminValidator().Validate(userDefinition);

            if (!validation.IsValid)
            {
                return(ErrorResult
                       .BadRequest(validation)
                       .ActionResult());
            }

            var adminUsers = await usersRepository
                             .ListAdminsAsync()
                             .AnyAsync()
                             .ConfigureAwait(false);

            if (adminUsers)
            {
                return(ErrorResult
                       .BadRequest($"The TeamCloud instance already has one or more Admin users. To add additional users to the TeamCloud instance POST to api/users.", ResultErrorCode.ValidationError)
                       .ActionResult());
            }

            var userId = await userService
                         .GetUserIdAsync(userDefinition.Identifier)
                         .ConfigureAwait(false);

            if (string.IsNullOrEmpty(userId))
            {
                return(ErrorResult
                       .NotFound($"The user '{userDefinition.Identifier}' could not be found.")
                       .ActionResult());
            }

            var user = new User
            {
                Id         = userId,
                Role       = Enum.Parse <TeamCloudUserRole>(userDefinition.Role, true),
                Properties = userDefinition.Properties,
                UserType   = UserType.User
            };

            // no users exist in the database yet and the cli calls this api implicitly immediatly
            // after the teamcloud instance is created to add the instance creator as an admin user
            // thus, we can assume the calling user and the user from the payload are the same
            var command = new OrchestratorTeamCloudUserCreateCommand(user, user);

            return(await orchestrator
                   .InvokeAndReturnAccepted(command)
                   .ConfigureAwait(false));
        }
예제 #3
0
        public async Task <IActionResult> Post([FromBody] UserDefinition userDefinition)
        {
            if (userDefinition is null)
            {
                throw new ArgumentNullException(nameof(userDefinition));
            }

            var validation = new UserDefinitionTeamCloudValidator().Validate(userDefinition);

            if (!validation.IsValid)
            {
                return(ErrorResult
                       .BadRequest(validation)
                       .ActionResult());
            }

            var userId = await userService
                         .GetUserIdAsync(userDefinition.Identifier)
                         .ConfigureAwait(false);

            if (string.IsNullOrEmpty(userId))
            {
                return(ErrorResult
                       .NotFound($"The user '{userDefinition.Identifier}' could not be found.")
                       .ActionResult());
            }

            var user = await usersRepository
                       .GetAsync(userId)
                       .ConfigureAwait(false);

            if (user != null)
            {
                return(ErrorResult
                       .Conflict($"The user '{userDefinition.Identifier}' already exists on this TeamCloud Instance. Please try your request again with a unique user or call PUT to update the existing User.")
                       .ActionResult());
            }

            user = new Model.Internal.Data.User
            {
                Id         = userId,
                Role       = Enum.Parse <TeamCloudUserRole>(userDefinition.Role, true),
                Properties = userDefinition.Properties,
                UserType   = UserType.User
            };

            var currentUserForCommand = await userService
                                        .CurrentUserAsync()
                                        .ConfigureAwait(false);

            var command = new OrchestratorTeamCloudUserCreateCommand(currentUserForCommand, user);

            return(await orchestrator
                   .InvokeAndReturnAccepted(command)
                   .ConfigureAwait(false));
        }
예제 #4
0
        public async Task InitializeAsync()
        {
            var log = loggerFactory.CreateLogger(this.GetType());

            if (!hostingEnvironment.IsDevelopment())
            {
                log.LogInformation($"Hosting environment is '{hostingEnvironment.EnvironmentName}' - skip admin initialization");

                return;
            }

            try
            {
                var exists = await usersRepository
                             .ListAdminsAsync()
                             .AnyAsync()
                             .ConfigureAwait(false);

                if (exists)
                {
                    log.LogInformation($"Environment is initialized with at least 1 admin user.");

                    return;
                }

                var user = new UserDocument
                {
                    Id       = await ResolveAzureCliUserId().ConfigureAwait(false),
                    Role     = TeamCloudUserRole.Admin,
                    UserType = UserType.User
                };

                var command = new OrchestratorTeamCloudUserCreateCommand(user, user);

                var commandResult = await orchestrator
                                    .ExecuteAsync(command)
                                    .ConfigureAwait(false);

                if (commandResult.RuntimeStatus == CommandRuntimeStatus.Completed)
                {
                    log.LogInformation($"Initialized environment with user '{user.Id}' as admin");
                }
                else
                {
                    log.LogWarning($"Failed to initialize environment with user '{user.Id}': {commandResult.Errors.FirstOrDefault()?.Message}");
                }
            }
            catch (Exception exc)
            {
                log.LogError(exc, $"Failed to process initializer {this.GetType().Name}: {exc.Message}");
            }
        }
예제 #5
0
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (next is null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            // teamcloud needs a at least one admin user to work properly.
            // to avoid calls that will fail because of a missing user
            // we will check its existance in this middleware and block
            // calls until at least one admin user is in place.

            // as we ensure there is at least one admin user in the delete
            // and update apis we can keep the HasAdmin state once it is
            // evaluated to true to avoid unnecessary request to the
            // teamcloud repository in the future.

            HasAdmin = HasAdmin || await AdminExistsAsync().ConfigureAwait(false);

            if (HasAdmin)
            {
                await next(context).ConfigureAwait(false);
            }
            else
            {
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;

                var error     = ErrorResult.BadRequest("Must POST an Admin user to api/admin/users before calling any other APIs.", ResultErrorCode.ValidationError);
                var errorJson = JsonConvert.SerializeObject(error);

                await context.Response
                .WriteAsync(errorJson)
                .ConfigureAwait(false);
            }

            async Task <bool> AdminExistsAsync()
            {
                var exists = await usersRepository
                             .ListAdminsAsync()
                             .AnyAsync()
                             .ConfigureAwait(false);

                if (!exists && hostingEnvironment.IsDevelopment())
                {
                    var objectId = context.User.GetObjectId();

                    if (!string.IsNullOrEmpty(objectId))
                    {
                        var user = new UserDocument
                        {
                            Id       = objectId,
                            Role     = TeamCloudUserRole.Admin,
                            UserType = UserType.User
                        };

                        var command = new OrchestratorTeamCloudUserCreateCommand(context.GetApplicationBaseUrl(), user, user);

                        _ = await orchestrator
                            .InvokeAsync(command)
                            .ConfigureAwait(false);

                        for (int i = 0; i < 60; i++)
                        {
                            await Task
                            .Delay(1000)
                            .ConfigureAwait(false);

                            exists = await usersRepository
                                     .ListAdminsAsync()
                                     .AnyAsync()
                                     .ConfigureAwait(false);

                            if (exists)
                            {
                                break;
                            }
                        }
                    }
                }

                return(exists);
            }
        }
        public async Task InitializeAsync()
        {
            var log = loggerFactory.CreateLogger(this.GetType());

            if (!hostingEnvironment.IsDevelopment())
            {
                log.LogInformation($"Hosting environment is '{hostingEnvironment.EnvironmentName}' - skip admin initialization");

                return;
            }

            try
            {
                var exists = await userRepository
                             .ListAdminsAsync()
                             .AnyAsync()
                             .ConfigureAwait(false);

                if (exists)
                {
                    log.LogInformation($"Environment is initialized with at least 1 admin user.");

                    return;
                }

                var user = new UserDocument
                {
                    Id       = await ResolveAzureCliUserId().ConfigureAwait(false),
                    Role     = TeamCloudUserRole.Admin,
                    UserType = UserType.User
                };

                var command       = new OrchestratorTeamCloudUserCreateCommand(user, user);
                var commandResult = (ICommandResult)command.CreateResult();

                var commandSendDuration = TimeSpan.FromMinutes(5);
                var commandSendTimeout  = DateTime.UtcNow.Add(commandSendDuration);

                while (DateTime.UtcNow < commandSendTimeout)
                {
                    try
                    {
                        commandResult = await orchestrator
                                        .InvokeAsync(command)
                                        .ConfigureAwait(false);

                        break;
                    }
                    catch (FlurlHttpException exc) when(exc.Call.HttpStatus == System.Net.HttpStatusCode.BadGateway)
                    {
                        log.LogWarning(exc, $"Failed to initialize environment with user '{user.Id}' - will retry in a second");

                        await Task
                        .Delay(1000)
                        .ConfigureAwait(false);
                    }
                }

                var commandResultDuration = TimeSpan.FromMinutes(5);
                var commandResultTimeout  = DateTime.UtcNow.Add(commandResultDuration);

                while (DateTime.UtcNow < commandResultTimeout && commandResult.RuntimeStatus.IsActive())
                {
                    await Task
                    .Delay(1000)
                    .ConfigureAwait(false);

                    commandResult = await orchestrator
                                    .QueryAsync(command)
                                    .ConfigureAwait(false);
                }

                if (commandResult.RuntimeStatus == CommandRuntimeStatus.Completed)
                {
                    log.LogInformation($"Initialized environment with user '{user.Id}' as admin");
                }
                else
                {
                    log.LogWarning($"Failed to initialize environment with user '{user.Id}': {commandResult.Errors.FirstOrDefault()?.Message ?? commandResult.RuntimeStatus.ToString()}");
                }
            }
            catch (Exception exc)
            {
                log.LogError(exc, $"Failed to process initializer {this.GetType().Name}: {exc.Message}");
            }
        }