Skip to content

Commit a3c0078

Browse files
Stagging file to solve conflict
1 parent 9916fef commit a3c0078

File tree

10 files changed

+193
-87
lines changed

10 files changed

+193
-87
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/checkstyle/checkstyle.xml

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
44
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
55

6-
76
<module name="Checker">
87
<property name="charset" value="UTF-8"/>
98
<property name="localeLanguage" value=""/>
@@ -12,8 +11,7 @@
1211
<module name="SuppressionFilter">
1312
<property name="file" value="config/checkstyle/suppressions.xml"/>
1413
</module>
15-
<!--Add more checks from google style guide:-->
16-
<!--https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml-->
14+
1715
<module name="TreeWalker">
1816
<property name="tabWidth" value="2"/>
1917
<module name="PackageName">
@@ -24,7 +22,7 @@
2422
<property name="illegalClasses" value="java.util.logging.Logger"/>
2523
</module>
2624
<module name="RedundantImport"/>
27-
<module name="AvoidStarImport"/>
25+
<module name="AvoidStarImport"/> <!-- already blocks star imports -->
2826
<module name="UnusedImports">
2927
<property name="processJavadoc" value="true"/>
3028
</module>
@@ -33,10 +31,8 @@
3331
<module name="MethodParamPad"/>
3432
<module name="NoWhitespaceAfter"/>
3533
<module name="NoWhitespaceBefore"/>
36-
<module name="WhitespaceAfter">
37-
</module>
38-
<module name="WhitespaceAround">
39-
</module>
34+
<module name="WhitespaceAfter"/>
35+
<module name="WhitespaceAround"/>
4036

4137
<module name="ModifierOrder"/>
4238
<module name="RedundantModifier"/>
@@ -55,37 +51,30 @@
5551
</module>
5652
<module name="NPathComplexity"/>
5753

58-
5954
<module name="ArrayTypeStyle"/>
6055
<module name="Indentation">
61-
<property name="basicOffset" value="2"/>
62-
<property name="caseIndent" value="2"/>
63-
<property name="throwsIndent" value="2"/>
64-
<property name="arrayInitIndent" value="2"/>
65-
<property name="lineWrappingIndentation" value="2"/>
56+
<property name="basicOffset" value="4"/>
57+
<property name="caseIndent" value="4"/>
58+
<property name="throwsIndent" value="4"/>
59+
<property name="arrayInitIndent" value="4"/>
60+
<property name="lineWrappingIndentation" value="4"/>
6661
</module>
6762

6863
<module name="JavadocMethod">
6964
<property name="severity" value="ignore"/>
7065
</module>
71-
7266
<module name="JavadocType">
7367
<property name="severity" value="ignore"/>
7468
</module>
75-
7669
<module name="JavadocVariable">
7770
<property name="severity" value="ignore"/>
7871
</module>
79-
8072
</module>
8173

8274
<module name="LineLength">
8375
<property name="ignorePattern" value="^ *\* *@see.+$"/>
8476
<property name="max" value="136"/>
8577
</module>
8678

87-
<module name="NewlineAtEndOfFile">
88-
<property name="lineSeparator" value="lf"/>
89-
</module>
9079
<module name="FileTabCharacter"/>
91-
</module>
80+
</module>

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@
7474
<groupId>org.springframework.boot</groupId>
7575
<artifactId>spring-boot-starter-data-jpa</artifactId>
7676
</dependency>
77+
<dependency>
78+
<groupId>org.springframework.boot</groupId>
79+
<artifactId>spring-boot-starter-mail</artifactId>
80+
<version>4.0.0-M3</version>
81+
</dependency>
7782
</dependencies>
7883

7984
<build>

src/main/java/org/spacehub/configuration/SecurityConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
2929
http
3030
.csrf(AbstractHttpConfigurer::disable)
3131
.authorizeHttpRequests(auth -> auth
32-
.requestMatchers("/api/v1/registration/**").permitAll()
32+
.requestMatchers("/api/v1/**").permitAll()
3333
.anyRequest().authenticated()
3434
)
3535
.httpBasic(AbstractHttpConfigurer::disable)

src/main/java/org/spacehub/controller/UserController.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
package org.spacehub.controller;
22

33
import org.spacehub.entities.User;
4-
import org.spacehub.service.VerificationService;
54
import org.spacehub.entities.RegistrationRequest;
5+
import org.spacehub.service.OTPService;
6+
import org.spacehub.service.VerificationService;
67
import org.spacehub.service.RegistrationService;
8+
import org.springframework.beans.factory.annotation.Autowired;
79
import org.springframework.http.ResponseEntity;
10+
import org.springframework.web.bind.annotation.GetMapping;
811
import org.springframework.web.bind.annotation.PostMapping;
912
import org.springframework.web.bind.annotation.RequestBody;
13+
import org.springframework.web.bind.annotation.RequestParam;
1014
import org.springframework.web.bind.annotation.RequestMapping;
1115
import org.springframework.web.bind.annotation.RestController;
1216

