토큰 파싱
This commit is contained in:
parent
0b6b790425
commit
a1ca9d1328
6
pom.xml
6
pom.xml
|
|
@ -9,10 +9,10 @@
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.goi</groupId>
|
<groupId>com.goi</groupId>
|
||||||
<artifactId>auth-service</artifactId>
|
<artifactId>crm-rest-api</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>security</name>
|
<name>Customer Service</name>
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Customer Service REST Api</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,11 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
|
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
|
||||||
@EntityScan(basePackages = {"com.goi.erp"})
|
@EntityScan(basePackages = {"com.goi.erp.entity"})
|
||||||
@EnableJpaRepositories(basePackages = {"com.goi.erp"})
|
@EnableJpaRepositories(basePackages = {"com.goi.erp.repository"})
|
||||||
public class SecurityApplication {
|
public class SecurityApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(SecurityApplication.class, args);
|
SpringApplication.run(SecurityApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Bean
|
|
||||||
// public CommandLineRunner commandLineRunner(
|
|
||||||
// AuthenticationService service
|
|
||||||
// ) {
|
|
||||||
// return args -> {
|
|
||||||
// var admin = RegisterRequest.builder()
|
|
||||||
// .firstname("Admin")
|
|
||||||
// .lastname("Admin")
|
|
||||||
// .email("admin@mail.com")
|
|
||||||
// .password("password")
|
|
||||||
// .role(ADMIN)
|
|
||||||
// .build();
|
|
||||||
// System.out.println("Admin token: " + service.register(admin).getAccessToken());
|
|
||||||
//
|
|
||||||
// var manager = RegisterRequest.builder()
|
|
||||||
// .firstname("Admin")
|
|
||||||
// .lastname("Admin")
|
|
||||||
// .email("manager@mail.com")
|
|
||||||
// .password("password")
|
|
||||||
// .role(MANAGER)
|
|
||||||
// .build();
|
|
||||||
// System.out.println("Manager token: " + service.register(manager).getAccessToken());
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package com.goi.erp.auditing;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.AuditorAware;
|
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
|
|
||||||
import com.goi.erp.employee.EmployeeDetails;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class ApplicationAuditAware implements AuditorAware<Integer> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> getCurrentAuditor() {
|
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
|
|
||||||
if (authentication == null ||
|
|
||||||
!authentication.isAuthenticated() ||
|
|
||||||
authentication instanceof AnonymousAuthenticationToken) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmployeeDetails로 캐스팅
|
|
||||||
EmployeeDetails employeeDetails = (EmployeeDetails) authentication.getPrincipal();
|
|
||||||
|
|
||||||
// 내부 PK(empId) 반환
|
|
||||||
return Optional.ofNullable(employeeDetails.getEmployee().getEmpId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
package com.goi.erp.auth;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/auth")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthenticationController {
|
|
||||||
|
|
||||||
private final AuthenticationService service;
|
|
||||||
|
|
||||||
// @PostMapping("/register")
|
|
||||||
// public ResponseEntity<AuthenticationResponse> register(
|
|
||||||
// @RequestBody RegisterRequest request
|
|
||||||
// ) {
|
|
||||||
// return ResponseEntity.ok(service.register(request));
|
|
||||||
// }
|
|
||||||
@PostMapping("/authenticate")
|
|
||||||
public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody AuthenticationRequest request) {
|
|
||||||
return ResponseEntity.ok(service.authenticate(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/refresh-token")
|
|
||||||
public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
|
||||||
service.refreshToken(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package com.goi.erp.auth;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class AuthenticationRequest {
|
|
||||||
|
|
||||||
private String empLoginId; // 기존 email 대신
|
|
||||||
private String empLoginPassword;
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package com.goi.erp.auth;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class AuthenticationResponse {
|
|
||||||
|
|
||||||
@JsonProperty("access_token")
|
|
||||||
private String accessToken;
|
|
||||||
@JsonProperty("refresh_token")
|
|
||||||
private String refreshToken;
|
|
||||||
}
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
package com.goi.erp.auth;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.goi.erp.config.JwtService;
|
|
||||||
import com.goi.erp.token.Token;
|
|
||||||
import com.goi.erp.token.TokenRepository;
|
|
||||||
import com.goi.erp.token.TokenType;
|
|
||||||
import com.goi.erp.employee.Employee;
|
|
||||||
import com.goi.erp.employee.EmployeeRepository;
|
|
||||||
import com.goi.erp.employee.EmployeeRole;
|
|
||||||
import com.goi.erp.employee.EmployeeRoleRepository;
|
|
||||||
import com.goi.erp.role.RolePermissionRepository;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthenticationService {
|
|
||||||
private final EmployeeRepository employeeRepository;
|
|
||||||
private final EmployeeRoleRepository employeeRoleRepository;
|
|
||||||
private final TokenRepository tokenRepository;
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
|
||||||
private final RolePermissionRepository rolePermissionRepository;
|
|
||||||
|
|
||||||
private final JwtService jwtService;
|
|
||||||
// private final AuthenticationManager authenticationManager;
|
|
||||||
|
|
||||||
// public AuthenticationResponse register(RegisterRequest request) {
|
|
||||||
// var user = User.builder().firstname(request.getFirstname()).lastname(request.getLastname())
|
|
||||||
// .email(request.getEmail()).password(passwordEncoder.encode(request.getPassword()))
|
|
||||||
// .role(request.getRole()).build();
|
|
||||||
// var savedUser = repository.save(user);
|
|
||||||
// var jwtToken = jwtService.generateToken(user);
|
|
||||||
// var refreshToken = jwtService.generateRefreshToken(user);
|
|
||||||
// saveUserToken(savedUser, jwtToken);
|
|
||||||
// return AuthenticationResponse.builder().accessToken(jwtToken).refreshToken(refreshToken).build();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 로그인 처리
|
|
||||||
public AuthenticationResponse authenticate(AuthenticationRequest request) {
|
|
||||||
// 1. Employee 조회
|
|
||||||
Employee employee = employeeRepository.findByEmpLoginId(request.getEmpLoginId())
|
|
||||||
.orElseThrow(() -> new RuntimeException("Employee not found"));
|
|
||||||
|
|
||||||
// 2. 비밀번호 검증
|
|
||||||
if (!passwordEncoder.matches(request.getEmpLoginPassword(), employee.getEmpLoginPassword())) {
|
|
||||||
throw new RuntimeException("Invalid password");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. EmployeeRole 조회 → Role 이름 리스트 생성
|
|
||||||
List<EmployeeRole> activeRoles = employeeRoleRepository.findActiveRolesByEmployeeId(employee.getEmpId());
|
|
||||||
|
|
||||||
List<String> roles = activeRoles.stream()
|
|
||||||
.map(er -> er.getRoleInfo().getRoleName())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
|
|
||||||
// 4. Role → Permission 조회
|
|
||||||
List<String> permissions = activeRoles.stream()
|
|
||||||
.flatMap(er -> rolePermissionRepository.findByRoleId(er.getRoleInfo().getRoleId()).stream())
|
|
||||||
.map(rp -> rp.getPermissionInfo().getPermModule() + ":" + rp.getPermissionInfo().getPermAction() + ":" + rp.getPermissionInfo().getPermScope())
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
// 5. generate token
|
|
||||||
String jwtToken = jwtService.generateToken(employee, roles, permissions);
|
|
||||||
String refreshToken = jwtService.generateRefreshToken(employee, roles, permissions);
|
|
||||||
|
|
||||||
// 기존 토큰 회수 및 새 토큰 저장
|
|
||||||
revokeAllEmployeeTokens(employee);
|
|
||||||
saveEmployeeToken(employee, jwtToken);
|
|
||||||
|
|
||||||
return AuthenticationResponse.builder()
|
|
||||||
.accessToken(jwtToken)
|
|
||||||
.refreshToken(refreshToken)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// JWT 토큰 저장
|
|
||||||
private void saveEmployeeToken(Employee employee, String jwtToken) {
|
|
||||||
Token token = Token.builder()
|
|
||||||
.employee(employee)
|
|
||||||
.token(jwtToken)
|
|
||||||
.tokenType(TokenType.BEARER)
|
|
||||||
.expired(false)
|
|
||||||
.revoked(false)
|
|
||||||
.build();
|
|
||||||
tokenRepository.save(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 기존 토큰 회수
|
|
||||||
private void revokeAllEmployeeTokens(Employee employee) {
|
|
||||||
List<Token> validTokens = tokenRepository.findAllValidTokenByEmployee(employee.getEmpId());
|
|
||||||
if (validTokens.isEmpty()) return;
|
|
||||||
|
|
||||||
validTokens.forEach(token -> {
|
|
||||||
token.setExpired(true);
|
|
||||||
token.setRevoked(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
tokenRepository.saveAll(validTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 리프레시 토큰 처리
|
|
||||||
public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
|
||||||
final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
||||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String refreshToken = authHeader.substring(7);
|
|
||||||
String empLoginId = jwtService.extractUsername(refreshToken);
|
|
||||||
|
|
||||||
if (empLoginId != null) {
|
|
||||||
Employee employee = employeeRepository.findByEmpLoginId(empLoginId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Employee not found"));
|
|
||||||
|
|
||||||
if (jwtService.isTokenValid(refreshToken, employee)) {
|
|
||||||
// 3. EmployeeRole 조회 → Role 이름 리스트 생성
|
|
||||||
List<EmployeeRole> activeRoles = employeeRoleRepository.findActiveRolesByEmployeeId(employee.getEmpId());
|
|
||||||
|
|
||||||
List<String> roles = activeRoles.stream()
|
|
||||||
.map(er -> er.getRoleInfo().getRoleName())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
|
|
||||||
// 4. Role → Permission 조회
|
|
||||||
List<String> permissions = activeRoles.stream()
|
|
||||||
.flatMap(er -> rolePermissionRepository.findByRoleId(er.getRoleInfo().getRoleId()).stream())
|
|
||||||
.map(rp -> rp.getPermissionInfo().getPermModule() + ":" + rp.getPermissionInfo().getPermAction() + ":" + rp.getPermissionInfo().getPermScope())
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
// 5. generate token
|
|
||||||
String accessToken = jwtService.generateToken(employee, roles, permissions);
|
|
||||||
|
|
||||||
revokeAllEmployeeTokens(employee);
|
|
||||||
saveEmployeeToken(employee, accessToken);
|
|
||||||
|
|
||||||
AuthenticationResponse authResponse = AuthenticationResponse.builder()
|
|
||||||
.accessToken(accessToken)
|
|
||||||
.refreshToken(refreshToken)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
new ObjectMapper().writeValue(response.getOutputStream(), authResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.goi.erp.auth;
|
|
||||||
|
|
||||||
import com.goi.erp.user.Role;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class RegisterRequest {
|
|
||||||
|
|
||||||
private String firstname;
|
|
||||||
private String lastname;
|
|
||||||
private String email;
|
|
||||||
private String password;
|
|
||||||
private Role role;
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +1,21 @@
|
||||||
package com.goi.erp.config;
|
package com.goi.erp.config;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.domain.AuditorAware;
|
import org.springframework.data.domain.AuditorAware;
|
||||||
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 org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
|
|
||||||
import com.goi.erp.auditing.ApplicationAuditAware;
|
import com.goi.erp.token.ApplicationAuditAware;
|
||||||
import com.goi.erp.employee.Employee;
|
|
||||||
import com.goi.erp.employee.EmployeeRole;
|
|
||||||
import com.goi.erp.employee.EmployeeRoleRepository;
|
|
||||||
import com.goi.erp.employee.EmployeeDetails;
|
|
||||||
import com.goi.erp.employee.EmployeeRepository;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ApplicationConfig {
|
public class ApplicationConfig {
|
||||||
|
|
||||||
private final EmployeeRepository employeeRepository;
|
@Value("${application.security.jwt.secret-key}")
|
||||||
private final EmployeeRoleRepository employeeRoleRepository;
|
private String jwtSecret;
|
||||||
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService userDetailsService() {
|
|
||||||
return username -> {
|
|
||||||
Employee employee = employeeRepository.findByEmpLoginId(username)
|
|
||||||
.orElseThrow(() -> new UsernameNotFoundException("Employee not found"));
|
|
||||||
|
|
||||||
// EmployeeRole 조회
|
|
||||||
List<EmployeeRole> roles = employeeRoleRepository.findActiveRolesByEmployeeId(employee.getEmpId());
|
|
||||||
|
|
||||||
// EmployeeDetails 생성
|
|
||||||
return new EmployeeDetails(employee, roles);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationProvider authenticationProvider() {
|
|
||||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
|
||||||
authProvider.setUserDetailsService(userDetailsService());
|
|
||||||
authProvider.setPasswordEncoder(passwordEncoder());
|
|
||||||
return authProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public AuditorAware<Integer> auditorAware() {
|
public AuditorAware<Integer> auditorAware() {
|
||||||
return new ApplicationAuditAware();
|
return new ApplicationAuditAware(jwtSecret);
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
|
||||||
return config.getAuthenticationManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new BCryptPasswordEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
String rawPassword = "1111"; // 테스트할 비밀번호
|
|
||||||
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
|
||||||
|
|
||||||
String hashedPassword = passwordEncoder.encode(rawPassword);
|
|
||||||
System.out.println("Raw password: " + rawPassword);
|
|
||||||
System.out.println("Hashed password: " + hashedPassword);
|
|
||||||
|
|
||||||
// 확인용 matches 테스트
|
|
||||||
boolean matches = passwordEncoder.matches(rawPassword, hashedPassword);
|
|
||||||
System.out.println("Matches: " + matches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
package com.goi.erp.config;
|
package com.goi.erp.config;
|
||||||
|
|
||||||
import com.goi.erp.employee.Employee;
|
import com.goi.erp.token.JwtService;
|
||||||
import com.goi.erp.employee.EmployeeDetails;
|
|
||||||
import com.goi.erp.employee.EmployeeRepository;
|
|
||||||
import com.goi.erp.employee.EmployeeRole;
|
|
||||||
import com.goi.erp.employee.EmployeeRoleRepository;
|
|
||||||
import com.goi.erp.token.TokenRepository;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
@ -18,19 +14,15 @@ import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
private final EmployeeRepository employeeRepository;
|
|
||||||
private final EmployeeRoleRepository employeeRoleRepository;
|
|
||||||
private final TokenRepository tokenRepository;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(
|
protected void doFilterInternal(
|
||||||
|
|
@ -39,52 +31,33 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
@NonNull FilterChain filterChain
|
@NonNull FilterChain filterChain
|
||||||
) throws ServletException, IOException {
|
) throws ServletException, IOException {
|
||||||
|
|
||||||
// 인증 API는 필터링 제외
|
|
||||||
if (request.getServletPath().contains("/api/v1/auth")) {
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String authHeader = request.getHeader("Authorization");
|
final String authHeader = request.getHeader("Authorization");
|
||||||
final String jwt;
|
|
||||||
|
|
||||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt = authHeader.substring(7);
|
final String jwt = authHeader.substring(7);
|
||||||
final String empUuidStr = jwtService.extractUsername(jwt);
|
|
||||||
|
|
||||||
if (empUuidStr != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
if (SecurityContextHolder.getContext().getAuthentication() == null && jwtService.isTokenValid(jwt)) {
|
||||||
UUID empUuid = UUID.fromString(empUuidStr);
|
|
||||||
|
|
||||||
// Employee 조회
|
// 토큰에서 empUuid와 권한 추출
|
||||||
Employee employee = employeeRepository.findByEmpUuid(empUuid)
|
String empUuid = jwtService.extractEmpUuid(jwt);
|
||||||
.orElseThrow(() -> new RuntimeException("Employee not found"));
|
List<String> permissions = jwtService.extractPermissions(jwt);
|
||||||
// Role 조회
|
List<SimpleGrantedAuthority> authorities = permissions.stream()
|
||||||
List<EmployeeRole> roles = employeeRoleRepository.findActiveRolesByEmployeeId(employee.getEmpId());
|
.map(SimpleGrantedAuthority::new)
|
||||||
EmployeeDetails employeeDetails = new EmployeeDetails(employee, roles);
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// DB 토큰 검증
|
// 인증 정보 SecurityContextHolder에 세팅
|
||||||
boolean isTokenValid = tokenRepository.findByToken(jwt)
|
|
||||||
.map(t -> !t.isExpired() && !t.isRevoked())
|
|
||||||
.orElse(false);
|
|
||||||
|
|
||||||
// JWT 유효성 검증 + DB 토큰 검증
|
|
||||||
if (jwtService.isTokenValid(jwt, employee) && isTokenValid) {
|
|
||||||
UsernamePasswordAuthenticationToken authToken =
|
UsernamePasswordAuthenticationToken authToken =
|
||||||
new UsernamePasswordAuthenticationToken(
|
new UsernamePasswordAuthenticationToken(
|
||||||
employeeDetails,
|
empUuid, // principal
|
||||||
null,
|
null, // credentials
|
||||||
employeeDetails.getAuthorities()
|
authorities
|
||||||
);
|
|
||||||
authToken.setDetails(
|
|
||||||
new WebAuthenticationDetailsSource().buildDetails(request)
|
|
||||||
);
|
);
|
||||||
|
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
package com.goi.erp.config;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
|
||||||
import io.jsonwebtoken.Jwts;
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.io.Decoders;
|
|
||||||
import io.jsonwebtoken.io.Encoders;
|
|
||||||
import io.jsonwebtoken.security.Keys;
|
|
||||||
import java.security.Key;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import com.goi.erp.employee.Employee;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class JwtService {
|
|
||||||
|
|
||||||
@Value("${application.security.jwt.secret-key}")
|
|
||||||
private String secretKey;
|
|
||||||
|
|
||||||
@Value("${application.security.jwt.expiration}")
|
|
||||||
private long jwtExpiration;
|
|
||||||
|
|
||||||
@Value("${application.security.jwt.refresh-token.expiration}")
|
|
||||||
private long refreshExpiration;
|
|
||||||
|
|
||||||
// =================== 기존 UserDetails용 ===================
|
|
||||||
public String extractUsername(String token) {
|
|
||||||
return extractClaim(token, Claims::getSubject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
|
|
||||||
final Claims claims = extractAllClaims(token);
|
|
||||||
return claimsResolver.apply(claims);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateToken(Employee employee, List<String> roles, List<String> permissions) {
|
|
||||||
Map<String, Object> extraClaims = new HashMap<>();
|
|
||||||
extraClaims.put("roles", roles);
|
|
||||||
|
|
||||||
// Admin 계정 여부 확인
|
|
||||||
boolean isAdmin = roles.stream().anyMatch(r -> r.equalsIgnoreCase("Admin"));
|
|
||||||
|
|
||||||
if (isAdmin) {
|
|
||||||
// Admin이면 permissions를 ALL로 단순화
|
|
||||||
extraClaims.put("permissions", List.of("ALL"));
|
|
||||||
} else {
|
|
||||||
// 일반 계정이면 상세 권한 넣기
|
|
||||||
extraClaims.put("permissions", permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildToken(extraClaims, employee.getEmpUuid().toString(), jwtExpiration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateRefreshToken(Employee employee, List<String> roles, List<String> permissions) {
|
|
||||||
Map<String, Object> extraClaims = new HashMap<>();
|
|
||||||
extraClaims.put("roles", roles);
|
|
||||||
// Admin 계정 여부 확인
|
|
||||||
boolean isAdmin = roles.stream().anyMatch(r -> r.equalsIgnoreCase("Admin"));
|
|
||||||
|
|
||||||
if (isAdmin) {
|
|
||||||
// Admin이면 permissions를 ALL로 단순화
|
|
||||||
extraClaims.put("permissions", List.of("ALL"));
|
|
||||||
} else {
|
|
||||||
// 일반 계정이면 상세 권한 넣기
|
|
||||||
extraClaims.put("permissions", permissions);
|
|
||||||
}
|
|
||||||
return buildToken(extraClaims, employee.getEmpUuid().toString(), refreshExpiration);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildToken(Map<String, Object> extraClaims, String subject, long expiration) {
|
|
||||||
return Jwts.builder().setClaims(extraClaims).setSubject(subject)
|
|
||||||
.setIssuedAt(new Date(System.currentTimeMillis()))
|
|
||||||
.setExpiration(new Date(System.currentTimeMillis() + expiration))
|
|
||||||
.signWith(getSignInKey(), SignatureAlgorithm.HS256).compact();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTokenValid(String token, Employee employee) {
|
|
||||||
final String username = extractUsername(token);
|
|
||||||
return (username.equals(employee.getEmpUuid().toString())) && !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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
JwtService jwtService = new JwtService();
|
|
||||||
jwtService.secretKey = "D0HaHnTPKLkUO9ULL1Ulm6XDZjhzuFtvTCcxTxSoCS8=";
|
|
||||||
|
|
||||||
String token = "eyJhbGciOiJIUzI1NiJ9.eyJwZXJtaXNzaW9ucyI6WyJIOlI6UCIsIk86QzpBIiwiTzpSOkEiLCJPOlU6QSIsIk86RDpBIiwiUzpDOkEiLCJTOlI6QSIsIlM6VTpBIl0sInJvbGVzIjpbIk9wZXJhdGlvbnMgTWFuYWdlciJdLCJzdWIiOiJmZGE1NGZkZS03MTBmLTQ4ZDItYTRmYi00NzM2YjJhM2RhNWEiLCJpYXQiOjE3NjMxMzU4MzMsImV4cCI6MTc2MzIyMjIzM30.ie38b2JnkP3k4Vz7TzAwI7oRgOsIFYf0yMYADq5EhNM";
|
|
||||||
|
|
||||||
// user 정보
|
|
||||||
Claims claims = jwtService.extractAllClaims(token);
|
|
||||||
|
|
||||||
System.out.println("Subject (emp_uuid): " + claims.getSubject());
|
|
||||||
System.out.println("Roles: " + claims.get("roles"));
|
|
||||||
System.out.println("Roles: " + claims.get("permissions"));
|
|
||||||
System.out.println("IssuedAt: " + claims.getIssuedAt());
|
|
||||||
System.out.println("Expiration: " + claims.getExpiration());
|
|
||||||
|
|
||||||
// 모든 Claims 확인
|
|
||||||
// Claims claims = Jwts.parserBuilder()
|
|
||||||
// .setSigningKey(Keys.hmacShaKeyFor("<secret_key>".getBytes()))
|
|
||||||
// .build()
|
|
||||||
// .parseClaimsJws(token)
|
|
||||||
// .getBody();
|
|
||||||
|
|
||||||
System.out.println("Claims: " + claims);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package com.goi.erp.config;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import com.goi.erp.token.TokenRepository;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class LogoutService implements LogoutHandler {
|
|
||||||
|
|
||||||
private final TokenRepository tokenRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logout(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
Authentication authentication
|
|
||||||
) {
|
|
||||||
final String authHeader = request.getHeader("Authorization");
|
|
||||||
final String jwt;
|
|
||||||
if (authHeader == null ||!authHeader.startsWith("Bearer ")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jwt = authHeader.substring(7);
|
|
||||||
var storedToken = tokenRepository.findByToken(jwt)
|
|
||||||
.orElse(null);
|
|
||||||
if (storedToken != null) {
|
|
||||||
storedToken.setExpired(true);
|
|
||||||
storedToken.setRevoked(true);
|
|
||||||
tokenRepository.save(storedToken);
|
|
||||||
SecurityContextHolder.clearContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.goi.erp.config;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableMethodSecurity // @PreAuthorize 등 사용 가능
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
private final JwtAuthenticationFilter jwtAuthFilter; // JWT 인증 필터
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
// CSRF 비활성화 (API 서버라면 stateless)
|
||||||
|
.csrf(csrf -> csrf.disable())
|
||||||
|
|
||||||
|
// 세션 사용 안함
|
||||||
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
|
||||||
|
// 요청 권한 설정
|
||||||
|
.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers(
|
||||||
|
"/swagger-ui/**",
|
||||||
|
"/v3/api-docs/**"
|
||||||
|
).permitAll() // 인증 없이 접근 허용
|
||||||
|
.anyRequest().authenticated() // 나머지는 JWT 인증 필요
|
||||||
|
)
|
||||||
|
|
||||||
|
// JWT 필터 등록
|
||||||
|
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
package com.goi.erp.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.method.configuration.EnableMethodSecurity;
|
|
||||||
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.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
||||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
|
||||||
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_CREATE;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_DELETE;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_READ;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_UPDATE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_CREATE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_DELETE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_READ;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_UPDATE;
|
|
||||||
import static com.goi.erp.user.Role.ADMIN;
|
|
||||||
import static com.goi.erp.user.Role.MANAGER;
|
|
||||||
import static org.springframework.http.HttpMethod.DELETE;
|
|
||||||
import static org.springframework.http.HttpMethod.GET;
|
|
||||||
import static org.springframework.http.HttpMethod.POST;
|
|
||||||
import static org.springframework.http.HttpMethod.PUT;
|
|
||||||
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@EnableMethodSecurity
|
|
||||||
public class SecurityConfiguration {
|
|
||||||
|
|
||||||
private static final String[] WHITE_LIST_URL = {
|
|
||||||
"/auth/**",
|
|
||||||
"/v2/api-docs",
|
|
||||||
"/v3/api-docs",
|
|
||||||
"/v3/api-docs/**",
|
|
||||||
"/swagger-resources",
|
|
||||||
"/swagger-resources/**",
|
|
||||||
"/configuration/ui",
|
|
||||||
"/configuration/security",
|
|
||||||
"/swagger-ui/**",
|
|
||||||
"/webjars/**",
|
|
||||||
"/swagger-ui.html"};
|
|
||||||
private final JwtAuthenticationFilter jwtAuthFilter;
|
|
||||||
private final AuthenticationProvider authenticationProvider;
|
|
||||||
private final LogoutHandler logoutHandler;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
||||||
http
|
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
|
||||||
.authorizeHttpRequests(req ->
|
|
||||||
req.requestMatchers(WHITE_LIST_URL)
|
|
||||||
.permitAll()
|
|
||||||
.requestMatchers("/api/v1/management/**").hasAnyRole(ADMIN.name(), MANAGER.name())
|
|
||||||
.requestMatchers(GET, "/api/v1/management/**").hasAnyAuthority(ADMIN_READ.name(), MANAGER_READ.name())
|
|
||||||
.requestMatchers(POST, "/api/v1/management/**").hasAnyAuthority(ADMIN_CREATE.name(), MANAGER_CREATE.name())
|
|
||||||
.requestMatchers(PUT, "/api/v1/management/**").hasAnyAuthority(ADMIN_UPDATE.name(), MANAGER_UPDATE.name())
|
|
||||||
.requestMatchers(DELETE, "/api/v1/management/**").hasAnyAuthority(ADMIN_DELETE.name(), MANAGER_DELETE.name())
|
|
||||||
.anyRequest()
|
|
||||||
.authenticated()
|
|
||||||
)
|
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
|
|
||||||
.authenticationProvider(authenticationProvider)
|
|
||||||
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
|
|
||||||
.logout(logout ->
|
|
||||||
logout.logoutUrl("/api/v1/auth/logout")
|
|
||||||
.addLogoutHandler(logoutHandler)
|
|
||||||
.logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext())
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
return http.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.goi.erp.demo;
|
package com.goi.erp.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.goi.erp.controller;
|
||||||
|
|
||||||
|
import com.goi.erp.dto.CustomerRequestDto;
|
||||||
|
import com.goi.erp.dto.CustomerResponseDto;
|
||||||
|
import com.goi.erp.service.CustomerService;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/customer")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomerController {
|
||||||
|
|
||||||
|
private final CustomerService customerService;
|
||||||
|
|
||||||
|
// CREATE
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<CustomerResponseDto> createCustomer(@RequestBody CustomerRequestDto requestDto) {
|
||||||
|
CustomerResponseDto responseDto = customerService.createCustomer(requestDto);
|
||||||
|
return new ResponseEntity<>(responseDto, HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ ALL
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<List<CustomerResponseDto>> getAllCustomers() {
|
||||||
|
return ResponseEntity.ok(customerService.getAllCustomers());
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ ONE
|
||||||
|
@GetMapping("/{uuid}")
|
||||||
|
public ResponseEntity<CustomerResponseDto> getCustomer(@PathVariable UUID uuid) {
|
||||||
|
return ResponseEntity.ok(customerService.getCustomerByUuid(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
@PutMapping("/{uuid}")
|
||||||
|
public ResponseEntity<CustomerResponseDto> updateCustomer(
|
||||||
|
@PathVariable UUID uuid,
|
||||||
|
@RequestBody CustomerRequestDto requestDto) {
|
||||||
|
return ResponseEntity.ok(customerService.updateCustomer(uuid, requestDto));
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE
|
||||||
|
@DeleteMapping("/{uuid}")
|
||||||
|
public ResponseEntity<Void> deleteCustomer(@PathVariable UUID uuid) {
|
||||||
|
customerService.deleteCustomer(uuid);
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package com.goi.erp.demo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Hidden;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/demo-controller")
|
|
||||||
@Hidden
|
|
||||||
public class DemoController {
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public ResponseEntity<String> sayHello() {
|
|
||||||
return ResponseEntity.ok("Hello from secured endpoint");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package com.goi.erp.demo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/management")
|
|
||||||
@Tag(name = "Management")
|
|
||||||
public class ManagementController {
|
|
||||||
|
|
||||||
|
|
||||||
@Operation(
|
|
||||||
description = "Get endpoint for manager",
|
|
||||||
summary = "This is a summary for management get endpoint",
|
|
||||||
responses = {
|
|
||||||
@ApiResponse(
|
|
||||||
description = "Success",
|
|
||||||
responseCode = "200"
|
|
||||||
),
|
|
||||||
@ApiResponse(
|
|
||||||
description = "Unauthorized / Invalid Token",
|
|
||||||
responseCode = "403"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
)
|
|
||||||
@GetMapping
|
|
||||||
public String get() {
|
|
||||||
return "GET:: management controller";
|
|
||||||
}
|
|
||||||
@PostMapping
|
|
||||||
public String post() {
|
|
||||||
return "POST:: management controller";
|
|
||||||
}
|
|
||||||
@PutMapping
|
|
||||||
public String put() {
|
|
||||||
return "PUT:: management controller";
|
|
||||||
}
|
|
||||||
@DeleteMapping
|
|
||||||
public String delete() {
|
|
||||||
return "DELETE:: management controller";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.goi.erp.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CustomerRequestDto {
|
||||||
|
private String cusNo;
|
||||||
|
private String cusName;
|
||||||
|
private String cusStatus;
|
||||||
|
private Integer cusAreaId;
|
||||||
|
private String cusAddress1;
|
||||||
|
private String cusAddress2;
|
||||||
|
private String cusPostalCode;
|
||||||
|
private String cusCity;
|
||||||
|
private String cusProvince;
|
||||||
|
private BigDecimal cusGeoLat;
|
||||||
|
private BigDecimal cusGeoLon;
|
||||||
|
private String cusEmail;
|
||||||
|
private String cusPhone;
|
||||||
|
private String cusPhoneExt;
|
||||||
|
private LocalTime cusOpenTime;
|
||||||
|
private String cusNote;
|
||||||
|
private LocalDate cusContractDate;
|
||||||
|
private String cusContractedBy;
|
||||||
|
private LocalDate cusInstallDate;
|
||||||
|
private String cusInstallLocatoin;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.goi.erp.dto;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class CustomerResponseDto {
|
||||||
|
private UUID cusUuid;
|
||||||
|
private String cusNo;
|
||||||
|
private String cusName;
|
||||||
|
private String cusStatus;
|
||||||
|
private Integer cusAreaId;
|
||||||
|
private String cusAddress1;
|
||||||
|
private String cusAddress2;
|
||||||
|
private String cusPostalCode;
|
||||||
|
private String cusCity;
|
||||||
|
private String cusProvince;
|
||||||
|
private BigDecimal cusGeoLat;
|
||||||
|
private BigDecimal cusGeoLon;
|
||||||
|
private String cusEmail;
|
||||||
|
private String cusPhone;
|
||||||
|
private String cusPhoneExt;
|
||||||
|
private LocalTime cusOpenTime;
|
||||||
|
private String cusNote;
|
||||||
|
private LocalDate cusContractDate;
|
||||||
|
private String cusContractedBy;
|
||||||
|
private LocalDate cusInstallDate;
|
||||||
|
private String cusInstallLocatoin;
|
||||||
|
}
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
package com.goi.erp.employee;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
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.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class EmployeeDetails implements UserDetails {
|
|
||||||
// 이 UID는 객체를 직렬화 후 다시 역직렬화할 때, 클래스 버전이 맞는지 확인하는 용도
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private final Employee employee;
|
|
||||||
private final List<GrantedAuthority> authorities;
|
|
||||||
|
|
||||||
public EmployeeDetails(Employee employee, List<EmployeeRole> roles) {
|
|
||||||
this.employee = employee;
|
|
||||||
// EmployeeRole → GrantedAuthority 변환
|
|
||||||
this.authorities = roles.stream()
|
|
||||||
.map(er -> new SimpleGrantedAuthority(er.getRoleInfo().getRoleName()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPassword() {
|
|
||||||
return employee.getEmpLoginPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return employee.getEmpLoginId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAccountNonExpired() {
|
|
||||||
return true; // 필요에 따라 Employee 상태로 제어 가능
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAccountNonLocked() {
|
|
||||||
return !"I".equals(employee.getEmpStatus()); // 예: 'I'면 잠금
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCredentialsNonExpired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return "A".equals(employee.getEmpStatus()); // Active 상태만 사용 가능
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package com.goi.erp.employee;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class EmployeeDetailsService implements UserDetailsService {
|
|
||||||
|
|
||||||
private final EmployeeRepository employeeRepository;
|
|
||||||
private final EmployeeRoleRepository employeeRoleRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDetails loadUserByUsername(String empLoginId) throws UsernameNotFoundException {
|
|
||||||
// Employee 조회
|
|
||||||
Employee employee = employeeRepository.findByEmpLoginId(empLoginId)
|
|
||||||
.orElseThrow(() -> new UsernameNotFoundException("Employee not found"));
|
|
||||||
|
|
||||||
// EmployeeRole 조회 (활성화된 역할만)
|
|
||||||
List<EmployeeRole> roles = employeeRoleRepository.findActiveRolesByEmployeeId(employee.getEmpId());
|
|
||||||
|
|
||||||
// EmployeeDetails에 Employee + 역할 전달
|
|
||||||
return new EmployeeDetails(employee, roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package com.goi.erp.employee;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
|
|
||||||
Optional<Employee> findByEmpLoginId(String empLoginId);
|
|
||||||
Optional<Employee> findByEmpUuid(UUID empUuid);
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
package com.goi.erp.employee;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.goi.erp.role.RoleInfo;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "employee_role")
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder
|
|
||||||
public class EmployeeRole {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "emr_id")
|
|
||||||
private Integer emrId; // 내부 PK
|
|
||||||
|
|
||||||
@Column(name = "emr_uuid", unique = true, nullable = false)
|
|
||||||
private UUID emrUuid; // 외부용 UUID
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "emr_emp_id", nullable = false) // DB 컬럼명 지정
|
|
||||||
private Employee employee;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "emr_role_id", nullable = false) // DB 컬럼명 지정
|
|
||||||
private RoleInfo roleInfo;
|
|
||||||
|
|
||||||
@Column(name = "emr_revoked_at")
|
|
||||||
private LocalDateTime emrRevokedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package com.goi.erp.employee;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface EmployeeRoleRepository extends JpaRepository<EmployeeRole, Integer> {
|
|
||||||
|
|
||||||
@Query("""
|
|
||||||
SELECT er
|
|
||||||
FROM EmployeeRole er
|
|
||||||
WHERE er.employee.id = :empId
|
|
||||||
AND er.emrRevokedAt IS NULL
|
|
||||||
""")
|
|
||||||
List<EmployeeRole> findActiveRolesByEmployeeId(Integer empId);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.goi.erp.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "customer")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class Customer {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Integer cusId;
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private UUID cusUuid;
|
||||||
|
|
||||||
|
@Column(length = 50)
|
||||||
|
private String cusNo;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String cusName;
|
||||||
|
|
||||||
|
@Column(length = 1)
|
||||||
|
private String cusStatus;
|
||||||
|
|
||||||
|
private Integer cusAreaId;
|
||||||
|
|
||||||
|
private String cusAddress1;
|
||||||
|
private String cusAddress2;
|
||||||
|
private String cusPostalCode;
|
||||||
|
private String cusCity;
|
||||||
|
private String cusProvince;
|
||||||
|
|
||||||
|
private BigDecimal cusGeoLat;
|
||||||
|
private BigDecimal cusGeoLon;
|
||||||
|
|
||||||
|
private String cusEmail;
|
||||||
|
private String cusPhone;
|
||||||
|
private String cusPhoneExt;
|
||||||
|
|
||||||
|
private LocalTime cusOpenTime;
|
||||||
|
private String cusNote;
|
||||||
|
|
||||||
|
private LocalDate cusContractDate;
|
||||||
|
private String cusContractedBy;
|
||||||
|
|
||||||
|
private LocalDate cusInstallDate;
|
||||||
|
private String cusInstallLocatoin;
|
||||||
|
|
||||||
|
private LocalDate cusLastPickupDate;
|
||||||
|
private Integer cusLastPickupQty;
|
||||||
|
private BigDecimal cusLastPickupLat;
|
||||||
|
private BigDecimal cusLastPickupLon;
|
||||||
|
|
||||||
|
private Integer cusFullCycle;
|
||||||
|
private Boolean cusFullCycleFlag;
|
||||||
|
private Integer cusFullCycleForced;
|
||||||
|
private LocalDate cusFullCycleForcedDate;
|
||||||
|
|
||||||
|
private String cusSchedule;
|
||||||
|
private String cusScheduledays;
|
||||||
|
|
||||||
|
private LocalDate cusLastPaidDate;
|
||||||
|
private BigDecimal cusRate;
|
||||||
|
private String cusPayMethod;
|
||||||
|
private String cusAccountNo;
|
||||||
|
|
||||||
|
private LocalDate cusIsccDate;
|
||||||
|
private LocalDate cusCorsiaDate;
|
||||||
|
|
||||||
|
private String cusHstNo;
|
||||||
|
|
||||||
|
private LocalDate cusTerminatedDate;
|
||||||
|
private String cusTerminationReason;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.goi.erp.employee;
|
package com.goi.erp.entity;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
|
@ -28,22 +28,10 @@ public class Employee {
|
||||||
@Column(name = "emp_uuid", unique = true, nullable = false)
|
@Column(name = "emp_uuid", unique = true, nullable = false)
|
||||||
private UUID empUuid; // 외부 키로 사용
|
private UUID empUuid; // 외부 키로 사용
|
||||||
|
|
||||||
@Column(name = "emp_login_id", unique = true, nullable = false)
|
|
||||||
private String empLoginId;
|
|
||||||
|
|
||||||
@Column(name = "emp_login_password", nullable = false)
|
|
||||||
private String empLoginPassword;
|
|
||||||
|
|
||||||
@Column(name = "emp_first_name")
|
@Column(name = "emp_first_name")
|
||||||
private String empFirstName;
|
private String empFirstName;
|
||||||
|
|
||||||
@Column(name = "emp_last_name")
|
@Column(name = "emp_last_name")
|
||||||
private String empLastName;
|
private String empLastName;
|
||||||
|
|
||||||
@Column(name = "emp_dept_id")
|
|
||||||
private Integer empDeptId;
|
|
||||||
|
|
||||||
@Column(name = "emp_status", columnDefinition = "CHAR(1)")
|
|
||||||
private String empStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
package com.goi.erp.permission;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import jakarta.persistence.UniqueConstraint;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "permission_info",
|
|
||||||
uniqueConstraints = @UniqueConstraint(columnNames = {"perm_module", "perm_action", "perm_scope"}))
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder
|
|
||||||
public class PermissionInfo {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "perm_id")
|
|
||||||
private Integer permId;
|
|
||||||
|
|
||||||
@Column(name = "perm_uuid", nullable = false, updatable = false)
|
|
||||||
private UUID permUuid;
|
|
||||||
|
|
||||||
@Column(name = "perm_module", nullable = false)
|
|
||||||
private String permModule;
|
|
||||||
|
|
||||||
@Column(name = "perm_action", nullable = false, length = 1)
|
|
||||||
private String permAction; // C/R/U/D
|
|
||||||
|
|
||||||
@Column(name = "perm_scope", nullable = false, length = 10)
|
|
||||||
private String permScope; // Self / Part / All
|
|
||||||
|
|
||||||
@Column(name = "perm_desc")
|
|
||||||
private String permDesc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package com.goi.erp.permission;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface PermissionInfoRepository extends JpaRepository<PermissionInfo, Integer> {
|
|
||||||
Optional<PermissionInfo> findByPermUuid(UUID permUuid);
|
|
||||||
|
|
||||||
// 특정 모듈 + 액션 + 범위에 해당하는 권한 조회
|
|
||||||
Optional<PermissionInfo> findByPermModuleAndPermActionAndPermScope(String module, String action, String scope);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.goi.erp.repository;
|
||||||
|
|
||||||
|
import com.goi.erp.entity.Customer;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CustomerRepository extends JpaRepository<Customer, Long> {
|
||||||
|
Optional<Customer> findByCusUuid(UUID uuid);
|
||||||
|
}
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
package com.goi.erp.role;
|
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "role_info")
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder
|
|
||||||
public class RoleInfo {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "role_id")
|
|
||||||
private Integer roleId;
|
|
||||||
|
|
||||||
@Column(name = "role_uuid", unique = true, nullable = false)
|
|
||||||
private UUID roleUuid;
|
|
||||||
|
|
||||||
@Column(name = "role_name", unique = true, nullable = false)
|
|
||||||
private String roleName;
|
|
||||||
|
|
||||||
@Column(name = "role_desc")
|
|
||||||
private String roleDesc;
|
|
||||||
|
|
||||||
@Column(name = "role_level")
|
|
||||||
private Integer roleLevel;
|
|
||||||
|
|
||||||
@OneToMany(mappedBy = "roleInfo", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
|
||||||
private List<RolePermission> rolePermissions;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package com.goi.erp.role;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface RoleInfoRepository extends JpaRepository<RoleInfo, Integer> {
|
|
||||||
Optional<RoleInfo> findByRoleUuid(UUID roleUuid);
|
|
||||||
|
|
||||||
Optional<RoleInfo> findByRoleName(String roleName);
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package com.goi.erp.role;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import com.goi.erp.permission.PermissionInfo;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "role_permission")
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder
|
|
||||||
public class RolePermission {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "rpr_id")
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "rpr_role_id", nullable = false)
|
|
||||||
private RoleInfo roleInfo;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "rpr_perm_id", nullable = false)
|
|
||||||
private PermissionInfo permissionInfo;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package com.goi.erp.role;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.query.Param;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface RolePermissionRepository extends JpaRepository<RolePermission, Integer> {
|
|
||||||
|
|
||||||
// 특정 Role의 모든 권한 조회
|
|
||||||
@Query("SELECT r FROM RolePermission r WHERE r.roleInfo.id = :roleId")
|
|
||||||
List<RolePermission> findByRoleId(@Param("roleId") Integer roleId);
|
|
||||||
|
|
||||||
// Role과 Permission 매핑 존재 여부 확인
|
|
||||||
@Query("""
|
|
||||||
SELECT CASE WHEN COUNT(r) > 0 THEN true ELSE false END
|
|
||||||
FROM RolePermission r
|
|
||||||
WHERE r.roleInfo.id = :roleId
|
|
||||||
AND r.permissionInfo.id = :permId
|
|
||||||
""")
|
|
||||||
boolean existsByRoleInfoAndPermissionInfo(@Param("roleId") Integer roleId,
|
|
||||||
@Param("permId") Integer permId);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.goi.erp.service;
|
||||||
|
|
||||||
|
import com.goi.erp.dto.CustomerRequestDto;
|
||||||
|
import com.goi.erp.dto.CustomerResponseDto;
|
||||||
|
import com.goi.erp.entity.Customer;
|
||||||
|
import com.goi.erp.repository.CustomerRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomerService {
|
||||||
|
|
||||||
|
private final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
public CustomerResponseDto createCustomer(CustomerRequestDto dto) {
|
||||||
|
Customer customer = Customer.builder()
|
||||||
|
.cusUuid(UUID.randomUUID())
|
||||||
|
.cusName(dto.getCusName())
|
||||||
|
.cusNo(dto.getCusNo())
|
||||||
|
.cusStatus(dto.getCusStatus())
|
||||||
|
.cusAddress1(dto.getCusAddress1())
|
||||||
|
.cusAddress2(dto.getCusAddress2())
|
||||||
|
.cusCity(dto.getCusCity())
|
||||||
|
.cusProvince(dto.getCusProvince())
|
||||||
|
.build();
|
||||||
|
customer = customerRepository.save(customer);
|
||||||
|
return mapToDto(customer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CustomerResponseDto> getAllCustomers() {
|
||||||
|
return customerRepository.findAll().stream()
|
||||||
|
.map(this::mapToDto)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomerResponseDto getCustomerByUuid(UUID uuid) {
|
||||||
|
Customer customer = customerRepository.findByCusUuid(uuid)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Customer not found"));
|
||||||
|
return mapToDto(customer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomerResponseDto updateCustomer(UUID uuid, CustomerRequestDto dto) {
|
||||||
|
Customer customer = customerRepository.findByCusUuid(uuid)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Customer not found"));
|
||||||
|
|
||||||
|
customer.setCusName(dto.getCusName());
|
||||||
|
customer.setCusNo(dto.getCusNo());
|
||||||
|
customer.setCusStatus(dto.getCusStatus());
|
||||||
|
customer.setCusAddress1(dto.getCusAddress1());
|
||||||
|
customer.setCusAddress2(dto.getCusAddress2());
|
||||||
|
customer.setCusCity(dto.getCusCity());
|
||||||
|
customer.setCusProvince(dto.getCusProvince());
|
||||||
|
|
||||||
|
customerRepository.save(customer);
|
||||||
|
return mapToDto(customer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteCustomer(UUID uuid) {
|
||||||
|
Customer customer = customerRepository.findByCusUuid(uuid)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Customer not found"));
|
||||||
|
customerRepository.delete(customer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomerResponseDto mapToDto(Customer customer) {
|
||||||
|
return CustomerResponseDto.builder()
|
||||||
|
.cusUuid(customer.getCusUuid())
|
||||||
|
.cusName(customer.getCusName())
|
||||||
|
.cusNo(customer.getCusNo())
|
||||||
|
.cusStatus(customer.getCusStatus())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.goi.erp.token;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.data.domain.AuditorAware;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* auth-service에서 발급한 JWT 토큰 기반으로 현재 사용자(empId)를 가져오는 AuditorAware 구현체
|
||||||
|
*
|
||||||
|
* - JPA auditing에서 사용자가 누군지 기록할 때 사용
|
||||||
|
* - SecurityContextHolder 없이도 동작 가능
|
||||||
|
* - HttpServletRequest에서 Authorization 헤더를 읽어 토큰 파싱
|
||||||
|
*/
|
||||||
|
public class ApplicationAuditAware implements AuditorAware<Integer> {
|
||||||
|
|
||||||
|
private final String jwtSecret;
|
||||||
|
|
||||||
|
public ApplicationAuditAware(String jwtSecret) {
|
||||||
|
this.jwtSecret = jwtSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 현재 요청을 수행하는 사용자의 empId 반환
|
||||||
|
* @return Optional<Integer> - empId가 없거나 토큰이 유효하지 않으면 Optional.empty()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> getCurrentAuditor() {
|
||||||
|
HttpServletRequest request = getCurrentHttpRequest();
|
||||||
|
if (request == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = resolveToken(request);
|
||||||
|
if (token == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// JWT 파싱
|
||||||
|
Claims claims = Jwts.parserBuilder()
|
||||||
|
// HMAC SHA 키 객체 생성 (secret 길이와 안전성 체크)
|
||||||
|
.setSigningKey(Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)))
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
|
||||||
|
// 토큰에 empId 클레임이 있어야 함
|
||||||
|
Integer empId = claims.get("empId", Integer.class);
|
||||||
|
return Optional.ofNullable(empId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 토큰 파싱/검증 실패 시 Optional.empty() 반환
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 현재 스레드의 HttpServletRequest 가져오기
|
||||||
|
* @return HttpServletRequest 또는 null
|
||||||
|
*/
|
||||||
|
private HttpServletRequest getCurrentHttpRequest() {
|
||||||
|
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
if (attrs == null) return null;
|
||||||
|
return attrs.getRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpServletRequest에서 Authorization 헤더의 Bearer 토큰 추출
|
||||||
|
* @param request 현재 HttpServletRequest
|
||||||
|
* @return JWT 문자열 또는 null
|
||||||
|
*/
|
||||||
|
private String resolveToken(HttpServletRequest request) {
|
||||||
|
String bearerToken = request.getHeader("Authorization");
|
||||||
|
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||||||
|
return bearerToken.substring(7);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.goi.erp.token;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.io.Decoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* - DB 접근 없음
|
||||||
|
* - JWT에 포함된 empUuid, 이름, roles, permissions 추출
|
||||||
|
* - 토큰 유효기간 체크 가능
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class JwtService {
|
||||||
|
|
||||||
|
@Value("${application.security.jwt.secret-key}")
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
@Value("${application.security.jwt.expiration}")
|
||||||
|
private long jwtExpiration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* empUuid(sub) 추출
|
||||||
|
*/
|
||||||
|
public String extractEmpUuid(String token) {
|
||||||
|
return extractClaim(token, Claims::getSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* firstName 추출
|
||||||
|
*/
|
||||||
|
public String extractFirstName(String token) {
|
||||||
|
return extractClaim(token, claims -> claims.get("firstName", String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lastName 추출
|
||||||
|
*/
|
||||||
|
public String extractLastName(String token) {
|
||||||
|
return extractClaim(token, claims -> claims.get("lastName", String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* roles 리스트 추출
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public List<String> extractRoles(String token) {
|
||||||
|
return extractClaim(token, claims -> (List<String>) claims.get("roles"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* permissions 리스트 추출
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public List<String> extractPermissions(String token) {
|
||||||
|
return extractClaim(token, claims -> (List<String>) claims.get("permissions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 토큰 만료 여부 확인
|
||||||
|
*/
|
||||||
|
public boolean isTokenExpired(String token) {
|
||||||
|
return extractClaim(token, Claims::getExpiration).before(new java.util.Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 토큰 유효성 검사 (만료 체크)
|
||||||
|
*/
|
||||||
|
public boolean isTokenValid(String token) {
|
||||||
|
return !isTokenExpired(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT에서 Claims 추출
|
||||||
|
*/
|
||||||
|
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
|
||||||
|
final Claims claims = extractAllClaims(token);
|
||||||
|
return claimsResolver.apply(claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT 전체 Claims 추출
|
||||||
|
*/
|
||||||
|
private Claims extractAllClaims(String token) {
|
||||||
|
return Jwts.parserBuilder()
|
||||||
|
.setSigningKey(getSignInKey())
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Key getSignInKey() {
|
||||||
|
byte[] keyBytes = Decoders.BASE64.decode(secretKey); // auth-service와 동일한 Base64 secret
|
||||||
|
return Keys.hmacShaKeyFor(keyBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JwtService jwtService = new JwtService();
|
||||||
|
jwtService.secretKey = "D0HaHnTPKLkUO9ULL1Ulm6XDZjhzuFtvTCcxTxSoCS8=";
|
||||||
|
|
||||||
|
String token = "eyJhbGciOiJIUzI1NiJ9.eyJmaXJzdE5hbWUiOiJIeW9KaW4iLCJsYXN0TmFtZSI6IkFobiIsInBlcm1pc3Npb25zIjpbIkFMTCJdLCJyb2xlcyI6WyJBZG1pbiJdLCJzdWIiOiJhMjM4ZWQ0OC03OGRjLTQ2YWEtOWNiMC1hNWYxZGQyZDJmMTMiLCJpYXQiOjE3NjM1NzE2ODYsImV4cCI6MTc2MzY1ODA4Nn0.0fQT-I4dqHMapIEbxfy8X_SdCReYhUy6djnXUzw4gWc";
|
||||||
|
|
||||||
|
// user 정보
|
||||||
|
Claims claims = jwtService.extractAllClaims(token);
|
||||||
|
|
||||||
|
System.out.println("Subject (emp_uuid): " + claims.getSubject());
|
||||||
|
System.out.println("Roles: " + claims.get("roles"));
|
||||||
|
System.out.println("Roles: " + claims.get("permissions"));
|
||||||
|
System.out.println("IssuedAt: " + claims.getIssuedAt());
|
||||||
|
System.out.println("Expiration: " + claims.getExpiration());
|
||||||
|
System.out.println("FirstName: " + claims.get("firstName", String.class));
|
||||||
|
System.out.println("LastName: " + claims.get("LastName", String.class));
|
||||||
|
|
||||||
|
// 모든 Claims 확인
|
||||||
|
// Claims claims = Jwts.parserBuilder()
|
||||||
|
// .setSigningKey(Keys.hmacShaKeyFor("<secret_key>".getBytes()))
|
||||||
|
// .build()
|
||||||
|
// .parseClaimsJws(token)
|
||||||
|
// .getBody();
|
||||||
|
|
||||||
|
System.out.println("Claims: " + claims);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package com.goi.erp.token;
|
|
||||||
|
|
||||||
import com.goi.erp.employee.Employee;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.EnumType;
|
|
||||||
import jakarta.persistence.Enumerated;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "employee_token")
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder
|
|
||||||
public class Token {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "emt_id")
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "emt_emp_id", nullable = false)
|
|
||||||
private Employee employee;
|
|
||||||
|
|
||||||
@Column(name = "emt_token", nullable = false)
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
@Column(name = "emt_token_type")
|
|
||||||
private TokenType tokenType;
|
|
||||||
|
|
||||||
@Column(name = "emt_is_expired")
|
|
||||||
private boolean expired;
|
|
||||||
|
|
||||||
@Column(name = "emt_is_revoked")
|
|
||||||
private boolean revoked;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.goi.erp.token;
|
|
||||||
|
|
||||||
import com.goi.erp.employee.Employee;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface TokenRepository extends JpaRepository<Token, Integer> {
|
|
||||||
|
|
||||||
@Query("""
|
|
||||||
select t from Token t
|
|
||||||
where t.employee.id = :employeeId
|
|
||||||
and (t.expired = false or t.revoked = false)
|
|
||||||
""")
|
|
||||||
List<Token> findAllValidTokenByEmployee(Integer employeeId);
|
|
||||||
|
|
||||||
Optional<Token> findByToken(String token);
|
|
||||||
|
|
||||||
List<Token> findByEmployee(Employee employee);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package com.goi.erp.token;
|
|
||||||
|
|
||||||
public enum TokenType {
|
|
||||||
BEARER
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package com.goi.erp.user;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Builder
|
|
||||||
public class ChangePasswordRequest {
|
|
||||||
|
|
||||||
private String currentPassword;
|
|
||||||
private String newPassword;
|
|
||||||
private String confirmationPassword;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.goi.erp.user;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public enum Permission {
|
|
||||||
|
|
||||||
ADMIN_READ("admin:read"),
|
|
||||||
ADMIN_UPDATE("admin:update"),
|
|
||||||
ADMIN_CREATE("admin:create"),
|
|
||||||
ADMIN_DELETE("admin:delete"),
|
|
||||||
MANAGER_READ("management:read"),
|
|
||||||
MANAGER_UPDATE("management:update"),
|
|
||||||
MANAGER_CREATE("management:create"),
|
|
||||||
MANAGER_DELETE("management:delete")
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final String permission;
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
package com.goi.erp.user;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_CREATE;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_DELETE;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_READ;
|
|
||||||
import static com.goi.erp.user.Permission.ADMIN_UPDATE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_CREATE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_DELETE;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_READ;
|
|
||||||
import static com.goi.erp.user.Permission.MANAGER_UPDATE;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public enum Role {
|
|
||||||
|
|
||||||
USER(Collections.emptySet()),
|
|
||||||
ADMIN(
|
|
||||||
Set.of(
|
|
||||||
ADMIN_READ,
|
|
||||||
ADMIN_UPDATE,
|
|
||||||
ADMIN_DELETE,
|
|
||||||
ADMIN_CREATE,
|
|
||||||
MANAGER_READ,
|
|
||||||
MANAGER_UPDATE,
|
|
||||||
MANAGER_DELETE,
|
|
||||||
MANAGER_CREATE
|
|
||||||
)
|
|
||||||
),
|
|
||||||
MANAGER(
|
|
||||||
Set.of(
|
|
||||||
MANAGER_READ,
|
|
||||||
MANAGER_UPDATE,
|
|
||||||
MANAGER_DELETE,
|
|
||||||
MANAGER_CREATE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final Set<Permission> permissions;
|
|
||||||
|
|
||||||
public List<SimpleGrantedAuthority> getAuthorities() {
|
|
||||||
var authorities = getPermissions()
|
|
||||||
.stream()
|
|
||||||
.map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
|
|
||||||
return authorities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,8 @@ spring:
|
||||||
format_sql: true
|
format_sql: true
|
||||||
database: postgresql
|
database: postgresql
|
||||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
autoconfigure:
|
||||||
|
exclude: org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
|
||||||
application:
|
application:
|
||||||
security:
|
security:
|
||||||
jwt:
|
jwt:
|
||||||
|
|
@ -22,6 +23,6 @@ application:
|
||||||
refresh-token:
|
refresh-token:
|
||||||
expiration: 604800000 # 7 days
|
expiration: 604800000 # 7 days
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8082
|
||||||
servlet:
|
servlet:
|
||||||
context-path: /auth-service
|
context-path: /crm-rest-api
|
||||||
Loading…
Reference in New Issue