하석형 하석형 04-02
250402 하석형 Context Path 저장 기능 추가
@7ffa1fdc9fc1d2c7f2f6dde2a12139ba366d0d29
client/resources/api/cntxtPth.js
--- client/resources/api/cntxtPth.js
+++ client/resources/api/cntxtPth.js
@@ -1,21 +1,9 @@
 import apiClient from "./index";
 
-export const findAll = search => {
-    return apiClient.post(`/admin/cntxtPth/findAll.json`, search);
+export const getCntxtPth = () => {
+    return apiClient.get(`/admin/cntxtPth/findLatestCntxtPth.json`);
 }
 
-export const findByCntxtPth = cntxtPth => {
-    return apiClient.post(`/admin/cntxtPth/findByCntxtPth.json`, cntxtPth);
-}
-
-export const save = cntxtPth => {
+export const saveCntxtPth = cntxtPth => {
     return apiClient.post(`/admin/cntxtPth/saveProc.json`, cntxtPth);
-}
-
-export const update = cntxtPth => {
-    return apiClient.post(`/admin/cntxtPth/updateProc.json`, cntxtPth);
-}
-
-export const del = cntxtPth => {
-    return apiClient.post(`/admin/cntxtPth/deleteProc.json`, cntxtPth);
 }
(파일 끝에 줄바꿈 문자 없음)
client/resources/api/router.js
--- client/resources/api/router.js
+++ client/resources/api/router.js
@@ -1,9 +1,5 @@
 import apiClient from "./index";
 
-export const getCntxtPth = () => {
-    return apiClient.get(`/admin/cntxtPth/findLatestCntxtPth.json`);
-}
-
 export const findAll = () => {
     return apiClient.post(`/sys/contsType/findByContsAuthrtSys.json`);
 }
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -21,7 +21,8 @@
   },
 ];
 
-import { getCntxtPth, findAll, accessCheck } from "../../resources/api/router";
+import { findAll, accessCheck } from "../../resources/api/router";
+import { getCntxtPth } from "../../resources/api/cntxtPth";
 import { save } from "../../resources/api/cntnStats";
 import { mdiConsoleLine } from "@mdi/js";
 
client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
--- client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
+++ client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
@@ -3,127 +3,205 @@
     <div class="content">
       <div class="scroll">
         <div open class="form-box">
-            <div class="form-box-title">
-                <p class="summary-style pl10">기본 정보</p> 
-                <span style="color: red;"> ※ 로그인 정책을 변경하면 전체 사용자가 로그아웃됩니다.</span>
-            </div>
-            <div class="form-content">
-              <div class="gd-12 pl0">
-                  <label class="form-title">중복로그인 설정</label>
-                  <div class="form-group">
-                    <div class="check-area">
-                          <div class="form-check">
-                            <input type="radio" id="allowMultipleLoginY" class="mr5" value="Y" v-model="allowMultipleLogin" @change="saveByLoginPolicy" /> 
-                            <label for="allowMultipleLoginY">허용</label>
-                          </div>
-                          <div class="form-check">
-                            <input type="radio" id= "allowMultipleLoginN" class="mr5" value="N" v-model="allowMultipleLogin" @change="saveByLoginPolicy" /> 
-                            <label for="allowMultipleLoginN">비허용</label>
-                          </div>
-                      </div>
-                <!--    <p>{{ allowMultipleLogin ? '중복 로그인을 허용하고 있습니다.' : '중복 로그인을 허용하지 않습니다.' }}</p>-->  
+          <div class="form-box-title">
+            <p class="summary-style pl10">기본 정보</p>
+            <span style="color: red;"> ※ 로그인 정책을 변경하면 전체 사용자가 로그아웃됩니다.</span>
+          </div>
+          <div class="form-content">
+            <div class="gd-12 pl0">
+              <label class="form-title">중복로그인 설정</label>
+              <div class="form-group">
+                <div class="check-area">
+                  <div class="form-check">
+                    <input type="radio" id="allowMultipleLoginY" class="mr5" value="Y" v-model="allowMultipleLogin"
+                      @change="saveByLoginPolicy" />
+                    <label for="allowMultipleLoginY">허용</label>
                   </div>
-              </div>
-                <div>
-                    <label class="form-title">로그인 방식 설정</label>
-                      <div class="form-group">
-                        <div class="check-area">
-                          <div class="form-check">
-                            <input type="radio" id= "loginModeJ" class="mr5" value="J" v-model="lgnMode" @change="saveByLoginMode" /> 
-                            <label for="loginModeJ">JWT 방식</label>
-                          </div>
-                          <div class="form-check">
-                            <input type="radio" id= "loginModeS" class="mr5" value="S" v-model="lgnMode" @change="saveByLoginMode" /> 
-                            <label for="loginModeS">SESSION 방식</label>
-                          </div>
-                        </div>
-                        <span class="ml10 gray">
-                          현재 로그인 방식은 <strong>{{ loginModeLabel  }}</strong> 입니다.
-                        </span>
-                      </div>
+                  <div class="form-check">
+                    <input type="radio" id="allowMultipleLoginN" class="mr5" value="N" v-model="allowMultipleLogin"
+                      @change="saveByLoginPolicy" />
+                    <label for="allowMultipleLoginN">비허용</label>
+                  </div>
                 </div>
