authentication
This commit is contained in:
@ -54,7 +54,7 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
private void isValidToken(HttpServletRequest request, String jwtToken) {
|
private void isValidToken(HttpServletRequest request, String jwtToken) {
|
||||||
String requestUrl = request.getRequestURI();
|
String requestUrl = request.getRequestURI();
|
||||||
String refreshTokenUrl = "/authentication-service/authentication/v1/refresh-token";
|
String refreshTokenUrl = "/api/authentication/refresh-token";
|
||||||
if (!refreshTokenUrl.equals(requestUrl)) {
|
if (!refreshTokenUrl.equals(requestUrl)) {
|
||||||
var isValid = isValidAuthenticateToken(jwtToken);
|
var isValid = isValidAuthenticateToken(jwtToken);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
|
@ -39,11 +39,11 @@ public class JwtTokenUtil implements Serializable {
|
|||||||
return expiration.before(new Date());
|
return expiration.before(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateToken(String username, TokenContent tokenContent, Integer expirationInMs, String channel, String scopeType) {
|
public String generateToken(String username, TokenContent tokenContent, Integer expirationInMs) {
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
|
||||||
claims.put("authorities", tokenContent.getAccessMenu());
|
claims.put("authorities", tokenContent.getAccessMenu());
|
||||||
claims.put("fullname", tokenContent.getFullname());
|
claims.put("nama", tokenContent.getNama());
|
||||||
claims.put("username", tokenContent.getUsername());
|
claims.put("username", tokenContent.getUsername());
|
||||||
claims.put("user_id", tokenContent.getUserId());
|
claims.put("user_id", tokenContent.getUserId());
|
||||||
claims.put("role", tokenContent.getRole());
|
claims.put("role", tokenContent.getRole());
|
||||||
|
@ -34,6 +34,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.csrf().disable();
|
.csrf().disable();
|
||||||
httpSecurity.authorizeRequests()
|
httpSecurity.authorizeRequests()
|
||||||
.antMatchers("/api*/**").permitAll()
|
.antMatchers("/api*/**").permitAll()
|
||||||
|
.antMatchers("/api/authentication/*").permitAll()
|
||||||
.antMatchers("/actuator/health").permitAll()
|
.antMatchers("/actuator/health").permitAll()
|
||||||
.antMatchers("/swagger*/**").permitAll()
|
.antMatchers("/swagger*/**").permitAll()
|
||||||
.antMatchers("/v2*/**").permitAll()
|
.antMatchers("/v2*/**").permitAll()
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.iconplus.smartproc.controller;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.model.request.LoginRequest;
|
||||||
|
import com.iconplus.smartproc.model.request.RefreshTokenRequest;
|
||||||
|
import com.iconplus.smartproc.model.response.LoginResponse;
|
||||||
|
import com.iconplus.smartproc.model.response.RefreshTokenResponse;
|
||||||
|
import com.iconplus.smartproc.service.authentication.LoginService;
|
||||||
|
import com.iconplus.smartproc.service.authentication.TokenManagementService;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@CrossOrigin(origins = "http://localhost:8080", allowCredentials = "true")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/authentication")
|
||||||
|
public class AuthenticationController {
|
||||||
|
|
||||||
|
private LoginService loginService;
|
||||||
|
private TokenManagementService tokenManagementService;
|
||||||
|
|
||||||
|
public AuthenticationController(LoginService loginService,
|
||||||
|
TokenManagementService tokenManagementService) {
|
||||||
|
this.loginService = loginService;
|
||||||
|
this.tokenManagementService = tokenManagementService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public LoginResponse getLoginResponse(@RequestBody LoginRequest loginRequest) {
|
||||||
|
return loginService.execute(loginRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/refresh-token")
|
||||||
|
public RefreshTokenResponse getRefreshToken(@RequestBody RefreshTokenRequest refreshTokenRequest) {
|
||||||
|
return tokenManagementService.execute(refreshTokenRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
package com.iconplus.smartproc.model.entity;
|
|
||||||
|
|
||||||
import com.iconplus.smartproc.helper.base.BaseEntity;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.hibernate.annotations.GeneratorType;
|
|
||||||
import org.hibernate.annotations.Type;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Entity
|
|
||||||
@Table(name = "permission")
|
|
||||||
public class Menu extends BaseEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Column(name = "id")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(name = "subMenu")
|
|
||||||
private String subMenu;
|
|
||||||
|
|
||||||
@Column(name = "menu")
|
|
||||||
private String menu;
|
|
||||||
|
|
||||||
// @Column(name = "can_view")
|
|
||||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
|
||||||
// private Boolean canView;
|
|
||||||
//
|
|
||||||
// @Column(name = "can_read")
|
|
||||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
|
||||||
// private Boolean canRead;
|
|
||||||
//
|
|
||||||
// @Column(name = "can_create")
|
|
||||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
|
||||||
// private Boolean canCreate;
|
|
||||||
//
|
|
||||||
// @Column(name = "can_delete")
|
|
||||||
// @Type(type = "org.hibernate.type.NumericBooleanType")
|
|
||||||
// private Boolean canDelete;
|
|
||||||
|
|
||||||
@Column(name = "deleted")
|
|
||||||
@Type(type = "org.hibernate.type.NumericBooleanType")
|
|
||||||
private Boolean deleted;
|
|
||||||
}
|
|
45
src/main/java/com/iconplus/smartproc/model/entity/Menus.java
Normal file
45
src/main/java/com/iconplus/smartproc/model/entity/Menus.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package com.iconplus.smartproc.model.entity;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.helper.base.BaseEntity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.GeneratorType;
|
||||||
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Entity
|
||||||
|
@Table(name = "menus")
|
||||||
|
public class Menus extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "parent_id")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Column(name = "nama")
|
||||||
|
private String nama;
|
||||||
|
|
||||||
|
@Column(name = "link")
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
@Column(name = "urutan")
|
||||||
|
private Long urutan;
|
||||||
|
|
||||||
|
@Column(name = "icon")
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
@Column(name = "is_delete")
|
||||||
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
|
private Boolean isDelete;
|
||||||
|
}
|
@ -8,10 +8,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.Type;
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.*;
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@ -21,13 +18,9 @@ import javax.persistence.Table;
|
|||||||
public class Permission extends BaseEntity {
|
public class Permission extends BaseEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(generator = "UUID")
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@GenericGenerator(
|
|
||||||
name = "UUID",
|
|
||||||
strategy = "org.hibernate.id.UUIDGenerator"
|
|
||||||
)
|
|
||||||
@Column(name = "id")
|
@Column(name = "id")
|
||||||
private String id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "role_id")
|
@Column(name = "role_id")
|
||||||
private Long roleId;
|
private Long roleId;
|
||||||
@ -35,7 +28,23 @@ public class Permission extends BaseEntity {
|
|||||||
@Column(name = "menu_id")
|
@Column(name = "menu_id")
|
||||||
private Long menuId;
|
private Long menuId;
|
||||||
|
|
||||||
@Column(name = "deleted")
|
@Column(name = "can_view")
|
||||||
@Type(type = "org.hibernate.type.NumericBooleanType")
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
private Boolean deleted;
|
private Boolean canView;
|
||||||
|
|
||||||
|
@Column(name = "can_read")
|
||||||
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
|
private Boolean canRead;
|
||||||
|
|
||||||
|
@Column(name = "can_update")
|
||||||
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
|
private Boolean canUpdate;
|
||||||
|
|
||||||
|
@Column(name = "can_delete")
|
||||||
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
|
private Boolean canDelete;
|
||||||
|
|
||||||
|
@Column(name = "is_delete")
|
||||||
|
@Type(type = "org.hibernate.type.NumericBooleanType")
|
||||||
|
private Boolean isDelete;
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,12 @@ public class TokenManagement extends BaseEntity {
|
|||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Column(name = "user_id")
|
@Column(name = "user_id")
|
||||||
private String userId;
|
private Long userId;
|
||||||
|
|
||||||
@Lob
|
@Column(name = "access_token", length = 2500)
|
||||||
@Column(name = "access_token")
|
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
|
|
||||||
@Lob
|
@Column(name = "refresh_token", length = 2500)
|
||||||
@Column(name = "refresh_token")
|
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
|
|
||||||
@Column(name = "issued_time")
|
@Column(name = "issued_time")
|
||||||
|
@ -7,10 +7,10 @@ public interface TokenManagementView {
|
|||||||
String getId();
|
String getId();
|
||||||
void setId(String id);
|
void setId(String id);
|
||||||
|
|
||||||
String getUserId();
|
Long getUserId();
|
||||||
void setUserId(String userId);
|
void setUserId(Long userId);
|
||||||
|
|
||||||
Clob getAccessToken();
|
String getAccessToken();
|
||||||
void setAccessToken(Clob accessToken);
|
void setAccessToken(String accessToken);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.iconplus.smartproc.model.request;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.helper.base.BaseRequest;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RefreshTokenRequest extends BaseRequest {
|
||||||
|
private String refreshToken;
|
||||||
|
}
|
@ -15,7 +15,7 @@ import java.util.Set;
|
|||||||
public class LoginResponse extends BaseResponse {
|
public class LoginResponse extends BaseResponse {
|
||||||
|
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
private String validity;
|
private Integer validity;
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
private String username;
|
private String username;
|
||||||
private String email;
|
private String email;
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.iconplus.smartproc.model.response;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.helper.base.BaseResponse;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RefreshTokenResponse extends BaseResponse {
|
||||||
|
private String accessToken;
|
||||||
|
private String refreshToken;
|
||||||
|
private Integer validity;
|
||||||
|
}
|
@ -8,9 +8,9 @@ import java.util.Set;
|
|||||||
@Builder
|
@Builder
|
||||||
@Data
|
@Data
|
||||||
public class TokenContent {
|
public class TokenContent {
|
||||||
private String userId;
|
private Long userId;
|
||||||
private String role;
|
private String role;
|
||||||
private Set<String> accessMenu;
|
private Set<String> accessMenu;
|
||||||
private String fullname;
|
private String nama;
|
||||||
private String username;
|
private String username;
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,21 @@ import org.springframework.data.jpa.repository.Query;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface TokenManagementRepository extends JpaRepository<TokenManagement, String> {
|
public interface TokenManagementRepository extends JpaRepository<TokenManagement, String> {
|
||||||
|
|
||||||
@Query(value = "SELECT access_token as accessToken FROM token_management " +
|
@Query(value = "SELECT access_token as accessToken FROM token_management " +
|
||||||
"WHERE user_id = :userId " +
|
"WHERE user_id = :userId " +
|
||||||
"AND isDelete = false " +
|
"AND is_delete = 0 " +
|
||||||
"AND expired_time >= SYSDATE", nativeQuery = true)
|
"AND expired_time >= CURRENT_TIMESTAMP", nativeQuery = true)
|
||||||
List<TokenManagementView> findAccessTokenByUserIdAndDeletedFalse(String userId);
|
List<TokenManagementView> findAccessTokenByUserIdAndDeletedFalse(Long userId);
|
||||||
|
|
||||||
|
@Query(value = "SELECT tm from TokenManagement tm " +
|
||||||
|
"WHERE tm.refreshToken = :refreshToken " +
|
||||||
|
"and tm.isDelete = false")
|
||||||
|
Optional<TokenManagement> findByRefreshToken(String refreshToken);
|
||||||
|
|
||||||
|
Optional<TokenManagement> findByUserId(Long id);
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,28 @@ public interface UsersRepository extends JpaRepository<Users, Long> {
|
|||||||
|
|
||||||
Optional<Users> findByEmailAndIsDeleteFalse(String email);
|
Optional<Users> findByEmailAndIsDeleteFalse(String email);
|
||||||
|
|
||||||
|
@Query("SELECT u.id as id, " +
|
||||||
|
"u.nama as nama, " +
|
||||||
|
"u.username as username, " +
|
||||||
|
"u.password as password, " +
|
||||||
|
"u.jabatan as jabatan, " +
|
||||||
|
"u.roleId as roleId, " +
|
||||||
|
"r.role as role, " +
|
||||||
|
"u.bidangId as bidangId, " +
|
||||||
|
"b.bidang as bidang, " +
|
||||||
|
"u.instansiId as instansiId, " +
|
||||||
|
"i.instansi as instansi, " +
|
||||||
|
"u.email as email, " +
|
||||||
|
"u.isActive as isActive, " +
|
||||||
|
"u.isDelete as isDelete " +
|
||||||
|
"FROM Users u " +
|
||||||
|
"JOIN Roles r ON r.id = u.roleId " +
|
||||||
|
"JOIN Bidang b ON b.id = u.bidangId " +
|
||||||
|
"JOIN Instansi i ON i.id = u.instansiId " +
|
||||||
|
"Where u.isDelete = false " +
|
||||||
|
"AND (u.username = :input OR u.email = :input)")
|
||||||
|
Optional<UserRoleView> getByUsernameOrEmail(String input);
|
||||||
|
|
||||||
Optional<Users> findByIdAndIsDeleteFalse(Long id);
|
Optional<Users> findByIdAndIsDeleteFalse(Long id);
|
||||||
|
|
||||||
@Query("SELECT u.id as id, " +
|
@Query("SELECT u.id as id, " +
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package com.iconplus.smartproc.service;
|
package com.iconplus.smartproc.service;
|
||||||
|
|
||||||
import com.iconplus.smartproc.exception.BusinessException;
|
import com.iconplus.smartproc.exception.BusinessException;
|
||||||
|
import com.iconplus.smartproc.model.entity.TokenManagement;
|
||||||
import com.iconplus.smartproc.model.request.UsersRequest;
|
import com.iconplus.smartproc.model.request.UsersRequest;
|
||||||
import com.iconplus.smartproc.repository.BidangRepository;
|
import com.iconplus.smartproc.repository.*;
|
||||||
import com.iconplus.smartproc.repository.InstansiRepository;
|
|
||||||
import com.iconplus.smartproc.repository.RolesRepository;
|
|
||||||
import com.iconplus.smartproc.repository.UsersRepository;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CommonService {
|
public class CommonService {
|
||||||
|
|
||||||
@ -16,15 +17,18 @@ public class CommonService {
|
|||||||
private RolesRepository rolesRepository;
|
private RolesRepository rolesRepository;
|
||||||
private BidangRepository bidangRepository;
|
private BidangRepository bidangRepository;
|
||||||
private InstansiRepository instansiRepository;
|
private InstansiRepository instansiRepository;
|
||||||
|
private TokenManagementRepository tokenManagementRepository;
|
||||||
|
|
||||||
public CommonService(UsersRepository usersRepository,
|
public CommonService(UsersRepository usersRepository,
|
||||||
RolesRepository rolesRepository,
|
RolesRepository rolesRepository,
|
||||||
BidangRepository bidangRepository,
|
BidangRepository bidangRepository,
|
||||||
InstansiRepository instansiRepository) {
|
InstansiRepository instansiRepository,
|
||||||
|
TokenManagementRepository tokenManagementRepository) {
|
||||||
this.usersRepository = usersRepository;
|
this.usersRepository = usersRepository;
|
||||||
this.rolesRepository = rolesRepository;
|
this.rolesRepository = rolesRepository;
|
||||||
this.bidangRepository = bidangRepository;
|
this.bidangRepository = bidangRepository;
|
||||||
this.instansiRepository = instansiRepository;
|
this.instansiRepository = instansiRepository;
|
||||||
|
this.tokenManagementRepository = tokenManagementRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateUserRequst(UsersRequest input) {
|
public void validateUserRequst(UsersRequest input) {
|
||||||
@ -44,4 +48,37 @@ public class CommonService {
|
|||||||
throw new BusinessException("err", "err", "err");
|
throw new BusinessException("err", "err", "err");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveUserToken(TokenManagement tokenManagement, Integer tokenExpiry) {
|
||||||
|
|
||||||
|
var issuedTime = Timestamp.from(Instant.now());
|
||||||
|
var expirationTime = Timestamp.from(Instant.now().plusMillis(tokenExpiry * (long) 60000));
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(tokenManagement.getId())) {
|
||||||
|
tokenManagement.setIssuedTime(issuedTime);
|
||||||
|
tokenManagement.setExpiredTime(expirationTime);
|
||||||
|
tokenManagementRepository.save(tokenManagement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existToken = tokenManagementRepository.findByUserId(tokenManagement.getUserId());
|
||||||
|
|
||||||
|
if (existToken.isPresent()) {
|
||||||
|
existToken.get().setAccessToken(tokenManagement.getAccessToken());
|
||||||
|
existToken.get().setRefreshToken(tokenManagement.getRefreshToken());
|
||||||
|
existToken.get().setIsDelete(false);
|
||||||
|
existToken.get().setIssuedTime(issuedTime);
|
||||||
|
existToken.get().setExpiredTime(expirationTime);
|
||||||
|
tokenManagementRepository.save(existToken.get());
|
||||||
|
} else {
|
||||||
|
tokenManagementRepository.save(TokenManagement.builder()
|
||||||
|
.userId(tokenManagement.getUserId())
|
||||||
|
.accessToken(tokenManagement.getAccessToken())
|
||||||
|
.refreshToken(tokenManagement.getRefreshToken())
|
||||||
|
.issuedTime(issuedTime)
|
||||||
|
.expiredTime(expirationTime)
|
||||||
|
.isDelete(false)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,99 @@
|
|||||||
package com.iconplus.smartproc.service.authentication;
|
package com.iconplus.smartproc.service.authentication;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.configuration.JwtTokenUtil;
|
||||||
import com.iconplus.smartproc.exception.BusinessException;
|
import com.iconplus.smartproc.exception.BusinessException;
|
||||||
import com.iconplus.smartproc.helper.service.BaseService;
|
import com.iconplus.smartproc.helper.service.BaseService;
|
||||||
|
import com.iconplus.smartproc.model.entity.TokenManagement;
|
||||||
import com.iconplus.smartproc.model.request.LoginRequest;
|
import com.iconplus.smartproc.model.request.LoginRequest;
|
||||||
import com.iconplus.smartproc.model.response.LoginResponse;
|
import com.iconplus.smartproc.model.response.LoginResponse;
|
||||||
|
import com.iconplus.smartproc.model.token.TokenContent;
|
||||||
import com.iconplus.smartproc.repository.UsersRepository;
|
import com.iconplus.smartproc.repository.UsersRepository;
|
||||||
|
import com.iconplus.smartproc.service.CommonService;
|
||||||
import com.iconplus.smartproc.util.Constants;
|
import com.iconplus.smartproc.util.Constants;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LoginService implements BaseService<LoginRequest, LoginResponse> {
|
public class LoginService implements BaseService<LoginRequest, LoginResponse> {
|
||||||
|
|
||||||
|
@Value("${jwt.expired-time.access-token:15}")
|
||||||
|
private Integer accessTokenExp;
|
||||||
|
@Value("${jwt.expired-time.refresh-token:60}")
|
||||||
|
private Integer refreshTokenExp;
|
||||||
|
|
||||||
private final UsersRepository usersRepository;
|
private final UsersRepository usersRepository;
|
||||||
|
private final JwtTokenUtil jwtTokenUtil;
|
||||||
|
private final CommonService commonService;
|
||||||
|
|
||||||
public LoginService(UsersRepository userRepository) {
|
|
||||||
|
public LoginService(UsersRepository userRepository,
|
||||||
|
JwtTokenUtil jwtTokenUtil,
|
||||||
|
CommonService commonService) {
|
||||||
this.usersRepository = userRepository;
|
this.usersRepository = userRepository;
|
||||||
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
|
this.commonService = commonService;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public LoginResponse execute(LoginRequest input) {
|
public LoginResponse execute(LoginRequest input) {
|
||||||
|
|
||||||
var user= usersRepository.findByEmailAndIsDeleteFalse(input.getEmail())
|
var userRoleView= usersRepository.getByUsernameOrEmail(input.getEmail())
|
||||||
.orElseThrow(() -> new BusinessException(HttpStatus.CONFLICT,
|
.orElseThrow(() -> new BusinessException(HttpStatus.CONFLICT,
|
||||||
Constants.ERR_CODE_10003,
|
Constants.ERR_CODE_10003,
|
||||||
Constants.ERR_TTL_10003,
|
Constants.ERR_TTL_10003,
|
||||||
String.format(Constants.ERR_MSG_10003, input.getEmail())));
|
String.format(Constants.ERR_MSG_10003, input.getEmail())));
|
||||||
|
|
||||||
if (!StringUtils.equalsIgnoreCase(input.getPassword(), user.getPassword())) {
|
if (!StringUtils.equalsIgnoreCase(input.getPassword(), userRoleView.getPassword())) {
|
||||||
throw new BusinessException(HttpStatus.CONFLICT,
|
throw new BusinessException(HttpStatus.CONFLICT,
|
||||||
Constants.ERR_CODE_10004,
|
Constants.ERR_CODE_10004,
|
||||||
Constants.ERR_TTL_10004,
|
Constants.ERR_TTL_10004,
|
||||||
Constants.ERR_MSG_10004);
|
Constants.ERR_MSG_10004);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenContent = TokenContent.builder()
|
||||||
|
.userId(userRoleView.getId())
|
||||||
|
.username(userRoleView.getUsername())
|
||||||
|
.nama(userRoleView.getNama())
|
||||||
|
.role(userRoleView.getRole())
|
||||||
|
.accessMenu(new HashSet<>())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
claims.put("userId", userRoleView.getId());
|
||||||
|
|
||||||
|
final String accessToken = jwtTokenUtil.generateToken(String.valueOf(userRoleView.getId()), tokenContent, accessTokenExp * 60000);
|
||||||
|
String refreshToken = jwtTokenUtil.doGenerateToken(claims, String.valueOf(userRoleView.getId()), refreshTokenExp * 60000);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(accessToken) || StringUtils.isBlank(refreshToken)) {
|
||||||
|
log.error("token null");
|
||||||
|
throw new BusinessException("err", "err", "err");
|
||||||
|
}
|
||||||
|
|
||||||
|
commonService.saveUserToken(TokenManagement.builder()
|
||||||
|
.userId(userRoleView.getId())
|
||||||
|
.accessToken(accessToken)
|
||||||
|
.refreshToken(refreshToken)
|
||||||
|
.build(), accessTokenExp);
|
||||||
|
|
||||||
|
|
||||||
return LoginResponse.builder()
|
return LoginResponse.builder()
|
||||||
|
.accessToken(accessToken)
|
||||||
|
.validity(accessTokenExp * 60)
|
||||||
|
.refreshToken(refreshToken)
|
||||||
|
.username(userRoleView.getUsername())
|
||||||
|
.email(userRoleView.getEmail())
|
||||||
|
.role(userRoleView.getRole())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class PostCheckAccessTokenService implements BaseService<PostAccessTokenR
|
|||||||
public PostAccessTokenResponse execute(PostAccessTokenRequest input) {
|
public PostAccessTokenResponse execute(PostAccessTokenRequest input) {
|
||||||
|
|
||||||
var decodeToken = TokenUtils.decodeToken(input.getAccessToken());
|
var decodeToken = TokenUtils.decodeToken(input.getAccessToken());
|
||||||
String userId = decodeToken.get("user_id");
|
Long userId = Long.valueOf(decodeToken.get("user_id"));
|
||||||
|
|
||||||
List<TokenManagementView> tokenManagementViews = tokenManagementRepository.findAccessTokenByUserIdAndDeletedFalse(userId);
|
List<TokenManagementView> tokenManagementViews = tokenManagementRepository.findAccessTokenByUserIdAndDeletedFalse(userId);
|
||||||
if (tokenManagementViews.isEmpty()) {
|
if (tokenManagementViews.isEmpty()) {
|
||||||
@ -38,7 +38,7 @@ public class PostCheckAccessTokenService implements BaseService<PostAccessTokenR
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<String> userTokenList = tokenManagementViews.stream()
|
List<String> userTokenList = tokenManagementViews.stream()
|
||||||
.map(c-> CommonUtil.clobToString(c.getAccessToken()))
|
.map(TokenManagementView::getAccessToken)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
boolean isMatch = userTokenList.stream().anyMatch(s -> s.equals(input.getAccessToken()));
|
boolean isMatch = userTokenList.stream().anyMatch(s -> s.equals(input.getAccessToken()));
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.iconplus.smartproc.service.authentication;
|
||||||
|
|
||||||
|
import com.iconplus.smartproc.configuration.JwtTokenUtil;
|
||||||
|
import com.iconplus.smartproc.exception.BusinessException;
|
||||||
|
import com.iconplus.smartproc.helper.service.BaseService;
|
||||||
|
import com.iconplus.smartproc.helper.service.TokenUtils;
|
||||||
|
import com.iconplus.smartproc.model.entity.TokenManagement;
|
||||||
|
import com.iconplus.smartproc.model.request.RefreshTokenRequest;
|
||||||
|
import com.iconplus.smartproc.model.response.RefreshTokenResponse;
|
||||||
|
import com.iconplus.smartproc.model.token.TokenContent;
|
||||||
|
import com.iconplus.smartproc.repository.TokenManagementRepository;
|
||||||
|
import com.iconplus.smartproc.repository.UsersRepository;
|
||||||
|
import com.iconplus.smartproc.service.CommonService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class TokenManagementService implements BaseService<RefreshTokenRequest, RefreshTokenResponse> {
|
||||||
|
|
||||||
|
@Value("${jwt.expired-time.access-token:15}")
|
||||||
|
private Integer accessTokenExp;
|
||||||
|
|
||||||
|
private final TokenManagementRepository tokenManagementRepository;
|
||||||
|
private final UsersRepository usersRepository;
|
||||||
|
private final JwtTokenUtil jwtTokenUtil;
|
||||||
|
private final CommonService commonService;
|
||||||
|
|
||||||
|
public TokenManagementService(TokenManagementRepository tokenManagementRepository,
|
||||||
|
JwtTokenUtil jwtTokenUtil,
|
||||||
|
UsersRepository usersRepository,
|
||||||
|
CommonService commonService) {
|
||||||
|
this.tokenManagementRepository = tokenManagementRepository;
|
||||||
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
|
this.usersRepository = usersRepository;
|
||||||
|
this.commonService = commonService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public RefreshTokenResponse execute(RefreshTokenRequest input) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
jwtTokenUtil.validateTokenOnly(input.getRefreshToken());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessException(HttpStatus.UNAUTHORIZED, "err", "err", "err");
|
||||||
|
}
|
||||||
|
|
||||||
|
var decodeToken = TokenUtils.decodeToken(input.getRefreshToken());
|
||||||
|
Long userId = Long.valueOf(decodeToken.get("userId"));
|
||||||
|
|
||||||
|
var tokenManagement1 = tokenManagementRepository.findByRefreshToken(input.getRefreshToken());
|
||||||
|
|
||||||
|
TokenManagement tokenManagement = tokenManagementRepository.findByRefreshToken(input.getRefreshToken())
|
||||||
|
.map(c -> verifyRefreshToken(c, userId))
|
||||||
|
.orElseThrow(() -> {
|
||||||
|
log.error("failed validate token to existing db");
|
||||||
|
return new BusinessException(
|
||||||
|
HttpStatus.UNAUTHORIZED, "err", "err",
|
||||||
|
"err");
|
||||||
|
});
|
||||||
|
|
||||||
|
var userRoleView = usersRepository.getUserByIdAndDeletedFase(userId).orElseThrow(() -> new BusinessException("err", "err", "err"));
|
||||||
|
|
||||||
|
var tokenContent = TokenContent.builder()
|
||||||
|
.userId(userRoleView.getId())
|
||||||
|
.username(userRoleView.getUsername())
|
||||||
|
.nama(userRoleView.getNama())
|
||||||
|
.role(userRoleView.getRole())
|
||||||
|
.accessMenu(new HashSet<>())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final String accessToken = jwtTokenUtil.generateToken(String.valueOf(userRoleView.getId()), tokenContent, accessTokenExp * 60000);
|
||||||
|
|
||||||
|
tokenManagement.setAccessToken(accessToken);
|
||||||
|
tokenManagement.setRefreshToken(input.getRefreshToken());
|
||||||
|
commonService.saveUserToken(tokenManagement, accessTokenExp);
|
||||||
|
|
||||||
|
return RefreshTokenResponse.builder()
|
||||||
|
.accessToken(accessToken)
|
||||||
|
.refreshToken(input.getRefreshToken())
|
||||||
|
.validity(accessTokenExp * 60)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TokenManagement verifyRefreshToken(TokenManagement tokenManagement, Long userId) {
|
||||||
|
if (!Objects.equals(userId, tokenManagement.getUserId())) {
|
||||||
|
throw new BusinessException(HttpStatus.UNAUTHORIZED,
|
||||||
|
"err",
|
||||||
|
"err",
|
||||||
|
"err");
|
||||||
|
}
|
||||||
|
return tokenManagement;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user