diff --git a/connectors/slack/element-templates/slack-connector.json b/connectors/slack/element-templates/slack-connector.json index dcddf5ad71..a169aa7bf3 100644 --- a/connectors/slack/element-templates/slack-connector.json +++ b/connectors/slack/element-templates/slack-connector.json @@ -34,6 +34,10 @@ "id": "channel", "label": "Channel" }, + { + "id": "invite", + "label": "Invite" + }, { "id": "output", "label": "Output Mapping" @@ -65,6 +69,10 @@ { "name": "Create Channel", "value": "conversations.create" + }, + { + "name": "Invite to Channel", + "value": "conversations.invite" } ], "binding": { @@ -169,6 +177,44 @@ "equals": "chat.postMessage" } }, + { + "label": "Channel Name", + "group": "invite", + "type": "String", + "feel": "optional", + "binding": { + "type": "zeebe:input", + "name": "data.channelName" + }, + "constraints": { + "notEmpty": true, + "pattern": { + "value": "^(=|[-_a-z0-9]{1,80}$)", + "message": "May contain up to 80 lowercase letters, digits, underscores, and dashes" + } + }, + "condition": { + "property": "method", + "equals": "conversations.invite" + } + }, + { + "label": "Users", + "description": "Comma separated list of invitee names", + "group": "invite", + "type": "String", + "binding": { + "type": "zeebe:input", + "name": "data.users" + }, + "constraints": { + "notEmpty": true + }, + "condition": { + "property": "method", + "equals": "conversations.invite" + } + }, { "label": "Result Variable", "description": "Name of variable to store the response in", diff --git a/connectors/slack/pom.xml b/connectors/slack/pom.xml index 742ee8c2e6..d7456cbd28 100644 --- a/connectors/slack/pom.xml +++ b/connectors/slack/pom.xml @@ -99,6 +99,11 @@ except in compliance with the proprietary license. mockito-junit-jupiter test + + io.camunda + spring-zeebe-connector-runtime + test + diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/ChatPostMessageData.java b/connectors/slack/src/main/java/io/camunda/connector/slack/ChatPostMessageData.java index 8872b1a41e..bb642e206e 100644 --- a/connectors/slack/src/main/java/io/camunda/connector/slack/ChatPostMessageData.java +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/ChatPostMessageData.java @@ -9,10 +9,8 @@ import com.slack.api.methods.MethodsClient; import com.slack.api.methods.SlackApiException; import com.slack.api.methods.request.chat.ChatPostMessageRequest; -import com.slack.api.methods.request.users.UsersListRequest; import com.slack.api.methods.request.users.UsersLookupByEmailRequest; import com.slack.api.methods.response.chat.ChatPostMessageResponse; -import com.slack.api.methods.response.users.UsersListResponse; import com.slack.api.methods.response.users.UsersLookupByEmailResponse; import com.slack.api.model.User; import io.camunda.connector.api.annotation.Secret; @@ -24,16 +22,14 @@ public class ChatPostMessageData implements SlackRequestData { - private static final String EMAIL_REGEX = "^.+[@].+[.].{2,4}$"; - @NotBlank @Secret private String channel; @NotBlank @Secret private String text; @Override public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiException, IOException { if (channel.startsWith("@")) { - channel = getUserId(channel.substring(1), methodsClient); - } else if (isEmail(channel)) { + channel = DataLookupService.getUserIdByName(channel.substring(1), methodsClient); + } else if (DataLookupService.isEmail(channel)) { channel = getUserIdByEmail(methodsClient); } ChatPostMessageRequest request = @@ -52,44 +48,6 @@ public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiExceptio } } - private String getUserId(String userName, MethodsClient methodsClient) { - String userId = null; - String nextCursor = null; - - do { - UsersListRequest request = UsersListRequest.builder().limit(100).cursor(nextCursor).build(); - - try { - UsersListResponse response = methodsClient.usersList(request); - if (response.isOk()) { - userId = - response.getMembers().stream() - .filter(user -> userName.equals(user.getRealName())) - .map(User::getId) - .findFirst() - .orElse(null); - nextCursor = response.getResponseMetadata().getNextCursor(); - } else { - throw new RuntimeException( - "Unable to find user with name: " + userName + "; message: " + response.getError()); - } - } catch (Exception e) { - throw new RuntimeException("Unable to find user with name: " + userName, e); - } - - } while (userId == null && nextCursor != null && !nextCursor.isBlank()); - - if (userId == null) { - throw new RuntimeException("Unable to find user with name: " + userName); - } - - return userId; - } - - private boolean isEmail(final String str) { - return str.matches(EMAIL_REGEX); - } - private String getUserIdByEmail(final MethodsClient methodsClient) throws IOException, SlackApiException { UsersLookupByEmailRequest lookupByEmailRequest = diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/Conversation.java b/connectors/slack/src/main/java/io/camunda/connector/slack/Conversation.java new file mode 100644 index 0000000000..c1844b8797 --- /dev/null +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/Conversation.java @@ -0,0 +1,44 @@ +package io.camunda.connector.slack; + +import java.util.Objects; + +public class Conversation { + + private final String id; + private final String name; + + public Conversation(com.slack.api.model.Conversation conversation) { + this.id = conversation.getId(); + this.name = conversation.getName(); + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Conversation that = (Conversation) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + return "Conversation{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; + } +} diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsCreateSlackResponse.java b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsCreateSlackResponse.java index 152511b656..93bed4ae86 100644 --- a/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsCreateSlackResponse.java +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsCreateSlackResponse.java @@ -42,45 +42,4 @@ public int hashCode() { public String toString() { return "ConversationsCreateSlackResponse{" + "channel=" + channel + '}'; } - - protected static class Conversation { - - private final String id; - private final String name; - - public Conversation(com.slack.api.model.Conversation conversation) { - this.id = conversation.getId(); - this.name = conversation.getName(); - } - - public String getId() { - return id; - } - - public String getName() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Conversation that = (Conversation) o; - return Objects.equals(id, that.id) && Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } - - @Override - public String toString() { - return "Conversation{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; - } - } } diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteData.java b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteData.java new file mode 100644 index 0000000000..6392b19057 --- /dev/null +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteData.java @@ -0,0 +1,78 @@ +package io.camunda.connector.slack; + +import com.slack.api.methods.MethodsClient; +import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.request.conversations.ConversationsInviteRequest; +import com.slack.api.methods.response.conversations.ConversationsInviteResponse; +import io.camunda.connector.api.annotation.Secret; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +public class ConversationsInviteData implements SlackRequestData { + + @NotBlank + @Secret + private String channelName; + @NotBlank + @Secret + private String users; + + @Override + public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiException, IOException { + List userList = DataLookupService.getUserIdsFromNameOrEmail(DataLookupService.convertStringToList(users), methodsClient); + ConversationsInviteRequest request = + ConversationsInviteRequest.builder() + .channel(DataLookupService.getChannelIdByName(channelName, methodsClient)) + .users(userList) + .build(); + + ConversationsInviteResponse response = methodsClient.conversationsInvite(request); + + if (response.isOk()) { + return new ConversationsInviteSlackResponse(response); + } else { + throw new RuntimeException(response.getError()); + } + } + + public String getChannelName() { + return channelName; + } + + public void setChannelName(String channelName) { + this.channelName = channelName; + } + + public String getUsers() { + return users; + } + + public void setUsers(String users) { + this.users = users; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConversationsInviteData that = (ConversationsInviteData) o; + return channelName.equals(that.channelName) && Objects.equals(users, that.users); + } + + @Override + public int hashCode() { + return Objects.hash(channelName, users); + } + + @Override + public String toString() { + return "ConversationsInviteData{" + + "channelName='" + channelName + '\'' + + ", users=" + users + + '}'; + } +} diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteSlackResponse.java b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteSlackResponse.java new file mode 100644 index 0000000000..cf9ef57ac0 --- /dev/null +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/ConversationsInviteSlackResponse.java @@ -0,0 +1,42 @@ +package io.camunda.connector.slack; + +import com.slack.api.methods.response.conversations.ConversationsInviteResponse; +import java.util.Objects; + +public class ConversationsInviteSlackResponse implements SlackResponse { + + private final Conversation channel; + private final String needed; + private final String provided; + + public ConversationsInviteSlackResponse(ConversationsInviteResponse conversationsInviteResponse) { + this.channel = new Conversation(conversationsInviteResponse.getChannel()); + this.needed = conversationsInviteResponse.getNeeded(); + this.provided = conversationsInviteResponse.getProvided(); + } + + public Conversation getChannel() { + return channel; + } + + public String getNeeded() { + return needed; + } + + public String getProvided() { + return provided; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConversationsInviteSlackResponse that = (ConversationsInviteSlackResponse) o; + return Objects.equals(channel, that.channel) && Objects.equals(needed, that.needed) && Objects.equals(provided, that.provided); + } + + @Override + public int hashCode() { + return Objects.hash(channel, needed, provided); + } +} diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/DataLookupService.java b/connectors/slack/src/main/java/io/camunda/connector/slack/DataLookupService.java new file mode 100644 index 0000000000..065eb64c68 --- /dev/null +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/DataLookupService.java @@ -0,0 +1,166 @@ +package io.camunda.connector.slack; + +import com.slack.api.methods.MethodsClient; +import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.request.conversations.ConversationsListRequest; +import com.slack.api.methods.request.users.UsersListRequest; +import com.slack.api.methods.request.users.UsersLookupByEmailRequest; +import com.slack.api.methods.response.conversations.ConversationsListResponse; +import com.slack.api.methods.response.users.UsersListResponse; +import com.slack.api.methods.response.users.UsersLookupByEmailResponse; +import com.slack.api.model.Conversation; +import com.slack.api.model.User; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class DataLookupService { + + private static final String EMAIL_REGEX = "^.+[@].+[.].{2,4}$"; + + public static List convertStringToList(String string) { + if(StringUtils.isBlank(string)) { + return new ArrayList<>(); + } + return Arrays.stream(string.split(",")).map(s -> s.trim()).collect(Collectors.toList()); + } + + public static boolean isEmail(final String str) { + return str.matches(EMAIL_REGEX); + } + + public static List getUserIdsFromNameOrEmail(List userList, MethodsClient methodsClient) { + if(Objects.isNull(userList) || userList.isEmpty()) { + return new ArrayList<>(); + } + + List emails = new ArrayList<>(); + List usernames = new ArrayList<>(); + userList.stream().forEach(user -> (isEmail(user) ? emails : usernames).add(user)); + + List idListByEmail = emails.stream() + .map(email -> { + try { + return getUserIdByEmail(email, methodsClient); + } catch (Exception e) { + throw new RuntimeException("Unable to find user with name or email : " + email, e); + } + }) + .collect(Collectors.toList()); + + List idListByUserName = getIdListByUserNameList(usernames, methodsClient); + + return Stream.concat(idListByEmail.stream(), idListByUserName.stream()).collect(Collectors.toList()); + } + + public static String getUserIdByEmail(String email, MethodsClient methodsClient) throws SlackApiException, IOException { + UsersLookupByEmailRequest lookupByEmailRequest = UsersLookupByEmailRequest.builder().email(email).build(); + return Optional.ofNullable(methodsClient.usersLookupByEmail(lookupByEmailRequest)) + .filter(UsersLookupByEmailResponse::isOk) + .map(UsersLookupByEmailResponse::getUser) + .map(User::getId) + .orElseThrow(() -> new RuntimeException("Unable to find user with email: " + email)); + } + + public static List getIdListByUserNameList(List userNameList, MethodsClient methodsClient) { + if(userNameList == null || userNameList.isEmpty()) { + return new ArrayList<>(); + } + String nextCursor = null; + List idList = new ArrayList<>(); + do { + UsersListRequest request = UsersListRequest.builder().limit(100).cursor(nextCursor).build(); + + try { + UsersListResponse response = methodsClient.usersList(request); + if (response.isOk()) { + idList.addAll(response.getMembers().stream() + .filter(user -> userNameList.contains(user.getRealName())) + .map(User::getId) + .collect(Collectors.toList())); + nextCursor = response.getResponseMetadata().getNextCursor(); + } else { + throw new RuntimeException( + "Unable to get users; message: " + response.getError()); + } + } catch (Exception e) { + throw new RuntimeException("Unable to find users by name", e); + } + + } while (idList.size() < userNameList.size() && nextCursor != null && !nextCursor.isBlank()); + return idList; + } + + public static String getChannelIdByName(String channelName, MethodsClient methodsClient) { + String channelId = null; + String nextCursor = null; + + do { + ConversationsListRequest request = ConversationsListRequest.builder().limit(100).cursor(nextCursor).build(); + + try { + ConversationsListResponse response = methodsClient.conversationsList(request); + if (response.isOk()) { + channelId = + response.getChannels().stream() + .filter(channel -> channelName.equals(channel.getName())) + .map(Conversation::getId) + .findFirst() + .orElse(null); + nextCursor = response.getResponseMetadata().getNextCursor(); + } else { + throw new RuntimeException( + "Unable to find conversation with channel name: " + channelName + "; message: " + response.getError()); + } + } catch (Exception e) { + throw new RuntimeException("Unable to find conversation with name: " + channelName, e); + } + + } while (channelId == null && nextCursor != null && !nextCursor.isBlank()); + + if (channelId == null) { + throw new RuntimeException("Unable to find conversation with name: " + channelName); + } + + return channelId; + } + + public static String getUserIdByName(String userName, MethodsClient methodsClient) { + String userId = null; + String nextCursor = null; + + do { + UsersListRequest request = UsersListRequest.builder().limit(100).cursor(nextCursor).build(); + + try { + UsersListResponse response = methodsClient.usersList(request); + if (response.isOk()) { + userId = + response.getMembers().stream() + .filter(user -> userName.equals(user.getRealName())) + .map(User::getId) + .findFirst() + .orElse(null); + nextCursor = response.getResponseMetadata().getNextCursor(); + } else { + throw new RuntimeException( + "Unable to find user with name: " + userName + "; message: " + response.getError()); + } + } catch (Exception e) { + throw new RuntimeException("Unable to find user with name: " + userName, e); + } + + } while (userId == null && nextCursor != null && !nextCursor.isBlank()); + + if (userId == null) { + throw new RuntimeException("Unable to find user with name: " + userName); + } + + return userId; + } + + +} diff --git a/connectors/slack/src/main/java/io/camunda/connector/slack/GsonSupplier.java b/connectors/slack/src/main/java/io/camunda/connector/slack/GsonSupplier.java index ac77809758..f9f155f1d1 100644 --- a/connectors/slack/src/main/java/io/camunda/connector/slack/GsonSupplier.java +++ b/connectors/slack/src/main/java/io/camunda/connector/slack/GsonSupplier.java @@ -13,8 +13,9 @@ public final class GsonSupplier { private static final SlackRequestDeserializer DESERIALIZER = new SlackRequestDeserializer("method") - .registerType("chat.postMessage", ChatPostMessageData.class) - .registerType("conversations.create", ConversationsCreateData.class); + .registerType("chat.postMessage", ChatPostMessageData.class) + .registerType("conversations.create", ConversationsCreateData.class) + .registerType("conversations.invite", ConversationsInviteData.class); private static final Gson GSON = new GsonBuilder().registerTypeAdapter(SlackRequest.class, DESERIALIZER).create(); diff --git a/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteDataTest.java b/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteDataTest.java new file mode 100644 index 0000000000..e0b082d904 --- /dev/null +++ b/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteDataTest.java @@ -0,0 +1,111 @@ +package io.camunda.connector.slack; + +import com.slack.api.methods.MethodsClient; +import com.slack.api.methods.SlackApiException; +import com.slack.api.methods.request.conversations.ConversationsInviteRequest; +import com.slack.api.methods.request.conversations.ConversationsListRequest; +import com.slack.api.methods.request.users.UsersLookupByEmailRequest; +import com.slack.api.methods.response.conversations.ConversationsInviteResponse; +import com.slack.api.methods.response.conversations.ConversationsListResponse; +import com.slack.api.methods.response.users.UsersLookupByEmailResponse; +import com.slack.api.model.*; +import com.slack.api.model.Conversation; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class ConversationsInviteDataTest { + @Mock + private MethodsClient methodsClient; + @Mock private UsersLookupByEmailResponse lookupByEmailResponse; + @Mock private ConversationsListResponse conversationsListResponse; + @Mock private User user; + @Mock private ConversationsInviteResponse conversationsInviteResponse; + + @Captor + private ArgumentCaptor conversationsInviteRequest; + + private static final String USERID = "testUserId"; + + private static final String CHANNEL_NAME = "channel"; + + @Test + void invoke_shouldThrowExceptionWhenUserNotFoundByEmail() throws SlackApiException, IOException { + // Given + ConversationsInviteData conversationsInviteData = new ConversationsInviteData(); + conversationsInviteData.setChannelName(CHANNEL_NAME); + conversationsInviteData.setUsers("test1@test.com, test2@test.com"); + when(methodsClient.usersLookupByEmail(any(UsersLookupByEmailRequest.class))).thenReturn(null); + // When and then + RuntimeException thrown = + assertThrows( + RuntimeException.class, + () -> conversationsInviteData.invoke(methodsClient), + "RuntimeException was expected"); + assertThat(thrown.getMessage()) + .contains( + "Unable to find user with name or email : test1@test.com"); + } + + @ParameterizedTest + @ValueSource( + strings = { + "test1@test.com, test2@test.com", + "firstName.LastName1@mail.org,firstName.LastName2@mail.org", + "n.a.m.e@mail.ua", + "a@m.uat", + "_23@ma.au" + }) + void invoke_shouldFindUserIdByEmail(final String emailList) throws SlackApiException, IOException { + // Given + ConversationsInviteData conversationsInviteData = new ConversationsInviteData(); + conversationsInviteData.setUsers(emailList); + conversationsInviteData.setChannelName(CHANNEL_NAME); + + when(methodsClient.usersLookupByEmail(any(UsersLookupByEmailRequest.class))) + .thenReturn(lookupByEmailResponse); + when(lookupByEmailResponse.isOk()).thenReturn(true); + when(lookupByEmailResponse.getUser()).thenReturn(user); + when(user.getId()).thenReturn(USERID); + + when(methodsClient.conversationsList(any(ConversationsListRequest.class))) + .thenReturn(conversationsListResponse); + when(conversationsListResponse.isOk()).thenReturn(true); + when(conversationsListResponse.getChannels()) + .thenReturn(Arrays.asList(Conversation.builder().id("wrong_id").name("wrong_name").build(), + Conversation.builder().id("good_id").name(CHANNEL_NAME).build())); + when(conversationsListResponse.getResponseMetadata()) + .thenReturn(new ResponseMetadata()); + + when(methodsClient.conversationsInvite(conversationsInviteRequest.capture())) + .thenReturn(conversationsInviteResponse); + when(conversationsInviteResponse.isOk()).thenReturn(true); + when(conversationsInviteResponse.getChannel()).thenReturn(new Conversation()); + when(conversationsInviteResponse.getNeeded()).thenReturn("needed"); + when(conversationsInviteResponse.getProvided()).thenReturn("provided"); + // When + conversationsInviteData.invoke(methodsClient); + // Then + ConversationsInviteRequest value = conversationsInviteRequest.getValue(); + List expectedResolvedUserIds = Arrays.stream(emailList.split(",")).map(s -> USERID).collect(Collectors.toList()); + + assertEquals("good_id", value.getChannel()); + assertTrue(value.getUsers().containsAll(expectedResolvedUserIds) && expectedResolvedUserIds.containsAll(value.getUsers())); + } +} diff --git a/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteSlackResponseTest.java b/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteSlackResponseTest.java new file mode 100644 index 0000000000..df4b58ab33 --- /dev/null +++ b/connectors/slack/src/test/java/io/camunda/connector/slack/ConversationsInviteSlackResponseTest.java @@ -0,0 +1,31 @@ +package io.camunda.connector.slack; + +import com.slack.api.methods.response.conversations.ConversationsInviteResponse; +import com.slack.api.model.Conversation; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class ConversationsInviteSlackResponseTest { + private static final String CHANNEL_NAME = "channel"; + @Mock private ConversationsInviteResponse conversationsInviteResponse; + @Mock private Conversation conversation; + + @Test + public void shouldReturnCorrectResponse() { + // Given + when(conversationsInviteResponse.getChannel()).thenReturn(conversation); + when(conversation.getName()).thenReturn(CHANNEL_NAME); + // When + ConversationsInviteSlackResponse response = + new ConversationsInviteSlackResponse(conversationsInviteResponse); + // Then + assertThat(response.getChannel().getName()).isEqualTo(CHANNEL_NAME); + } + +} diff --git a/connectors/slack/src/test/java/io/camunda/connector/slack/LocalConnectorRuntime.java b/connectors/slack/src/test/java/io/camunda/connector/slack/LocalConnectorRuntime.java new file mode 100644 index 0000000000..df166179da --- /dev/null +++ b/connectors/slack/src/test/java/io/camunda/connector/slack/LocalConnectorRuntime.java @@ -0,0 +1,27 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.camunda.connector.slack; + +import io.camunda.connector.runtime.ConnectorRuntimeApplication; +import org.springframework.boot.SpringApplication; + +public class LocalConnectorRuntime { + + public static void main(String[] args) { + SpringApplication.run(ConnectorRuntimeApplication.class, args); + } +} diff --git a/connectors/slack/src/test/resources/application.properties b/connectors/slack/src/test/resources/application.properties new file mode 100644 index 0000000000..a1e4eff8e7 --- /dev/null +++ b/connectors/slack/src/test/resources/application.properties @@ -0,0 +1,4 @@ +# Configuration for running connectors locally in bundle with connector-runtime +server.port=9898 +zeebe.broker.gateway-address=localhost:26500 +zeebe.client.security.plaintext=true