+                <!--    <p>{{ allowMultipleLogin ? '중복 로그인을 허용하고 있습니다.' : '중복 로그인을 허용하지 않습니다.' }}</p>-->
+              </div>
             </div>
+            <div>
+              <label class="form-title">로그인 방식 설정</label>
+              <div class="form-group">
+                <div class="check-area">
+                  <div class="form-check">
+                    <input type="radio" id="loginModeJ" class="mr5" value="J" v-model="lgnMode"
+                      @change="saveByLoginMode" />
+                    <label for="loginModeJ">JWT 방식</label>
+                  </div>
+                  <div class="form-check">
+                    <input type="radio" id="loginModeS" class="mr5" value="S" v-model="lgnMode"
+                      @change="saveByLoginMode" />
+                    <label for="loginModeS">SESSION 방식</label>
+                  </div>
+                </div>
+                <span class="ml10 gray">
+                  현재 로그인 방식은 <strong>{{ loginModeLabel }}</strong> 입니다.
+                </span>
+              </div>
+            </div>
+            <div>
+              <label class="form-title">Context Path 설정</label>
+              <div class="form-group">
+                <div class="check-area">
+                  <div class="form-check">
+                    <input type="text" id="cntxtPth" class="form-control sm" v-model="cntxtPth" ref="cntxtPth" />
+                  </div>
+                  <button class="btn sm primary" @click="fnSave">저장</button>
+                </div>
+                <span class="ml10 gray">
+                  <strong>/경로</strong> 형식으로 입력해주세요.
+                </span>
+              </div>
+            </div>
+          </div>
         </div>
       </div>
     </div>
   </div>
 </template>
