diff --git a/batch-quartz/pom.xml b/batch-quartz/pom.xml index ff1d3aa..176879a 100644 --- a/batch-quartz/pom.xml +++ b/batch-quartz/pom.xml @@ -61,6 +61,10 @@ mybatis-spring-boot-starter 2.2.0 + + org.springframework.boot + spring-boot-starter-thymeleaf + io.jsonwebtoken jjwt-api diff --git a/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java b/batch-quartz/src/main/java/com/spring/domain/user/api/GenerateTokenApi.java similarity index 97% rename from batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java rename to batch-quartz/src/main/java/com/spring/domain/user/api/GenerateTokenApi.java index 5bafd12..f7dbed8 100644 --- a/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java +++ b/batch-quartz/src/main/java/com/spring/domain/user/api/GenerateTokenApi.java @@ -18,7 +18,7 @@ import lombok.RequiredArgsConstructor; @RestController @RequiredArgsConstructor @RequestMapping("/api") -public class AuthController { +public class GenerateTokenApi { private final AuthService authService; private final JwtTokenService jwtTokenService; diff --git a/batch-quartz/src/main/java/com/spring/domain/user/view/UserView.java b/batch-quartz/src/main/java/com/spring/domain/user/view/UserView.java new file mode 100644 index 0000000..a341bfe --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/domain/user/view/UserView.java @@ -0,0 +1,16 @@ +package com.spring.domain.user.view; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/user") +public class UserView { + + @GetMapping("/sign-in") + public String signin() { + return "/views/user/signIn"; + } + +} diff --git a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java index 74a7fef..fd7549c 100644 --- a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java +++ b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java @@ -77,7 +77,7 @@ public class QuartzConfig { factory.setDataSource(dataSource); factory.setTransactionManager(transactionManager); factory.setJobFactory(jobFactory); - factory.setAutoStartup(true); + factory.setAutoStartup(false); factory.setWaitForJobsToCompleteOnShutdown(true); return factory; } diff --git a/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java b/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java index 48867b2..6450b8f 100644 --- a/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java +++ b/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java @@ -2,8 +2,11 @@ package com.spring.infra.security.config; import java.util.List; +import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; 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; @@ -18,10 +21,15 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.spring.infra.security.filter.AuthenticationProcessingFilter; import com.spring.infra.security.filter.JwtAuthenticationFilter; -import com.spring.infra.security.handler.JwtAccessDeniedHandler; -import com.spring.infra.security.handler.JwtAuthenticationEntryPoint; +import com.spring.infra.security.handler.SecurityAccessDeniedHandler; +import com.spring.infra.security.handler.SecurityAuthenticationEntryPoint; +import com.spring.infra.security.handler.SigninFailureHandler; +import com.spring.infra.security.handler.SigninSuccessHandler; import com.spring.infra.security.jwt.JwtTokenService; +import com.spring.infra.security.provider.UserAuthenticationProvider; /** * 애플리케이션의 보안 설정을 담당하는 구성 클래스입니다. @@ -36,7 +44,7 @@ import com.spring.infra.security.jwt.JwtTokenService; @EnableMethodSecurity public class SecurityConfig { - private static final String[] PERMITTED_URI = {"/favicon.ico", "/api/auth/**", "/signIn", "/h2-console/**"}; + private static final String[] PERMITTED_URI = {"/favicon.ico", "/api/auth/**", "/user/sign-in", "/h2-console/**"}; /** * Spring Security의 필터 체인을 구성합니다. @@ -51,9 +59,10 @@ public class SecurityConfig { SecurityFilterChain securityFilterChain( HttpSecurity http, JwtTokenService tokenService, - JwtAuthenticationEntryPoint authenticationEntryPoint, - JwtAccessDeniedHandler accessDeniedHandler) throws Exception - { + SecurityAuthenticationEntryPoint authenticationEntryPoint, + SecurityAccessDeniedHandler accessDeniedHandler, + AuthenticationProcessingFilter authenticationProcessingFilter + ) throws Exception { http .headers(headers -> headers.frameOptions(FrameOptionsConfig::sameOrigin)) .csrf(CsrfConfigurer::disable) @@ -64,12 +73,19 @@ public class SecurityConfig { .anyRequest().authenticated() ) .logout(logout -> logout - .logoutSuccessUrl("/signIn") + .logoutSuccessUrl("/user/sign-in") .invalidateHttpSession(true)) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) - .addFilterBefore(new JwtAuthenticationFilter(tokenService, List.of(PERMITTED_URI)), UsernamePasswordAuthenticationFilter.class) + .addFilterBefore( + authenticationProcessingFilter, + UsernamePasswordAuthenticationFilter.class + ) + .addFilterAfter( + new JwtAuthenticationFilter(tokenService, List.of(PERMITTED_URI)), + AuthenticationProcessingFilter.class + ) .exceptionHandling(ex -> ex .authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler) @@ -84,7 +100,8 @@ public class SecurityConfig { */ @Bean WebSecurityCustomizer ignoringCustomizer() { - return web -> web.ignoring().antMatchers("/h2-console/**"); + return web -> web.ignoring() + .requestMatchers(PathRequest.toStaticResources().atCommonLocations()); } /** @@ -97,4 +114,23 @@ public class SecurityConfig { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } + @Bean + AuthenticationManager authenticationManager(UserAuthenticationProvider provider) { + return new ProviderManager(provider); + } + + @Bean + AuthenticationProcessingFilter authenticationProcessingFilter( + ObjectMapper objectMapper, + AuthenticationManager authenticationManager, + SigninSuccessHandler signinSuccessHandler, + SigninFailureHandler signinFailureHandler + ) { + var filter = new AuthenticationProcessingFilter(objectMapper); + filter.setAuthenticationManager(authenticationManager); + filter.setAuthenticationSuccessHandler(signinSuccessHandler); + filter.setAuthenticationFailureHandler(signinFailureHandler); + return filter; + } + } diff --git a/batch-quartz/src/main/java/com/spring/infra/security/dto/SignInRequest.java b/batch-quartz/src/main/java/com/spring/infra/security/dto/SignInRequest.java new file mode 100644 index 0000000..9f3e572 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/infra/security/dto/SignInRequest.java @@ -0,0 +1,14 @@ +package com.spring.infra.security.dto; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class SignInRequest { + + private String username; + private String password; + +} diff --git a/batch-quartz/src/main/java/com/spring/infra/security/filter/AuthenticationProcessingFilter.java b/batch-quartz/src/main/java/com/spring/infra/security/filter/AuthenticationProcessingFilter.java new file mode 100644 index 0000000..afa3f4a --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/infra/security/filter/AuthenticationProcessingFilter.java @@ -0,0 +1,60 @@ +package com.spring.infra.security.filter; + +import java.io.IOException; +import java.util.Objects; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.spring.infra.security.dto.SignInRequest; + +public class AuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter { + + private static final String DEFAULT_LOGIN_REQUEST_URL = "/sign-in"; + private static final String HTTP_METHOD = "POST"; + private static final AntPathRequestMatcher DEFAULT_LOGIN_PATH_REQUEST_MATCHER = + new AntPathRequestMatcher(DEFAULT_LOGIN_REQUEST_URL, HTTP_METHOD); + + private final ObjectMapper objectMapper; + + public AuthenticationProcessingFilter(ObjectMapper objectMapper) { + super(DEFAULT_LOGIN_PATH_REQUEST_MATCHER); + this.objectMapper = objectMapper; + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { + if (!isValidRequestType(request)) { + throw new IllegalStateException("request is not supported. check request method and content-type"); + } + var signInRequest = objectMapper.readValue(request.getReader(), SignInRequest.class); + if (!isValidRequest(signInRequest)) { + throw new IllegalArgumentException("Ussername & Password are not empty!!"); + } + var token = new UsernamePasswordAuthenticationToken(signInRequest.getUsername(), signInRequest.getPassword()); + return this.getAuthenticationManager().authenticate(token); + } + + private boolean isValidRequestType(HttpServletRequest request) { + return Objects.equals(request.getMethod(), HttpMethod.POST.name()) && + Objects.equals(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); + } + + private boolean isValidRequest(SignInRequest signInRequest) { + return StringUtils.hasText(signInRequest.getUsername()) || + StringUtils.hasText(signInRequest.getPassword()); + } + +} diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAccessDeniedHandler.java similarity index 95% rename from batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java rename to batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAccessDeniedHandler.java index 199e21b..c57dae4 100644 --- a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java +++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAccessDeniedHandler.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; * @version 1.0 */ @Component -public class JwtAccessDeniedHandler implements AccessDeniedHandler { +public class SecurityAccessDeniedHandler implements AccessDeniedHandler { /** * 접근 거부 상황을 처리합니다. diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAuthenticationEntryPoint.java similarity index 94% rename from batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java rename to batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAuthenticationEntryPoint.java index aaa70d0..5e4185e 100644 --- a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java +++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/SecurityAuthenticationEntryPoint.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; * @version 1.0 */ @Component -public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { +public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint { /** * 인증되지 않은 접근을 처리합니다. diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninFailureHandler.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninFailureHandler.java new file mode 100644 index 0000000..f724b35 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninFailureHandler.java @@ -0,0 +1,25 @@ +package com.spring.infra.security.handler; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +@Component +public class SigninFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException exception + ) throws IOException, ServletException { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //401 인증 실패 + } + +} diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninSuccessHandler.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninSuccessHandler.java new file mode 100644 index 0000000..c88cb67 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/SigninSuccessHandler.java @@ -0,0 +1,48 @@ +package com.spring.infra.security.handler; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.stereotype.Component; + +import com.spring.infra.security.jwt.JwtTokenService; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class SigninSuccessHandler implements AuthenticationSuccessHandler { + + private final JwtTokenService jwtTokenService; + private RequestCache requestCache = new HttpSessionRequestCache(); + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + @Override + public void onAuthenticationSuccess( + HttpServletRequest request, + HttpServletResponse response, + Authentication authentication + ) throws IOException, ServletException { + jwtTokenService.generateAccessToken(response, authentication); + jwtTokenService.generateRefreshToken(response, authentication); + + SavedRequest savedRequest = requestCache.getRequest(request, response); + if (savedRequest != null) { // 접근 권한 없는 경로 접근해서 스프링 시큐리티가 인터셉트해서 로그인폼으로 이동 후 로그인 성공한 경우 + redirectStrategy.sendRedirect(request, response, savedRequest.getRedirectUrl()); + } else { // 로그인 버튼 눌러서 로그인한 경우 기존에 있던 페이지로 리다이렉트 + String prevPage = String.valueOf(request.getSession().getAttribute("prevPage")); + redirectStrategy.sendRedirect(request, response, prevPage); + } + } + +} diff --git a/batch-quartz/src/main/java/com/spring/infra/security/provider/UserAuthenticationProvider.java b/batch-quartz/src/main/java/com/spring/infra/security/provider/UserAuthenticationProvider.java new file mode 100644 index 0000000..20e6f42 --- /dev/null +++ b/batch-quartz/src/main/java/com/spring/infra/security/provider/UserAuthenticationProvider.java @@ -0,0 +1,43 @@ +package com.spring.infra.security.provider; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +import com.spring.infra.security.service.UserPrincipalService; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class UserAuthenticationProvider implements AuthenticationProvider { + + private final PasswordEncoder passwordEncoder; + private final UserPrincipalService userPrincipalService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String loginId = authentication.getName(); + String password = String.valueOf(authentication.getCredentials()); + UserDetails user = userPrincipalService.loadUserByUsername(loginId); + if (isNotMatches(password, user.getPassword())) { + throw new BadCredentialsException(loginId); + } + return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()); + } + + @Override + public boolean supports(Class authentication) { + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } + + private boolean isNotMatches(String password, String encodePassword) { + return !passwordEncoder.matches(password, encodePassword); + } + +} diff --git a/batch-quartz/src/main/resources/application.yml b/batch-quartz/src/main/resources/application.yml index 702a3fe..53e57ac 100644 --- a/batch-quartz/src/main/resources/application.yml +++ b/batch-quartz/src/main/resources/application.yml @@ -73,6 +73,14 @@ spring: threadCount: 10 threadPriority: 5 + thymeleaf: + cache: false + check-template-location: false + enabled: true + prefix: classpath:/templates + suffix: .html + view-names: /views/* + h2: console: # H2 DB를 웹에서 관리할 수 있는 기능 enabled: true # H2 Console 사용 여부 diff --git a/batch-quartz/src/main/resources/quartz.yml b/batch-quartz/src/main/resources/quartz.yml deleted file mode 100644 index 7c88af7..0000000 --- a/batch-quartz/src/main/resources/quartz.yml +++ /dev/null @@ -1,40 +0,0 @@ -spring: - quartz: - scheduler: - instanceName: batch-quartz - instance-id: SYS_PROP - name: BatchQuartzScheduler - -org: - quartz: - jobStore: - tablePrefix: QRTZ_ - isClustered: true - misfireThreshold: 2000 - clusterCheckinInterval: 1000 - class: org.quartz.impl.jdbcjobstore.JobStoreTX - driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #org.quartz.impl.jdbcjobstore.oracle.OracleDelegate - acquireTriggersWithinLock: true - scheduler: - instance-id: - instanceName: - rmi: - export: false - proxy: false - batchTriggerAcquisitionMaxCount: 20 - idleWaitTime: 1000 - skipUpdateCheck: true - threadPool: - class: org.quartz.simpl.SimpleThreadPool - threadCount: 10 - threadPriority: 5 - threadsInheritContextClassLoaderOfInitializingThread: true - threadNamePrefix: BatchQuartz -# dataSource: -# nxcus: -# driver: org.h2.Driver #oracle.jdbc.driver.OracleDriver -# URL: 'jdbc:h2:mem:test' #jdbc:oracle:thin:@polarbear:1521:dev -# user: mindol1004 -# password: 1111 -# maxConnections: 5 -# validationQuery: select 0 from dual \ No newline at end of file diff --git a/batch-quartz/src/main/resources/batch-schema.sql b/batch-quartz/src/main/resources/sql-schema/batch-schema.sql similarity index 100% rename from batch-quartz/src/main/resources/batch-schema.sql rename to batch-quartz/src/main/resources/sql-schema/batch-schema.sql diff --git a/batch-quartz/src/main/resources/quartz-schema.sql b/batch-quartz/src/main/resources/sql-schema/quartz-schema.sql similarity index 100% rename from batch-quartz/src/main/resources/quartz-schema.sql rename to batch-quartz/src/main/resources/sql-schema/quartz-schema.sql diff --git a/batch-quartz/src/main/resources/static/css/style.css b/batch-quartz/src/main/resources/static/css/style.css new file mode 100644 index 0000000..49eb822 --- /dev/null +++ b/batch-quartz/src/main/resources/static/css/style.css @@ -0,0 +1,87 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background: linear-gradient(to right, #f0f0f5, #e9ecef); + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; +} + +.container { + background-color: white; + padding: 30px; + border-radius: 15px; + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); + width: 350px; + text-align: center; +} + +.icon { + margin-bottom: 20px; +} + +.icon img { + width: 50px; /* 아이콘 크기 조정 */ +} + +h1 { + color: #333; + margin-bottom: 20px; +} + +.input-group { + margin-bottom: 15px; +} + +.input-icon { + display: flex; + align-items: center; + border: 1px solid #ccc; + border-radius: 5px; + padding: 10px; +} + +.input-icon img { + margin-right: 10px; /* 아이콘과 인풋 간격 조정 */ + width: 20px; /* 아이콘 크기 조정 */ + height: 20px; /* 아이콘 크기 조정 */ +} + +input { + width: 100%; + border: none; + outline: none; + font-size: 16px; +} + +input::placeholder { + color: #aaa; /* 플레이스홀더 색상 */ +} + +.remember-me { + display: flex; + align-items: center; + justify-content: flex-start; + margin-bottom: 15px; +} + +.remember-me label { + margin-left: 5px; +} + +button { + width: 100%; + padding: 12px; + background-color: #007aff; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 16px; + transition: background-color 0.3s; +} + +button:hover { + background-color: #005bb5; +} \ No newline at end of file diff --git a/batch-quartz/src/main/resources/static/favicon.ico b/batch-quartz/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..039dc7a Binary files /dev/null and b/batch-quartz/src/main/resources/static/favicon.ico differ diff --git a/batch-quartz/src/main/resources/static/images/user-id.png b/batch-quartz/src/main/resources/static/images/user-id.png new file mode 100644 index 0000000..b7f95f4 Binary files /dev/null and b/batch-quartz/src/main/resources/static/images/user-id.png differ diff --git a/batch-quartz/src/main/resources/static/images/user-lock.png b/batch-quartz/src/main/resources/static/images/user-lock.png new file mode 100644 index 0000000..f6e8d6b Binary files /dev/null and b/batch-quartz/src/main/resources/static/images/user-lock.png differ diff --git a/batch-quartz/src/main/resources/static/images/user.png b/batch-quartz/src/main/resources/static/images/user.png new file mode 100644 index 0000000..eab9166 Binary files /dev/null and b/batch-quartz/src/main/resources/static/images/user.png differ diff --git a/batch-quartz/src/main/resources/static/js/common/axiosInstance.js b/batch-quartz/src/main/resources/static/js/common/axiosInstance.js new file mode 100644 index 0000000..e2352b8 --- /dev/null +++ b/batch-quartz/src/main/resources/static/js/common/axiosInstance.js @@ -0,0 +1,43 @@ +// Axios 인스턴스 생성 +const axiosInstance = axios.create({ + baseURL: 'http://localhost:8081', // 기본 URL 설정 + timeout: 10000, // 요청 타임아웃 설정 (10초) + headers: { + 'Content-Type': 'application/json', + // 필요한 경우 추가 헤더 설정 + } +}); + +// 요청 인터셉터 (필요한 경우) +axiosInstance.interceptors.request.use( + config => { + // 요청 전에 수행할 작업 (예: 토큰 추가) + const token = localStorage.getItem('token'); // 예시: 로컬 스토리지에서 토큰 가져오기 + if (token) { + config.headers['Authorization'] = `Bearer ${token}`; + } + return config; + }, + error => { + return Promise.reject(error); + } +); + +// 응답 인터셉터 (필요한 경우) +axiosInstance.interceptors.response.use( + response => { + return response; + }, + error => { + console.log(error.response); + // 오류 처리 (예: 401 Unauthorized 처리) + if (error.response && error.response.status === 401) { + // 로그아웃 처리 또는 리다이렉트 + console.log("111111111111111"); + console.log(error.response); + } + return Promise.reject(error); + } +); + +export default axiosInstance; \ No newline at end of file diff --git a/batch-quartz/src/main/resources/static/js/lib/axios/axios.min.js b/batch-quartz/src/main/resources/static/js/lib/axios/axios.min.js new file mode 100644 index 0000000..c868e94 --- /dev/null +++ b/batch-quartz/src/main/resources/static/js/lib/axios/axios.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).axios=t()}(this,(function(){"use strict";function e(e){var r,n;function o(r,n){try{var a=e[r](n),s=a.value,u=s instanceof t;Promise.resolve(u?s.v:s).then((function(t){if(u){var n="return"===r?"return":"next";if(!s.k||t.done)return o(n,t);t=e[n](t).value}i(a.done?"return":"normal",t)}),(function(e){o("throw",e)}))}catch(e){i("throw",e)}}function i(e,t){switch(e){case"return":r.resolve({value:t,done:!0});break;case"throw":r.reject(t);break;default:r.resolve({value:t,done:!1})}(r=r.next)?o(r.key,r.arg):n=null}this._invoke=function(e,t){return new Promise((function(i,a){var s={key:e,arg:t,resolve:i,reject:a,next:null};n?n=n.next=s:(r=n=s,o(e,t))}))},"function"!=typeof e.return&&(this.return=void 0)}function t(e,t){this.v=e,this.k=t}function r(e){var r={},n=!1;function o(r,o){return n=!0,o=new Promise((function(t){t(e[r](o))})),{done:!1,value:new t(o,1)}}return r["undefined"!=typeof Symbol&&Symbol.iterator||"@@iterator"]=function(){return this},r.next=function(e){return n?(n=!1,e):o("next",e)},"function"==typeof e.throw&&(r.throw=function(e){if(n)throw n=!1,e;return o("throw",e)}),"function"==typeof e.return&&(r.return=function(e){return n?(n=!1,e):o("return",e)}),r}function n(e){var t,r,n,i=2;for("undefined"!=typeof Symbol&&(r=Symbol.asyncIterator,n=Symbol.iterator);i--;){if(r&&null!=(t=e[r]))return t.call(e);if(n&&null!=(t=e[n]))return new o(t.call(e));r="@@asyncIterator",n="@@iterator"}throw new TypeError("Object is not async iterable")}function o(e){function t(e){if(Object(e)!==e)return Promise.reject(new TypeError(e+" is not an object."));var t=e.done;return Promise.resolve(e.value).then((function(e){return{value:e,done:t}}))}return o=function(e){this.s=e,this.n=e.next},o.prototype={s:null,n:null,next:function(){return t(this.n.apply(this.s,arguments))},return:function(e){var r=this.s.return;return void 0===r?Promise.resolve({value:e,done:!0}):t(r.apply(this.s,arguments))},throw:function(e){var r=this.s.return;return void 0===r?Promise.reject(e):t(r.apply(this.s,arguments))}},new o(e)}function i(e){return new t(e,0)}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=n.call(a,"catchLoc"),c=n.call(a,"finallyLoc");if(u&&c){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),A(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;A(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:L(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),y}},t}function c(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}function f(e){return f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f(e)}function l(e,t,r,n,o,i,a){try{var s=e[i](a),u=s.value}catch(e){return void r(e)}s.done?t(u):Promise.resolve(u).then(n,o)}function h(e){return function(){var t=this,r=arguments;return new Promise((function(n,o){var i=e.apply(t,r);function a(e){l(i,n,o,a,s,"next",e)}function s(e){l(i,n,o,a,s,"throw",e)}a(void 0)}))}}function p(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function d(e,t){for(var r=0;re.length)&&(t=e.length);for(var r=0,n=new Array(t);r2&&void 0!==arguments[2]?arguments[2]:{},i=o.allOwnKeys,a=void 0!==i&&i;if(null!=e)if("object"!==f(e)&&(e=[e]),L(e))for(r=0,n=e.length;r0;)if(t===(r=n[o]).toLowerCase())return r;return null}var Y="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,Q=function(e){return!N(e)&&e!==Y};var Z,ee=(Z="undefined"!=typeof Uint8Array&&j(Uint8Array),function(e){return Z&&e instanceof Z}),te=A("HTMLFormElement"),re=function(e){var t=Object.prototype.hasOwnProperty;return function(e,r){return t.call(e,r)}}(),ne=A("RegExp"),oe=function(e,t){var r=Object.getOwnPropertyDescriptors(e),n={};X(r,(function(r,o){var i;!1!==(i=t(r,o,e))&&(n[o]=i||r)})),Object.defineProperties(e,n)},ie="abcdefghijklmnopqrstuvwxyz",ae="0123456789",se={DIGIT:ae,ALPHA:ie,ALPHA_DIGIT:ie+ie.toUpperCase()+ae};var ue,ce,fe,le,he=A("AsyncFunction"),pe=(ue="function"==typeof setImmediate,ce=F(Y.postMessage),ue?setImmediate:ce?(fe="axios@".concat(Math.random()),le=[],Y.addEventListener("message",(function(e){var t=e.source,r=e.data;t===Y&&r===fe&&le.length&&le.shift()()}),!1),function(e){le.push(e),Y.postMessage(fe,"*")}):function(e){return setTimeout(e)}),de="undefined"!=typeof queueMicrotask?queueMicrotask.bind(Y):"undefined"!=typeof process&&process.nextTick||pe,ve={isArray:L,isArrayBuffer:_,isBuffer:function(e){return null!==e&&!N(e)&&null!==e.constructor&&!N(e.constructor)&&F(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:function(e){var t;return e&&("function"==typeof FormData&&e instanceof FormData||F(e.append)&&("formdata"===(t=k(e))||"object"===t&&F(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&_(e.buffer)},isString:C,isNumber:U,isBoolean:function(e){return!0===e||!1===e},isObject:B,isPlainObject:D,isReadableStream:W,isRequest:G,isResponse:K,isHeaders:V,isUndefined:N,isDate:I,isFile:q,isBlob:M,isRegExp:ne,isFunction:F,isStream:function(e){return B(e)&&F(e.pipe)},isURLSearchParams:H,isTypedArray:ee,isFileList:z,forEach:X,merge:function e(){for(var t=Q(this)&&this||{},r=t.caseless,n={},o=function(t,o){var i=r&&$(n,o)||o;D(n[i])&&D(t)?n[i]=e(n[i],t):D(t)?n[i]=e({},t):L(t)?n[i]=t.slice():n[i]=t},i=0,a=arguments.length;i3&&void 0!==arguments[3]?arguments[3]:{},o=n.allOwnKeys;return X(t,(function(t,n){r&&F(t)?e[n]=x(t,r):e[n]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,r,n){e.prototype=Object.create(t.prototype,n),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),r&&Object.assign(e.prototype,r)},toFlatObject:function(e,t,r,n){var o,i,a,s={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],n&&!n(a,e,t)||s[a]||(t[a]=e[a],s[a]=!0);e=!1!==r&&j(e)}while(e&&(!r||r(e,t))&&e!==Object.prototype);return t},kindOf:k,kindOfTest:A,endsWith:function(e,t,r){e=String(e),(void 0===r||r>e.length)&&(r=e.length),r-=t.length;var n=e.indexOf(t,r);return-1!==n&&n===r},toArray:function(e){if(!e)return null;if(L(e))return e;var t=e.length;if(!U(t))return null;for(var r=new Array(t);t-- >0;)r[t]=e[t];return r},forEachEntry:function(e,t){for(var r,n=(e&&e[Symbol.iterator]).call(e);(r=n.next())&&!r.done;){var o=r.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var r,n=[];null!==(r=e.exec(t));)n.push(r);return n},isHTMLForm:te,hasOwnProperty:re,hasOwnProp:re,reduceDescriptors:oe,freezeMethods:function(e){oe(e,(function(t,r){if(F(e)&&-1!==["arguments","caller","callee"].indexOf(r))return!1;var n=e[r];F(n)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=function(){throw Error("Can not rewrite read-only method '"+r+"'")}))}))},toObjectSet:function(e,t){var r={},n=function(e){e.forEach((function(e){r[e]=!0}))};return L(e)?n(e):n(String(e).split(t)),r},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))},noop:function(){},toFiniteNumber:function(e,t){return null!=e&&Number.isFinite(e=+e)?e:t},findKey:$,global:Y,isContextDefined:Q,ALPHABET:se,generateString:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:se.ALPHA_DIGIT,r="",n=t.length;e--;)r+=t[Math.random()*n|0];return r},isSpecCompliantForm:function(e){return!!(e&&F(e.append)&&"FormData"===e[Symbol.toStringTag]&&e[Symbol.iterator])},toJSONObject:function(e){var t=new Array(10);return function e(r,n){if(B(r)){if(t.indexOf(r)>=0)return;if(!("toJSON"in r)){t[n]=r;var o=L(r)?[]:{};return X(r,(function(t,r){var i=e(t,n+1);!N(i)&&(o[r]=i)})),t[n]=void 0,o}}return r}(e,0)},isAsyncFn:he,isThenable:function(e){return e&&(B(e)||F(e))&&F(e.then)&&F(e.catch)},setImmediate:pe,asap:de};function ye(e,t,r,n,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),r&&(this.config=r),n&&(this.request=n),o&&(this.response=o,this.status=o.status?o.status:null)}ve.inherits(ye,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:ve.toJSONObject(this.config),code:this.code,status:this.status}}});var me=ye.prototype,be={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((function(e){be[e]={value:e}})),Object.defineProperties(ye,be),Object.defineProperty(me,"isAxiosError",{value:!0}),ye.from=function(e,t,r,n,o,i){var a=Object.create(me);return ve.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return"isAxiosError"!==e})),ye.call(a,e.message,t,r,n,o),a.cause=e,a.name=e.name,i&&Object.assign(a,i),a};function ge(e){return ve.isPlainObject(e)||ve.isArray(e)}function we(e){return ve.endsWith(e,"[]")?e.slice(0,-2):e}function Ee(e,t,r){return e?e.concat(t).map((function(e,t){return e=we(e),!r&&t?"["+e+"]":e})).join(r?".":""):t}var Oe=ve.toFlatObject(ve,{},null,(function(e){return/^is[A-Z]/.test(e)}));function Se(e,t,r){if(!ve.isObject(e))throw new TypeError("target must be an object");t=t||new FormData;var n=(r=ve.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!ve.isUndefined(t[e])}))).metaTokens,o=r.visitor||c,i=r.dots,a=r.indexes,s=(r.Blob||"undefined"!=typeof Blob&&Blob)&&ve.isSpecCompliantForm(t);if(!ve.isFunction(o))throw new TypeError("visitor must be a function");function u(e){if(null===e)return"";if(ve.isDate(e))return e.toISOString();if(!s&&ve.isBlob(e))throw new ye("Blob is not supported. Use a Buffer instead.");return ve.isArrayBuffer(e)||ve.isTypedArray(e)?s&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function c(e,r,o){var s=e;if(e&&!o&&"object"===f(e))if(ve.endsWith(r,"{}"))r=n?r:r.slice(0,-2),e=JSON.stringify(e);else if(ve.isArray(e)&&function(e){return ve.isArray(e)&&!e.some(ge)}(e)||(ve.isFileList(e)||ve.endsWith(r,"[]"))&&(s=ve.toArray(e)))return r=we(r),s.forEach((function(e,n){!ve.isUndefined(e)&&null!==e&&t.append(!0===a?Ee([r],n,i):null===a?r:r+"[]",u(e))})),!1;return!!ge(e)||(t.append(Ee(o,r,i),u(e)),!1)}var l=[],h=Object.assign(Oe,{defaultVisitor:c,convertValue:u,isVisitable:ge});if(!ve.isObject(e))throw new TypeError("data must be an object");return function e(r,n){if(!ve.isUndefined(r)){if(-1!==l.indexOf(r))throw Error("Circular reference detected in "+n.join("."));l.push(r),ve.forEach(r,(function(r,i){!0===(!(ve.isUndefined(r)||null===r)&&o.call(t,r,ve.isString(i)?i.trim():i,n,h))&&e(r,n?n.concat(i):[i])})),l.pop()}}(e),t}function xe(e){var t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function Re(e,t){this._pairs=[],e&&Se(e,this,t)}var Te=Re.prototype;function je(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function ke(e,t,r){if(!t)return e;var n,o=r&&r.encode||je,i=r&&r.serialize;if(n=i?i(t,r):ve.isURLSearchParams(t)?t.toString():new Re(t,r).toString(o)){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+n}return e}Te.append=function(e,t){this._pairs.push([e,t])},Te.toString=function(e){var t=e?function(t){return e.call(this,t,xe)}:xe;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var Ae=function(){function e(){p(this,e),this.handlers=[]}return v(e,[{key:"use",value:function(e,t,r){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!r&&r.synchronous,runWhen:r?r.runWhen:null}),this.handlers.length-1}},{key:"eject",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:"clear",value:function(){this.handlers&&(this.handlers=[])}},{key:"forEach",value:function(e){ve.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),Pe={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Le={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:Re,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},Ne="undefined"!=typeof window&&"undefined"!=typeof document,_e="object"===("undefined"==typeof navigator?"undefined":f(navigator))&&navigator||void 0,Ce=Ne&&(!_e||["ReactNative","NativeScript","NS"].indexOf(_e.product)<0),Fe="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,Ue=Ne&&window.location.href||"http://localhost",Be=s(s({},Object.freeze({__proto__:null,hasBrowserEnv:Ne,hasStandardBrowserWebWorkerEnv:Fe,hasStandardBrowserEnv:Ce,navigator:_e,origin:Ue})),Le);function De(e){function t(e,r,n,o){var i=e[o++];if("__proto__"===i)return!0;var a=Number.isFinite(+i),s=o>=e.length;return i=!i&&ve.isArray(n)?n.length:i,s?(ve.hasOwnProp(n,i)?n[i]=[n[i],r]:n[i]=r,!a):(n[i]&&ve.isObject(n[i])||(n[i]=[]),t(e,r,n[i],o)&&ve.isArray(n[i])&&(n[i]=function(e){var t,r,n={},o=Object.keys(e),i=o.length;for(t=0;t-1,i=ve.isObject(e);if(i&&ve.isHTMLForm(e)&&(e=new FormData(e)),ve.isFormData(e))return o?JSON.stringify(De(e)):e;if(ve.isArrayBuffer(e)||ve.isBuffer(e)||ve.isStream(e)||ve.isFile(e)||ve.isBlob(e)||ve.isReadableStream(e))return e;if(ve.isArrayBufferView(e))return e.buffer;if(ve.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();if(i){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return Se(e,new Be.classes.URLSearchParams,Object.assign({visitor:function(e,t,r,n){return Be.isNode&&ve.isBuffer(e)?(this.append(t,e.toString("base64")),!1):n.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((r=ve.isFileList(e))||n.indexOf("multipart/form-data")>-1){var a=this.env&&this.env.FormData;return Se(r?{"files[]":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType("application/json",!1),function(e,t,r){if(ve.isString(e))try{return(t||JSON.parse)(e),ve.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(r||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||Ie.transitional,r=t&&t.forcedJSONParsing,n="json"===this.responseType;if(ve.isResponse(e)||ve.isReadableStream(e))return e;if(e&&ve.isString(e)&&(r&&!this.responseType||n)){var o=!(t&&t.silentJSONParsing)&&n;try{return JSON.parse(e)}catch(e){if(o){if("SyntaxError"===e.name)throw ye.from(e,ye.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Be.classes.FormData,Blob:Be.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};ve.forEach(["delete","get","head","post","put","patch"],(function(e){Ie.headers[e]={}}));var qe=Ie,Me=ve.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),ze=Symbol("internals");function He(e){return e&&String(e).trim().toLowerCase()}function Je(e){return!1===e||null==e?e:ve.isArray(e)?e.map(Je):String(e)}function We(e,t,r,n,o){return ve.isFunction(n)?n.call(this,t,r):(o&&(t=r),ve.isString(t)?ve.isString(n)?-1!==t.indexOf(n):ve.isRegExp(n)?n.test(t):void 0:void 0)}var Ge=function(e,t){function r(e){p(this,r),e&&this.set(e)}return v(r,[{key:"set",value:function(e,t,r){var n=this;function o(e,t,r){var o=He(t);if(!o)throw new Error("header name must be a non-empty string");var i=ve.findKey(n,o);(!i||void 0===n[i]||!0===r||void 0===r&&!1!==n[i])&&(n[i||t]=Je(e))}var i=function(e,t){return ve.forEach(e,(function(e,r){return o(e,r,t)}))};if(ve.isPlainObject(e)||e instanceof this.constructor)i(e,t);else if(ve.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()))i(function(e){var t,r,n,o={};return e&&e.split("\n").forEach((function(e){n=e.indexOf(":"),t=e.substring(0,n).trim().toLowerCase(),r=e.substring(n+1).trim(),!t||o[t]&&Me[t]||("set-cookie"===t?o[t]?o[t].push(r):o[t]=[r]:o[t]=o[t]?o[t]+", "+r:r)})),o}(e),t);else if(ve.isHeaders(e)){var a,s=function(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=E(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(s)throw i}}}}(e.entries());try{for(s.s();!(a=s.n()).done;){var u=m(a.value,2),c=u[0];o(u[1],c,r)}}catch(e){s.e(e)}finally{s.f()}}else null!=e&&o(t,e,r);return this}},{key:"get",value:function(e,t){if(e=He(e)){var r=ve.findKey(this,e);if(r){var n=this[r];if(!t)return n;if(!0===t)return function(e){for(var t,r=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;t=n.exec(e);)r[t[1]]=t[2];return r}(n);if(ve.isFunction(t))return t.call(this,n,r);if(ve.isRegExp(t))return t.exec(n);throw new TypeError("parser must be boolean|regexp|function")}}}},{key:"has",value:function(e,t){if(e=He(e)){var r=ve.findKey(this,e);return!(!r||void 0===this[r]||t&&!We(0,this[r],r,t))}return!1}},{key:"delete",value:function(e,t){var r=this,n=!1;function o(e){if(e=He(e)){var o=ve.findKey(r,e);!o||t&&!We(0,r[o],o,t)||(delete r[o],n=!0)}}return ve.isArray(e)?e.forEach(o):o(e),n}},{key:"clear",value:function(e){for(var t=Object.keys(this),r=t.length,n=!1;r--;){var o=t[r];e&&!We(0,this[o],o,e,!0)||(delete this[o],n=!0)}return n}},{key:"normalize",value:function(e){var t=this,r={};return ve.forEach(this,(function(n,o){var i=ve.findKey(r,o);if(i)return t[i]=Je(n),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=Je(n),r[a]=!0})),this}},{key:"concat",value:function(){for(var e,t=arguments.length,r=new Array(t),n=0;n1?r-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:Date.now();o=i,r=null,n&&(clearTimeout(n),n=null),e.apply(null,t)};return[function(){for(var e=Date.now(),t=e-o,s=arguments.length,u=new Array(s),c=0;c=i?a(u,e):(r=u,n||(n=setTimeout((function(){n=null,a(r)}),i-t)))},function(){return r&&a(r)}]}ve.inherits($e,ye,{__CANCEL__:!0});var et=function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3,n=0,o=Qe(50,250);return Ze((function(r){var i=r.loaded,a=r.lengthComputable?r.total:void 0,s=i-n,u=o(s);n=i;var c=y({loaded:i,total:a,progress:a?i/a:void 0,bytes:s,rate:u||void 0,estimated:u&&a&&i<=a?(a-i)/u:void 0,event:r,lengthComputable:null!=a},t?"download":"upload",!0);e(c)}),r)},tt=function(e,t){var r=null!=e;return[function(n){return t[0]({lengthComputable:r,total:e,loaded:n})},t[1]]},rt=function(e){return function(){for(var t=arguments.length,r=new Array(t),n=0;n1?t-1:0),n=1;n1?"since :\n"+s.map(jt).join("\n"):" "+jt(s[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return r};function Pt(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new $e(null,e)}function Lt(e){return Pt(e),e.headers=Ke.from(e.headers),e.data=Ve.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1),At(e.adapter||qe.adapter)(e).then((function(t){return Pt(e),t.data=Ve.call(e,e.transformResponse,t),t.headers=Ke.from(t.headers),t}),(function(t){return Xe(t)||(Pt(e),t&&t.response&&(t.response.data=Ve.call(e,e.transformResponse,t.response),t.response.headers=Ke.from(t.response.headers))),Promise.reject(t)}))}var Nt="1.7.5",_t={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){_t[e]=function(r){return f(r)===e||"a"+(t<1?"n ":" ")+e}}));var Ct={};_t.transitional=function(e,t,r){function n(e,t){return"[Axios v1.7.5] Transitional option '"+e+"'"+t+(r?". "+r:"")}return function(r,o,i){if(!1===e)throw new ye(n(o," has been removed"+(t?" in "+t:"")),ye.ERR_DEPRECATED);return t&&!Ct[o]&&(Ct[o]=!0,console.warn(n(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(r,o,i)}};var Ft={assertOptions:function(e,t,r){if("object"!==f(e))throw new ye("options must be an object",ye.ERR_BAD_OPTION_VALUE);for(var n=Object.keys(e),o=n.length;o-- >0;){var i=n[o],a=t[i];if(a){var s=e[i],u=void 0===s||a(s,i,e);if(!0!==u)throw new ye("option "+i+" must be "+u,ye.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new ye("Unknown option "+i,ye.ERR_BAD_OPTION)}},validators:_t},Ut=Ft.validators,Bt=function(){function e(t){p(this,e),this.defaults=t,this.interceptors={request:new Ae,response:new Ae}}var t;return v(e,[{key:"request",value:(t=h(u().mark((function e(t,r){var n,o;return u().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,this._request(t,r);case 3:return e.abrupt("return",e.sent);case 6:if(e.prev=6,e.t0=e.catch(0),e.t0 instanceof Error){Error.captureStackTrace?Error.captureStackTrace(n={}):n=new Error,o=n.stack?n.stack.replace(/^.+\n/,""):"";try{e.t0.stack?o&&!String(e.t0.stack).endsWith(o.replace(/^.+\n.+\n/,""))&&(e.t0.stack+="\n"+o):e.t0.stack=o}catch(e){}}throw e.t0;case 10:case"end":return e.stop()}}),e,this,[[0,6]])}))),function(e,r){return t.apply(this,arguments)})},{key:"_request",value:function(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{};var r=t=st(this.defaults,t),n=r.transitional,o=r.paramsSerializer,i=r.headers;void 0!==n&&Ft.assertOptions(n,{silentJSONParsing:Ut.transitional(Ut.boolean),forcedJSONParsing:Ut.transitional(Ut.boolean),clarifyTimeoutError:Ut.transitional(Ut.boolean)},!1),null!=o&&(ve.isFunction(o)?t.paramsSerializer={serialize:o}:Ft.assertOptions(o,{encode:Ut.function,serialize:Ut.function},!0)),t.method=(t.method||this.defaults.method||"get").toLowerCase();var a=i&&ve.merge(i.common,i[t.method]);i&&ve.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete i[e]})),t.headers=Ke.concat(a,i);var s=[],u=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(u=u&&e.synchronous,s.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,h=0;if(!u){var p=[Lt.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,f),l=p.length,c=Promise.resolve(t);h0;)n._listeners[t](e);n._listeners=null}})),this.promise.then=function(e){var t,r=new Promise((function(e){n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},t((function(e,t,o){n.reason||(n.reason=new $e(e,t,o),r(n.reason))}))}return v(e,[{key:"throwIfRequested",value:function(){if(this.reason)throw this.reason}},{key:"subscribe",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:"unsubscribe",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}}],[{key:"source",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}(),qt=It;var Mt={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Mt).forEach((function(e){var t=m(e,2),r=t[0],n=t[1];Mt[n]=r}));var zt=Mt;var Ht=function e(t){var r=new Dt(t),n=x(Dt.prototype.request,r);return ve.extend(n,Dt.prototype,r,{allOwnKeys:!0}),ve.extend(n,r,null,{allOwnKeys:!0}),n.create=function(r){return e(st(t,r))},n}(qe);return Ht.Axios=Dt,Ht.CanceledError=$e,Ht.CancelToken=qt,Ht.isCancel=Xe,Ht.VERSION=Nt,Ht.toFormData=Se,Ht.AxiosError=ye,Ht.Cancel=Ht.CanceledError,Ht.all=function(e){return Promise.all(e)},Ht.spread=function(e){return function(t){return e.apply(null,t)}},Ht.isAxiosError=function(e){return ve.isObject(e)&&!0===e.isAxiosError},Ht.mergeConfig=st,Ht.AxiosHeaders=Ke,Ht.formToJSON=function(e){return De(ve.isHTMLForm(e)?new FormData(e):e)},Ht.getAdapter=At,Ht.HttpStatusCode=zt,Ht.default=Ht,Ht})); +//# sourceMappingURL=axios.min.js.map \ No newline at end of file diff --git a/batch-quartz/src/main/resources/static/js/user/signIn.js b/batch-quartz/src/main/resources/static/js/user/signIn.js new file mode 100644 index 0000000..4cd5478 --- /dev/null +++ b/batch-quartz/src/main/resources/static/js/user/signIn.js @@ -0,0 +1,20 @@ +import axiosInstance from '../common/axiosInstance.js'; + +const login = async (username, password) => { + try { + const response = await axiosInstance.post('/sign-in', { + username, + password + }); + console.log('로그인 성공:', response.data); + } catch (error) { + console.error('로그인 실패:', error); + } +}; + +document.getElementById('signinForm').addEventListener('submit', function(event) { + event.preventDefault(); // 기본 폼 제출 방지 + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + login(username, password); +}); \ No newline at end of file diff --git a/batch-quartz/src/main/resources/templates/views/user/signIn.html b/batch-quartz/src/main/resources/templates/views/user/signIn.html new file mode 100644 index 0000000..36a4adb --- /dev/null +++ b/batch-quartz/src/main/resources/templates/views/user/signIn.html @@ -0,0 +1,33 @@ + + + + + 로그인 페이지 + + + + + +
+
+ User Icon +
+

로그인

+
+
+
+ User Icon + +
+
+
+
+ Password Icon + +
+
+ +
+
+ + \ No newline at end of file