Skip to content

Commit adeec4f

Browse files
fix(digest): compile and cover per-recipient Slack delivery
Seed checks User.isActiveAccount() (there is no isActive), and delivery tests construct SlackDailyDigestService with the assembler + user repo. Create-preference now asserts connection access and refuses EMAIL so the UI cannot advertise a delivery path this PR does not implement. Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
1 parent 7bd3ed1 commit adeec4f

9 files changed

Lines changed: 240 additions & 71 deletions

File tree

backend/src/main/java/com/dbaagent/controller/DigestPreferenceController.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,23 @@ public ResponseEntity<List<UserDigestPreference>> getMyPreferences() {
4949
public ResponseEntity<UserDigestPreference> createPreference(@RequestBody CreatePreferenceRequest request) {
5050
String username = accessControlService.requireCurrentUsername();
5151

52-
DigestDeliveryMethod method = request.deliveryMethod != null
53-
? DigestDeliveryMethod.fromString(request.deliveryMethod)
54-
: DigestDeliveryMethod.SLACK_DM;
52+
DigestDeliveryMethod method;
53+
if (request.deliveryMethod == null || request.deliveryMethod.isBlank()) {
54+
method = DigestDeliveryMethod.SLACK_DM;
55+
} else {
56+
method = DigestDeliveryMethod.fromString(request.deliveryMethod);
57+
if (method == null) {
58+
throw new IllegalArgumentException("Unknown delivery method: " + request.deliveryMethod);
59+
}
60+
}
61+
62+
if (method == DigestDeliveryMethod.EMAIL) {
63+
throw new IllegalArgumentException("Email digest delivery is not available yet");
64+
}
65+
66+
if (request.connectionId != null && !request.connectionId.isBlank()) {
67+
accessControlService.assertCanReadConnectionContent(request.connectionId);
68+
}
5569

5670
PersonaTag persona = request.personaTag != null
5771
? PersonaTag.fromString(request.personaTag)
@@ -164,10 +178,10 @@ public ResponseEntity<List<Map<String, String>>> getPersonaTags() {
164178
*/
165179
@GetMapping("/delivery-methods")
166180
public ResponseEntity<List<Map<String, String>>> getDeliveryMethods() {
181+
// Only advertise methods this PR actually delivers. EMAIL/WhatsApp are PR4.
167182
List<Map<String, String>> methods = List.of(
168183
Map.of("value", "SLACK_DM", "label", DigestDeliveryMethod.SLACK_DM.getDisplayName(), "description", DigestDeliveryMethod.SLACK_DM.getDescription()),
169-
Map.of("value", "SLACK_CHANNEL", "label", DigestDeliveryMethod.SLACK_CHANNEL.getDisplayName(), "description", DigestDeliveryMethod.SLACK_CHANNEL.getDescription()),
170-
Map.of("value", "EMAIL", "label", DigestDeliveryMethod.EMAIL.getDisplayName(), "description", DigestDeliveryMethod.EMAIL.getDescription())
184+
Map.of("value", "SLACK_CHANNEL", "label", DigestDeliveryMethod.SLACK_CHANNEL.getDisplayName(), "description", DigestDeliveryMethod.SLACK_CHANNEL.getDescription())
171185
);
172186
return ResponseEntity.ok(methods);
173187
}

backend/src/main/java/com/dbaagent/service/DigestPreferenceSeedService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public SeedResult seedPreferencesFromSingleton(boolean dryRun) {
7373
}
7474

7575
User user = userOpt.get();
76-
if (!user.isActive()) {
76+
if (!user.isActiveAccount()) {
7777
skipped.add(username + ": user inactive");
7878
continue;
7979
}
@@ -136,7 +136,7 @@ public SeedResult seedPreferencesForUser(String username, boolean dryRun) {
136136
}
137137

138138
User user = userOpt.get();
139-
if (!user.isActive()) {
139+
if (!user.isActiveAccount()) {
140140
return new SeedResult(0, 0, List.of(username + ": user inactive"), List.of());
141141
}
142142

backend/src/main/java/com/dbaagent/service/SlackDailyDigestService.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,14 @@ private PersonalizedDigestResult sendPersonalizedDigestToUser(
542542
String username = pref.getUsername();
543543
PersonaTag personaTag = pref.getPersonaTag();
544544

545-
// Resolve user's role
546-
Role role = userRepository.findByUsernameIgnoreCase(username)
547-
.map(User::getRoleEnum)
548-
.orElse(Role.DEVELOPER);
545+
// Resolve user's built-in role. Custom roles have no Role enum — rank as
546+
// DEVELOPER rather than NPE on role.name(). Persist the stored role code
547+
// on the log so the audit trail still names ANALYST, not a silent fallback.
548+
User recipient = userRepository.findByUsernameIgnoreCase(username).orElse(null);
549+
Role role = recipient != null && recipient.getRoleEnum() != null
550+
? recipient.getRoleEnum()
551+
: Role.DEVELOPER;
552+
String roleCode = recipient != null ? recipient.getRoleCode() : Role.DEVELOPER.name();
549553

550554
// Assemble personalized digest
551555
DigestAssemblyResult assembly = digestInsightAssemblerService.assembleDigest(
@@ -562,7 +566,7 @@ private PersonalizedDigestResult sendPersonalizedDigestToUser(
562566
logEntry.setContent(message);
563567
logEntry.setHeadline(assembly.getHeadline());
564568
logEntry.setRecipientUsername(username);
565-
logEntry.setRecipientRole(role.name());
569+
logEntry.setRecipientRole(roleCode);
566570
logEntry.setPersonaTag(personaTag);
567571
logEntry.setDeliveryMethod(DigestDeliveryMethod.SLACK_DM);
568572
logEntry.setPreferenceId(pref.getId());

backend/src/test/java/com/dbaagent/service/DigestPreferenceSeedServiceTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void seedPreferences_createsPreferenceForLinkedUser() {
6767
User alice = new User();
6868
alice.setUsername("alice");
6969
alice.setRole("DBA");
70-
alice.setStatus("ACTIVE");
70+
alice.setAccountStatus("ACTIVE");
7171
when(userRepository.findByUsernameIgnoreCase("alice")).thenReturn(Optional.of(alice));
7272

7373
DatabaseConnection conn = new DatabaseConnection();
@@ -159,7 +159,7 @@ void seedPreferences_skipsExistingPreference() {
159159
User alice = new User();
160160
alice.setUsername("alice");
161161
alice.setRole("DBA");
162-
alice.setStatus("ACTIVE");
162+
alice.setAccountStatus("ACTIVE");
163163
when(userRepository.findByUsernameIgnoreCase("alice")).thenReturn(Optional.of(alice));
164164

165165
DatabaseConnection conn = new DatabaseConnection();
@@ -193,7 +193,7 @@ void seedPreferences_dryRun_doesNotPersist() {
193193
User alice = new User();
194194
alice.setUsername("alice");
195195
alice.setRole("DBA");
196-
alice.setStatus("ACTIVE");
196+
alice.setAccountStatus("ACTIVE");
197197
when(userRepository.findByUsernameIgnoreCase("alice")).thenReturn(Optional.of(alice));
198198

199199
DatabaseConnection conn = new DatabaseConnection();
@@ -221,7 +221,7 @@ void seedPreferences_skipsInactiveUser() {
221221

222222
User inactive = new User();
223223
inactive.setUsername("inactive");
224-
inactive.setStatus("SUSPENDED");
224+
inactive.setAccountStatus("DISABLED");
225225
when(userRepository.findByUsernameIgnoreCase("inactive")).thenReturn(Optional.of(inactive));
226226

227227
// When: seeding
@@ -239,7 +239,7 @@ void seedPreferences_skipsUserWithNoConnections() {
239239

240240
User noconn = new User();
241241
noconn.setUsername("noconn");
242-
noconn.setStatus("ACTIVE");
242+
noconn.setAccountStatus("ACTIVE");
243243
when(userRepository.findByUsernameIgnoreCase("noconn")).thenReturn(Optional.of(noconn));
244244

245245
when(connectionAccessService.getVisibleConnections("noconn", false))
@@ -259,7 +259,7 @@ void seedForUser_createsPreferencesForSpecificUser() {
259259
User alice = new User();
260260
alice.setUsername("alice");
261261
alice.setRole("DBA");
262-
alice.setStatus("ACTIVE");
262+
alice.setAccountStatus("ACTIVE");
263263
when(userRepository.findByUsernameIgnoreCase("alice")).thenReturn(Optional.of(alice));
264264

265265
SlackUserLink link = new SlackUserLink();
@@ -288,7 +288,7 @@ private void setupUser(String username, String role) {
288288
User user = new User();
289289
user.setUsername(username);
290290
user.setRole(role);
291-
user.setStatus("ACTIVE");
291+
user.setAccountStatus("ACTIVE");
292292
when(userRepository.findByUsernameIgnoreCase(username)).thenReturn(Optional.of(user));
293293
}
294294
}

0 commit comments

Comments
 (0)