public async Task Handle_WILL_InviteToChannel_AND_AddUserGroupUser()
        {
            // Arrange
            var capability = Capability.Create(
                id: Guid.NewGuid(),
                name: "FooCapability",
                slackChannelId: "FooChannelId",
                slackUserGroupId: "FooUserGroupId"
                );
            var slackFacadeSpy           = new SlackFacadeSpy();
            var stubCapabilityRepository = new StubCapabilityRepository();
            await stubCapabilityRepository.Add(capability);

            var slackMemberJoinedCapabilityDomainEventHandler = new SlackMemberJoinedCapabilityDomainEventHandler(
                null,
                slackFacadeSpy,
                stubCapabilityRepository,
                new SlackService(slackFacadeSpy, null)
                );
            var memberEmail = "*****@*****.**";
            var memberJoinedCapabilityDomainEvent = MemberJoinedCapabilityDomainEvent.Create(capability.Id, memberEmail);


            // Act
            await slackMemberJoinedCapabilityDomainEventHandler.HandleAsync(memberJoinedCapabilityDomainEvent);


            // Assert
            Assert.Equal(memberEmail, slackFacadeSpy.InvitedToChannel[new SlackChannelIdentifier(capability.SlackChannelId)].Single());
            Assert.Equal(memberEmail, slackFacadeSpy.UserGroupsUsers[capability.SlackUserGroupId].Single());
        }
예제 #2
0
        public async Task <IActionResult> UpdateCapability(string id, [FromBody] CapabilityInput input)
        {
            var capabilityId = Guid.Empty;

            Guid.TryParse(id, out capabilityId);


            IActionResult actionResult;

            try
            {
                var capability =
                    await _capabilityApplicationService.UpdateCapability(capabilityId, input.Name, input.Description);

                var dto = Capability.Create(capability);

                actionResult = Ok(
                    value: dto
                    );
            }
            catch (Exception exception) when(ExceptionToStatusCode.CanConvert(exception, out actionResult))
            {
            }

            return(actionResult);
        }
예제 #3
0
        public void expected_domain_event_is_raised_when_creating_a_capability()
        {
            var capability = Capability.Create("foo", "bar");

            Assert.Equal(
                expected: new[] { new CapabilityCreated(capability.Id, "foo") },
                actual: capability.DomainEvents,
                comparer: new PropertiesComparer <IDomainEvent>()
                );
        }
예제 #4
0
        public async Task HandleAsync(CapabilityCreatedDomainEvent domainEvent)
        {
            _logger.LogInformation($"Creating capability with name: {domainEvent.Data.CapabilityName}");

            var capability = Capability.Create(
                id: domainEvent.Data.CapabilityId,
                name: domainEvent.Data.CapabilityName);

            await _argocdFacade.CreateProject(capability.Name);
        }
예제 #5
0
        public async Task HandleAsync(CapabilityCreatedDomainEvent domainEvent)
        {
            var createChannelResponse = await _slackFacade.CreateChannel(domainEvent.Payload.CapabilityName);

            UserGroupDto userGroup = null;

            try
            {
                userGroup = await _slackService.EnsureUserGroupExists(domainEvent.Payload.CapabilityName);
            }
            catch (SlackFacadeException ex)
            {
                _logger.LogError($"Issue with Slack API during CreateUserGroup: {ex} : {ex.Message}");
            }


            var channelName = createChannelResponse?.Channel?.Name;


            if (createChannelResponse.Ok)
            {
                var channelId = new ChannelId(createChannelResponse?.Channel?.Id);
                _logger.LogInformation($"Slack channel '{channelName}' for capability '{domainEvent.Payload.CapabilityName}' created with ID: {channelId}");

                var userGroupId = userGroup?.Id;
                // Save even without user group.
                var capability = Capability.Create(
                    id: domainEvent.Payload.CapabilityId,
                    name: domainEvent.Payload.CapabilityName,
                    slackChannelId: channelId,
                    slackUserGroupId: userGroupId);
                _logger.LogInformation($"Capability id: '{capability.Id}'  name: '{capability.Name}' slackChannelId: '{capability.SlackChannelId}', userGroupId: '{capability.SlackUserGroupId}'");

                await _capabilityRepository.Add(capability);

                // Notify channel about handle.
                var sendNotificationResponse = await _slackFacade.SendNotificationToChannel(
                    channelIdentifier : channelId.ToString(),
                    message :
                    $"Thank you for creating capability '{capability.Name}'.\n" +
                    $"This channel along with handle @{userGroup.Handle} has been created.\n" +
                    "Use the handle to notify capability members.\n" +
                    $"If you want to define a better handle, you can do this in the '{userGroup.Name}'");

                // Pin message.
                await _slackFacade.PinMessageToChannel(channelId.ToString(), sendNotificationResponse.TimeStamp);
            }
            else
            {
                _logger.LogError($"Error creating Slack channel '{channelName}', Error: '{createChannelResponse.Error}'");
            }
        }
 public StubCapabilityRepository(List <Guid> capabilityIds)
 {
     foreach (var capabilityId in capabilityIds)
     {
         _capabilities.Add(
             Capability.Create(
                 id: capabilityId,
                 name: "FooCapability",
                 slackChannelId: "FooChannelId",
                 slackUserGroupId: "FooUserGroupId"
                 ));
     }
 }
