Skip to content

Commit f45b758

Browse files
committed
feat(test): add custom email service to support E2E testing
Extends UserEmailService to allow disabling password reset emails during Playwright tests. When disabled, tokens are still created so tests can retrieve them via the Test API. - Adds @primary bean to override default UserEmailService - Controlled by app.mail.sendPasswordResetEmail config property - Generates secure tokens even when email sending is disabled
1 parent 535c57d commit f45b758

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.digitalsanctuary.spring.demo.service;
2+
3+
import java.security.SecureRandom;
4+
import java.util.Base64;
5+
6+
import org.springframework.beans.factory.annotation.Value;
7+
import org.springframework.context.ApplicationEventPublisher;
8+
import org.springframework.context.annotation.Primary;
9+
import org.springframework.stereotype.Service;
10+
11+
import com.digitalsanctuary.spring.user.persistence.repository.PasswordResetTokenRepository;
12+
import com.digitalsanctuary.spring.user.persistence.model.User;
13+
import com.digitalsanctuary.spring.user.mail.MailService;
14+
import com.digitalsanctuary.spring.user.service.SessionInvalidationService;
15+
import com.digitalsanctuary.spring.user.service.UserEmailService;
16+
import com.digitalsanctuary.spring.user.service.UserVerificationService;
17+
18+
import lombok.extern.slf4j.Slf4j;
19+
20+
/**
21+
* Custom extension of UserEmailService that allows disabling password reset emails during tests.
22+
* When email sending is disabled, tokens are still created so tests can retrieve them via the Test API.
23+
*/
24+
@Slf4j
25+
@Service
26+
@Primary
27+
public class CustomUserEmailService extends UserEmailService {
28+
29+
@Value("${app.mail.sendPasswordResetEmail:true}")
30+
private boolean sendPasswordResetEmail;
31+
32+
private final SecureRandom secureRandom = new SecureRandom();
33+
34+
public CustomUserEmailService(
35+
MailService mailService,
36+
UserVerificationService userVerificationService,
37+
PasswordResetTokenRepository passwordTokenRepository,
38+
ApplicationEventPublisher eventPublisher,
39+
SessionInvalidationService sessionInvalidationService) {
40+
super(mailService, userVerificationService, passwordTokenRepository, eventPublisher, sessionInvalidationService);
41+
}
42+
43+
@Override
44+
public void sendForgotPasswordVerificationEmail(final User user, final String appUrl) {
45+
if (!sendPasswordResetEmail) {
46+
log.debug("Password reset email disabled, creating token only for: {}", user.getEmail());
47+
// Generate token and save it so tests can retrieve via Test API
48+
String token = generateToken();
49+
createPasswordResetTokenForUser(user, token);
50+
return;
51+
}
52+
super.sendForgotPasswordVerificationEmail(user, appUrl);
53+
}
54+
55+
/**
56+
* Generates a secure random token for password reset.
57+
* This mirrors the private generateToken() method in the parent class.
58+
*/
59+
private String generateToken() {
60+
byte[] tokenBytes = new byte[32]; // 256 bits of entropy
61+
secureRandom.nextBytes(tokenBytes);
62+
return Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes);
63+
}
64+
}

0 commit comments

Comments
 (0)