diff --git a/src/main/java/com/example/nto/config/WebSecurityConfig.java b/src/main/java/com/example/nto/config/WebSecurityConfig.java index 8ddce5d..d1eb63e 100644 --- a/src/main/java/com/example/nto/config/WebSecurityConfig.java +++ b/src/main/java/com/example/nto/config/WebSecurityConfig.java @@ -1,5 +1,52 @@ package com.example.nto.config; -public class WebSecurityConfig { +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +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.configuration.WebSecurityConfiguration; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private final UserDetailsService userDetailsService; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/h2-console/**").permitAll() +// .antMatchers("/api/auth").permitAll() +// .antMatchers("/api/users/username/{username}").permitAll() +// .antMatchers("/api/volunteer/one/1").hasAnyAuthority("ROLE_ADMIN") +// .antMatchers("/api/authority/**").hasAnyAuthority("ROLE_ADMIN") + .antMatchers("/api/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN") + .anyRequest().authenticated() + .and() + .httpBasic() + .and() + .headers().frameOptions().disable(); + + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService) + .passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } } diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index a65cc76..e7a3b19 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -5,25 +5,28 @@ import com.example.nto.entity.Code; import com.example.nto.entity.Employee; import com.example.nto.service.impl.EmployeeServiceImpl; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor +@RequestMapping("/api") public class EmployeeController { private final EmployeeServiceImpl employeeService; - @GetMapping("/api/{login}/auth") - public String auth(@PathVariable("login") String login){ - return employeeService.getAuth(login); + @GetMapping("/login") + public ResponseEntity login(Authentication authentication){ + return ResponseEntity.ok(employeeService.getEmployeeByUsername(authentication.getName())); } - @GetMapping("/api/{login}/info") - public Employee info(@PathVariable("login") String login){ - return employeeService.getInfo(login); + @GetMapping("/info/{login}") + public Employee info(@PathVariable("login") String username){ + return employeeService.getInfo(username); } - @PatchMapping("/api/{login}/open") + @PatchMapping("/open/{login}") public String open(@PathVariable("login") String login, @RequestBody Code value){ return employeeService.patchOpen(login, value.getValue()); } diff --git a/src/main/java/com/example/nto/dto/EmployeeRegisterDTO.java b/src/main/java/com/example/nto/dto/EmployeeDTO.java similarity index 56% rename from src/main/java/com/example/nto/dto/EmployeeRegisterDTO.java rename to src/main/java/com/example/nto/dto/EmployeeDTO.java index c837eed..452ebdb 100644 --- a/src/main/java/com/example/nto/dto/EmployeeRegisterDTO.java +++ b/src/main/java/com/example/nto/dto/EmployeeDTO.java @@ -3,8 +3,9 @@ package com.example.nto.dto; import lombok.Data; @Data -public class EmployeeRegisterDTO { - private String login; +public class EmployeeDTO { + private String username; private String name; private String password; + private String lastVisit; } diff --git a/src/main/java/com/example/nto/entity/Authority.java b/src/main/java/com/example/nto/entity/Authority.java new file mode 100644 index 0000000..b1f60d7 --- /dev/null +++ b/src/main/java/com/example/nto/entity/Authority.java @@ -0,0 +1,17 @@ +package com.example.nto.entity; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; + +import javax.persistence.*; + +@Data +@Entity +@Table(name="authority") +public class Authority implements GrantedAuthority { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @Column(name="authorities") + private String authority; +} diff --git a/src/main/java/com/example/nto/entity/Employee.java b/src/main/java/com/example/nto/entity/Employee.java index f387774..2173c41 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -2,28 +2,65 @@ package com.example.nto.entity; import lombok.AllArgsConstructor; import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Set; @Data @Entity @Table(name="employee") -public class Employee { +public class Employee implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id") private long id; - @Column(name = "login") - private String login; + + @Column(name = "username") + private String username; + @Column(name = "name") private String name; + @Column(name="password") private String password; + @Column(name = "photo_url") private String photoUrl; + @Column(name = "position") private String position; + @Column(name = "last_visit") private LocalDateTime lastVisit; + + @ManyToOne + @JoinColumn(name="enter_type_id") + private EnterType typeId; + + @ManyToMany(fetch = FetchType.EAGER) + private Set authorities; + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } } diff --git a/src/main/java/com/example/nto/entity/EnterType.java b/src/main/java/com/example/nto/entity/EnterType.java new file mode 100644 index 0000000..2a0df24 --- /dev/null +++ b/src/main/java/com/example/nto/entity/EnterType.java @@ -0,0 +1,16 @@ +package com.example.nto.entity; + +import lombok.Data; + +import javax.persistence.*; + +@Data +@Entity +public class EnterType { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + @Column(name = "enter_type") + private String type; +} diff --git a/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java b/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java new file mode 100644 index 0000000..d427077 --- /dev/null +++ b/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class EmployeeNotFoundException extends RuntimeException { + public EmployeeNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/IncorrectCodeException.java b/src/main/java/com/example/nto/exception/IncorrectCodeException.java new file mode 100644 index 0000000..17ebbe0 --- /dev/null +++ b/src/main/java/com/example/nto/exception/IncorrectCodeException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class IncorrectCodeException extends RuntimeException { + public IncorrectCodeException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/IncorrectPasswordException.java b/src/main/java/com/example/nto/exception/IncorrectPasswordException.java new file mode 100644 index 0000000..5af19e6 --- /dev/null +++ b/src/main/java/com/example/nto/exception/IncorrectPasswordException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class IncorrectPasswordException extends RuntimeException { + public IncorrectPasswordException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..93f4c7c --- /dev/null +++ b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package com.example.nto.exception.handler; + +import com.example.nto.exception.EmployeeNotFoundException; +import com.example.nto.exception.IncorrectCodeException; +import com.example.nto.exception.IncorrectPasswordException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler + public ResponseEntity handleEmployeeNotFoundException(EmployeeNotFoundException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler + public ResponseEntity handleIncorrectCodeException(IncorrectCodeException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.valueOf(430)); + } + + @ExceptionHandler(IncorrectPasswordException.class) + public ResponseEntity handlerIncorrectPasswordException(IncorrectPasswordException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); + } +} diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java index 02c79a3..3b74fc6 100644 --- a/src/main/java/com/example/nto/repository/EmployeeRepository.java +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -4,7 +4,9 @@ import com.example.nto.entity.Employee; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface EmployeeRepository extends JpaRepository { - Employee findByLogin(String login); + Optional findByUsername(String username); } diff --git a/src/main/java/com/example/nto/repository/EnterTypeRepository.java b/src/main/java/com/example/nto/repository/EnterTypeRepository.java new file mode 100644 index 0000000..541a3d4 --- /dev/null +++ b/src/main/java/com/example/nto/repository/EnterTypeRepository.java @@ -0,0 +1,7 @@ +package com.example.nto.repository; + +import com.example.nto.entity.EnterType; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface EnterTypeRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index 48d16f6..0e6f147 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,8 +1,9 @@ package com.example.nto.service; -import com.example.nto.entity.Code; import com.example.nto.entity.Employee; public interface EmployeeService { - + Employee getEmployeeByUsername(String username); + Employee getInfo(String username); + String patchOpen(String username, long value); } diff --git a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java index ce5eb31..b258d92 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -2,6 +2,7 @@ package com.example.nto.service.impl; import com.example.nto.entity.Code; import com.example.nto.entity.Employee; +import com.example.nto.exception.EmployeeNotFoundException; import com.example.nto.repository.CodeRepository; import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; @@ -22,35 +23,28 @@ public class EmployeeServiceImpl implements EmployeeService { private final CodeRepository codeRepository; @Override - public String getAuth(String login) { - Employee employeeOptional = employeeRepository.findByLogin(login); - if(employeeOptional==null){ - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); - } - return ("Данный логин существует - можно пользоваться приложением"); - } - @Override - public Employee getInfo(String login) { - Employee employeeLogin=employeeRepository.findByLogin(login); - if(employeeLogin==null) { - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); - } - Optional employeeOptional=employeeRepository.findById(employeeLogin.getId()); + public Employee getEmployeeByUsername(String username) { + Optional optionalEmployee = employeeRepository.findByUsername(username); - return employeeOptional.get(); + if(optionalEmployee.isEmpty()) + throw new EmployeeNotFoundException("Employee with username: " + username + " not found"); + + return optionalEmployee.get(); } @Override - public String patchOpen(String login, long value) { // Сделать возвращение статуса, а не строчки - Employee employeeLogin=employeeRepository.findByLogin(login); - Code codeValue=codeRepository.findByValue(value); - if(employeeLogin==null) { - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); - } - if(codeValue==null){ - throw new ResponseStatusException(HttpStatus.BAD_REQUEST); + public Employee getInfo(String username) { + Optional optionalEmployee = employeeRepository.findByUsername(username); + if(optionalEmployee.isEmpty()) { + throw new EmployeeNotFoundException("Employee with username: " + username + " not found"); } + return optionalEmployee.get(); + } + + @Override + public String patchOpen(String username, long value) { + return ("Дверь открыта"); } } diff --git a/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java b/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java new file mode 100644 index 0000000..926ee00 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/UserDetailsServiceImpl.java @@ -0,0 +1,30 @@ +package com.example.nto.service.impl; + +import com.example.nto.entity.Employee; +import com.example.nto.repository.EmployeeRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.User; +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; + +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class UserDetailsServiceImpl implements UserDetailsService { + + private final EmployeeRepository employeeRepository; + + @Override + public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { + Optional optionalEmployee = employeeRepository.findByUsername(s); + + if(optionalEmployee.isEmpty()) { + throw new UsernameNotFoundException("User not found"); + } + + return optionalEmployee.get(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/util/EmployeeMapper.java b/src/main/java/com/example/nto/util/EmployeeMapper.java index 84824a7..22d3129 100644 --- a/src/main/java/com/example/nto/util/EmployeeMapper.java +++ b/src/main/java/com/example/nto/util/EmployeeMapper.java @@ -1,17 +1,17 @@ package com.example.nto.util; -import com.example.nto.dto.EmployeeRegisterDTO; +import com.example.nto.dto.EmployeeDTO; import com.example.nto.entity.Employee; import lombok.experimental.UtilityClass; @UtilityClass public class EmployeeMapper { - public EmployeeRegisterDTO convertToRegisterDTO(Employee employee){ - EmployeeRegisterDTO employeeRegisterDTO = new EmployeeRegisterDTO(); - employeeRegisterDTO.setLogin(employee.getLogin()); - employeeRegisterDTO.setPassword(employee.getPassword()); - employeeRegisterDTO.setName(employee.getName()); + public EmployeeDTO convertToDTO(Employee employee){ + EmployeeDTO employeeDTO = new EmployeeDTO(); + employeeDTO.setUsername(employee.getUsername()); + employeeDTO.setPassword(employee.getPassword()); + employeeDTO.setName(employee.getName()); - return employeeRegisterDTO; + return employeeDTO; } } diff --git a/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0001-employee.xml b/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0001-employee.xml index 74dce1f..17c9a86 100644 --- a/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0001-employee.xml +++ b/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0001-employee.xml @@ -15,7 +15,7 @@ - + @@ -24,6 +24,9 @@ + + + diff --git a/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0004-employee-authority.xml b/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0004-employee-authority.xml index 413653d..111e4db 100644 --- a/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0004-employee-authority.xml +++ b/src/main/resources/db.changelog/1.0/1.0/2025-02-18-0004-employee-authority.xml @@ -18,7 +18,7 @@ - + diff --git a/src/main/resources/db.changelog/1.0/1.0/2025-02-19-0005-enter-type.xml b/src/main/resources/db.changelog/1.0/1.0/2025-02-19-0005-enter-type.xml new file mode 100644 index 0000000..07567f1 --- /dev/null +++ b/src/main/resources/db.changelog/1.0/1.0/2025-02-19-0005-enter-type.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db.changelog/1.0/data/2025-02-19-0005-enter-type-data.xml b/src/main/resources/db.changelog/1.0/data/2025-02-19-0005-enter-type-data.xml new file mode 100644 index 0000000..d312833 --- /dev/null +++ b/src/main/resources/db.changelog/1.0/data/2025-02-19-0005-enter-type-data.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0001-employee-data.csv b/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0001-employee-data.csv index 8eebab1..ab13f7c 100644 --- a/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0001-employee-data.csv +++ b/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0001-employee-data.csv @@ -1,8 +1,8 @@ -login;name;password;position;photo_url;last_visit -pivanov;Иванов Петр Федорович;abcd;Разработчик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-12T08:30:21 -ipetrov;Петров Иван Константинович;abcd;Аналитик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-13T08:35:44 -asemenov;Семенов Анатолий Анатольевич;abcd;Разработчик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-13T08:31:33 -afedorov;Федоров Александр Сергеевич;abcd;Тестировщик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-12T08:36:09 +username;name;password;position;photo_url;last_visit +pivanov;Иванов Петр Федорович;$2a$12$sgNQzK6r02WoGZb0rJolB.AkVWYc.ZF0RtxZ6PXjhw8EhakqvoFU6;Разработчик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-12T08:30:21 +ipetrov;Петров Иван Константинович;$2a$12$sgNQzK6r02WoGZb0rJolB.AkVWYc.ZF0RtxZ6PXjhw8EhakqvoFU6;Аналитик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-13T08:35:44 +asemenov;Семенов Анатолий Анатольевич;$2a$12$sgNQzK6r02WoGZb0rJolB.AkVWYc.ZF0RtxZ6PXjhw8EhakqvoFU6;Разработчик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-13T08:31:33 +afedorov;Федоров Александр Сергеевич;$2a$12$sgNQzK6r02WoGZb0rJolB.AkVWYc.ZF0RtxZ6PXjhw8EhakqvoFU6;Тестировщик;https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg;2024-02-12T08:36:09 diff --git a/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0004-employee-authority-data.csv b/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0004-employee-authority-data.csv index 6e6f6fb..5828070 100644 --- a/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0004-employee-authority-data.csv +++ b/src/main/resources/db.changelog/1.0/data/csv/2025-02-18-0004-employee-authority-data.csv @@ -1,4 +1,4 @@ -employee_id;authority_id +employee_id;authorities_id 1;1 2;1 3;1 diff --git a/src/main/resources/db.changelog/1.0/data/csv/2025-02-19-0005-enter-type-data.csv b/src/main/resources/db.changelog/1.0/data/csv/2025-02-19-0005-enter-type-data.csv new file mode 100644 index 0000000..ba686b2 --- /dev/null +++ b/src/main/resources/db.changelog/1.0/data/csv/2025-02-19-0005-enter-type-data.csv @@ -0,0 +1,3 @@ +types +card +qr \ No newline at end of file diff --git a/src/main/resources/db.changelog/1.0/db.changelog-master.xml b/src/main/resources/db.changelog/1.0/db.changelog-master.xml index 6bf3c31..07dc9d6 100644 --- a/src/main/resources/db.changelog/1.0/db.changelog-master.xml +++ b/src/main/resources/db.changelog/1.0/db.changelog-master.xml @@ -4,14 +4,24 @@ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog-ext.xsd"> - - - - + + + + + + + + + + + + + + \ No newline at end of file