diff --git a/backend/Dockerfile b/backend/Dockerfile
index f016d66..d83eca3 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,4 +1,3 @@
-# Stage 1: Сборка приложения
FROM maven:3.8.3-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
@@ -10,5 +9,4 @@ RUN mvn package -Dmaven.test.skip=true
FROM openjdk:17
WORKDIR /app
COPY --from=build /app/target/QuickProjectApp-0.0.1-SNAPSHOT.jar /app/QuickProjectApp.jar
-CMD ["java", "-jar", "QuickProjectApp.jar"]
-
+CMD ["java", "-jar", "QuickProjectApp.jar"]
\ No newline at end of file
diff --git a/backend/QuickProject.postman_collection.json b/backend/QuickProject.postman_collection.json
new file mode 100644
index 0000000..cf9b242
--- /dev/null
+++ b/backend/QuickProject.postman_collection.json
@@ -0,0 +1,116 @@
+{
+ "info": {
+ "_postman_id": "71a90115-759d-4f6b-93e0-a28d0c86f1fd",
+ "name": "QuickProject",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "29891838"
+ },
+ "item": [
+ {
+ "name": "auth/register",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"email\" : \"ela@mail.ru\",\r\n \"password\" : \"1\",\r\n \"created_at\": \"2024-03-22T18:00:00\",\r\n \"tz\" : \"+3\",\r\n \"enable\" : true\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8081/api/auth/register",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8081",
+ "path": [
+ "api",
+ "auth",
+ "register"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "New Request",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"email\" : \"ela@mail.ru\",\r\n \"password\" : \"1\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8081/api/auth/authenticate",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8081",
+ "path": [
+ "api",
+ "auth",
+ "authenticate"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "New Request",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:8081/api/users",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8081",
+ "path": [
+ "api",
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "New Request",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:8081/api/projects",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8081",
+ "path": [
+ "api",
+ "projects"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/backend/docker-compose.yaml b/backend/docker-compose.yaml
index 205e548..b0df597 100644
--- a/backend/docker-compose.yaml
+++ b/backend/docker-compose.yaml
@@ -2,21 +2,21 @@ version: '3.8'
services:
- dev_app:
+ pet_app:
image: pet:dev
- container_name: dev_app
+ container_name: pet_app
build:
context: .
dockerfile: Dockerfile
depends_on:
- dev_db:
+ pet_db:
condition: service_healthy
links:
- - dev_db
+ - pet_db
environment:
WAIT_HOSTS: dev_db:5432
SPRING_PROFILES_ACTIVE: dev
- SPRING_DATASOURCE_URL: jdbc:postgresql://dev_db:5432/pet
+ SPRING_DATASOURCE_URL: jdbc:postgresql://pet_db:5432/pet
SPRING_DATASOURCE_USERNAME: ${DB_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
SPRING_PARENT_DIRECTORY: /
@@ -26,9 +26,9 @@ services:
volumes:
- ${HOST_PARENT_DIRECTORY}:/pet
- dev_db:
+ pet_db:
image: postgres
- container_name: dev_db
+ container_name: pet_db
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
diff --git a/backend/pom.xml b/backend/pom.xml
index 79e229d..996728e 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -8,7 +8,8 @@
spring-boot-starter-parent
3.2.2
-
+
+
com.QuickProject
QuickProjectApp
0.0.1-SNAPSHOT
@@ -33,7 +34,7 @@
org.springframework.boot
- spring-boot-starter-data-rest
+ spring-boot-starter-security
@@ -49,15 +50,27 @@
- org.flywaydb
- flyway-core
- 9.16.0
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
- org.postgresql
- postgresql
- runtime
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+
+
+
+ org.flywaydb
+ flyway-core
+ 9.16.0
@@ -69,11 +82,10 @@
spring-boot-starter-data-rest
-
org.postgresql
postgresql
- 42.7.1
+ 42.7.2
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationController.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationController.java
new file mode 100644
index 0000000..8be048f
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationController.java
@@ -0,0 +1,32 @@
+package com.QuickProject.QuickProjectApp.auth;
+
+import lombok.RequiredArgsConstructor;
+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;
+
+@RestController
+@RequestMapping("/api/auth")
+@RequiredArgsConstructor
+public class AuthenticationController {
+
+ private final AuthenticationService service;
+
+ @PostMapping("/register")
+ public ResponseEntity register(
+ @RequestBody RegisterRequest request
+ ) {
+ return ResponseEntity.ok(service.register(request));
+ }
+
+
+ @PostMapping("/authenticate")
+ public ResponseEntity authenticate(
+ @RequestBody AuthenticationRequest request
+ ) {
+ return ResponseEntity.ok(service.authenticate(request));
+ }
+
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationRequest.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationRequest.java
new file mode 100644
index 0000000..00a3ea1
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationRequest.java
@@ -0,0 +1,19 @@
+package com.QuickProject.QuickProjectApp.auth;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuthenticationRequest {
+
+ private String email;
+
+ private String password;
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationResponse.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationResponse.java
new file mode 100644
index 0000000..8e9c215
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationResponse.java
@@ -0,0 +1,15 @@
+package com.QuickProject.QuickProjectApp.auth;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuthenticationResponse {
+
+ private String token;
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationService.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationService.java
new file mode 100644
index 0000000..148670e
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/AuthenticationService.java
@@ -0,0 +1,54 @@
+package com.QuickProject.QuickProjectApp.auth;
+
+import com.QuickProject.QuickProjectApp.config.JwtService;
+import com.QuickProject.QuickProjectApp.dao.UserRepository;
+import com.QuickProject.QuickProjectApp.entity.user.Role;
+import com.QuickProject.QuickProjectApp.entity.user.User;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class AuthenticationService {
+
+ private final UserRepository repository;
+
+ private final JwtService jwtService;
+
+ private final PasswordEncoder passwordEncoder;
+
+ private final AuthenticationManager authenticationManager;
+
+ public AuthenticationResponse register(RegisterRequest request) {
+ var user = User.builder()
+ .email(request.getEmail())
+ .password(passwordEncoder.encode(request.getPassword()))
+ .role(Role.USER)
+ .created_at(request.getCreated_at())
+ .enable(request.isEnable())
+ .tz(request.getTz())
+ .build();
+ repository.save(user);
+ var jwtToken = jwtService.generateToken(user);
+ return AuthenticationResponse.builder()
+ .token(jwtToken)
+ .build();
+ }
+
+ public AuthenticationResponse authenticate(AuthenticationRequest request) {
+ authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(
+ request.getEmail(),
+ request.getPassword()
+ )
+ );
+ var user = repository.findByEmail(request.getEmail()).orElseThrow();
+ var jwtToken = jwtService.generateToken(user);
+ return AuthenticationResponse.builder()
+ .token(jwtToken)
+ .build();
+ }
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/RegisterRequest.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/RegisterRequest.java
new file mode 100644
index 0000000..b25ebf1
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/auth/RegisterRequest.java
@@ -0,0 +1,29 @@
+package com.QuickProject.QuickProjectApp.auth;
+
+
+import com.QuickProject.QuickProjectApp.entity.user.Role;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class RegisterRequest {
+
+ private String email;
+
+ private String password;
+
+ private LocalDateTime created_at;
+
+ private boolean enable;
+
+ private String tz;
+
+ private final Role user_role = Role.USER;
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/config/ApplicationConfig.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/ApplicationConfig.java
new file mode 100644
index 0000000..1d6aa7c
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/ApplicationConfig.java
@@ -0,0 +1,49 @@
+package com.QuickProject.QuickProjectApp.config;
+
+import com.QuickProject.QuickProjectApp.dao.UserRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+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.config.ldap.LdapUserServiceBeanDefinitionParser;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+@RequiredArgsConstructor
+public class ApplicationConfig {
+
+ private final UserRepository repository;
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return username -> repository.findByEmail(username)
+ .orElseThrow(() -> new UsernameNotFoundException("User not found"));
+ }
+
+ @Bean
+ public AuthenticationProvider authenticationProvider() {
+ DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
+ authProvider.setUserDetailsService(userDetailsService());
+ authProvider.setPasswordEncoder(passwordEncoder());
+ return authProvider;
+ }
+
+ @Bean
+ public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
+ return configuration.getAuthenticationManager();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtAuthenticationFilter.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..cb8d5fb
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtAuthenticationFilter.java
@@ -0,0 +1,61 @@
+package com.QuickProject.QuickProjectApp.config;
+
+import jakarta.annotation.Nonnull;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContext;
+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 java.io.IOException;
+
+@Component
+@RequiredArgsConstructor
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+
+ private final JwtService jwtService;
+
+ private final UserDetailsService userDetailsService;
+
+ @Override
+ protected void doFilterInternal(
+ @Nonnull HttpServletRequest request,
+ @Nonnull HttpServletResponse response,
+ @Nonnull FilterChain filterChain
+ ) throws ServletException, IOException {
+ final String authHeader = request.getHeader("Authorization");
+ final String jwt;
+ final String userEmail;
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+ jwt = authHeader.substring(7);
+ userEmail = jwtService.extractUsername(jwt);
+ if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == 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);
+ }
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtService.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtService.java
new file mode 100644
index 0000000..ae82cc0
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/JwtService.java
@@ -0,0 +1,74 @@
+package com.QuickProject.QuickProjectApp.config;
+
+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.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 {
+ private static final String SECRET_KEY = "96c8f1ee65af9fa52e8f7bf75bb308a866fbaca5db8ee702e911818224f40e77150fc6dcf5e6e03ececdf1631017f7194a2c7fb1fe58226e7bc743b8a7e8127c";
+
+ public String extractUsername(String token) {
+ return extractClaims(token, Claims::getSubject);
+ }
+
+ public String generateToken(
+ Map extraClaims,
+ UserDetails userDetails
+ ) {
+ return Jwts
+ .builder()
+ .setClaims(extraClaims)
+ .setSubject(userDetails.getUsername())
+ .setIssuedAt(new Date(System.currentTimeMillis()))
+ .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 24))
+ .signWith(getSignKey(), 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 extractClaims(token, Claims::getExpiration);
+ }
+
+ public T extractClaims(String token, Function claimsResolver) {
+ final Claims claims = extractAllClaims(token);
+ return claimsResolver.apply(claims);
+ }
+
+ public String generateToken(UserDetails userDetails) {
+ return generateToken(new HashMap<>(), userDetails);
+ }
+
+ private Claims extractAllClaims(String token) {
+ return Jwts
+ .parserBuilder()
+ .setSigningKey(getSignKey())
+ .build()
+ .parseClaimsJws(token)
+ .getBody();
+ }
+
+ private Key getSignKey() {
+ byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
+ return Keys.hmacShaKeyFor(keyBytes);
+ }
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/config/SecurityConfiguration.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/SecurityConfiguration.java
new file mode 100644
index 0000000..7f8772d
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/config/SecurityConfiguration.java
@@ -0,0 +1,49 @@
+package com.QuickProject.QuickProjectApp.config;
+
+import lombok.RequiredArgsConstructor;
+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.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
+
+@Configuration
+@EnableWebSecurity
+@RequiredArgsConstructor
+public class SecurityConfiguration {
+
+ private final JwtAuthenticationFilter jwtAuthFilter;
+ private final AuthenticationProvider authenticationProvider;
+
+ private static final String[] WHITE_LIST_URL = {"/api/auth/**",
+ "/api/users",
+ "/api/projects",
+ "/api/journal",
+ "/api/queue",
+ "/api/projects_roles"};
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+
+ http
+ .csrf(AbstractHttpConfigurer::disable)
+ .authorizeHttpRequests(req ->
+ req.requestMatchers(WHITE_LIST_URL)
+ .permitAll()
+ .anyRequest()
+ .authenticated())
+ .sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
+ .authenticationProvider(authenticationProvider)
+ .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
+
+ return http.build();
+ }
+}
+
+
+
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/dao/UserRepository.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/dao/UserRepository.java
index c5c3b9f..bf9740d 100644
--- a/backend/src/main/java/com/QuickProject/QuickProjectApp/dao/UserRepository.java
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/dao/UserRepository.java
@@ -1,13 +1,13 @@
package com.QuickProject.QuickProjectApp.dao;
-import com.QuickProject.QuickProjectApp.entity.User;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
-import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
/**
@@ -16,7 +16,5 @@
@RepositoryRestResource(path="users")
public interface UserRepository extends JpaRepository {
@Transactional(readOnly = true)
- List findByEmail(String email) throws DataAccessException;
-
-
+ Optional findByEmail(String email) throws DataAccessException;
}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Journal.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Journal.java
index c05dd91..59ac76e 100644
--- a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Journal.java
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Journal.java
@@ -3,6 +3,7 @@
import java.time.LocalDateTime;
import java.util.UUID;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Project.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Project.java
index fa50c8a..d90304a 100644
--- a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Project.java
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Project.java
@@ -5,6 +5,7 @@
import java.util.List;
import java.util.UUID;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Queue.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Queue.java
index 90c7871..fce1e45 100644
--- a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Queue.java
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/Queue.java
@@ -2,6 +2,7 @@
import java.util.UUID;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/Role.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/Role.java
new file mode 100644
index 0000000..219ebb6
--- /dev/null
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/Role.java
@@ -0,0 +1,6 @@
+package com.QuickProject.QuickProjectApp.entity.user;
+
+public enum Role {
+ USER,
+ ADMIN
+}
diff --git a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/User.java b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/User.java
similarity index 51%
rename from backend/src/main/java/com/QuickProject/QuickProjectApp/entity/User.java
rename to backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/User.java
index de6be1d..60fa02c 100644
--- a/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/User.java
+++ b/backend/src/main/java/com/QuickProject/QuickProjectApp/entity/user/User.java
@@ -1,30 +1,38 @@
-package com.QuickProject.QuickProjectApp.entity;
+package com.QuickProject.QuickProjectApp.entity.user;
+import com.QuickProject.QuickProjectApp.entity.Journal;
+import com.QuickProject.QuickProjectApp.entity.Project;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
+import org.hibernate.annotations.UuidGenerator;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
import java.time.LocalDateTime;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
* Класс для работы с сущностью "user"
-*/
+ */
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Data
@Table(name = "users")
-public class User {
+public class User implements UserDetails {
@Id
@Column(name = "id")
- private UUID id = UUID.randomUUID();
+ @UuidGenerator
+ private UUID id;
@Column(name = "nickname")
private String nickname;
@@ -41,6 +49,11 @@ public class User {
@Column(name = "password")
private String password;
+ @Column(name = "user_role")
+ @Enumerated(EnumType.STRING)
+ @Builder.Default
+ Role role = Role.USER;
+
@Column(name = "created_at")
private LocalDateTime created_at;
@@ -66,4 +79,33 @@ public class User {
@OneToOne(mappedBy = "creator")
private Project project;
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return List.of(new SimpleGrantedAuthority(role.name()));
+ }
+
+ @Override
+ public String getUsername() {
+ return email;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enable;
+ }
}
diff --git a/backend/src/main/resources/db/migration/V1__Init.sql b/backend/src/main/resources/db/migration/V1__Init.sql
index fe858bb..24f23c1 100644
--- a/backend/src/main/resources/db/migration/V1__Init.sql
+++ b/backend/src/main/resources/db/migration/V1__Init.sql
@@ -1,3 +1,5 @@
+CREATE TYPE role AS ENUM ('USER', 'ADMIN');
+
create table if not exists users
(
id uuid not null primary key,
@@ -5,10 +7,11 @@ create table if not exists users
email varchar(100) not null unique,
telegram varchar(100) unique,
phone varchar(15) unique,
- password varchar(30) not null,
+ password varchar(80) not null,
created_at timestamp not null,
enable boolean not null default true,
project_role varchar(300),
+ user_role role not null,
photo bytea
);
diff --git a/backend/src/main/resources/db/migration/V3__Insert_Users.sql b/backend/src/main/resources/db/migration/V3__Insert_Users.sql
index 05a4c12..86bb57f 100644
--- a/backend/src/main/resources/db/migration/V3__Insert_Users.sql
+++ b/backend/src/main/resources/db/migration/V3__Insert_Users.sql
@@ -1,7 +1,7 @@
-INSERT INTO users (id, email, password, created_at, project_role)
+INSERT INTO users (id, email, password, created_at, project_role, user_role)
VALUES
- ('223e4567-e89b-12d3-a456-426614174000', 'test@test.com', '12345678', NOW(), 'Программист'),
- ('223e4567-e89b-12d3-a456-426614174001', 'designer@test.com', '123', NOW(), 'Дизайнер');
+ ('223e4567-e89b-12d3-a456-426614174000', 'test@test.com', '123', NOW(), 'Программист', 'USER'),
+ ('223e4567-e89b-12d3-a456-426614174001', 'designer@test.com', '123', NOW(), 'Дизайнер', 'USER');
INSERT INTO projects (id, creator_id, name, description, enable, created_at)
VALUES
diff --git a/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectRoleRepositoyTest.java b/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectRoleRepositoyTest.java
index 4679cb4..3536042 100644
--- a/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectRoleRepositoyTest.java
+++ b/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectRoleRepositoyTest.java
@@ -5,7 +5,7 @@
import com.QuickProject.QuickProjectApp.dao.UserRepository;
import com.QuickProject.QuickProjectApp.entity.Project;
import com.QuickProject.QuickProjectApp.entity.ProjectRole;
-import com.QuickProject.QuickProjectApp.entity.User;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import io.zonky.test.db.AutoConfigureEmbeddedDatabase;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectsRepositoyTest.java b/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectsRepositoyTest.java
index 3591751..7a75a61 100644
--- a/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectsRepositoyTest.java
+++ b/backend/src/test/java/com/QuickProject/QuickProjectApp/ProjectsRepositoyTest.java
@@ -3,16 +3,16 @@
import com.QuickProject.QuickProjectApp.dao.ProjectRepository;
import com.QuickProject.QuickProjectApp.dao.UserRepository;
import com.QuickProject.QuickProjectApp.entity.Project;
-import com.QuickProject.QuickProjectApp.entity.User;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import io.zonky.test.db.AutoConfigureEmbeddedDatabase;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.time.LocalDateTime;
-import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
+
@DataJpaTest
@AutoConfigureEmbeddedDatabase(provider = AutoConfigureEmbeddedDatabase.DatabaseProvider.ZONKY)
public class ProjectsRepositoyTest {
diff --git a/backend/src/test/java/com/QuickProject/QuickProjectApp/UserRepositoyTest.java b/backend/src/test/java/com/QuickProject/QuickProjectApp/UserRepositoyTest.java
index 8ed6dad..bac54eb 100644
--- a/backend/src/test/java/com/QuickProject/QuickProjectApp/UserRepositoyTest.java
+++ b/backend/src/test/java/com/QuickProject/QuickProjectApp/UserRepositoyTest.java
@@ -1,7 +1,7 @@
package com.QuickProject.QuickProjectApp;
import com.QuickProject.QuickProjectApp.dao.UserRepository;
-import com.QuickProject.QuickProjectApp.entity.User;
+import com.QuickProject.QuickProjectApp.entity.user.User;
import io.zonky.test.db.AutoConfigureEmbeddedDatabase;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +29,6 @@ void saveProject(){
user.setTz("+3");
repository.saveAndFlush(user);
- assertThat(repository.findByEmail("test_user@test.com").get(0).getEmail()).isEqualTo("test_user@test.com");
+ assertThat(repository.findByEmail("test_user@test.com").get().getEmail()).isEqualTo("test_user@test.com");
}
}