Refactor and secure backend configuration, DTOs, and authentication flow

- Updated pom.xml: removed redundant tags, grouped dependencies, added scopes, and upgraded plugins
- Enhanced RegisterUserDto with validation annotations and added missing fields (username, fullname)
- Updated User entity with builder constructor and removed redundant getters/setters
- Completed FileMetadata entity with Lombok and required setters/getters
- Improved HDFSConfig with correct annotation and clearer exception message
- Adjusted HTTP to HTTPS redirect port (8085 -> 8443)
- Allowed /actuator/** in SecurityConfig and disabled deprecated XSS protection
- Skipped JWT filter for /api/auth and /actuator paths
- Refactored AuthenticationService to use builder pattern and RSA key injection
- Fixed application.properties for static MySQL connection (removed ${MYSQL_PASSWORD})
This commit is contained in:
K
2025-07-03 04:48:29 +05:30
parent 88fd49c807
commit 7f6b2eb344
11 changed files with 240 additions and 387 deletions
+59 -91
View File
@@ -1,89 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version> <version>3.4.4</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/>
</parent> </parent>
<groupId>com.skycrate.backend</groupId> <groupId>com.skycrate.backend</groupId>
<artifactId>skycrateBackend</artifactId> <artifactId>skycrateBackend</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<name>skycrateBackend</name> <name>skycrateBackend</name>
<description>Cloud Storage App using HDFS</description> <description>Cloud Storage App using HDFS</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties> <properties>
<java.version>17</java.version> <java.version>17</java.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- Spring Boot Starters -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- NEWLY ADDED DEPENDECIES-->
<!-- Spring Boot Web -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>3.2.4</version>
</dependency> </dependency>
<!-- Spring Boot Security -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
<version>3.2.4</version>
</dependency> </dependency>
<!-- Spring Boot Data JPA -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.2.4</version> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<!-- MySQL Driver --> <!-- MySQL JDBC -->
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version> <version>8.3.0</version>
</dependency> </dependency>
<!-- Spring Boot Validation --> <!-- JWT -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.2.4</version>
</dependency>
<!-- JSON Web Token (JWT) -->
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId> <artifactId>jjwt-api</artifactId>
@@ -93,14 +61,16 @@
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId> <artifactId>jjwt-impl</artifactId>
<version>0.11.5</version> <version>0.11.5</version>
<scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version> <version>0.11.5</version>
<scope>runtime</scope>
</dependency> </dependency>
<!-- Hadoop Dependencies --> <!-- Hadoop HDFS -->
<dependency> <dependency>
<groupId>org.apache.hadoop</groupId> <groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId> <artifactId>hadoop-common</artifactId>
@@ -112,74 +82,72 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.hadoop</groupId> <groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId> <artifactId>hadoop-hdfs</artifactId>
<version>3.4.1</version> <version>3.4.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.hadoop</groupId> <groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId> <artifactId>hadoop-client</artifactId>
<version>3.4.1</version> <version>3.4.1</version>
</dependency> </dependency>
<!-- Logging (SLF4J + Logback) --> <!-- Commons IO -->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- <version>1.7.36</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>ch.qos.logback</groupId>-->
<!-- <artifactId>logback-classic</artifactId>-->
<!-- <version>1.2.11</version>-->
<!-- </dependency>-->
<!-- Apache Commons IO (for file operations) -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.11.0</version> <version>2.11.0</version>
</dependency> </dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<!-- Caffeine Cache -->
<dependency> <dependency>
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
<version>3.1.8</version> <version>3.1.8</version>
</dependency> </dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<!-- Spring Boot Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>
@@ -1,6 +1,6 @@
package com.skycrate.backend.skycrateBackend.config; package com.skycrate.backend.skycrateBackend.config;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration; // Hadoop Configuration
import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -8,20 +8,17 @@ import org.springframework.context.annotation.Bean;
import java.net.URI; import java.net.URI;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
// HDFS configuration bean to securely connect to a remote Hadoop cluster. @org.springframework.context.annotation.Configuration
@Configuration
public class HDFSConfig { public class HDFSConfig {
private static final String HDFS_URI = System.getenv("HDFS_URI"); // export HDFS_URI=hdfs://192.168.29.30:9000 private static final String HDFS_URI = System.getenv("HDFS_URI"); // e.g., hdfs://namenode:9000
private static final String HDFS_USER = System.getenv("HDFS_USER"); // Hadoop user (if needed) private static final String HDFS_USER = System.getenv("HDFS_USER"); // e.g., hdfsuser
// Configures and returns a secured HDFS FileSystem instance.
@Bean @Bean
public FileSystem fileSystem() throws Exception { public FileSystem fileSystem() throws Exception {
return getHDFS(); // use the static method internally return getHDFS();
} }
// Static method to get a FileSystem instance. Used by other classes like HDFSController.
public static FileSystem getHDFS() throws Exception { public static FileSystem getHDFS() throws Exception {
if (HDFS_URI == null || HDFS_URI.isBlank()) { if (HDFS_URI == null || HDFS_URI.isBlank()) {
throw new IllegalStateException("HDFS_URI environment variable not set."); throw new IllegalStateException("HDFS_URI environment variable not set.");
@@ -14,7 +14,7 @@ public class HttpToHttpsRedirectConfig {
return factory -> { return factory -> {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http"); connector.setScheme("http");
connector.setPort(8080); // HTTP port connector.setPort(8085); // HTTP port
connector.setSecure(false); connector.setSecure(false);
connector.setRedirectPort(8443); // HTTPS port connector.setRedirectPort(8443); // HTTPS port
factory.addAdditionalTomcatConnectors(connector); factory.addAdditionalTomcatConnectors(connector);
@@ -1,74 +0,0 @@
package com.skycrate.backend.skycrateBackend.config;
import java.io.IOException;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import com.skycrate.backend.skycrateBackend.services.JwtService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final HandlerExceptionResolver handlerExceptionResolver;
private JwtService jwtService;
private UserDetailsService userDetailsService;
public JwtAuthenticationFilter(JwtService jwtService,UserDetailsService userDetailsService,HandlerExceptionResolver handlerExceptionResolver){
this.handlerExceptionResolver=handlerExceptionResolver;
this.jwtService=jwtService;
this.userDetailsService=userDetailsService;
}
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
final String authHeader=request.getHeader("Authorization");
if (authHeader==null || !authHeader.startsWith("Bearer")){
filterChain.doFilter(request, response);
return;
}
try {
final String userjwt=authHeader.substring(7);
final String userEmail=jwtService.extractUsername(userjwt);
Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
if(userEmail!=null && authentication==null){
UserDetails userDetails=this.userDetailsService.loadUserByUsername(userEmail);
if (jwtService.isTokenValid(userjwt, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}
catch (Exception err) {
handlerExceptionResolver.resolveException(request, response, null, err);
}
}
}
@@ -29,7 +29,7 @@ public class SecurityConfig {
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider) .authenticationProvider(authenticationProvider)
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/auth/**", "/actuator/**").permitAll()
.requestMatchers(HttpMethod.GET, "/public/**").permitAll() .requestMatchers(HttpMethod.GET, "/public/**").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
) )
@@ -41,7 +41,8 @@ public class SecurityConfig {
.includeSubDomains(true) .includeSubDomains(true)
.maxAgeInSeconds(31536000) .maxAgeInSeconds(31536000)
) )
.xssProtection(xss -> xss.block(true)) // Spring Security 6+ no longer supports xss.block(true), so we just enable or disable it.
.xssProtection(xss -> xss.disable())
.frameOptions(frame -> frame.deny()) .frameOptions(frame -> frame.deny())
) )
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
@@ -1,46 +1,46 @@
package com.skycrate.backend.skycrateBackend.dto; package com.skycrate.backend.skycrateBackend.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
public class RegisterUserDto { public class RegisterUserDto {
@NotBlank(message = "Email is required")
@Email(message = "Email should be valid")
private String email; private String email;
@NotBlank(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters")
private String password; private String password;
@NotBlank(message = "Username is required")
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "Username must be alphanumeric")
private String username;
@NotBlank(message = "Full name is required")
private String fullname;
@NotBlank(message = "First name is required")
private String firstname; private String firstname;
@NotBlank(message = "Last name is required")
private String lastname; private String lastname;
public String getEmail() { // Getters
return email; public String getEmail() { return email; }
} public String getPassword() { return password; }
public String getUsername() { return username; }
public String getFullname() { return fullname; }
public String getFirstname() { return firstname; }
public String getLastname() { return lastname; }
public RegisterUserDto setEmail(String email) { // Setters
this.email = email; public void setEmail(String email) { this.email = email; }
return this; public void setPassword(String password) { this.password = password; }
} public void setUsername(String username) { this.username = username; }
public void setFullname(String fullname) { this.fullname = fullname; }
public String getPassword() { public void setFirstname(String firstname) { this.firstname = firstname; }
return password; public void setLastname(String lastname) { this.lastname = lastname; }
}
public RegisterUserDto setPassword(String password) {
this.password = password;
return this;
}
public String getFirstname() {
return firstname;
}
public RegisterUserDto setFirstname(String firstname) {
this.firstname = firstname;
return this;
}
public String getLastname() {
return lastname;
}
public RegisterUserDto setLastname(String lastname) {
this.lastname = lastname;
return this;
}
} }
@@ -1,23 +1,43 @@
package com.skycrate.backend.skycrateBackend.entity; package com.skycrate.backend.skycrateBackend.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.*;
@Entity @Entity
@Table(name = "file_metadata")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FileMetadata { public class FileMetadata {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Column(nullable = false)
private String filePath; private String filePath;
@Column(nullable = false)
private String username; private String username;
@Lob @Lob
@Column(nullable = false)
private byte[] salt; private byte[] salt;
@Lob @Lob
@Column(nullable = false)
private byte[] iv; private byte[] iv;
// Getters and Setters public void setUsername(String username) { this.username = username; }
public void setFilePath(String filePath) { this.filePath = filePath; }
public void setSalt(byte[] salt) { this.salt = salt; }
public void setIv(byte[] iv) { this.iv = iv; }
public String getUsername() { return this.username; }
public String getFilePath() { return this.filePath; }
public byte[] getSalt() { return this.salt; }
public byte[] getIv() { return this.iv; }
} }
@@ -14,7 +14,6 @@ import java.util.List;
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Builder
public class User implements UserDetails { public class User implements UserDetails {
@Id @Id
@@ -39,6 +38,16 @@ public class User implements UserDetails {
@Lob @Lob
private byte[] privateKey; private byte[] privateKey;
@Builder
public User(String email, String password, String username, String fullname, byte[] publicKey, byte[] privateKey) {
this.email = email;
this.password = password;
this.username = username;
this.fullname = fullname;
this.publicKey = publicKey;
this.privateKey = privateKey;
}
// --- UserDetails interface methods --- // --- UserDetails interface methods ---
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
@@ -74,45 +83,4 @@ public class User implements UserDetails {
public boolean isEnabled() { public boolean isEnabled() {
return true; return true;
} }
// --- Extra getter methods for HDFScontroller compatibility ---
public byte[] getPublicKey() {
return publicKey;
}
public byte[] getPrivateKey() {
return privateKey;
}
public String getFullname() {
return fullname;
}
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
} }
@@ -37,6 +37,12 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
FilterChain filterChain) FilterChain filterChain)
throws ServletException, IOException { throws ServletException, IOException {
String path = request.getRequestURI();
if (path.startsWith("/api/auth") || path.startsWith("/actuator")) {
filterChain.doFilter(request, response);
return;
}
final String authHeader = request.getHeader("Authorization"); final String authHeader = request.getHeader("Authorization");
final String jwt; final String jwt;
final String userEmail; final String userEmail;
@@ -1,35 +0,0 @@
package com.skycrate.backend.skycrateBackend.security;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class RateLimiterService {
private final Cache<String, Integer> attemptsCache;
private static final int MAX_ATTEMPTS = 5;
public RateLimiterService() {
this.attemptsCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build();
}
public boolean isBlocked(String key) {
Integer attempts = attemptsCache.getIfPresent(key);
return attempts != null && attempts >= MAX_ATTEMPTS;
}
public void recordFailedAttempt(String key) {
int attempts = attemptsCache.getIfPresent(key) == null ? 0 : attemptsCache.getIfPresent(key);
attemptsCache.put(key, attempts + 1);
}
public void resetAttempts(String key) {
attemptsCache.invalidate(key);
}
}
@@ -1,15 +1,14 @@
package com.skycrate.backend.skycrateBackend.services; package com.skycrate.backend.skycrateBackend.services;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.skycrate.backend.skycrateBackend.dto.LoginUserDto; import com.skycrate.backend.skycrateBackend.dto.LoginUserDto;
import com.skycrate.backend.skycrateBackend.dto.RegisterUserDto; import com.skycrate.backend.skycrateBackend.dto.RegisterUserDto;
import com.skycrate.backend.skycrateBackend.entity.User; import com.skycrate.backend.skycrateBackend.entity.User;
import com.skycrate.backend.skycrateBackend.repository.UserRepository; import com.skycrate.backend.skycrateBackend.repository.UserRepository;
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil; import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@@ -21,28 +20,31 @@ public class AuthenticationService {
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager; private final AuthenticationManager authenticationManager;
public AuthenticationService(UserRepository userRepository, AuthenticationManager authenticationManager, PasswordEncoder passwordEncoder) { public AuthenticationService(UserRepository userRepository,
AuthenticationManager authenticationManager,
PasswordEncoder passwordEncoder) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
} }
public User signUp(RegisterUserDto inputUser) { public User signUp(RegisterUserDto inputUser) {
User user = new User( KeyPair keyPair;
inputUser.getFirstname(),
inputUser.getLastname(),
inputUser.getEmail(),
passwordEncoder.encode(inputUser.getPassword())
);
try { try {
KeyPair keyPair = RSAKeyUtil.generateKeyPair(); keyPair = RSAKeyUtil.generateKeyPair();
user.setPublicKey(keyPair.getPublic().getEncoded());
user.setPrivateKey(keyPair.getPrivate().getEncoded());
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Failed to generate RSA key pair", e); throw new RuntimeException("Failed to generate RSA key pair", e);
} }
User user = User.builder()
.fullname(inputUser.getFirstname() + " " + inputUser.getLastname())
.username(inputUser.getUsername())
.email(inputUser.getEmail())
.password(passwordEncoder.encode(inputUser.getPassword()))
.publicKey(keyPair.getPublic().getEncoded())
.privateKey(keyPair.getPrivate().getEncoded())
.build();
return userRepository.save(user); return userRepository.save(user);
} }