예제 #7
0
        public async Task <Capability> CreateCapability(string name, string description)
        {
            if (!_nameValidationRegex.Match(name).Success)
            {
                throw new CapabilityValidationException("Name must be a string of length 3 to 32. consisting of only alphanumeric ASCII characters, starting with a capital letter. Underscores and hyphens are allowed.");
            }

            var capability = Capability.Create(name, description);
            await _capabilityRepository.Add(capability);

            await _roleService.CreateRoleFor(capability);

            return(capability);
        }
        public async Task GIVEN_query_with_ClientId_set_EXPECT_only_capabilities_with_given_id()
        {
            // Arrange
            var idOfWantedSender     = Guid.NewGuid();
            var capabilityRepository = new StubCapabilityRepository();
            await capabilityRepository.Add(Capability.Create(
                                               idOfWantedSender,
                                               "foo",
                                               "slackChannelId",
                                               "slackUserGroupId"
                                               ));

            await capabilityRepository.Add(Capability.Create(
                                               idOfWantedSender,
                                               "bar",
                                               "slackChannelId",
                                               "slackUserGroupId"
                                               ));

            await capabilityRepository.Add(Capability.Create(
                                               Guid.NewGuid(),
                                               "sheep",
                                               "slackChannelId",
                                               "slackUserGroupId"
                                               ));

            var slackFacadeSpy = new SlackFacadeSpy();

            var sut = new FindConnectionsByClientTypeClientIdChannelTypeChannelIdHandler(capabilityRepository, slackFacadeSpy);

            var clientIdOfWantedSender = new ClientId(idOfWantedSender.ToString());
            var query = new FindConnectionsByClientTypeClientIdChannelTypeChannelId(
                new ClientTypeCapability(),
                clientIdOfWantedSender,
                new ChannelTypeSlack(),
                null
                );


            // Act
            var results = await sut.HandleAsync(query);

            // Assert
            Assert.All(
                results,
                connection =>
                Assert.Equal(clientIdOfWantedSender, connection.ClientId)
                );
        }
        public async Task GIVEN_empty_query_EXPECT_connections_for_all_capabilities()
        {
            // Arrange
            var capabilityRepository = new StubCapabilityRepository();
            await capabilityRepository.Add(Capability.Create(
                                               Guid.NewGuid(),
                                               "foo",
                                               "slackChannelId",
                                               "slackUserGroupId"
                                               ));

            await capabilityRepository.Add(Capability.Create(
                                               Guid.NewGuid(),
                                               "bar",
                                               "slackChannelId",
                                               "slackUserGroupId"
                                               ));

            var slackFacadeSpy = new SlackFacadeSpy();

            slackFacadeSpy.Conversations.AddRange(new [] { new ChannelDto {
                                                               Id = "slackChannelId", Name = "slackChannelName"
                                                           } });
            var sut = new FindConnectionsByClientTypeClientIdChannelTypeChannelIdHandler(capabilityRepository, slackFacadeSpy);

            var query = new FindConnectionsByClientTypeClientIdChannelTypeChannelId(
                null,
                null,
                null,
                null
                );

            // Act
            var results = await sut.HandleAsync(query);

            Assert.All(
                capabilityRepository.GetAll().Result,
                capability =>
                results.Single(r =>
                               r.ClientId.ToString() == capability.Id.ToString()
                               )
                );
        }
