Skip to content

Commit

Permalink
Merge pull request #141 from camunda/134-allow-slack-to-use-email-add…
Browse files Browse the repository at this point in the history
…ress-as-input-to-find-users

feat: allow post message with user email
  • Loading branch information
Oleksiivanov authored Nov 21, 2022
2 parents 6455982 + ff8ce29 commit c2e63d5
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 4 deletions.
6 changes: 3 additions & 3 deletions connectors/slack/element-templates/slack-connector.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
}
},
{
"label": "Channel/User Name",
"label": "Channel/User Name/Email",
"group": "channel",
"type": "String",
"feel": "optional",
Expand All @@ -97,8 +97,8 @@
"constraints": {
"notEmpty": true,
"pattern": {
"value": "^(#|@|=).*",
"message": "Must be a #channel, @user or FEEL expression."
"value": "(^(#|@|=).*)|(^.+[@].+[.].{2,4}$)",
"message": "Must be a #channel, @user, email or FEEL expression."
}
},
"condition": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,32 @@
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;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
import javax.validation.constraints.NotEmpty;
import org.apache.commons.text.StringEscapeUtils;

public class ChatPostMessageData implements SlackRequestData {

private static final String EMAIL_REGEX = "^.+[@].+[.].{2,4}$";

@NotEmpty @Secret private String channel;
@NotEmpty @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 = getUserIdByEmail(methodsClient);
}

ChatPostMessageRequest request =
ChatPostMessageRequest.builder()
.channel(channel)
Expand Down Expand Up @@ -80,6 +86,26 @@ private String getUserId(String userName, MethodsClient methodsClient) {
return userId;
}

private boolean isEmail(final String str) {
return str.matches(EMAIL_REGEX);
}

private String getUserIdByEmail(final MethodsClient methodsClient)
throws IOException, SlackApiException {
UsersLookupByEmailRequest lookupByEmailRequest =
UsersLookupByEmailRequest.builder().email(channel).build();

return Optional.ofNullable(methodsClient.usersLookupByEmail(lookupByEmailRequest))
.map(UsersLookupByEmailResponse::getUser)
.map(User::getId)
.orElseThrow(
() ->
new RuntimeException(
"User with email "
+ channel
+ " not found; or unable 'users:read.email' permission"));
}

public String getChannel() {
return channel;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. Licensed under a proprietary license.
* See the License.txt file for more information. You may not use this file
* except in compliance with the proprietary license.
*/
package io.camunda.connector.slack;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

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.UsersLookupByEmailRequest;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
import com.slack.api.methods.response.users.UsersLookupByEmailResponse;
import com.slack.api.model.Message;
import com.slack.api.model.User;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ChatPostMessageDataTest {

@Mock private MethodsClient methodsClient;
@Mock private UsersLookupByEmailResponse lookupByEmailResponse;
@Mock private User user;
@Mock private ChatPostMessageResponse chatPostMessageResponse;

@Captor private ArgumentCaptor<ChatPostMessageRequest> chatPostMessageRequest;

private static final String USERID = "testUserId";

@Test
void invoke_shouldThrowExceptionWhenUserWithoutEmail() throws SlackApiException, IOException {
// Given
ChatPostMessageData chatPostMessageData = new ChatPostMessageData();
chatPostMessageData.setChannel("[email protected]");
when(methodsClient.usersLookupByEmail(any(UsersLookupByEmailRequest.class))).thenReturn(null);
// When and then
RuntimeException thrown =
assertThrows(
RuntimeException.class,
() -> chatPostMessageData.invoke(methodsClient),
"RuntimeException was expected");
assertThat(thrown.getMessage())
.contains(
"User with email [email protected] not found; or unable 'users:read.email' permission");
}

@Test
void invoke_shouldFindUserIdByEmail() throws SlackApiException, IOException {
// Given
ChatPostMessageData chatPostMessageData = new ChatPostMessageData();
chatPostMessageData.setChannel("[email protected]");
chatPostMessageData.setText("test");

when(methodsClient.usersLookupByEmail(any(UsersLookupByEmailRequest.class)))
.thenReturn(lookupByEmailResponse);
when(lookupByEmailResponse.getUser()).thenReturn(user);
when(user.getId()).thenReturn(USERID);
when(methodsClient.chatPostMessage(chatPostMessageRequest.capture()))
.thenReturn(chatPostMessageResponse);
when(chatPostMessageResponse.isOk()).thenReturn(true);
when(chatPostMessageResponse.getMessage()).thenReturn(new Message());
// When
chatPostMessageData.invoke(methodsClient);
// Then
ChatPostMessageRequest value = chatPostMessageRequest.getValue();
assertThat(value.getChannel()).isEqualTo(USERID);
}
}

0 comments on commit c2e63d5

Please sign in to comment.