added refresh token logic

This commit is contained in:
Sascha Kühl 2025-03-28 16:01:25 +01:00
parent 08201b954c
commit bae8d26e59
10 changed files with 162 additions and 33 deletions

View File

@ -6,4 +6,27 @@
<script setup lang="ts">
import { IonApp, IonRouterOutlet } from '@ionic/vue';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex'
import { AppStore } from '@/store';
import { onMounted, onBeforeUnmount } from "vue";
import EventBus from "./common/EventBus";
const router = useRouter();
const store = useStore<AppStore>();
const logout = () => {
store.dispatch('auth/logout');
router.push('/login');
}
onMounted(() => {
EventBus.on("logout", () => {
logout();
});
});
onBeforeUnmount(() => {
EventBus.remove("logout", null);
})
</script>

View File

@ -0,0 +1,13 @@
const eventBus = {
on(event: string, callback) {
document.addEventListener(event, (e) => callback(e.detail));
},
dispatch(event: string, data) {
document.dispatchEvent(new CustomEvent(event, { detail: data }));
},
remove(event: string, callback) {
document.removeEventListener(event, callback);
},
};
export default eventBus;

View File

@ -1,7 +1,7 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import Vuex from 'vuex'
import setupInterceptors from './services/SetupInterceptors';
import { IonicVue } from '@ionic/vue';
@ -37,6 +37,8 @@ import './theme/variables.css';
import store from './store';
setupInterceptors(store);
const app = createApp(App)
.use(store)
.use(IonicVue)

10
app/src/services/Api.ts Normal file
View File

@ -0,0 +1,10 @@
import axios from "axios";
const instance = axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-Type": "application/json",
},
});
export default instance;

View File

@ -1,17 +1,16 @@
import axios from 'axios';
const API_URL = 'http://localhost:8080/api/auth/';
import api from './Api';
import TokenService from './TokenService';
class AuthService {
public login(email: string, password: string) {
return axios
.post(API_URL + 'login', {
return api
.post('/auth/login', {
email,
password
})
.then(response => {
if (response.data.accessToken) {
localStorage.setItem('user', JSON.stringify(response.data));
TokenService.setUser(response.data);
}
return response.data;
@ -19,12 +18,11 @@ class AuthService {
}
public logout() {
localStorage.removeItem('user');
TokenService.removeUser();
}
public register(username: string, email: string, password: string) {
return axios.post(API_URL + 'register', {
username,
public register(email: string, password: string) {
return api.post('/auth/register', {
email,
password
});

View File

@ -1,12 +1,5 @@
import PitchType from "@/types/PitchType";
import axios, {AxiosInstance} from "axios";
const apiClient: AxiosInstance = axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json",
},
});
import api from './Api';
class PitchTypeService {
private static instance: PitchTypeService;
@ -22,12 +15,12 @@ class PitchTypeService {
}
async getAllPitchTypes(): Promise<PitchType[]> {
const users = await apiClient.get('/pitch_types');
const users = await api.get('/pitch_types');
return users.data;
}
async getPitchType(id: number): Promise<PitchType> {
const pitchType = await apiClient.get(`/pitch_types/${id}`);
const pitchType = await api.get(`/pitch_types/${id}`);
return pitchType.data;
// if (pitcher !== undefined) {
// return pitcher;

View File

@ -1,12 +1,6 @@
import Pitcher from "@/types/Pitcher";
import axios, { AxiosInstance } from "axios";
import api from './Api';
const apiClient: AxiosInstance = axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json",
},
});
class PitcherService {
private static instance: PitcherService;
@ -21,12 +15,12 @@ class PitcherService {
}
async getAllPitchers(): Promise<Pitcher[]> {
const users = await apiClient.get('/users');
const users = await api.get('/users');
return users.data;
}
async getPitcher(id: number): Promise<Pitcher> {
const pitcher = await apiClient.get(`/users/${id}`);
const pitcher = await api.get(`/users/${id}`);
return pitcher.data;
// const pitcher = pitchers.get(id);
// if (pitcher !== undefined) {

View File

@ -0,0 +1,55 @@
import axiosInstance from "./Api";
import TokenService from "./TokenService";
import { Store } from 'vuex';
import {RootState} from '@/store';
const setup = (store: Store<RootState>) => {
axiosInstance.interceptors.request.use(
(config) => {
const token = TokenService.getLocalAccessToken();
if (token) {
// config.headers["Authorization"] = 'Bearer ' + token; // for Spring Boot back-end
config.headers["x-access-token"] = token; // for Node.js Express back-end
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
axiosInstance.interceptors.response.use(
(res) => {
return res;
},
async (err) => {
const originalConfig = err.config;
if (originalConfig.url !== "/auth/login" && err.response) {
// Access Token was expired
if (err.response.status === 401 && !originalConfig._retry) {
originalConfig._retry = true;
try {
const rs = await axiosInstance.post("/auth/refreshtoken", {
refreshToken: TokenService.getLocalRefreshToken(),
});
const { accessToken } = rs.data;
await store.dispatch('auth/refreshToken', accessToken);
TokenService.updateLocalAccessToken(accessToken);
return axiosInstance(originalConfig);
} catch (_error) {
return Promise.reject(_error);
}
}
}
return Promise.reject(err);
}
);
};
export default setup;

View File

@ -0,0 +1,34 @@
import UserInfo from '@/types/UserInfo';
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: string) {
const user: UserInfo = JSON.parse(localStorage.getItem("user")|| '""');
user.accessToken = token;
localStorage.setItem("user", JSON.stringify(user));
}
getUser() {
return JSON.parse(localStorage.getItem("user")|| '""');
}
setUser(user: UserInfo) {
console.log(JSON.stringify(user));
localStorage.setItem("user", JSON.stringify(user));
}
removeUser() {
localStorage.removeItem("user");
}
}
export default new TokenService();

View File

@ -0,0 +1,7 @@
export default interface UserInfo {
id: number,
email: string,
roles: string[],
accessToken: string,
refreshToken: string
}