예제 #10
0
        public async Task <IActionResult> CreateCapability(CapabilityInput input)
        {
            try {
                var capability = await _capabilityApplicationService.CreateCapability(input.Name, input.Description);

                var dto = Capability.Create(capability);

                return(CreatedAtAction(
                           actionName: nameof(GetCapability),
                           routeValues: new { id = capability.Id },
                           value: dto
                           ));
            } catch (CapabilityValidationException tve) {
                return(BadRequest(new
                {
                    Message = tve.Message
                }));
            }
        }
예제 #11
0
        public async Task <IActionResult> AddConnection(ConnectionDto connection)
        {
            if (string.IsNullOrEmpty(connection.ClientId))
            {
                return(BadRequest("ClientId ID is required."));
            }

            if (string.IsNullOrEmpty(connection.ClientType))
            {
                return(BadRequest("ClientType is required."));
            }

            if (string.IsNullOrEmpty(connection.ClientName))
            {
                return(BadRequest("ClientName is required."));
            }

            if (string.IsNullOrEmpty(connection.ChannelId))
            {
                return(BadRequest("Channel ID is required."));
            }

            if (string.IsNullOrEmpty(connection.ChannelType))
            {
                return(BadRequest("ChannelType is required."));
            }

            if (string.IsNullOrEmpty(connection.ChannelName))
            {
                return(BadRequest("ChannelName is required."));
            }

            var userGroup = await _slackService.EnsureUserGroupExists(connection.ClientName);

            var capability = Capability.Create(Guid.Parse(connection.ClientId), connection.ClientName,
                                               connection.ChannelId, userGroup.Id);

            await _capabilityRepository.Add(capability);

            var response = await _slackFacade.JoinChannel(((ChannelName)connection.ChannelName).ToString());

            return(Accepted(response.Channel));
        }
예제 #12
0
        public async Task <IActionResult> GetCapability(string id)
        {
            var capabilityId = Guid.Empty;

            Guid.TryParse(id, out capabilityId);

            var capability = await _capabilityApplicationService.GetCapability(capabilityId);

            if (capability == null)
            {
                return(NotFound(new
                {
                    Message = $"A capability with id \"{id}\" could not be found."
                }));
            }

            var dto = Capability.Create(capability);

            return(Ok(dto));
        }
예제 #13
0
        public async Task <IActionResult> CreateCapability(CapabilityInput input)
        {
            IActionResult actionResult;

            try
            {
                var capability = await _capabilityApplicationService.CreateCapability(input.Name, input.Description);

                var dto = Capability.Create(capability);

                actionResult = CreatedAtAction(
                    actionName: nameof(GetCapability),
                    routeValues: new { id = capability.Id },
                    value: dto
                    );
            }
            catch (Exception exception) when(ExceptionToStatusCode.CanConvert(exception, out actionResult))
            {
            }

            return(actionResult);
        }
        public async Task Handle_will_SendNotificationToChannel_Ded_AND_SendNotificationToChannel_CapabilityId()
        {
            // Arrange
            var capability = Capability.Create(
                Guid.NewGuid(),
                "",
                "slackChannelId",
                ""
                );
            var slackFacadeSpy           = new SlackFacadeSpy();
            var stubCapabilityRepository = new StubCapabilityRepository();
            await stubCapabilityRepository.Add(capability);

            var slackContextAddedToCapabilityDomainEventHandler = new SlackContextAddedToCapabilityDomainEventHandler(
                stubCapabilityRepository,
                slackFacadeSpy,
                new ExternalEventMetaDataStore()
                );

            var contextAddedToCapabilityDomainEvent = ContextAddedToCapabilityDomainEvent.Create(
                capability.Id,
                "",
                "",
                Guid.NewGuid(),
                ""
                );


            // Act
            await slackContextAddedToCapabilityDomainEventHandler
            .HandleAsync(contextAddedToCapabilityDomainEvent);

            // Assert
            var hardCodedDedChannelId = new SlackChannelIdentifier("GFYE9B99Q");

            Assert.NotEmpty(slackFacadeSpy.ChannelsMessages[hardCodedDedChannelId]);
            Assert.NotEmpty(slackFacadeSpy.ChannelsMessages[capability.SlackChannelId.ToString()]);
        }