-  
-  <script>
-  import { findAllByLoginPolicy, saveByLoginPolicy, findAllByLoginMode, saveByLoginMode } from '../../../../../resources/api/loginPolicy'
-  import store from "../../../../../views/pages/AppStore";
-  export default { 
-    data() {
-      return {
-        allowMultipleLogin:  null,
-        lgnMode : null,
-        previousLgnMode: null, // 이전 로그인 모드 저장
-        previousAllowMultipleLogin: null
-      }
-    },
-    created() {
-      this.findAll();
-    },
-    mounted() {
-    },
-    computed: {
-      loginModeLabel() {
-        return this.lgnMode === 'J' ? 'JWT' : 'SESSION';
-      }
-    },
-    methods: {
-        async findAll() {
-          try {
-            const res1 = await findAllByLoginPolicy();
-            this.allowMultipleLogin = res1.data.data === true ? 'Y' : 'N';
-            this.previousAllowMultipleLogin = this.allowMultipleLogin;
-            const res2 = await findAllByLoginMode();
-            this.lgnMode = res2.data.data;
-            this.previousLgnMode = this.lgnMode; // 초기 상태를 저장
-          } catch (err) {
-            alert('설정 정보를 불러오는 데 실패했습니다.');
-          }
-        },
-        async saveByLoginPolicy() {
-          const confirmed = confirm(
-          '로그인 설정을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?'
-        );
-        if (!confirmed) { 
-          this.allowMultipleLogin = this.previousAllowMultipleLogin; 
-          return;
-        }
 
-          try {
-            const loginPolicy = {};
-            loginPolicy.allowMultipleLogin = this.allowMultipleLogin;
-            await saveByLoginPolicy(loginPolicy);
-            alert('중복 로그인 설정이 저장되었습니다.');
-          } catch (err) {
-            alert('중복 로그인 설정 저장 실패');
-            this.allowMultipleLogin = this.previousAllowMultipleLogin; 
-          }
-      },
-      async saveByLoginMode() {
-        const confirmed = confirm(
-          '로그인 방식을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?'
-        );
-        if (!confirmed) { 
-          this.lgnMode = this.previousLgnMode; 
-          return;
-        }
+<script>
+import { findAllByLoginPolicy, saveByLoginPolicy, findAllByLoginMode, saveByLoginMode } from '../../../../../resources/api/loginPolicy';
+import { getCntxtPth, saveCntxtPth } from '../../../../../resources/api/cntxtPth';
+import { cacheReSet } from "../../../../../resources/api/cacheReSet";
+import store from "../../../../../views/pages/AppStore";
+export default {
+  data() {
+    return {
+      allowMultipleLogin: null,
+      lgnMode: null,
+      previousLgnMode: null, // 이전 로그인 모드 저장
+      previousAllowMultipleLogin: null,
 
-        try {
-          const loginMode = {};
-          loginMode.lgnMode = this.lgnMode;
- //         await saveByLoginMode(loginMode);
-          alert('로그인 방식이 변경되었습니다.\n다시 로그인해주세요.');
-          store.commit("setStoreReset");
-          window.location = '/login.page';
-        } catch (err) {
-          alert('로그인 방식 저장 실패: ' + (err.response?.data?.message || err.message));
-          this.lgnMode = this.previousLgnMode;
-        }
-      }
+      cntxtPth: '/', // context path 초기값
+      defaultCntxtPth: null, // 현재 설정된 Context Path
     }
+  },
+  created() {
+    this.findAll();
+    this.findCntxtPth();
+  },
+  mounted() {
+  },
+  computed: {
+    loginModeLabel() {
+      return this.lgnMode === 'J' ? 'JWT' : 'SESSION';
+    }
+  },
+  methods: {
+    async findAll() {
+      try {
+        const res1 = await findAllByLoginPolicy();
+        this.allowMultipleLogin = res1.data.data === true ? 'Y' : 'N';
+        this.previousAllowMultipleLogin = this.allowMultipleLogin;
+        const res2 = await findAllByLoginMode();
+        this.lgnMode = res2.data.data;
+        this.previousLgnMode = this.lgnMode; // 초기 상태를 저장
+      } catch (err) {
+        alert('설정 정보를 불러오는 데 실패했습니다.');
+      }
+    },
+    async saveByLoginPolicy() {
+      const confirmed = confirm(
+        '로그인 설정을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?'
+      );
+      if (!confirmed) {
+        this.allowMultipleLogin = this.previousAllowMultipleLogin;
+        return;
+      }
+
+      try {
+        const loginPolicy = {};
+        loginPolicy.allowMultipleLogin = this.allowMultipleLogin;
+        await saveByLoginPolicy(loginPolicy);
+        alert('중복 로그인 설정이 저장되었습니다.');
+      } catch (err) {
+        alert('중복 로그인 설정 저장 실패');
+        this.allowMultipleLogin = this.previousAllowMultipleLogin;
+      }
+    },
+    async saveByLoginMode() {
+      const confirmed = confirm(
+        '로그인 방식을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?'
+      );
+      if (!confirmed) {
+        this.lgnMode = this.previousLgnMode;
+        return;
+      }
+
+      try {
+        const loginMode = {};
+        loginMode.lgnMode = this.lgnMode;
+        //         await saveByLoginMode(loginMode);
+        alert('로그인 방식이 변경되었습니다.\n다시 로그인해주세요.');
+        store.commit("setStoreReset");
+        window.location = '/login.page';
+      } catch (err) {
+        alert('로그인 방식 저장 실패: ' + (err.response?.data?.message || err.message));
+        this.lgnMode = this.previousLgnMode;
+      }
+    },
+
+    // 최신 Context Path 조회
+    async findCntxtPth() {
+      try {
+        const res = await getCntxtPth();
+        if (res.status == 200) {
+          this.cntxtPth = res.data.data;
+          this.defaultCntxtPth = res.data.data;
+        }
+      } catch (error) {
+        alert(error.response.data.message);
+      }
+    },
+
+    // Context Path 저장
+    async fnSave() {
+      if (!this.validation()) {
+        return;
+      }
+      const isCheck = confirm("Context Path를 변경하면 로그아웃됩니다.\n계속하시겠습니까?");
+        if (isCheck) {
+        try {
+          let ctx = {path: this.cntxtPth};
+          const res = await saveCntxtPth(ctx);
+          alert(res.data.message);
+          if (res.status == 200) {
+            store.commit("setStoreReset");
+            const cacheRes = await cacheReSet(); // 캐시 초기화
+            alert(cacheRes.data.message);
+            window.location = `${store.state.contextPath}/login.page`;
+          } else {
+            alert(res.data.message);
+          }
+        } catch (error) {
+          alert('에러가 발생했습니다.\n시스템관리자에게 문의하세요.');
+        }
+      }
+    },
+
+    // 유효성 검사
+    validation() {
+      const regex = /^\/[a-zA-Z0-9\-_]*$/;
+      if (this.cntxtPth == null || this.cntxtPth == "") {
+        alert("Context Path를 입력해주세요.");
+        this.$refs.cntxtPth.focus();
+        return false;
+      }
+      if(!regex.test(this.cntxtPth)) {
+        alert("Context Path는 '/'로 시작해야 하며, 알파벳, 숫자, '-' 또는 '_'만 포함할 수 있습니다.");
+        this.$refs.cntxtPth.focus();
+        return false;
+      }
+      return true;
+    },
   }
-  </script>
(파일 끝에 줄바꿈 문자 없음)
+}
+</script>
(파일 끝에 줄바꿈 문자 없음)
Add a comment
List