1317
@RestController
14-
@RequestMapping(path = "api/v1/registration")
18+
@RequestMapping(path = "api/v1")
1519
public class UserController {
1620

1721
private final VerificationService verificationService;
1822
private final RegistrationService registrationService;
1923

24+
@Autowired
25+
private OTPService otpService;
26+
2027
public UserController(VerificationService verificationService, RegistrationService registrationService) {
2128
this.verificationService = verificationService;
2229
this.registrationService = registrationService;
@@ -29,7 +36,7 @@ public ResponseEntity<String> login(@RequestBody User user) {
2936
return ResponseEntity.ok(token);
3037
}
3138

32-
@PostMapping
39+
@PostMapping("/registration")
3340
public ResponseEntity<String> register(@RequestBody RegistrationRequest request) {
3441
try {
3542
String result = registrationService.register(request);
@@ -40,4 +47,24 @@ public ResponseEntity<String> register(@RequestBody RegistrationRequest request)
4047
return ResponseEntity.internalServerError().body("Registration failed");
4148
}
4249
}
50+
51+
@GetMapping("/sendotp")
52+
public ResponseEntity<String> sendOTP(@RequestParam(required = false) String email) {
53+
try {
54+
otpService.sendOTP(email);
55+
return ResponseEntity.ok("OTP sent successfully to " + (email != null ? email : "default email"));
56+
} catch (Exception e) {
57+
return ResponseEntity.status(500).body("Error sending OTP: " + e.getMessage());
58+
}
59+
}
60+
61+
@GetMapping("/validateotp")
62+
public ResponseEntity<String> validateOTP(@RequestParam String otp) {
63+
boolean valid = otpService.validateOTP(otp);
64+
if (valid) {
65+
return ResponseEntity.ok("OTP is valid");
66+
} else {
67+
return ResponseEntity.status(400).body("OTP is invalid or expired");
68+
}
69+
}
4370
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.spacehub.service;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.mail.SimpleMailMessage;
5+
import org.springframework.mail.javamail.JavaMailSender;
6+
import org.springframework.stereotype.Service;
7+
8+
import java.time.Instant;
9+
import java.util.Random;
10+
11+
@Service
12+
public class OTPService {
13+
14+
@Autowired
15+
private JavaMailSender mailSender;
16+
17+
private final String DEFAULT_EMAIL = "[email protected]";
18+
19+
private String prev_OTP;
20+
private Instant send_Time;
21+
22+
public void sendOTP(String email) {
23+
if (email == null || email.isEmpty()) {
24+
email = DEFAULT_EMAIL;
25+
}
26+
27+
int num = new Random().nextInt(1000000);
28+
String otp = String.format("%06d", num);
29+
30+
this.prev_OTP = otp;
31+
this.send_Time = Instant.now();
32+
33+
SimpleMailMessage message = new SimpleMailMessage();
34+
message.setFrom(DEFAULT_EMAIL);
35+
message.setTo(email);
36+
message.setSubject("OTP Verification");
37+
message.setText("Your OTP is: " + otp);
38+
39+
mailSender.send(message);
40+
}
41+
42+
public boolean validateOTP(String otp) {
43+
if (prev_OTP == null || send_Time == null) {
44+
return false;
45+
}
46+
47+
long timeTakenMillis = Instant.now().toEpochMilli() - send_Time.toEpochMilli();
48+
49+
if (timeTakenMillis > 3000000) {
50+
this.prev_OTP = null;
51+
this.send_Time = null;
52+
return false;
53+
}
54+
55+
boolean isValid = prev_OTP.equals(otp);
56+
57+
if (isValid) {
58+
this.prev_OTP = null;
59+
this.send_Time = null;
60+
}
61+
62+
return isValid;
63+
}
64+
}

src/main/java/org/spacehub/service/RegistrationService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ public class RegistrationService {
1919
private final EmailValidator emailValidator;
2020
private final UserRepository userRepository;
2121
private final ConfirmationTokenService confirmationTokenService;
22+
private final OTPService otpService;
2223

23-
public RegistrationService(PasswordEncoder passwordEncoder, EmailValidator emailValidator, UserRepository userRepository,
24-
ConfirmationTokenService confirmationTokenService) {
24+
public RegistrationService(PasswordEncoder passwordEncoder, EmailValidator emailValidator,
25+
UserRepository userRepository, ConfirmationTokenService confirmationTokenService,
26+
OTPService otpService) {
2527
this.passwordEncoder = passwordEncoder;
2628
this.emailValidator = emailValidator;
2729
this.userRepository = userRepository;
2830
this.confirmationTokenService = confirmationTokenService;
31+
this.otpService = otpService;
2932
}
3033

3134
@Transactional
@@ -54,6 +57,8 @@ public String register(RegistrationRequest request) {
5457
newUser
5558
);
5659
confirmationTokenService.saveConfirmationToken(confirmationToken);
60+
61+
otpService.sendOTP(newUser.getEmail());
5762
return token;
5863
}
5964
}

src/main/java/org/spacehub/service/UserNameService.java

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,67 +17,69 @@
1717
@Service
1818
public class UserNameService {
1919

20-
private static final Logger logger = LoggerFactory.getLogger(UserNameService.class);
20+
private static final Logger logger = LoggerFactory.getLogger(UserNameService.class);
2121

22-
// Base64-encoded secret key
23-
private static final String SECRET_KEY = "7de8e1761eeac40efc9314980ebd00fbd55978f497b50ffee42902bba14d0596";
22+
private static final String SECRET_KEY = "7de8e1761eeac40efc9314980ebd00fbd55978f497b50ffee42902bba14d0596";
2423

25-
private SecretKey getSigningKey() {
26-
byte[] keyBytes = Base64.getDecoder().decode(SECRET_KEY);
27-
return Keys.hmacShaKeyFor(keyBytes);
28-
}
24+
private SecretKey getSigningKey() {
25+
byte[] keyBytes = Base64.getDecoder().decode(SECRET_KEY);
26+
return Keys.hmacShaKeyFor(keyBytes);
27+
}
28+
29+
public String generateToken(UserDetails userDetails) {
30+
return generateToken(Map.of(), userDetails);
31+
}
32+
33+
public String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {
34+
SecretKey key = getSigningKey();
35+
long nowMillis = System.currentTimeMillis();
36+
long expMillis = nowMillis + 1000L * 60 * 60 * 24;
37+
Map<String, Object> payload = Map.of(
38+
"username", userDetails.getUsername(),
39+
"iat", nowMillis / 1000,
40+
"exp", expMillis / 1000
41+
);
42+
43+
if (extraClaims != null && !extraClaims.isEmpty()) {
44+
payload = new java.util.HashMap<>(payload);
45+
payload.putAll(extraClaims);
46+
}
2947

30-
public String generateToken(UserDetails userDetails) {
31-
return generateToken(Map.of(), userDetails);
32-
}
48+
return Jwts.builder()
49+
.setHeaderParam("typ", "JWT")
50+
.setClaims(payload)
51+
.signWith(key)
52+
.compact();
53+
}
3354

34-
public String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {
35-
SecretKey key = getSigningKey();
36-
long nowMillis = System.currentTimeMillis();
37-
long expMillis = nowMillis + 1000L * 60 * 60 * 24;
38-
Map<String, Object> payload = Map.of(
39-
"username", userDetails.getUsername(),
40-
"iat", nowMillis / 1000,
41-
"exp", expMillis / 1000
42-
);
43-
if (extraClaims != null && !extraClaims.isEmpty()) {
44-
payload = new java.util.HashMap<>(payload);
45-
payload.putAll(extraClaims);
55+
public String extractUsername(String token) {
56+
return extractClaim(token, Claims::getSubject);
4657
}
47-
return Jwts.builder()
48-
.setHeaderParam("typ", "JWT")
49-
.setClaims(payload)
50-
.signWith(key)
51-
.compact();
52-
}
53-
public String extractUsername(String token) {
54-
return extractClaim(token, Claims::getSubject);
55-
}
5658

57-
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
58-
try {
59-
Claims claims = (Claims) Jwts.parser()
60-
.setSigningKey(getSigningKey());
61-
return claimsResolver.apply(claims);
62-
} catch (Exception e) {
63-
logger.warn("Failed to extract claim from token: {}", e.getMessage());
64-
return null;
59+
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
60+
try {
61+
Claims claims = (Claims) Jwts.parser()
62+
.setSigningKey(getSigningKey());
63+
return claimsResolver.apply(claims);
64+
}
65+
catch (Exception e) {
66+
logger.warn("Failed to extract claim from token: {}", e.getMessage());
67+
return null;
68+
}
6569
}
66-
}
6770

68-
public boolean isTokenValid(String token, UserDetails userDetails) {
69-
final String username = extractUsername(token);
70-
return username != null && username.equals(userDetails.getUsername()) && !isTokenExpired(token);
71-
}
71+
public boolean isTokenValid(String token, UserDetails userDetails) {
72+
final String username = extractUsername(token);
73+
return username != null && username.equals(userDetails.getUsername()) && !isTokenExpired(token);
74+
}
7275

73-
private boolean isTokenExpired(String token) {
74-
Date expiration = extractClaim(token, Claims::getExpiration);
75-
return expiration == null || expiration.before(new Date());
76-
}
76+
private boolean isTokenExpired(String token) {
77+
Date expiration = extractClaim(token, Claims::getExpiration);
78+
return expiration == null || expiration.before(new Date());
79+
}
7780

78-
public boolean validToken(String token, UserDetails userDetails) {
79-
final String username = extractUsername(token);
80-
return username != null && username.equals(userDetails.getUsername());
81-
}
81+
public boolean validToken(String token, UserDetails userDetails) {
82+
final String username = extractUsername(token);
83+
return username != null && username.equals(userDetails.getUsername());
84+
}
8285
}
83-

0 commit comments

Comments
 (0)