예제 #15
0
        public async Task Handle_WILL_remove_user_from_channel_AND_user_group_AND_notify_user()
        {
            // Arrange
            var capability = Capability.Create(
                Guid.NewGuid(),
                "",
                "slackChannelId",
                "theUserGroup"
                );
            var userEmail = "*****@*****.**";
            await capability.AddMember(userEmail);

            var nullLogger               = new NullLogger <SlackMemberLeftCapabilityDomainEventHandler>();
            var slackFacadeSpy           = new SlackFacadeSpy();
            var stubCapabilityRepository = new StubCapabilityRepository();
            await stubCapabilityRepository.Add(capability);

            var slackMemberLeftCapabilityDomainEventHandler = new SlackMemberLeftCapabilityDomainEventHandler(
                nullLogger,
                slackFacadeSpy,
                stubCapabilityRepository
                );


            var memberLeftCapabilityDomainEvent = MemberLeftCapabilityDomainEvent.Create(capability.Id, userEmail);


            // Act

            await slackMemberLeftCapabilityDomainEventHandler.HandleAsync(memberLeftCapabilityDomainEvent);

            // Assert
            Assert.Equal(userEmail, slackFacadeSpy.RemovedFromChannel[capability.SlackChannelId.ToString()].First());
            Assert.Equal(userEmail, slackFacadeSpy.RemovedFromUsergroup[capability.SlackUserGroupId.ToString()].First());
            Assert.NotEmpty(slackFacadeSpy.UsersToNotifications[userEmail]);
        }
예제 #16
0
        public async Task <IActionResult> DeleteConnection(
            [FromQuery] string clientType,
            [FromQuery] string clientId,
            [FromQuery] string channelType,
            [FromQuery] string channelId)
        {
            if (string.IsNullOrEmpty(clientId))
            {
                return(BadRequest(new { message = "ClientId ID is required." }));
            }

            ClientType  clientTypeValueObject;
            ChannelType channelTypeValueObject;

            try
            {
                clientTypeValueObject  = string.IsNullOrEmpty(clientType) ? null : (ClientType)clientType;
                channelTypeValueObject = string.IsNullOrEmpty(channelType) ? null : (ChannelType)channelType;
            }
            catch (ValidationException validationException)
            {
                return(StatusCode(
                           (int)HttpStatusCode.UnprocessableEntity,
                           new { message = validationException.MessageToUser }
                           ));
            }

            var getMatchedConnectionsQuery = new FindConnectionsByClientTypeClientIdChannelTypeChannelId(
                clientTypeValueObject,
                (ClientId)clientId,
                channelTypeValueObject,
                (ChannelId)channelId);

            var matchedConnections =
                await _findConnectionsByClientTypeClientIdChannelTypeChannelIdQueryHandler.HandleAsync(
                    getMatchedConnectionsQuery);

            foreach (var connection in matchedConnections)
            {
                await _slackFacade.LeaveChannel(connection.ChannelId.ToString());

                var getAllChannelConnectionsQuery = new FindConnectionsByClientTypeClientIdChannelTypeChannelId(
                    null,
                    null,
                    connection.ChannelType,
                    connection.ChannelId);

                var allChannelConnections =
                    await _findConnectionsByClientTypeClientIdChannelTypeChannelIdQueryHandler.HandleAsync(
                        getAllChannelConnectionsQuery);

                var capability = Capability.Create(Guid.Parse(connection.ClientId), connection.ClientName,
                                                   connection.ChannelId, "");
                await _capabilityRepository.Remove(capability);

                if (allChannelConnections.All(c => c.ClientId.ToString().Equals(clientId)))
                {
                    var channelsAll = await _slackFacade.GetConversations();

                    var channelsWhereConnectionIdAndChannelCreatorMatches = channelsAll.Channels.Where(ch =>
                                                                                                       ch.Creator.Equals(_slackFacade.GetBotUserId())
                                                                                                       &&
                                                                                                       ch.Id.Equals(connection.ChannelId));

                    if (channelsWhereConnectionIdAndChannelCreatorMatches.Any())
                    {
                        await _slackFacade.ArchiveChannel(connection.ChannelId.ToString());
                    }
                }
            }

            return(Accepted());
        }