diff --git a/pom.xml b/pom.xml
index 33b56a1..0536c6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,59 @@
11
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+ 2.5.4
+
+
+ org.springframework.security
+ spring-security-web
+
+
+ org.springframework.security
+ spring-security-config
+
+
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ 2.5.2
+
+
+ org.springframework.security
+ spring-security-web
+
+
+ org.springframework.security
+ spring-security-config
+
+
+
+
+ org.springframework.security
+ spring-security-web
+ 5.3.9.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 5.3.9.RELEASE
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+ com.nimbusds
+ nimbus-jose-jwt
+ 8.19
+
+
org.springframework.boot
spring-boot-starter-data-jpa
@@ -34,20 +87,16 @@
brave
5.16.0
-
+
+ org.apache.velocity
+ velocity-engine-core
+ 2.3
+
org.apache.commons
commons-lang3
3.12.0
-
-
- org.apache.velocity
- velocity
- 1.7
-
-
-
org.springframework.boot
spring-boot-devtools
diff --git a/src/main/java/com/iconplus/smartproc/configuration/CustomUserDetailsService.java b/src/main/java/com/iconplus/smartproc/configuration/CustomUserDetailsService.java
new file mode 100644
index 0000000..3d6bc23
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/CustomUserDetailsService.java
@@ -0,0 +1,33 @@
+package com.iconplus.smartproc.configuration;
+
+import com.iconplus.smartproc.model.projection.UserRoleView;
+import com.iconplus.smartproc.repository.RolesRepository;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class CustomUserDetailsService implements UserDetailsService {
+
+ private final RolesRepository rolesRepository;
+
+ public CustomUserDetailsService(RolesRepository rolesRepository) {
+ this.rolesRepository = rolesRepository;
+ }
+
+
+ @Override
+ public UserDetails loadUserByUsername(String username) {
+ List authorities = null;
+ Optional userRole = rolesRepository.getUserRoleByUserId(username);
+ if (userRole.isPresent()) {
+ authorities=List.of(new SimpleGrantedAuthority(userRole.get().getRole()));
+ }
+
+ return new org.springframework.security.core.userdetails.User(username, username, authorities);
+ }
+}
diff --git a/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationAccessDenied.java b/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationAccessDenied.java
new file mode 100644
index 0000000..a7d80d5
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationAccessDenied.java
@@ -0,0 +1,39 @@
+package com.iconplus.smartproc.configuration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.iconplus.smartproc.exception.ErrorResponse;
+import com.iconplus.smartproc.util.Constants;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.http.MediaType;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+@Log4j2
+public class JwtAuthenticationAccessDenied implements AccessDeniedHandler {
+
+ private static final String DEFAULT_CODE = "30000";
+ private static final String DEFAULT_MESSAGE = "Access denied";
+
+ @Override
+ public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
+
+ log.error("Access denied, {}", e.getMessage());
+
+ ErrorResponse errorResponse = new ErrorResponse();
+ errorResponse.setCode(DEFAULT_CODE);
+ errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
+ errorResponse.setMessage(DEFAULT_MESSAGE);
+
+ httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
+
+ httpServletResponse.getOutputStream()
+ .println(new ObjectMapper().writeValueAsString(errorResponse));
+ }
+}
diff --git a/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationEntryPoint.java b/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationEntryPoint.java
new file mode 100644
index 0000000..e6fa58d
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/JwtAuthenticationEntryPoint.java
@@ -0,0 +1,54 @@
+package com.iconplus.smartproc.configuration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.iconplus.smartproc.exception.ErrorResponse;
+import com.iconplus.smartproc.util.Constants;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException authException) throws IOException {
+
+ ErrorResponse errorResponse = new ErrorResponse();
+
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+
+ var exception = (Exception) request.getAttribute("exception");
+
+ String message;
+
+ if (exception != null) {
+
+ if (exception.getCause() != null) {
+ message = exception.getCause().toString() + " " + exception.getMessage();
+ } else {
+ message = exception.getMessage();
+ }
+
+ errorResponse.setCode(Constants.ERR_CODE_40051);
+ errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
+ errorResponse.setMessage(message);
+ response.getOutputStream()
+ .println(new ObjectMapper().writeValueAsString(errorResponse));
+ } else {
+ errorResponse.setCode(Constants.ERR_CODE_80007);
+ errorResponse.setTitle(Constants.TITLE_INVALID_NEXT_STEP);
+ errorResponse.setMessage("Invalid Access Token");
+ response.getOutputStream()
+ .println(new ObjectMapper().writeValueAsString(errorResponse));
+ }
+ }
+
+}
diff --git a/src/main/java/com/iconplus/smartproc/configuration/JwtRequestFilter.java b/src/main/java/com/iconplus/smartproc/configuration/JwtRequestFilter.java
new file mode 100644
index 0000000..b04e38b
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/JwtRequestFilter.java
@@ -0,0 +1,79 @@
+package com.iconplus.smartproc.configuration;
+
+import com.iconplus.smartproc.exception.BusinessException;
+import com.iconplus.smartproc.model.request.PostAccessTokenRequest;
+import com.iconplus.smartproc.service.authentication.PostCheckAccessTokenService;
+import io.jsonwebtoken.ExpiredJwtException;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class JwtRequestFilter extends OncePerRequestFilter {
+
+ private final JwtTokenUtil jwtTokenUtil;
+ private final PostCheckAccessTokenService postCheckAccessTokenService;
+
+ public JwtRequestFilter(JwtTokenUtil jwtTokenUtil,
+ PostCheckAccessTokenService postCheckAccessTokenService) {
+ this.jwtTokenUtil = jwtTokenUtil;
+ this.postCheckAccessTokenService = postCheckAccessTokenService;
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
+ try {
+ String jwtToken = extractJwtFromRequest(request);
+ if (StringUtils.hasText(jwtToken) && jwtTokenUtil.validateTokenOnly(jwtToken)) {
+ isValidToken(request, jwtToken);
+ UserDetails userDetails = new org.springframework.security.core.userdetails.User(jwtTokenUtil.getUsernameFromToken(jwtToken), "",
+ jwtTokenUtil.getRolesFromToken(jwtToken));
+
+ UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
+ userDetails, null, userDetails.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
+ }
+ } catch(ExpiredJwtException | BadCredentialsException ex)
+ {
+ request.setAttribute("exception", ex);
+ }
+ chain.doFilter(request, response);
+ }
+
+ private void isValidToken(HttpServletRequest request, String jwtToken) {
+ String requestUrl = request.getRequestURI();
+ String refreshTokenUrl = "/authentication-service/authentication/v1/refresh-token";
+ if (!refreshTokenUrl.equals(requestUrl)) {
+ var isValid = isValidAuthenticateToken(jwtToken);
+ if (!isValid) {
+ throw new BusinessException(HttpStatus.UNAUTHORIZED, "Invalid Access Token");
+ }
+ }
+ }
+
+ private boolean isValidAuthenticateToken(String jwtToken) {
+ return postCheckAccessTokenService.execute(PostAccessTokenRequest.builder()
+ .accessToken(jwtToken)
+ .build()).getIsValid();
+ }
+
+ private String extractJwtFromRequest(HttpServletRequest request) {
+ String bearerToken = request.getHeader("Authorization");
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ return bearerToken.substring(7);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/configuration/JwtTokenUtil.java b/src/main/java/com/iconplus/smartproc/configuration/JwtTokenUtil.java
new file mode 100644
index 0000000..ebab745
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/JwtTokenUtil.java
@@ -0,0 +1,91 @@
+package com.iconplus.smartproc.configuration;
+
+import com.iconplus.smartproc.model.token.TokenContent;
+import io.jsonwebtoken.*;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+import java.security.KeyPair;
+import java.util.*;
+import java.util.function.Function;
+
+@Component
+public class JwtTokenUtil implements Serializable {
+ private static final long serialVersionUID = -2550185165626007488L;
+
+ @Autowired
+ private KeyPair keyPair;
+
+ //retrieve expiration date from jwt token
+ public Date getExpirationDateFromToken(String token) {
+ return getClaimFromToken(token, Claims::getExpiration);
+ }
+ public T getClaimFromToken(String token, Function claimsResolver) {
+ final Claims claims = getAllClaimsFromToken(token);
+ return claimsResolver.apply(claims);
+ }
+ //for retrieveing any information from token we will need the secret key
+ public Claims getAllClaimsFromToken(String token) {
+ return Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
+ }
+
+ private Boolean isTokenExpired(String token) {
+ final Date expiration = getExpirationDateFromToken(token);
+ return expiration.before(new Date());
+ }
+
+ public String generateToken(String username, TokenContent tokenContent, Integer expirationInMs, String channel, String scopeType) {
+ Map claims = new HashMap<>();
+
+ claims.put("authorities", tokenContent.getAccessMenu());
+ claims.put("fullname", tokenContent.getFullname());
+ claims.put("username", tokenContent.getUsername());
+ claims.put("user_id", tokenContent.getUserId());
+ claims.put("role", tokenContent.getRole());
+
+ return doGenerateToken(claims, username, expirationInMs);
+ }
+
+ public String doGenerateToken(Map claims, String subject, Integer expirationInMs) {
+ return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
+ .setExpiration(new Date(System.currentTimeMillis() + expirationInMs))
+ .signWith(SignatureAlgorithm.RS256, keyPair.getPrivate()).compact();
+ }
+
+ public Boolean validateToken(String token, UserDetails userDetails) {
+ final String username = getUsernameFromToken(token);
+ return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
+ }
+
+ public boolean validateTokenOnly(String authToken) {
+ try {
+ Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(authToken);
+ return true;
+ } catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
+ throw new BadCredentialsException("INVALID_CREDENTIALS", ex);
+ } catch (ExpiredJwtException ex) {
+ throw ex;
+ }
+ }
+
+ public String getUsernameFromToken(String token) {
+ Claims claims = Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
+ return claims.getSubject();
+
+ }
+
+ @SuppressWarnings("squid:S4834")
+ public List getRolesFromToken(String token) {
+ Claims claims = Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(token).getBody();
+ List authorityList = new ArrayList<>();
+ ArrayList authorities = claims.get("authorities", ArrayList.class);
+ authorities.forEach(c-> authorityList.add(new SimpleGrantedAuthority(c)));
+ return authorityList;
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/configuration/KeyConfiguration.java b/src/main/java/com/iconplus/smartproc/configuration/KeyConfiguration.java
new file mode 100644
index 0000000..6077f9c
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/KeyConfiguration.java
@@ -0,0 +1,30 @@
+package com.iconplus.smartproc.configuration;
+
+import com.iconplus.smartproc.util.RSAUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+@Configuration
+public class KeyConfiguration {
+
+ @Value("${jwt.private-key}")
+ private String privateKey;
+
+ @Value("${jwt.public-key}")
+ private String publicKey;
+
+ @Bean
+ public KeyPair keypairBean() {
+
+ PublicKey pubKey = RSAUtil.getPublicKey(publicKey);
+ PrivateKey privKey = RSAUtil.getPrivateKey(privateKey);
+
+ return new KeyPair(pubKey, privKey);
+ }
+
+}
diff --git a/src/main/java/com/iconplus/smartproc/configuration/WebSecurityConfig.java b/src/main/java/com/iconplus/smartproc/configuration/WebSecurityConfig.java
new file mode 100644
index 0000000..9c6274a
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/configuration/WebSecurityConfig.java
@@ -0,0 +1,57 @@
+package com.iconplus.smartproc.configuration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
+
+ @Autowired
+ private JwtAuthenticationAccessDenied jwtAuthenticationAccessDenied;
+
+ @Autowired
+ private JwtRequestFilter jwtRequestFilter;
+
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ httpSecurity
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .sessionFixation().none().and()
+ .csrf().disable();
+ httpSecurity.authorizeRequests()
+ .antMatchers("/api*/**").permitAll()
+ .antMatchers("/actuator/health").permitAll()
+ .antMatchers("/swagger*/**").permitAll()
+ .antMatchers("/v2*/**").permitAll()
+ .antMatchers("/token/jwks.json").permitAll()
+ .anyRequest().authenticated().and()
+ .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
+ .accessDeniedHandler(jwtAuthenticationAccessDenied);
+ httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
+
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring().antMatchers("/v2/api-docs",
+ "/configuration/ui",
+ "/swagger-resources/**",
+ "/configuration/security",
+ "/swagger-ui.html",
+ "/webjars/**");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/controller/UsersController.java b/src/main/java/com/iconplus/smartproc/controller/UsersController.java
index 9a87b64..73758c8 100644
--- a/src/main/java/com/iconplus/smartproc/controller/UsersController.java
+++ b/src/main/java/com/iconplus/smartproc/controller/UsersController.java
@@ -45,7 +45,7 @@ public class UsersController {
.orElseThrow(() -> new ResourceNotFoundException("Users not exist with id :" + id));
users.setUsername(usersDetails.getUsername());
- users.setNama(usersDetails.getNama());
+ users.setFullname(usersDetails.getFullname());
users.setEmail(usersDetails.getEmail());
users.setPassword(usersDetails.getPassword());
// users.setInstansi(usersDetails.getInstansi());
diff --git a/src/main/java/com/iconplus/smartproc/exception/ErrorDetails.java b/src/main/java/com/iconplus/smartproc/exception/ErrorDetails.java
deleted file mode 100644
index a4ac27c..0000000
--- a/src/main/java/com/iconplus/smartproc/exception/ErrorDetails.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iconplus.smartproc.exception;
-
-import java.util.Date;
-
-public class ErrorDetails {
- private Date timestamp;
- private String message;
- private String details;
-
- public ErrorDetails(Date timestamp, String message, String details) {
- super();
- this.timestamp = timestamp;
- this.message = message;
- this.details = details;
- }
-
- public Date getTimestamp() {
- return timestamp;
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getDetails() {
- return details;
- }
-}
diff --git a/src/main/java/com/iconplus/smartproc/exception/ErrorHelper.java b/src/main/java/com/iconplus/smartproc/exception/ErrorHelper.java
index afdc490..012e13e 100644
--- a/src/main/java/com/iconplus/smartproc/exception/ErrorHelper.java
+++ b/src/main/java/com/iconplus/smartproc/exception/ErrorHelper.java
@@ -5,6 +5,7 @@ import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.springframework.context.annotation.Configuration;
@@ -88,7 +89,7 @@ public class ErrorHelper {
.getApplicationAttribute(StringResourceLoader.REPOSITORY_NAME_DEFAULT);
resourceRepository.putStringResource(RAW_TEMPLATE, rawNotificationTemplate);
- return new VelocityContext(parameters);
+ return new VelocityContext((Context) parameters);
}
private void addVelocityProperties() {
diff --git a/src/main/java/com/iconplus/smartproc/helper/service/TokenUtils.java b/src/main/java/com/iconplus/smartproc/helper/service/TokenUtils.java
new file mode 100644
index 0000000..4256cb4
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/helper/service/TokenUtils.java
@@ -0,0 +1,53 @@
+package com.iconplus.smartproc.helper.service;
+
+import com.nimbusds.jose.JWSObject;
+import com.nimbusds.jose.Payload;
+import lombok.extern.log4j.Log4j2;
+import net.minidev.json.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+@Log4j2
+public class TokenUtils {
+
+ private TokenUtils() {
+
+ }
+
+ public static Map decodeToken(String jwtToken) {
+ Map body = new HashMap<>();
+
+ try {
+ if (jwtToken != null) {
+ jwtToken = jwtToken.replace("Bearer", "");
+ jwtToken = jwtToken.trim();
+ }
+ if (StringUtils.isBlank(jwtToken)) {
+ return body;
+ }
+ JWSObject token = JWSObject.parse(jwtToken);
+
+ Payload tokenPayload = token.getPayload();
+ JSONObject tokenBody = tokenPayload.toJSONObject();
+
+ tokenBody.forEach((key, value) -> {
+ if (Objects.isNull(value)) {
+ value = "";
+ }
+
+ body.put(key, value.toString());
+ });
+ } catch (Exception e) {
+ log.error("Failed to parse JWT Token. Error: {}", e.getMessage());
+ }
+
+ return body;
+ }
+
+ public static Object getValueByParam(String param, String token) {
+ return decodeToken(token).get(param);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/model/entity/Menu.java b/src/main/java/com/iconplus/smartproc/model/entity/Menu.java
new file mode 100644
index 0000000..d37879f
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/entity/Menu.java
@@ -0,0 +1,52 @@
+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;
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/entity/Permission.java b/src/main/java/com/iconplus/smartproc/model/entity/Permission.java
new file mode 100644
index 0000000..9d54f1a
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/entity/Permission.java
@@ -0,0 +1,41 @@
+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.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Table(name = "permission")
+public class Permission extends BaseEntity {
+
+ @Id
+ @GeneratedValue(generator = "UUID")
+ @GenericGenerator(
+ name = "UUID",
+ strategy = "org.hibernate.id.UUIDGenerator"
+ )
+ @Column(name = "id")
+ private String id;
+
+ @Column(name = "role_id")
+ private Long roleId;
+
+ @Column(name = "role_id")
+ private Long menuId;
+
+ @Column(name = "deleted")
+ @Type(type = "org.hibernate.type.NumericBooleanType")
+ private Boolean deleted;
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/entity/TokenManagement.java b/src/main/java/com/iconplus/smartproc/model/entity/TokenManagement.java
new file mode 100644
index 0000000..10c7b65
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/entity/TokenManagement.java
@@ -0,0 +1,51 @@
+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.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+@Data
+@Builder
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Table(name = "token_management")
+public class TokenManagement extends BaseEntity {
+
+ @Id
+ @GeneratedValue(generator = "UUID")
+ @GenericGenerator(
+ name = "UUID",
+ strategy = "org.hibernate.id.UUIDGenerator"
+ )
+ @Column(name = "id")
+ private String id;
+
+ @Column(name = "user_id")
+ private String userId;
+
+ @Lob
+ @Column(name = "access_token")
+ private String accessToken;
+
+ @Lob
+ @Column(name = "refresh_token")
+ private String refreshToken;
+
+ @Column(name = "issued_time")
+ private Timestamp issuedTime;
+
+ @Column(name = "expired_time")
+ private Timestamp expiredTime;
+
+ @Column(name = "deleted")
+ @Type(type = "org.hibernate.type.NumericBooleanType")
+ private Boolean deleted;
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/entity/Users.java b/src/main/java/com/iconplus/smartproc/model/entity/Users.java
index f9bcffa..1e5ab59 100644
--- a/src/main/java/com/iconplus/smartproc/model/entity/Users.java
+++ b/src/main/java/com/iconplus/smartproc/model/entity/Users.java
@@ -20,8 +20,8 @@ public class Users extends BaseEntity {
@Column(name = "username")
private String username;
- @Column(name = "nama")
- private String nama;
+ @Column(name = "fullname")
+ private String fullname;
@Column(name = "email")
private String email;
diff --git a/src/main/java/com/iconplus/smartproc/model/projection/TokenManagementView.java b/src/main/java/com/iconplus/smartproc/model/projection/TokenManagementView.java
new file mode 100644
index 0000000..9e651d8
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/projection/TokenManagementView.java
@@ -0,0 +1,16 @@
+package com.iconplus.smartproc.model.projection;
+
+import java.sql.Clob;
+
+public interface TokenManagementView {
+
+ String getId();
+ void setId(String id);
+
+ String getUserId();
+ void setUserId(String userId);
+
+ Clob getAccessToken();
+ void setAccessToken(Clob accessToken);
+
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/projection/UserRoleView.java b/src/main/java/com/iconplus/smartproc/model/projection/UserRoleView.java
new file mode 100644
index 0000000..284aa4d
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/projection/UserRoleView.java
@@ -0,0 +1,19 @@
+package com.iconplus.smartproc.model.projection;
+
+public interface UserRoleView {
+
+ Long getId();
+ String getUsername();
+ String getPassword();
+ Long getRoleId();
+ String getRole();
+ Boolean getDeleted();
+
+ void setId(Long id);
+ void setUsername(String username);
+ void setPassword(String password);
+ void setRoleId(Long roleId);
+ void setRole(String role);
+ void setDeleted(Boolean deleted);
+
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/request/LoginRequest.java b/src/main/java/com/iconplus/smartproc/model/request/LoginRequest.java
new file mode 100644
index 0000000..c33198e
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/request/LoginRequest.java
@@ -0,0 +1,17 @@
+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
+@NoArgsConstructor
+@AllArgsConstructor
+public class LoginRequest extends BaseRequest {
+
+ private String email;
+ private String password;
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/request/PostAccessTokenRequest.java b/src/main/java/com/iconplus/smartproc/model/request/PostAccessTokenRequest.java
new file mode 100644
index 0000000..e426cf0
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/request/PostAccessTokenRequest.java
@@ -0,0 +1,16 @@
+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
+@NoArgsConstructor
+@AllArgsConstructor
+public class PostAccessTokenRequest extends BaseRequest {
+
+ private String accessToken;
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/model/response/LoginResponse.java b/src/main/java/com/iconplus/smartproc/model/response/LoginResponse.java
new file mode 100644
index 0000000..675e95b
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/response/LoginResponse.java
@@ -0,0 +1,26 @@
+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;
+
+import java.util.Set;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class LoginResponse extends BaseResponse {
+
+ private String accessToken;
+ private String validity;
+ private String refreshToken;
+ private String username;
+ private String email;
+ private Long roleId;
+ private String role;
+ Set accessMenu;
+
+}
diff --git a/src/main/java/com/iconplus/smartproc/model/response/PostAccessTokenResponse.java b/src/main/java/com/iconplus/smartproc/model/response/PostAccessTokenResponse.java
new file mode 100644
index 0000000..a9c4f88
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/response/PostAccessTokenResponse.java
@@ -0,0 +1,16 @@
+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 PostAccessTokenResponse extends BaseResponse {
+
+ private Boolean isValid;
+}
\ No newline at end of file
diff --git a/src/main/java/com/iconplus/smartproc/model/token/TokenContent.java b/src/main/java/com/iconplus/smartproc/model/token/TokenContent.java
new file mode 100644
index 0000000..28907de
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/model/token/TokenContent.java
@@ -0,0 +1,16 @@
+package com.iconplus.smartproc.model.token;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Set;
+
+@Builder
+@Data
+public class TokenContent {
+ private String userId;
+ private String role;
+ private Set accessMenu;
+ private String fullname;
+ private String username;
+}
diff --git a/src/main/java/com/iconplus/smartproc/repository/RolesRepository.java b/src/main/java/com/iconplus/smartproc/repository/RolesRepository.java
index 2abc8e5..9b55ea3 100644
--- a/src/main/java/com/iconplus/smartproc/repository/RolesRepository.java
+++ b/src/main/java/com/iconplus/smartproc/repository/RolesRepository.java
@@ -1,10 +1,26 @@
package com.iconplus.smartproc.repository;
import com.iconplus.smartproc.model.entity.Roles;
+import com.iconplus.smartproc.model.projection.UserRoleView;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
+import java.util.Optional;
+
@Repository
public interface RolesRepository extends JpaRepository {
+
+ @Query(value = "SELECT u.id as id, " +
+ "u.username as username, " +
+ "u.password as password, " +
+ "u.roleId as roleId, " +
+ "r.role as role " +
+ "FROM Users u " +
+ "join Roles r on r.id=u.roleId " +
+ "WHERE u.deleted = false " +
+ "AND r.deleted = false " +
+ "AND u.username = :userName ")
+ Optional getUserRoleByUserId(String userName);
}
diff --git a/src/main/java/com/iconplus/smartproc/repository/TokenManagementRepository.java b/src/main/java/com/iconplus/smartproc/repository/TokenManagementRepository.java
new file mode 100644
index 0000000..9809026
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/repository/TokenManagementRepository.java
@@ -0,0 +1,19 @@
+package com.iconplus.smartproc.repository;
+
+import com.iconplus.smartproc.model.entity.TokenManagement;
+import com.iconplus.smartproc.model.projection.TokenManagementView;
+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 TokenManagementRepository extends JpaRepository {
+
+ @Query(value = "SELECT access_token as accessToken FROM token_management " +
+ "WHERE user_id = :userId " +
+ "AND deleted = false " +
+ "AND expired_time >= SYSDATE", nativeQuery = true)
+ List findAccessTokenByUserIdAndDeletedFalse(String userId);
+}
diff --git a/src/main/java/com/iconplus/smartproc/repository/UsersRepository.java b/src/main/java/com/iconplus/smartproc/repository/UsersRepository.java
index aa25de3..e15d932 100644
--- a/src/main/java/com/iconplus/smartproc/repository/UsersRepository.java
+++ b/src/main/java/com/iconplus/smartproc/repository/UsersRepository.java
@@ -4,7 +4,11 @@ import com.iconplus.smartproc.model.entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
+import java.util.Optional;
+
@Repository
public interface UsersRepository extends JpaRepository {
+
+ Optional findByEmailAndDeletedFalse(String email);
}
diff --git a/src/main/java/com/iconplus/smartproc/service/authentication/LoginService.java b/src/main/java/com/iconplus/smartproc/service/authentication/LoginService.java
new file mode 100644
index 0000000..e824182
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/service/authentication/LoginService.java
@@ -0,0 +1,47 @@
+package com.iconplus.smartproc.service.authentication;
+
+import com.iconplus.smartproc.exception.BusinessException;
+import com.iconplus.smartproc.helper.service.BaseService;
+import com.iconplus.smartproc.model.request.LoginRequest;
+import com.iconplus.smartproc.model.response.LoginResponse;
+import com.iconplus.smartproc.repository.UsersRepository;
+import com.iconplus.smartproc.util.Constants;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class LoginService implements BaseService {
+
+
+ private final UsersRepository usersRepository;
+
+ public LoginService(UsersRepository userRepository) {
+ this.usersRepository = userRepository;
+
+ }
+
+ @Override
+ public LoginResponse execute(LoginRequest input) {
+
+ var user= usersRepository.findByEmailAndDeletedFalse(input.getEmail())
+ .orElseThrow(() -> new BusinessException(HttpStatus.CONFLICT,
+ Constants.ERR_CODE_10003,
+ Constants.ERR_TTL_10003,
+ String.format(Constants.ERR_MSG_10003, input.getEmail())));
+
+ if (!StringUtils.equalsIgnoreCase(input.getPassword(), user.getPassword())) {
+ throw new BusinessException(HttpStatus.CONFLICT,
+ Constants.ERR_CODE_10004,
+ Constants.ERR_TTL_10004,
+ Constants.ERR_MSG_10004);
+ }
+
+
+
+ return LoginResponse.builder()
+ .build();
+ }
+}
diff --git a/src/main/java/com/iconplus/smartproc/service/authentication/PostCheckAccessTokenService.java b/src/main/java/com/iconplus/smartproc/service/authentication/PostCheckAccessTokenService.java
new file mode 100644
index 0000000..a77aa51
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/service/authentication/PostCheckAccessTokenService.java
@@ -0,0 +1,55 @@
+package com.iconplus.smartproc.service.authentication;
+
+import com.iconplus.smartproc.helper.service.BaseService;
+import com.iconplus.smartproc.helper.service.TokenUtils;
+import com.iconplus.smartproc.model.projection.TokenManagementView;
+import com.iconplus.smartproc.model.request.PostAccessTokenRequest;
+import com.iconplus.smartproc.model.response.PostAccessTokenResponse;
+import com.iconplus.smartproc.repository.TokenManagementRepository;
+import com.iconplus.smartproc.util.CommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class PostCheckAccessTokenService implements BaseService {
+
+ private TokenManagementRepository tokenManagementRepository;
+
+ public PostCheckAccessTokenService(TokenManagementRepository tokenManagementRepository) {
+ this.tokenManagementRepository = tokenManagementRepository;
+ }
+
+ @Override
+ public PostAccessTokenResponse execute(PostAccessTokenRequest input) {
+
+ var decodeToken = TokenUtils.decodeToken(input.getAccessToken());
+ String userId = decodeToken.get("user_id");
+
+ List tokenManagementViews = tokenManagementRepository.findAccessTokenByUserIdAndDeletedFalse(userId);
+ if (tokenManagementViews.isEmpty()) {
+ log.error("access token not found in db");
+ return PostAccessTokenResponse.builder()
+ .isValid(false)
+ .build();
+ }
+
+ List userTokenList = tokenManagementViews.stream()
+ .map(c-> CommonUtil.clobToString(c.getAccessToken()))
+ .collect(Collectors.toList());
+
+ boolean isMatch = userTokenList.stream().anyMatch(s -> s.equals(input.getAccessToken()));
+ if (isMatch) {
+ return PostAccessTokenResponse.builder()
+ .isValid(true)
+ .build();
+ }
+
+ return PostAccessTokenResponse.builder()
+ .isValid(false)
+ .build();
+ }
+}
diff --git a/src/main/java/com/iconplus/smartproc/util/CommonUtil.java b/src/main/java/com/iconplus/smartproc/util/CommonUtil.java
new file mode 100644
index 0000000..617d5be
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/util/CommonUtil.java
@@ -0,0 +1,25 @@
+package com.iconplus.smartproc.util;
+
+import com.iconplus.smartproc.exception.TechnicalException;
+
+import java.sql.Clob;
+import java.sql.SQLException;
+
+public class CommonUtil {
+ private CommonUtil() {
+ }
+
+ public static String clobToString(Clob input) {
+ try {
+ if (input != null) {
+ return input.getSubString(1, (int) input.length());
+ } else {
+ return null;
+ }
+ } catch (SQLException exception) {
+ throw new TechnicalException(Constants.ERR_TTL_40041,
+ Constants.ERR_TTL_40041,
+ Constants.ERR_MSG_40041);
+ }
+ }
+}
diff --git a/src/main/java/com/iconplus/smartproc/util/Constants.java b/src/main/java/com/iconplus/smartproc/util/Constants.java
index 5a72c7a..9273684 100644
--- a/src/main/java/com/iconplus/smartproc/util/Constants.java
+++ b/src/main/java/com/iconplus/smartproc/util/Constants.java
@@ -12,4 +12,21 @@ public class Constants {
public static final String ERR_TTL_10002 = "Data tersedia";
public static final String ERR_MSG_10002 = "Jenis Anggaran dengan id : %s sudah tersedia";
+ public static final String ERR_CODE_10003 = "10003";
+ public static final String ERR_TTL_10003 = "Data tidak tersedia";
+ public static final String ERR_MSG_10003 = "User dengan email : %s tidak ditemukan";
+
+ public static final String ERR_CODE_10004 = "10004";
+ public static final String ERR_TTL_10004 = "Gagal Authentikasi User";
+ public static final String ERR_MSG_10004 = "Silahkan Periksa kembali Email dan Password Anda";
+
+ public static final String ERR_CODE_40041 = "40041";
+ public static final String ERR_TTL_40041 = "Terjadi Gangguan";
+ public static final String ERR_MSG_40041 = "Masalah Koneksi System";
+
+ public static final String ERR_CODE_40051 = "40051";
+ public static final String ERR_CODE_80007 = "80007";
+ public static final String TITLE_INVALID_NEXT_STEP = "Proses tidak dapat dilanjutkan";
+
+
}
diff --git a/src/main/java/com/iconplus/smartproc/util/RSAUtil.java b/src/main/java/com/iconplus/smartproc/util/RSAUtil.java
new file mode 100644
index 0000000..7d182e2
--- /dev/null
+++ b/src/main/java/com/iconplus/smartproc/util/RSAUtil.java
@@ -0,0 +1,109 @@
+package com.iconplus.smartproc.util;
+
+import com.iconplus.smartproc.exception.TechnicalException;
+import lombok.extern.log4j.Log4j2;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+@Log4j2
+public class RSAUtil {
+
+ private RSAUtil(){
+
+ }
+
+ public static PrivateKey getPrivateKey(String base64PrivateKey){
+ PrivateKey privateKey = null;
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ privateKey = keyFactory.generatePrivate(keySpec);
+ } catch (InvalidKeySpecException e) {
+ log.error("InvalidKeySpecException : "+e.getMessage());
+ throw new TechnicalException("80000", "InvalidKeySpecException : "+e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ log.error("NoSuchAlgorithmException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
+ }
+ return privateKey;
+ }
+
+ public static PublicKey getPublicKey(String base64PublicKey){
+ PublicKey publicKey = null;
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ publicKey = keyFactory.generatePublic(keySpec);
+ } catch (InvalidKeySpecException e) {
+ log.error("InvalidKeySpecException : "+e.getMessage());
+ throw new TechnicalException("80000", "InvalidKeySpecException : "+e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ log.error("NoSuchAlgorithmException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
+ }
+ return publicKey;
+ }
+
+ private static String decryptChipper(byte[] data, PrivateKey privateKey) {
+ try {
+ Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ return new String(cipher.doFinal(data));
+ } catch (NoSuchAlgorithmException e) {
+ log.error("NoSuchAlgorithmException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
+ } catch (NoSuchPaddingException e) {
+ log.error("NoSuchPaddingException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchPaddingException : "+e.getMessage());
+ } catch (InvalidKeyException e) {
+ log.error("InvalidKeyException : "+e.getMessage());
+ throw new TechnicalException("80000", "InvalidKeyException : "+e.getMessage());
+ } catch (IllegalBlockSizeException e) {
+ log.error("IllegalBlockSizeException : "+e.getMessage());
+ throw new TechnicalException("80000", "IllegalBlockSizeException : "+e.getMessage());
+ } catch (BadPaddingException e) {
+ log.error("BadPaddingException : "+e.getMessage());
+ throw new TechnicalException("80000", "BadPaddingException : "+e.getMessage());
+ }
+ }
+
+ private static byte[] encryptChipper(byte[] data, PublicKey publicKey) {
+ try {
+ Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ return cipher.doFinal(data);
+ } catch (NoSuchAlgorithmException e) {
+ log.error("NoSuchAlgorithmException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchAlgorithmException : "+e.getMessage());
+ } catch (NoSuchPaddingException e) {
+ log.error("NoSuchPaddingException : "+e.getMessage());
+ throw new TechnicalException("80000", "NoSuchPaddingException : "+e.getMessage());
+ } catch (InvalidKeyException e) {
+ log.error("InvalidKeyException : "+e.getMessage());
+ throw new TechnicalException("80000", "InvalidKeyException : "+e.getMessage());
+ } catch (IllegalBlockSizeException e) {
+ log.error("IllegalBlockSizeException : "+e.getMessage());
+ throw new TechnicalException("80000", "IllegalBlockSizeException : "+e.getMessage());
+ } catch (BadPaddingException e) {
+ log.error("BadPaddingException : "+e.getMessage());
+ throw new TechnicalException("80000", "BadPaddingException : "+e.getMessage());
+ }
+ }
+
+ public static String decrypt(String data, String base64PrivateKey) {
+ return decryptChipper(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey));
+ }
+
+ public static String encrypt(String data, String base64PublicKey) {
+ return Base64.getEncoder().encodeToString(encryptChipper(data.getBytes(), getPublicKey(base64PublicKey)));
+ }
+
+}
diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml
new file mode 100644
index 0000000..60a202b
--- /dev/null
+++ b/src/main/resources/application-local.yml
@@ -0,0 +1,22 @@
+#Configuration for database
+jwt:
+ public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3MRA7zxvaWKrtmPl2hRJLFiyryvj0ZUlmWw9OZIgqwJUDBTsg5yFX4hCQrANV1yy5ibTqAn2APdNCdhGgp8R2YLWrUR2vVGbmnKXXzEDsFpT6cgo+/a+lWaUq8aYEhzVg8Xjmy9oG1s521LklEz/jKD2xNE4OgY2Y1SgfUH+bexs84ZEyUhcSpCrcZenjCns7Ubp9zsWPrXa/j6kr7ZuFWH7nXN/i+oYF0HFhc+hDaVr2R9Q7s56wAQNE8XfI2Q+h4iRI1hWa5Vva9ha1DnCN9McJDLBHoGy1coIUEoQKkDhCNQmdHlubIJYDoFIyfDTrSQIXw2gzrrC9sOgYU64wIDAQAB
+ private-key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHcxEDvPG9pYqu2Y+XaFEksWLKvK+PRlSWZbD05kiCrAlQMFOyDnIVfiEJCsA1XXLLmJtOoCfYA900J2EaCnxHZgtatRHa9UZuacpdfMQOwWlPpyCj79r6VZpSrxpgSHNWDxeObL2gbWznbUuSUTP+MoPbE0Tg6BjZjVKB9Qf5t7GzzhkTJSFxKkKtxl6eMKeztRun3OxY+tdr+PqSvtm4VYfudc3+L6hgXQcWFz6ENpWvZH1DuznrABA0Txd8jZD6HiJEjWFZrlW9r2FrUOcI30xwkMsEegbLVyghQShAqQOEI1CZ0eW5sglgOgUjJ8NOtJAhfDaDOusL2w6BhTrjAgMBAAECggEAL8SPPqXx/8m1/Up96XVCeddCIewu39GoUJzqVL0SgLlTQbFRWkO7bwpWPyQkBKPs6nYSPDJ/WG0UfXkw+FuqiC8YaREUxawYwjj0Do/jJOWNo1YTqy+28l2uKD9nwceYV/QlYCcLA3Exs/upLdHk8eyHR+DFjlgIG5KNQDK/Rj8cLdQGJjAZjHUGzaRq/HhDi+0LVkOoUvzbzle8RSiiZnNrxCt0UV1CambQzvyxXzqLgtGe4s+qItwk/zzkvXDRnRju3+/AyaFaToA2Wnp9gdV2rT4cRGHhj0Dqh0vwrBH4RiPtEfLQjIa9DhTPHfpr6ACGe6GF96fJ889WIEl4gQKBgQDrGgYKGwIhY9j2V7tu6eHmLxYFGzxSPOtfBZPzSLUyQXrcd6wFlb+Fsae2bgBFZJzilIv4lG0wNaGSFjAjteyXMoqVCTIUKJCjzWs+g3qjuA5fu9IAeWEEaXuKSVvkV5tJrnwhmqYdH1jQx5xhpO434W2a4wuEgOnU6SzNjvS/TwKBgQDZLb3Q9KRwlMcyt/rgjeTOf2SD1jvlKD2t+YRuaxlzBs7j99hCEP3GLaTz6/rIptfkutwk10FM/piO5PCyoPXNc2A1Z73ukmsirMRy2G06PfqKBQrV/B9vtIqPW1Agz7KUpXARrHL8Bb6T2ljKl2HU+kC4Pgx2GZQgYnbEvNBGLQKBgQCNf3grFN5PYlzuxxbURofjlmtWX3IKvQechSrqvdPwj2B22L/8DIjc2nPqZIJdQZT6+hTUY+DjpyO7XQdUNuZSieTGlmZBo7iKHdRyJ4fkiZ59F/notyUhFqt4K3bXE7MuwYmMYBuiY399COaiDjYiA9eH5SbFdSFHN5/ziBreGQKBgGZHNG2DyS1745PvMScvq+HT/PJZojt5iBK2v7eAmKujOSwDPMVgWyNJu7VkHOcCLAp8NdDjzs0D2bTx/KkjRJ9NBrIf+UKxkeLymlG7uzUCm0sEtOWxptxkmhyJVGMfbWqzvuOT41LtIaNf4REH2fsDIBekoRm9UhUuSeC9SxjBAoGAP6pdT7HlMsr++XJFqs9+dj7tRsX+a6Coi3T8BFaf2Nl9YxMFFaSBbNOO4QfZWyCUcfbkLrcdEka5VTVt/HwckDKzckxWqH3hMn2+kAKJnHhAvB1M38KAyvdpA54vNgVyID+vL5VbqpHk8wsUbVWZc8F/ERELfuHwzcD0rt6Opnc=
+ expired-time :
+ service-account:
+ access-token: 480
+ refresh-token: 720
+
+spring:
+ datasource:
+ driver-class-name: org.postgresql.Driver
+ url: jdbc:postgresql://localhost:5432/smartproc
+ username: postgres
+ password: postgre
+ jackson:
+ default-property-inclusion: NON_NULL
+ jpa:
+ hibernate:
+ ddl-auto: update
+ database-platform: org.hibernate.dialect.PostgreSQLDialect
+ show-sql: true
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index dd5e35d..0000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-spring.datasource.url=jdbc:postgresql://localhost:5432/smartproc
-spring.datasource.username=postgres
-spring.datasource.password=postgre
-spring.jpa.show-sql=true
-
-## Hibernate Properties
-# The SQL dialect makes Hibernate generate better SQL for the chosen database
-spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
-
-# Hibernate ddl auto (create, create-drop, validate, update)
-spring.jpa.hibernate.ddl-auto = update
-server.port=9090
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..b14266e
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+spring:
+ application:
+ name: "smartproc-service"
+ profiles:
+ active: local
+server:
+ port: 9090
\ No newline at end of file
diff --git a/src/main/resources/bootstrap.properties b/src/main/resources/bootstrap.properties
new file mode 100644
index 0000000..68d2e92
--- /dev/null
+++ b/src/main/resources/bootstrap.properties
@@ -0,0 +1,5 @@
+spring.application.name=smartproc
+spring.profiles.active=@spring.profiles.active@
+management.endpoints.web.exposure.include=*
+management.endpoint.health.show-details=ALWAYS
+management.metrics.tags.application=${spring.application.name}
\ No newline at end of file