added jwt
This commit is contained in:
parent
78ba74cd0d
commit
43011c1509
@ -33,9 +33,12 @@ dependencies {
|
|||||||
runtimeOnly 'org.postgresql:postgresql'
|
runtimeOnly 'org.postgresql:postgresql'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
implementation "org.springframework.boot:spring-boot-starter-security"
|
||||||
implementation("org.simplejavamail:simple-java-mail:8.0.1")
|
implementation("org.simplejavamail:simple-java-mail:8.0.1")
|
||||||
implementation("net.sourceforge.htmlunit:htmlunit:2.70.0")
|
implementation("net.sourceforge.htmlunit:htmlunit:2.70.0")
|
||||||
|
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.13.0")
|
||||||
|
implementation("io.jsonwebtoken:jjwt-api:0.13.0")
|
||||||
|
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.13.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
generateJava {
|
generateJava {
|
||||||
|
|||||||
1
init.sql
1
init.sql
@ -45,6 +45,7 @@ CREATE TABLE IF NOT EXISTS public.users
|
|||||||
email character varying(255) COLLATE pg_catalog."default" NOT NULL,
|
email character varying(255) COLLATE pg_catalog."default" NOT NULL,
|
||||||
password character varying(255) COLLATE pg_catalog."default" NOT NULL,
|
password character varying(255) COLLATE pg_catalog."default" NOT NULL,
|
||||||
reg_time timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
reg_time timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
notification_type character varying(255) COLLATE pg_catalog."default" NOT NULL DEFAULT 'NO_NOTIFICATION'::character varying,
|
||||||
CONSTRAINT users_pkey PRIMARY KEY (id),
|
CONSTRAINT users_pkey PRIMARY KEY (id),
|
||||||
CONSTRAINT unique_email UNIQUE (email)
|
CONSTRAINT unique_email UNIQUE (email)
|
||||||
);
|
);
|
||||||
|
|||||||
53
src/main/java/dev/ksan/etfoglasiserver/config/JwtFilter.java
Normal file
53
src/main/java/dev/ksan/etfoglasiserver/config/JwtFilter.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.config;
|
||||||
|
|
||||||
|
import dev.ksan.etfoglasiserver.service.JWTService;
|
||||||
|
import dev.ksan.etfoglasiserver.service.MyUserDetailsService;
|
||||||
|
import dev.ksan.etfoglasiserver.service.UserService;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JWTService jwtService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ApplicationContext context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
String authHeader = request.getHeader("Authorization");
|
||||||
|
String token = null;
|
||||||
|
String username = null;
|
||||||
|
|
||||||
|
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||||
|
token = authHeader.substring(7);
|
||||||
|
username = jwtService.extractEmail(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
UserDetails userDetails = context.getBean(MyUserDetailsService.class).loadUserByUsername(username);
|
||||||
|
if (jwtService.validateToken(token, userDetails)) {
|
||||||
|
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||||
|
authToken.setDetails(new WebAuthenticationDetailsSource()
|
||||||
|
.buildDetails(request));
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtFilter jwtFilter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
|
return http.csrf(customizer -> customizer.disable()).
|
||||||
|
authorizeHttpRequests(request -> request
|
||||||
|
.requestMatchers("login", "register").permitAll()
|
||||||
|
.anyRequest().authenticated()).
|
||||||
|
httpBasic(Customizer.withDefaults()).
|
||||||
|
sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationProvider authenticationProvider() {
|
||||||
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
|
||||||
|
provider.setPasswordEncoder(new BCryptPasswordEncoder(12));
|
||||||
|
|
||||||
|
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||||
|
return config.getAuthenticationManager();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,50 +1,75 @@
|
|||||||
package dev.ksan.etfoglasiserver.controller;
|
package dev.ksan.etfoglasiserver.controller;
|
||||||
|
|
||||||
|
import dev.ksan.etfoglasiserver.dto.JwtResponseDTO;
|
||||||
import dev.ksan.etfoglasiserver.dto.UserCreationDTO;
|
import dev.ksan.etfoglasiserver.dto.UserCreationDTO;
|
||||||
import dev.ksan.etfoglasiserver.dto.UserDTO;
|
import dev.ksan.etfoglasiserver.dto.UserDTO;
|
||||||
|
import dev.ksan.etfoglasiserver.dto.UserLoginDTO;
|
||||||
import dev.ksan.etfoglasiserver.model.NotificationMethod;
|
import dev.ksan.etfoglasiserver.model.NotificationMethod;
|
||||||
import dev.ksan.etfoglasiserver.model.User;
|
|
||||||
import dev.ksan.etfoglasiserver.service.UserService;
|
import dev.ksan.etfoglasiserver.service.UserService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
@Autowired UserService service;
|
@Autowired UserService service;
|
||||||
|
|
||||||
@GetMapping("/users")
|
@GetMapping("/users")
|
||||||
public List<UserDTO> getUsers() {
|
public ResponseEntity<List<UserDTO>> getUsers() {
|
||||||
return service.getUsers().stream().map(this::getUserDTO).collect(Collectors.toList());
|
|
||||||
|
return new ResponseEntity(service.getUsers(), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("users/{userId}")
|
@GetMapping("users/{userId}")
|
||||||
public UserDTO getUserById(@PathVariable UUID userId) {
|
public ResponseEntity<UserDTO> getUserById(@PathVariable UUID userId) {
|
||||||
|
|
||||||
return getUserDTO(service.getUserById(userId));
|
UserDTO user = service.getUserById(userId);
|
||||||
|
|
||||||
|
if (user != null) {
|
||||||
|
return new ResponseEntity<>(user, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
public UserDTO getUserDTO(User user) {
|
|
||||||
|
|
||||||
return new UserDTO(user.getId(), user.getEmail(), user.getSubjectSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/users")
|
@PutMapping("/users")
|
||||||
public void updateUser(@RequestBody UserCreationDTO user) {
|
public ResponseEntity<UserDTO> updateUser(@RequestBody UserCreationDTO user) {
|
||||||
|
|
||||||
NotificationMethod method = NotificationMethod.valueOf(user.getNotification());
|
NotificationMethod method = NotificationMethod.valueOf(user.getNotification());
|
||||||
user.setNotificationMethod(method);
|
user.setNotificationMethod(method);
|
||||||
service.updateUser(user);
|
UserDTO userUpdated = service.updateUser(user);
|
||||||
|
if (userUpdated != null) {
|
||||||
|
return new ResponseEntity<>(userUpdated, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
@PostMapping("/users")
|
@PostMapping("/users")
|
||||||
public void addUser(@RequestBody UserCreationDTO user) {
|
public void addUser(@RequestBody UserCreationDTO user) {
|
||||||
NotificationMethod method = NotificationMethod.valueOf(user.getNotification());
|
NotificationMethod method = NotificationMethod.valueOf(user.getNotification());
|
||||||
user.setNotificationMethod(method);
|
user.setNotificationMethod(method);
|
||||||
service.addUser(user);
|
service.addUser(user);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@PostMapping("/login")
|
||||||
|
public ResponseEntity<JwtResponseDTO> login(@RequestBody UserLoginDTO user) {
|
||||||
|
JwtResponseDTO userVer = service.verify(user);
|
||||||
|
|
||||||
|
if (userVer != null) return new ResponseEntity<>(userVer, HttpStatus.OK);
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
public ResponseEntity<UserDTO> register(@RequestBody UserCreationDTO user) {
|
||||||
|
|
||||||
|
UserDTO newUser = service.register(user);
|
||||||
|
if (newUser != null) return new ResponseEntity<>(newUser, HttpStatus.CREATED);
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
@DeleteMapping("/users/{userId}")
|
@DeleteMapping("/users/{userId}")
|
||||||
public void deleteUser(@PathVariable UUID userId) {
|
public void deleteUser(@PathVariable UUID userId) {
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.dto;
|
||||||
|
|
||||||
|
public class JwtResponseDTO {
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
private String email;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public JwtResponseDTO(String token, String email, String message) {
|
||||||
|
this.token = token;
|
||||||
|
this.email = email;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package dev.ksan.etfoglasiserver.dto;
|
|||||||
|
|
||||||
import dev.ksan.etfoglasiserver.model.NotificationMethod;
|
import dev.ksan.etfoglasiserver.model.NotificationMethod;
|
||||||
import dev.ksan.etfoglasiserver.model.Subject;
|
import dev.ksan.etfoglasiserver.model.Subject;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -11,9 +10,11 @@ public class UserDTO {
|
|||||||
private String email;
|
private String email;
|
||||||
private Set<Subject> subjectSet;
|
private Set<Subject> subjectSet;
|
||||||
private NotificationMethod notificationMethod;
|
private NotificationMethod notificationMethod;
|
||||||
|
|
||||||
public UserDTO() {}
|
public UserDTO() {}
|
||||||
|
|
||||||
public UserDTO(UUID id, String email, Set<Subject> subjectSet) {
|
public UserDTO(
|
||||||
|
UUID id, String email, Set<Subject> subjectSet, NotificationMethod notificationMethod2) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.subjectSet = subjectSet;
|
this.subjectSet = subjectSet;
|
||||||
@ -22,12 +23,15 @@ public class UserDTO {
|
|||||||
public UUID getId() {
|
public UUID getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(UUID id) {
|
public void setId(UUID id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/main/java/dev/ksan/etfoglasiserver/dto/UserLoginDTO.java
Normal file
23
src/main/java/dev/ksan/etfoglasiserver/dto/UserLoginDTO.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.dto;
|
||||||
|
|
||||||
|
public class UserLoginDTO {
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.model;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class UserPrincipal implements UserDetails {
|
||||||
|
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
public UserPrincipal(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return Collections.singleton(new SimpleGrantedAuthority("USER"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return user.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return user.getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.service;
|
||||||
|
|
||||||
|
import dev.ksan.etfoglasiserver.model.User;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.io.Decoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JWTService {
|
||||||
|
|
||||||
|
private String secretKey = "";
|
||||||
|
|
||||||
|
private JWTService() {
|
||||||
|
try {
|
||||||
|
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");
|
||||||
|
SecretKey secKey = keyGen.generateKey();
|
||||||
|
secretKey = Base64.getEncoder().encodeToString(secKey.getEncoded());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(String email) {
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
return Jwts.builder().claims().add(claims).subject(email)
|
||||||
|
.issuedAt(new Date(System.currentTimeMillis())).expiration(new Date(System.currentTimeMillis()+60*60*300))
|
||||||
|
.and().signWith(getKey()).compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKey getKey() {
|
||||||
|
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
|
||||||
|
return Keys.hmacShaKeyFor(keyBytes);
|
||||||
|
}
|
||||||
|
public String extractEmail(String token) {
|
||||||
|
return extractClaim(token, Claims::getSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T extractClaim(String token, Function<Claims, T> claimResolver) {
|
||||||
|
final Claims claims = extractAllClaims(token);
|
||||||
|
return claimResolver.apply(claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Claims extractAllClaims(String token) {
|
||||||
|
return Jwts.parser()
|
||||||
|
.verifyWith(getKey())
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token)
|
||||||
|
.getPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean validateToken(String token, UserDetails userDetails) {
|
||||||
|
final String userName = extractEmail(token);
|
||||||
|
return (userName.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTokenExpired(String token) {
|
||||||
|
return extractExpiration(token).before(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date extractExpiration(String token) {
|
||||||
|
return extractClaim(token, Claims::getExpiration);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,15 +11,18 @@ import java.io.BufferedReader;
|
|||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Service
|
||||||
public class MailService {
|
public class MailService {
|
||||||
String address;
|
String address;
|
||||||
String passwd;
|
String passwd;
|
||||||
Mailer mailer;
|
Mailer mailer;
|
||||||
|
|
||||||
|
public MailService(){
|
||||||
|
this(".creds");
|
||||||
|
}
|
||||||
public MailService(String filename) {
|
public MailService(String filename) {
|
||||||
try(BufferedReader br = new BufferedReader((new FileReader(filename)))) {
|
try(BufferedReader br = new BufferedReader((new FileReader(filename)))) {
|
||||||
address = br.readLine();
|
address = br.readLine();
|
||||||
System.out.println(address);
|
|
||||||
passwd = br.readLine();
|
passwd = br.readLine();
|
||||||
}catch(IOException e) {
|
}catch(IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
package dev.ksan.etfoglasiserver.service;
|
||||||
|
|
||||||
|
import dev.ksan.etfoglasiserver.model.User;
|
||||||
|
import dev.ksan.etfoglasiserver.model.UserPrincipal;
|
||||||
|
import dev.ksan.etfoglasiserver.repository.UserRepo;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MyUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired private UserRepo userRepo;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
|
||||||
|
|
||||||
|
Optional<User> user = userRepo.findByEmail(email);
|
||||||
|
if (!user.isPresent()) {
|
||||||
|
throw new UsernameNotFoundException("user not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UserPrincipal(user.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -16,12 +16,15 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
public class SubjectService {
|
public class SubjectService {
|
||||||
|
|
||||||
@Autowired SubjectRepo subjectRepo;
|
@Autowired private SubjectRepo subjectRepo;
|
||||||
@Autowired
|
@Autowired
|
||||||
UserRepo userRepo;
|
private UserRepo userRepo;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MailService mailService;
|
||||||
|
|
||||||
public List<Subject> getSubjects() {
|
public List<Subject> getSubjects() {
|
||||||
return subjectRepo.findAll();
|
return subjectRepo.findAll();
|
||||||
}
|
}
|
||||||
@ -80,8 +83,7 @@ public class SubjectService {
|
|||||||
|
|
||||||
public void sendEmailNotification(Entry entry,User user) {
|
public void sendEmailNotification(Entry entry,User user) {
|
||||||
|
|
||||||
MailService mail = new MailService(".creds");
|
mailService.sendEmail(user.getEmail(),entry.getTitle(),entry.getParagraph());
|
||||||
mail.sendEmail(user.getEmail(),entry.getTitle(),entry.getParagraph());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo
|
//todo
|
||||||
|
|||||||
@ -1,13 +1,27 @@
|
|||||||
package dev.ksan.etfoglasiserver.service;
|
package dev.ksan.etfoglasiserver.service;
|
||||||
|
|
||||||
|
import dev.ksan.etfoglasiserver.dto.JwtResponseDTO;
|
||||||
import dev.ksan.etfoglasiserver.dto.UserCreationDTO;
|
import dev.ksan.etfoglasiserver.dto.UserCreationDTO;
|
||||||
import dev.ksan.etfoglasiserver.model.NotificationMethod;
|
import dev.ksan.etfoglasiserver.dto.UserDTO;
|
||||||
|
import dev.ksan.etfoglasiserver.dto.UserLoginDTO;
|
||||||
import dev.ksan.etfoglasiserver.model.User;
|
import dev.ksan.etfoglasiserver.model.User;
|
||||||
|
import dev.ksan.etfoglasiserver.model.UserPrincipal;
|
||||||
import dev.ksan.etfoglasiserver.repository.UserRepo;
|
import dev.ksan.etfoglasiserver.repository.UserRepo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@ -16,12 +30,20 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
public class UserService {
|
public class UserService {
|
||||||
@Autowired UserRepo userRepo;
|
@Autowired UserRepo userRepo;
|
||||||
|
|
||||||
public List<User> getUsers() {
|
@Autowired private AuthenticationManager authManager;
|
||||||
return userRepo.findAll();
|
|
||||||
|
@Autowired private JWTService jwtService;
|
||||||
|
|
||||||
|
private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
public List<UserDTO> getUsers() {
|
||||||
|
return userRepo.findAll().stream().map(this::getUserDTO).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getUserById(UUID userId) {
|
public UserDTO getUserById(UUID userId) {
|
||||||
return userRepo.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
|
User user = userRepo.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
|
||||||
|
|
||||||
|
return getUserDTO(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addUser(UserCreationDTO user) {
|
public void addUser(UserCreationDTO user) {
|
||||||
@ -34,47 +56,77 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserDTO updateUser(UserCreationDTO user) {
|
||||||
|
|
||||||
public void updateUser(UserCreationDTO user) {
|
|
||||||
Optional<User> existingUserOpt = userRepo.findByEmail(user.getEmail());
|
Optional<User> existingUserOpt = userRepo.findByEmail(user.getEmail());
|
||||||
if(userRepo.findByEmail(user.getNewEmail()).isPresent()) {
|
|
||||||
|
if (userRepo.findByEmail(user.getNewEmail()).isPresent()) {
|
||||||
throw new RuntimeException("Email taken");
|
throw new RuntimeException("Email taken");
|
||||||
}
|
}
|
||||||
if (userRepo.findByEmail(user.getEmail()).isPresent()) {
|
if (existingUserOpt.isPresent()) {
|
||||||
|
|
||||||
if (this.isValidEmail(user.getEmail())) {
|
if (this.isValidEmail(user.getEmail())) {
|
||||||
|
|
||||||
User existingUser = existingUserOpt.get();
|
User existingUser = existingUserOpt.get();
|
||||||
if(user.getPassword() != null && user.getPassword().length() > 0) {
|
if (user.getPassword() != null && user.getPassword().length() > 0) {
|
||||||
|
|
||||||
if (this.isValidPassword(user.getPassword())) {
|
if (this.isValidPassword(user.getPassword())) {
|
||||||
|
|
||||||
existingUser.setPassword(user.getPassword());
|
existingUser.setPassword(user.getPassword());
|
||||||
}else throw new RuntimeException("Password too short");
|
} else throw new RuntimeException("Password too short");
|
||||||
}
|
}
|
||||||
if(user.getNewEmail() != null && user.getNewEmail() != existingUser.getEmail()) {
|
if (user.getNewEmail() != null && user.getNewEmail() != existingUser.getEmail()) {
|
||||||
|
|
||||||
existingUser.setEmail(user.getNewEmail());
|
existingUser.setEmail(user.getNewEmail());
|
||||||
}else{
|
} else {
|
||||||
|
|
||||||
existingUser.setEmail(user.getEmail());
|
existingUser.setEmail(user.getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
existingUser.setSubjectSet(user.getSubjectSet());
|
existingUser.setSubjectSet(user.getSubjectSet());
|
||||||
|
|
||||||
existingUser.setNotificationMethod(user.getNotificationMethod());
|
existingUser.setNotificationMethod(user.getNotificationMethod());
|
||||||
|
|
||||||
userRepo.save(existingUser);
|
userRepo.save(existingUser);
|
||||||
|
|
||||||
|
return getUserDTO(existingUser);
|
||||||
|
|
||||||
} else throw new RuntimeException("Invalid email");
|
} else throw new RuntimeException("Invalid email");
|
||||||
} else throw new RuntimeException("User not found");
|
} else throw new RuntimeException("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void deleteUser(UUID userId) {
|
public void deleteUser(UUID userId) {
|
||||||
userRepo.deleteById(userId);
|
userRepo.deleteById(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserDTO register(UserCreationDTO user) {
|
||||||
|
|
||||||
|
if (userRepo.findByEmail(user.getEmail()).isPresent()) {
|
||||||
|
throw new RuntimeException("User already exists");
|
||||||
|
}
|
||||||
|
if (this.isValidEmail(user.getEmail()) && this.isValidPassword(user.getPassword())) {
|
||||||
|
User newUser = new User(user);
|
||||||
|
newUser.setPassword(encoder.encode(user.getPassword()));
|
||||||
|
userRepo.save(newUser);
|
||||||
|
return getUserDTO(newUser);
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Error creating user");
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDTO getUserDTO(User user) {
|
||||||
|
|
||||||
|
return new UserDTO(
|
||||||
|
user.getId(), user.getEmail(), user.getSubjectSet(), user.getNotificationMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidPassword(String pass) {
|
||||||
|
return pass.length() >= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> findUsersBySubjectId(UUID id) {
|
||||||
|
List<User> users = userRepo.findUsersBySubjectId(id);
|
||||||
|
if (users.isEmpty()) return null;
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValidEmail(String email) {
|
public boolean isValidEmail(String email) {
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -87,14 +139,24 @@ public class UserService {
|
|||||||
throw new RuntimeException("Invalid email");
|
throw new RuntimeException("Invalid email");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidPassword(String pass) {
|
public JwtResponseDTO verify(UserLoginDTO user) {
|
||||||
return pass.length() >= 8;
|
|
||||||
|
|
||||||
|
Authentication authentication = authManager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
|
||||||
|
|
||||||
|
if (authentication.isAuthenticated()) {
|
||||||
|
|
||||||
|
String token = jwtService.generateToken(user.getEmail());
|
||||||
|
return new JwtResponseDTO(token, user.getEmail(), HttpStatus.OK.toString());
|
||||||
|
} else {
|
||||||
|
|
||||||
|
throw new BadCredentialsException("Invalid username or password");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<User> findUsersBySubjectId(UUID id) {
|
public Optional<User> getAccountByEmail(String email) {
|
||||||
List<User> users = userRepo.findUsersBySubjectId(id);
|
return userRepo.findByEmail(email);
|
||||||
if (users.isEmpty()) return null;
|
|
||||||
return users;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user