Skip to content

Commit a73d878

Browse files
committed
Added a test for posting a pulse response via Slack
1 parent b90adcc commit a73d878

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.objectcomputing.checkins.services;
2+
3+
import com.objectcomputing.checkins.notifications.social_media.SlackSearch;
4+
import com.objectcomputing.checkins.configuration.CheckInsConfiguration;
5+
6+
import io.micronaut.context.annotation.Replaces;
7+
import io.micronaut.context.annotation.Requires;
8+
import io.micronaut.core.util.StringUtils;
9+
import io.micronaut.http.HttpResponse;
10+
import io.micronaut.http.HttpStatus;
11+
12+
import jakarta.inject.Singleton;
13+
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
@Singleton
18+
@Replaces(SlackSearch.class)
19+
@Requires(property = "replace.slacksearch", value = StringUtils.TRUE)
20+
public class SlackSearchReplacement extends SlackSearch {
21+
public final Map<String, String> channels = new HashMap<>();
22+
public final Map<String, String> users = new HashMap<>();
23+
24+
public SlackSearchReplacement(CheckInsConfiguration checkInsConfiguration) {
25+
super(checkInsConfiguration);
26+
}
27+
28+
@Override
29+
public String findChannelId(String channelName) {
30+
return channels.containsKey(channelName) ?
31+
channels.get(channelName) : null;
32+
}
33+
34+
@Override
35+
public String findUserEmail(String userId) {
36+
return users.containsKey(userId) ? users.get(userId) : null;
37+
}
38+
39+
@Override
40+
public String findUserId(String userEmail) {
41+
for (Map.Entry<String, String> entry : users.entrySet()) {
42+
if (entry.getValue().equals(userEmail)) {
43+
return entry.getKey();
44+
}
45+
}
46+
return null;
47+
}
48+
}
49+

server/src/test/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponseControllerTest.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
import com.objectcomputing.checkins.services.fixture.RoleFixture;
88
import com.objectcomputing.checkins.services.memberprofile.MemberProfile;
99
import com.objectcomputing.checkins.util.Util;
10+
import com.objectcomputing.checkins.configuration.CheckInsConfiguration;
11+
import com.objectcomputing.checkins.services.SlackSearchReplacement;
12+
13+
import io.micronaut.core.util.StringUtils;
1014
import io.micronaut.core.type.Argument;
15+
import io.micronaut.context.annotation.Property;
1116
import io.micronaut.http.HttpRequest;
1217
import io.micronaut.http.HttpResponse;
1318
import io.micronaut.http.HttpStatus;
@@ -27,19 +32,31 @@
2732
import java.util.UUID;
2833
import java.util.stream.Collectors;
2934
import java.util.stream.Stream;
35+
import javax.crypto.Mac;
36+
import javax.crypto.spec.SecretKeySpec;
37+
import java.nio.charset.StandardCharsets;
38+
import java.util.Base64;
39+
import java.time.Instant;
3040

3141
import static com.objectcomputing.checkins.services.role.RoleType.Constants.ADMIN_ROLE;
3242
import static com.objectcomputing.checkins.services.role.RoleType.Constants.MEMBER_ROLE;
3343
import static org.junit.jupiter.api.Assertions.assertEquals;
3444
import static org.junit.jupiter.api.Assertions.assertThrows;
3545
import static org.junit.jupiter.api.Assertions.assertTrue;
3646

47+
@Property(name = "replace.slacksearch", value = StringUtils.TRUE)
3748
class PulseResponseControllerTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture, PulseResponseFixture {
3849

3950
@Inject
4051
@Client("/services/pulse-responses")
4152
protected HttpClient client;
4253

54+
@Inject
55+
private CheckInsConfiguration configuration;
56+
57+
@Inject
58+
private SlackSearchReplacement slackSearch;
59+
4360
private Map<String, MemberProfile> hierarchy;
4461

4562
@BeforeEach
@@ -516,6 +533,50 @@ void testUpdateInvalidDatePulseResponse() {
516533
assertEquals(request.getPath(), href);
517534
}
518535

536+
@Test
537+
void testCreateAPulseResponseFromSlack() {
538+
MemberProfile memberProfile = createADefaultMemberProfile();
539+
slackSearch.users.put("SLACK_ID_HI", memberProfile.getWorkEmail());
540+
541+
final String rawBody = "payload=%7B%22type%22%3A+%22view_submission%22%2C+%22user%22%3A+%7B%22id%22%3A+%22SLACK_ID_HI%22%7D%2C+%22view%22%3A+%7B%22id%22%3A+%22VNHU13V36%22%2C+%22type%22%3A+%22modal%22%2C+%22state%22%3A+%7B%22values%22%3A+%7B%22internalNumber%22%3A+%7B%22internalScore%22%3A+%7B%22selected_option%22%3A+%7B%22type%22%3A+%22radio_buttons%22%2C+%22value%22%3A+%224%22%7D%7D%7D%2C+%22internalText%22%3A+%7B%22internalFeelings%22%3A+%7B%22type%22%3A+%22plain_text_input%22%2C+%22value%22%3A+%22I+am+a+robot.%22%7D%7D%2C+%22externalNumber%22%3A+%7B%22externalScore%22%3A+%7B%22selected_option%22%3A+%7B%22type%22%3A+%22radio_buttons%22%2C+%22value%22%3A+%225%22%7D%7D%7D%2C+%22externalText%22%3A+%7B%22externalFeelings%22%3A+%7B%22type%22%3A+%22plain_text_input%22%2C+%22value%22%3A+%22You+are+a+robot.%22%7D%7D%7D%7D%7D%7D";
542+
543+
long currentTime = Instant.now().getEpochSecond();
544+
String timestamp = String.valueOf(currentTime);
545+
546+
final HttpRequest request = HttpRequest.POST("/external", rawBody)
547+
.header("Content-Type", "application/x-www-form-urlencoded")
548+
.header("X-Slack-Signature", slackSignature(timestamp, rawBody))
549+
.header("X-Slack-Request-Timestamp", timestamp);
550+
551+
final HttpResponse response = client.toBlocking().exchange(request);
552+
553+
assertEquals(HttpStatus.OK, response.getStatus());
554+
}
555+
556+
private String slackSignature(String timestamp, String rawBody) {
557+
String baseString = "v0:" + timestamp + ":" + rawBody;
558+
String secret = configuration.getApplication()
559+
.getPulseResponse()
560+
.getSlack().getSigningSecret();
561+
562+
try {
563+
// Generate HMAC SHA-256 signature
564+
Mac mac = Mac.getInstance("HmacSHA256");
565+
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
566+
mac.init(secretKeySpec);
567+
byte[] hash = mac.doFinal(baseString.getBytes(StandardCharsets.UTF_8));
568+
569+
// Convert hash to hex
570+
StringBuilder hexString = new StringBuilder();
571+
for (byte b : hash) {
572+
hexString.append(String.format("%02x", b));
573+
}
574+
return "v0=" + hexString.toString();
575+
} catch (Exception e) {
576+
return null;
577+
}
578+
}
579+
519580
private static PulseResponseCreateDTO createPulseResponseCreateDTO() {
520581
return createPulseResponseCreateDTO(UUID.randomUUID());
521582
}

0 commit comments

Comments
 (0)