diff --git a/pom.xml b/pom.xml
index 10c31c7..b3b0dba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,6 +8,7 @@
release-hive
0.0.1-SNAPSHOT
+
@@ -32,13 +33,35 @@
spring-boot-starter-json
3.3.2
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ 3.3.2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+ 3.3.2
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+
-
- org.hibernate
- hibernate-core
- 6.6.0.CR1
-
org.postgresql
postgresql
diff --git a/src/main/java/wtf/beatrice/releasehive/config/ApplicationConfiguration.java b/src/main/java/wtf/beatrice/releasehive/config/ApplicationConfiguration.java
new file mode 100644
index 0000000..22d8cbd
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/config/ApplicationConfiguration.java
@@ -0,0 +1,51 @@
+package wtf.beatrice.releasehive.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.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import wtf.beatrice.releasehive.repository.UserRepository;
+
+@Configuration
+public class ApplicationConfiguration
+{
+
+ private final UserRepository userRepository;
+
+ public ApplicationConfiguration(@Autowired UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @Bean
+ UserDetailsService userDetailsService() {
+ return username -> userRepository.findByEmail(username)
+ .orElseThrow(() -> new UsernameNotFoundException("User not found"));
+ }
+
+ @Bean
+ BCryptPasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
+ return config.getAuthenticationManager();
+ }
+
+ @Bean
+ AuthenticationProvider authenticationProvider() {
+ DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
+
+ authProvider.setUserDetailsService(userDetailsService());
+ authProvider.setPasswordEncoder(passwordEncoder());
+
+ return authProvider;
+ }
+
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/config/JWTAuthenticationFilter.java b/src/main/java/wtf/beatrice/releasehive/config/JWTAuthenticationFilter.java
new file mode 100644
index 0000000..c226529
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/config/JWTAuthenticationFilter.java
@@ -0,0 +1,79 @@
+package wtf.beatrice.releasehive.config;
+
+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.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 wtf.beatrice.releasehive.service.JWTService;
+
+import java.io.IOException;
+
+@Component
+public class JWTAuthenticationFilter extends OncePerRequestFilter
+{
+ private final HandlerExceptionResolver handlerExceptionResolver;
+
+ private final JWTService jwtService;
+ private final UserDetailsService userDetailsService;
+
+ public JWTAuthenticationFilter(
+ @Autowired JWTService jwtService,
+ @Autowired UserDetailsService userDetailsService,
+ @Autowired HandlerExceptionResolver handlerExceptionResolver) {
+ this.jwtService = jwtService;
+ this.userDetailsService = userDetailsService;
+ this.handlerExceptionResolver = handlerExceptionResolver;
+ }
+
+
+ @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 jwt = authHeader.substring(7);
+ final String userEmail = jwtService.extractUsername(jwt);
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+ if (userEmail != null && authentication == null) {
+ UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
+
+ if (jwtService.isTokenValid(jwt, userDetails)) {
+ UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
+ userDetails,
+ null,
+ userDetails.getAuthorities()
+ );
+
+ authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authToken);
+ }
+ }
+
+ filterChain.doFilter(request, response);
+ } catch (Exception exception) {
+ handlerExceptionResolver.resolveException(request, response, null, exception);
+ }
+ }
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/config/SecurityConfiguration.java b/src/main/java/wtf/beatrice/releasehive/config/SecurityConfiguration.java
new file mode 100644
index 0000000..ffb6c12
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/config/SecurityConfiguration.java
@@ -0,0 +1,71 @@
+package wtf.beatrice.releasehive.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.AuthenticationProvider;
+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.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import java.util.List;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfiguration
+{
+
+ private final AuthenticationProvider authenticationProvider;
+ private final JWTAuthenticationFilter jwtAuthenticationFilter;
+
+ public SecurityConfiguration(
+ @Autowired JWTAuthenticationFilter jwtAuthenticationFilter,
+ @Autowired AuthenticationProvider authenticationProvider)
+ {
+ this.authenticationProvider = authenticationProvider;
+ this.jwtAuthenticationFilter = jwtAuthenticationFilter;
+ }
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http.csrf()
+ .disable()
+ .authorizeHttpRequests()
+ .requestMatchers("/api/v1/auth/**")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authenticationProvider(authenticationProvider)
+ .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
+
+ return http.build();
+ }
+
+ @Bean
+ CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration configuration = new CorsConfiguration();
+
+ configuration.setAllowedOrigins(List.of("http://localhost:8080"));
+ configuration.setAllowedMethods(List.of("GET","POST"));
+ configuration.setAllowedHeaders(List.of("Authorization","Content-Type"));
+
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+
+ source.registerCorsConfiguration("/**",configuration);
+
+ return source;
+ }
+
+
+
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/dto/LoginUserDto.java b/src/main/java/wtf/beatrice/releasehive/dto/LoginUserDto.java
new file mode 100644
index 0000000..42e9e97
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/dto/LoginUserDto.java
@@ -0,0 +1,24 @@
+package wtf.beatrice.releasehive.dto;
+
+public class LoginUserDto
+{
+ 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;
+ }
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/dto/RegisterUserDto.java b/src/main/java/wtf/beatrice/releasehive/dto/RegisterUserDto.java
new file mode 100644
index 0000000..5d24609
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/dto/RegisterUserDto.java
@@ -0,0 +1,34 @@
+package wtf.beatrice.releasehive.dto;
+
+public class RegisterUserDto
+{
+ private String email;
+
+ private String password;
+
+ private String 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;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/model/ApiError.java b/src/main/java/wtf/beatrice/releasehive/model/ApiError.java
deleted file mode 100644
index 794f0cd..0000000
--- a/src/main/java/wtf/beatrice/releasehive/model/ApiError.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package wtf.beatrice.releasehive.model;
-
-import jakarta.persistence.Entity;
-
-import java.util.UUID;
-
-@Entity
-public class ApiError
-{
- UUID exceptionId;
-
- String message;
-
- public ApiError() {
- exceptionId = UUID.randomUUID();
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public UUID getExceptionId() {
- return exceptionId;
- }
-
- public void setExceptionId(UUID exceptionId) {
- this.exceptionId = exceptionId;
- }
-}
diff --git a/src/main/java/wtf/beatrice/releasehive/model/LoginResponse.java b/src/main/java/wtf/beatrice/releasehive/model/LoginResponse.java
new file mode 100644
index 0000000..4ad4a98
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/model/LoginResponse.java
@@ -0,0 +1,34 @@
+package wtf.beatrice.releasehive.model;
+
+public class LoginResponse
+{
+ private String token;
+
+ private long expiresIn;
+
+ public String getToken() {
+ return token;
+ }
+
+ public LoginResponse setToken(String token) {
+ this.token = token;
+ return this;
+ }
+
+ public long getExpiresIn() {
+ return expiresIn;
+ }
+
+ public LoginResponse setExpiresIn(long expiresIn) {
+ this.expiresIn = expiresIn;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "LoginResponse{" +
+ "token='" + token + '\'' +
+ ", expiresIn=" + expiresIn +
+ '}';
+ }
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/model/User.java b/src/main/java/wtf/beatrice/releasehive/model/User.java
index a10b0fa..f0d2786 100644
--- a/src/main/java/wtf/beatrice/releasehive/model/User.java
+++ b/src/main/java/wtf/beatrice/releasehive/model/User.java
@@ -2,36 +2,81 @@ package wtf.beatrice.releasehive.model;
import jakarta.persistence.*;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
import java.util.UUID;
@Entity
@Table(name="users")
-public class User
+public class User implements UserDetails
{
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID uuid;
- @Column
+ @Column(nullable = false)
private String username;
- @Column
+
+ @Column(unique = true, length = 64, nullable = false)
+ private String email;
+
+ @Column(nullable = false)
private String password;
+ @CreationTimestamp
+ @Column(updatable = false, name = "created_at")
+ private Date createdAt;
+
+ @UpdateTimestamp
+ @Column(name = "updated_at")
+ private Date updatedAt;
+
public UUID getUuid() {
return uuid;
}
+ @Override
public String getUsername() {
return username;
}
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
public void setUsername(String username) {
this.username = username;
}
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return List.of();
+ }
+
public String getPassword() {
return password;
}
@@ -43,4 +88,28 @@ public class User
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
+
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public Date getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public void setUpdatedAt(Date updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
}
diff --git a/src/main/java/wtf/beatrice/releasehive/repository/UserRepository.java b/src/main/java/wtf/beatrice/releasehive/repository/UserRepository.java
new file mode 100644
index 0000000..51a8cad
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/repository/UserRepository.java
@@ -0,0 +1,14 @@
+package wtf.beatrice.releasehive.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import wtf.beatrice.releasehive.model.User;
+
+import java.util.Optional;
+import java.util.UUID;
+
+@Repository
+public interface UserRepository extends JpaRepository {
+
+ Optional findByEmail(String email);
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/resource/AccountResource.java b/src/main/java/wtf/beatrice/releasehive/resource/AccountResource.java
index 68a6841..2a73c34 100644
--- a/src/main/java/wtf/beatrice/releasehive/resource/AccountResource.java
+++ b/src/main/java/wtf/beatrice/releasehive/resource/AccountResource.java
@@ -1,29 +1,53 @@
package wtf.beatrice.releasehive.resource;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import wtf.beatrice.releasehive.dto.LoginUserDto;
+import wtf.beatrice.releasehive.dto.RegisterUserDto;
+import wtf.beatrice.releasehive.model.LoginResponse;
import wtf.beatrice.releasehive.model.User;
import wtf.beatrice.releasehive.service.AccountService;
+import wtf.beatrice.releasehive.service.JWTService;
@RestController
-@RequestMapping("/api/v1/users")
+@RequestMapping("/api/v1/auth")
public class AccountResource {
private final AccountService accountService;
+ private final JWTService jwtService;
- public AccountResource(@Autowired AccountService accountService) {
+ public AccountResource(
+ @Autowired AccountService accountService,
+ @Autowired JWTService jwtService) {
this.accountService = accountService;
+ this.jwtService = jwtService;
}
-
@PostMapping(
value="/register",
produces="application/json")
- public String register(@RequestBody User user)
+ public ResponseEntity register(@RequestBody RegisterUserDto userDto)
{
- return accountService.registerUser(user);
+ User user = accountService.register(userDto);
+ return ResponseEntity.ok(user);
}
+
+ @PostMapping(
+ value="/login",
+ produces="application/json")
+ public ResponseEntity login(@RequestBody LoginUserDto userDto)
+ {
+ User authenticatedUser = accountService.login(userDto);
+
+ String jwtToken = jwtService.generateToken(authenticatedUser);
+
+ LoginResponse loginResponse = new LoginResponse().setToken(jwtToken).setExpiresIn(jwtService.getExpirationTime());
+
+ return ResponseEntity.ok(loginResponse);
+ }
+
}
diff --git a/src/main/java/wtf/beatrice/releasehive/service/AccountService.java b/src/main/java/wtf/beatrice/releasehive/service/AccountService.java
index 048a18e..692f728 100644
--- a/src/main/java/wtf/beatrice/releasehive/service/AccountService.java
+++ b/src/main/java/wtf/beatrice/releasehive/service/AccountService.java
@@ -1,9 +1,13 @@
package wtf.beatrice.releasehive.service;
+import wtf.beatrice.releasehive.dto.LoginUserDto;
+import wtf.beatrice.releasehive.dto.RegisterUserDto;
import wtf.beatrice.releasehive.model.User;
public interface AccountService
{
- String registerUser(User user);
+ User register(RegisterUserDto user);
+
+ User login(LoginUserDto user);
}
diff --git a/src/main/java/wtf/beatrice/releasehive/service/AccountServiceImpl.java b/src/main/java/wtf/beatrice/releasehive/service/AccountServiceImpl.java
index d9b2914..6fe138e 100644
--- a/src/main/java/wtf/beatrice/releasehive/service/AccountServiceImpl.java
+++ b/src/main/java/wtf/beatrice/releasehive/service/AccountServiceImpl.java
@@ -2,30 +2,58 @@ package wtf.beatrice.releasehive.service;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.springframework.beans.factory.annotation.Autowired;
+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 wtf.beatrice.releasehive.db.HibernateManager;
+import wtf.beatrice.releasehive.dto.LoginUserDto;
+import wtf.beatrice.releasehive.dto.RegisterUserDto;
import wtf.beatrice.releasehive.model.User;
+import wtf.beatrice.releasehive.repository.UserRepository;
import wtf.beatrice.releasehive.util.JsonUtil;
@Service
public class AccountServiceImpl implements AccountService {
- @Override
- public String registerUser(User user) {
+ private final UserRepository userRepository;
+ private final PasswordEncoder passwordEncoder;
+ private final AuthenticationManager authenticationManager;
- if(null == user.getUsername() || user.getUsername().isEmpty()) {
- return JsonUtil.spawnJsonError("Cannot register user without username");
- }
-
- if(null == user.getPassword() || user.getPassword().isEmpty()) {
- return JsonUtil.spawnJsonError("Cannot register user without password");
- }
-
- Session session = HibernateManager.getSession();
- Transaction transaction = session.beginTransaction();
- session.persist(user);
- transaction.commit();
-
- return JsonUtil.convertToJson(user);
+ public AccountServiceImpl(
+ @Autowired UserRepository userRepository,
+ @Autowired AuthenticationManager authenticationManager,
+ @Autowired PasswordEncoder passwordEncoder
+ ) {
+ this.authenticationManager = authenticationManager;
+ this.userRepository = userRepository;
+ this.passwordEncoder = passwordEncoder;
}
+
+ @Override
+ public User register(RegisterUserDto userDto) {
+
+ User user = new User();
+ user.setUsername(userDto.getUsername());
+ user.setEmail(userDto.getEmail());
+ user.setPassword(passwordEncoder.encode(userDto.getPassword()));
+
+ return userRepository.save(user);
+ }
+
+ @Override
+ public User login(LoginUserDto user) {
+ authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(
+ user.getEmail(),
+ user.getPassword()
+ )
+ );
+
+ return userRepository.findByEmail(user.getEmail())
+ .orElseThrow();
+ }
+
+
}
diff --git a/src/main/java/wtf/beatrice/releasehive/service/JWTService.java b/src/main/java/wtf/beatrice/releasehive/service/JWTService.java
new file mode 100644
index 0000000..5e3193a
--- /dev/null
+++ b/src/main/java/wtf/beatrice/releasehive/service/JWTService.java
@@ -0,0 +1,89 @@
+package wtf.beatrice.releasehive.service;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.io.Decoders;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+
+import java.security.Key;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+@Service
+public class JWTService
+{
+ @Value("${security.jwt.secret-key}")
+ private String secretKey;
+
+ @Value("${security.jwt.expiration-time}")
+ private long jwtExpiration;
+
+ public String extractUsername(String token) {
+ return extractClaim(token, Claims::getSubject);
+ }
+
+ public T extractClaim(String token, Function claimsResolver) {
+ final Claims claims = extractAllClaims(token);
+ return claimsResolver.apply(claims);
+ }
+
+ public String generateToken(UserDetails userDetails) {
+ return generateToken(new HashMap<>(), userDetails);
+ }
+
+ public String generateToken(Map extraClaims, UserDetails userDetails) {
+ return buildToken(extraClaims, userDetails, jwtExpiration);
+ }
+
+ public long getExpirationTime() {
+ return jwtExpiration;
+ }
+
+ private String buildToken(
+ Map extraClaims,
+ UserDetails userDetails,
+ long expiration
+ ) {
+ return Jwts
+ .builder()
+ .setClaims(extraClaims)
+ .setSubject(userDetails.getUsername())
+ .setIssuedAt(new Date(System.currentTimeMillis()))
+ .setExpiration(new Date(System.currentTimeMillis() + expiration))
+ .signWith(getSignInKey(), SignatureAlgorithm.HS256)
+ .compact();
+ }
+
+ public boolean isTokenValid(String token, UserDetails userDetails) {
+ final String username = extractUsername(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);
+ }
+
+ private Claims extractAllClaims(String token) {
+ return Jwts
+ .parserBuilder()
+ .setSigningKey(getSignInKey())
+ .build()
+ .parseClaimsJws(token)
+ .getBody();
+ }
+
+ private Key getSignInKey() {
+ byte[] keyBytes = Decoders.BASE64.decode(secretKey);
+ return Keys.hmacShaKeyFor(keyBytes);
+ }
+}
diff --git a/src/main/java/wtf/beatrice/releasehive/util/JsonUtil.java b/src/main/java/wtf/beatrice/releasehive/util/JsonUtil.java
index c4d0ded..a73e3ce 100644
--- a/src/main/java/wtf/beatrice/releasehive/util/JsonUtil.java
+++ b/src/main/java/wtf/beatrice/releasehive/util/JsonUtil.java
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import wtf.beatrice.releasehive.model.ApiError;
public class JsonUtil
{
@@ -24,12 +23,4 @@ public class JsonUtil
return e.getMessage();
}
}
-
- public static String spawnJsonError(String errorMessage) {
- ApiError apiError = new ApiError();
- apiError.setMessage(errorMessage);
- String error = convertToJson(apiError);
- LOGGER.error(error);
- return error;
- }
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..d697a56
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,13 @@
+server.port=8080
+
+spring.datasource.url=jdbc:postgresql://localhost:5432/releasehive
+spring.datasource.username=relhive
+spring.datasource.password=beelover
+
+## Hibernate properties
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.open-in-view=false
+
+security.jwt.secret-key=ed725256582a23e94f81ba36d7df498ea330c7ba978e2d8876fe135b4bb34068
+# 1h in millisecond
+security.jwt.expiration-time=3600000
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..7d8b81b
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+spring:
+ autoconfigure:
+ exclude:
+ - org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
+ - org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration