Store_Vuex init...

This commit is contained in:
최준흠 2022-09-14 19:32:29 +09:00
parent 8790bcc516
commit 22543d0f15
16 changed files with 213 additions and 134 deletions

2
.env
View File

@ -5,7 +5,7 @@
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
VUE_APP_AUTH_HOST="http://localhost:2000"
VUE_APP_BACKEND_HOST="http://localhost:3000"
VUE_APP_TODO_HOST="http://localhost:3000"
#LocalStorage는 Edge 브라우저의 개발툴 > 응용프로그램 > 로컬 저장소에서 확인가능
VUE_APP_TABLE_DEFAULT_PERPAGE = 10

View File

@ -49,7 +49,7 @@
<script>
// : https://kdydesign.github.io/2019/04/06/vuejs-vuex-helper/
import authService from '../service/authService'
import authService from '../service/auth.service'
export default {
data() {
//console.log(this.$route)
@ -80,25 +80,18 @@ export default {
getValidationState({ dirty, validated, valid = null }) {
return dirty || validated ? valid : null
},
async onSubmit() {
//
authService
.post('/auth/login', {
onSubmit() {
try {
authService.login({
email: this.form.email,
password: this.form.password
})
.then(() => {
this.$router
.push({
name: this.$route.params.return_url || 'home'
})
.catch((e) => {
throw new Error('router 오류\n' + +e.response.data.message)
})
})
.catch((e) => {
alert(e)
this.$router.push({
name: this.$route.params.return_url || 'home'
})
} catch (e) {
alert(e.response.data.message)
}
}
}
}

View File

@ -136,6 +136,7 @@
</div>
</template>
<script>
import todoService from '@/service/todo.service'
import { createNamespacedHelpers } from 'vuex'
const todoStore = createNamespacedHelpers('TodoStore')
// : https://vuejsexamples.com/vuejs-tables-and-select-all-checkbox/
@ -247,8 +248,8 @@ export default {
},
methods: {
async setDatas(page = 1) {
await this.$store
.dispatch('TodoStore/setDatas', {
try {
const datas = await todoService.setDatas({
page: page,
perPage: this.perPage,
sortBy: this.sortBy,
@ -260,9 +261,11 @@ export default {
filterDateStart: this.filterDateStart,
filterDateEnd: this.filterDateEnd
})
.catch((e) => {
alert(e)
})
console.log(datas)
} catch (e) {
console.log(e)
alert(e.response.data.message)
}
},
searchClick() {
this.setDatas()

View File

@ -0,0 +1,53 @@
import api from './auth.api'
import jwt from '../service/jwt'
//참조: https://www.bezkoder.com/vue-refresh-token/
const setup = (store) => {
//API Request 전 처리용
api.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
//Request 처리용
api.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await api
.post('/auth/reload', {
refresh_token: jwt.getRefreshToken()
})
.then((rs) => {
store.dispatch('reload', rs.data.access_token)
})
return api(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
//Response 처리용
api.interceptors.response.use(
(response) => {
console.log('AUTH API Call 성공=>' + response)
return response
},
async (err) => {
// Do something with response error
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
return await reloadAccessToken(originalConfig)
}
}
return Promise.reject(err)
}
)
}
export default setup

View File

@ -1,7 +1,7 @@
import axios from 'axios'
const instance = axios.create({
const authAPI = axios.create({
baseURL: process.env.VUE_APP_AUTH_HOST,
headers: { 'Content-type': 'application/json' }
})
export default instance
export default authAPI

View File

@ -0,0 +1,58 @@
import api from './auth.api'
import jwt from '../service/jwt'
//참조: https://www.bezkoder.com/vue-refresh-token/
const setup = (store) => {
//API Request 전 처리용
api.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
//Request 처리용
api.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await api
.post('/auth/reload', {
refresh_token: jwt.getRefreshToken()
})
.then((rs) => {
store.dispatch('reload', rs.data.access_token)
})
return api(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
//Response 처리용
api.interceptors.response.use(
async (response) => {
switch (response.config.url) {
case '/todo':
await store.dispatch('setDatas', response.data)
break
}
return response
},
async (err) => {
// Do something with response error
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
return await reloadAccessToken(originalConfig)
}
}
console.log('TODO API Call 오류=>' + err)
return Promise.reject(err)
}
)
}
export default setup

View File

@ -0,0 +1,6 @@
import axios from 'axios'
const todoAPI = axios.create({
baseURL: process.env.VUE_APP_TODO_HOST,
headers: { 'Content-type': 'application/json' }
})
export default todoAPI

View File

@ -33,8 +33,8 @@ const routes = [
component: () =>
import(
/* webpackChunkName: "api", webpackPrefetch:true */ '@/views/todoView.vue'
),
meta: { requiredAuth: true }
)
//meta: { requiredAuth: true }
}
]
@ -62,9 +62,8 @@ router.beforeEach((to, from, next) => {
//1. routes 설정에서 meta: { requiredAuth: true } 가 선언된 경우
if (to.matched.some((route) => route.meta.requiredAuth)) {
//2. 로그인 체크용
const access_token = jwt.getToken('access_token')
const refresh_token = jwt.getToken('refresh_token')
if (access_token === null && refresh_token !== null) {
const access_token = jwt.getAccessToken()
if (access_token === null && jwt.getRefreshToken() !== null) {
//refreshToken은 있고 accessToken이 없을 경우 토큰 재발급 요청
this.$store.dispatch('refreshToken')
} else if (access_token) {

View File

@ -0,0 +1,7 @@
import api from '../interceptors/auth.api'
class AuthService {
async login(params) {
return await api.get('/auth/login', params)
}
}
export default new AuthService()

View File

@ -0,0 +1,7 @@
import api from '../interceptors/todo.api'
class TodoService {
async setDatas(params) {
return await api.get('/todo', { params: params })
}
}
export default new TodoService()

View File

@ -0,0 +1,26 @@
class TokenService {
getLocalRefreshToken() {
const user = JSON.parse(localStorage.getItem('user'))
return user?.refreshToken
}
getLocalAccessToken() {
const user = JSON.parse(localStorage.getItem('user'))
return user?.accessToken
}
updateLocalAccessToken(token) {
let user = JSON.parse(localStorage.getItem('user'))
user.accessToken = token
localStorage.setItem('user', JSON.stringify(user))
}
getUser() {
return JSON.parse(localStorage.getItem('user'))
}
setUser(user) {
console.log(JSON.stringify(user))
localStorage.setItem('user', JSON.stringify(user))
}
removeUser() {
localStorage.removeItem('user')
}
}
export default new TokenService()

View File

@ -1,46 +0,0 @@
import authService from '../service/authService'
import jwt from '../service/jwt'
//참조: https://www.bezkoder.com/vue-refresh-token/
const setup = (store) => {
//API Request 전 처리용
authService.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
//Request 처리용
authService.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//Response 처리용
authService.interceptors.response.use(
(res) => {
console.log('AuthService Call 성공=>' + res)
return res
},
async (err) => {
// Do something with response error
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
if (err.response.status === 401 && !originalConfig._retry) {
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
const rs = await authService.post('/auth/reload', {
refresh_token: jwt.getRefreshToken()
})
const { access_token } = rs.data
store.dispatch('auth/reload', access_token)
return authService(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
} //401처리
}
Promise.reject(err.response.data.message)
}
)
}
export default { setup }

View File

@ -1,11 +1,15 @@
import Vue from 'vue'
import Vuex from 'vuex'
import AuthStore from './authStore'
import AuthInterceptors from './authIterceptors'
import TodoStore from './todoStore'
import AuthStore from './auth.store'
import TodoStore from './todo.store'
Vue.use(Vuex)
AuthInterceptors(AuthStore)
//인터셉터 정의 및 Storage 연동
import setupAuthInterceptor from '../interceptors/auth.Iterceptor'
setupAuthInterceptor(AuthStore)
import setupTodoInterceptor from '../interceptors/todo.Iterceptor'
setupTodoInterceptor(TodoStore)
export default new Vuex.Store({
modules: {

24
src/store/todo.store.js Normal file
View File

@ -0,0 +1,24 @@
const state = {
total: 0,
rows: []
}
const getters = {
getTotal: function (state) {
return state.total
},
getRows: function (state) {
return state.rows
}
}
const mutations = {
setDatas: function (state, datas) {
state.total = datas.total
state.rows = datas.rows
}
}
const actions = {
setDatas: function (context, datas) {
context.commit('setDatas', datas.data)
}
}
export default { namespaced: true, state, getters, mutations, actions }

View File

@ -1,55 +0,0 @@
import axios from 'axios'
import jwt from '../service/jwt'
//참조: https://yamoo9.github.io/axios/guide/interceptors.html
const apiServer = axios.create({
baseURL: process.env.VUE_APP_BACKEND_HOST,
headers: { 'content-type': 'application/json' }
})
apiServer.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
(error) => {
// Do something with request error
Promise.reject(error)
}
)
apiServer.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
// count state 속성 추가
const state = {
total: 0,
rows: []
}
const getters = {
getTotal: function (state) {
return state.total
},
getRows: function (state) {
return state.rows
}
}
const mutations = {
setDatas: function (state, data) {
state.total = data.total
state.rows = data.rows
}
}
const actions = {
setDatas: async function (context, params) {
console.log(params)
//주의 .get의 parameter는 { params: params} 처럼 보내야함
return await apiServer
.get('/todo', { params: params })
.then((response) => {
console.log(response)
const { data } = response
context.commit('setDatas', data)
})
.catch((e) => {
//throw new Error('todo List 오류\n' + e.response.data.message)
console.log(e)
})
}
}
export default { namespaced: true, state, getters, mutations, actions }