mirror of
https://github.com/Spythere/station-manager-2.0.git
synced 2026-05-02 21:18:13 +00:00
poprawki bezpieczeństwa
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
VITE_API_URL="https://stacjownik.spythere.pl"
|
||||
VITE_API_URL_DEV="http://localhost:3001"
|
||||
VITE_API_DEV=0
|
||||
VITE_API_DEV=1
|
||||
+14
-20
@@ -10,8 +10,9 @@ import PopUpCard from './components/PopUpCard.vue';
|
||||
import { RouterView } from 'vue-router';
|
||||
import { AuthState } from './types/types';
|
||||
import useRouteGuard from './mixins/useRouteGuard';
|
||||
import { useStore } from './store';
|
||||
import { baseURL, useStore } from './store';
|
||||
import useLocalStorage from './mixins/useLocalStorage';
|
||||
import axios from 'axios';
|
||||
|
||||
export default defineComponent({
|
||||
components: { PopUpCard },
|
||||
@@ -20,7 +21,7 @@ export default defineComponent({
|
||||
const { routeAuthGuard } = useRouteGuard();
|
||||
const { setupStorage } = useLocalStorage();
|
||||
|
||||
routeAuthGuard();
|
||||
// routeAuthGuard();
|
||||
setupStorage();
|
||||
|
||||
return {
|
||||
@@ -30,28 +31,21 @@ export default defineComponent({
|
||||
|
||||
methods: {
|
||||
async autoLogin() {
|
||||
const token = window.localStorage.getItem('auth-token');
|
||||
if (!token) {
|
||||
this.store.authState = AuthState.UNAUTHORIZED;
|
||||
return;
|
||||
try {
|
||||
const response = await axios.post(
|
||||
'/auth/token',
|
||||
{},
|
||||
{
|
||||
baseURL,
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
|
||||
this.store.token = token;
|
||||
|
||||
this.store
|
||||
.fetchTokenData()
|
||||
.then((res) => {
|
||||
this.store.user = res.data.user;
|
||||
this.store.authState = AuthState.AUTHORIZED;
|
||||
this.store.user = response.data;
|
||||
this.$router.push('/');
|
||||
})
|
||||
.catch((err) => {
|
||||
this.store.isAuthorized = false;
|
||||
window.localStorage.removeItem('auth-token');
|
||||
|
||||
this.store.authState = AuthState.UNAUTHORIZED;
|
||||
} catch (error) {
|
||||
this.$router.push('/login');
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -82,9 +82,10 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import routesMixin from '../mixins/routesMixin';
|
||||
import { useStore } from '../store';
|
||||
import { useStore, baseURL } from '../store';
|
||||
import { AuthState, Availability, ChangeProp, HeaderTypes, SceneryRoutesInfo, SceneryRowItem } from '../types/types';
|
||||
import { getAvailabilityValue } from '../types/typeUitls';
|
||||
import axios from 'axios';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
@@ -154,13 +155,8 @@ export default defineComponent({
|
||||
if (confirmed) this.updateListToDb();
|
||||
},
|
||||
|
||||
signOut() {
|
||||
this.store.token = null;
|
||||
this.store.authState = AuthState.UNAUTHORIZED;
|
||||
|
||||
window.localStorage.removeItem('auth-token');
|
||||
window.localStorage.removeItem('user');
|
||||
|
||||
async signOut() {
|
||||
await axios.post('/auth/logout', {}, { baseURL, withCredentials: true });
|
||||
this.$router.push('/login');
|
||||
},
|
||||
|
||||
|
||||
+18
-2
@@ -1,9 +1,25 @@
|
||||
import { createApp } from 'vue';
|
||||
import router from './router';
|
||||
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
|
||||
import { createPinia } from 'pinia';
|
||||
import { useStore } from './store';
|
||||
|
||||
createApp(App).use(router).use(createPinia()).mount('#app');
|
||||
const pinia = createPinia();
|
||||
const app = createApp(App);
|
||||
|
||||
app.use(pinia).use(router);
|
||||
app.mount('#app');
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const store = useStore();
|
||||
|
||||
if (to.meta.protected && !store.user) {
|
||||
next('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
+3
-1
@@ -4,6 +4,9 @@ const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'ManagerView',
|
||||
meta: {
|
||||
protected: true,
|
||||
},
|
||||
component: () => import('./views/ManagerView.vue'),
|
||||
},
|
||||
{
|
||||
@@ -18,5 +21,4 @@ const router = createRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
|
||||
export default router;
|
||||
|
||||
+7
-33
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
||||
import { AuthState, ILoginResponse, IStore, IUser, SceneryRowItem } from './types/types';
|
||||
import axios from 'axios';
|
||||
|
||||
const baseURL = import.meta.env[`VITE_API_URL${import.meta.env.DEV ? '_DEV' : ''}`];
|
||||
export const baseURL = import.meta.env[`VITE_API_URL${import.meta.env.DEV ? '_DEV' : ''}`];
|
||||
|
||||
export const useStore = defineStore('store', {
|
||||
state: () =>
|
||||
@@ -20,9 +20,7 @@ export const useStore = defineStore('store', {
|
||||
routesModalVisible: true,
|
||||
currentStation: null,
|
||||
selectedStationName: '',
|
||||
token: null,
|
||||
user: null,
|
||||
isAuthorized: false,
|
||||
notifyDiscord: true,
|
||||
|
||||
alertMessage: '',
|
||||
@@ -37,12 +35,8 @@ export const useStore = defineStore('store', {
|
||||
fetchSceneriesData() {
|
||||
this.dataState = 'LOADING';
|
||||
|
||||
const data = axios.get<SceneryRowItem[]>(`api/getSceneries?time=${Date.now()}`, {
|
||||
const data = axios.get<SceneryRowItem[]>(`api/getSceneries`, {
|
||||
baseURL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
},
|
||||
});
|
||||
|
||||
data
|
||||
@@ -55,13 +49,13 @@ export const useStore = defineStore('store', {
|
||||
})
|
||||
.catch(() => {
|
||||
this.dataState = 'ERROR';
|
||||
this.token = '';
|
||||
this.isAuthorized = false;
|
||||
});
|
||||
},
|
||||
|
||||
updateSceneriesData(mappedChangeList: any[]) {
|
||||
const response = axios.post(
|
||||
async updateSceneriesData(mappedChangeList: any[]) {
|
||||
console.log(mappedChangeList);
|
||||
|
||||
const response = await axios.post(
|
||||
'/manager/updateSceneryList',
|
||||
{
|
||||
changeList: mappedChangeList,
|
||||
@@ -69,32 +63,12 @@ export const useStore = defineStore('store', {
|
||||
},
|
||||
{
|
||||
baseURL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
},
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
login(name: string, pwd: string) {
|
||||
return axios.post<ILoginResponse>(
|
||||
'auth/login',
|
||||
{ username: name, password: pwd },
|
||||
{
|
||||
baseURL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
fetchTokenData() {
|
||||
return axios.post<{ user: IUser }>('auth/token', { token: this.token }, { baseURL });
|
||||
},
|
||||
},
|
||||
|
||||
getters: {
|
||||
|
||||
+7
-8
@@ -87,6 +87,11 @@ export enum AuthState {
|
||||
'UNAUTHORIZED' = 2,
|
||||
}
|
||||
|
||||
export interface IUser {
|
||||
name: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface IStore {
|
||||
dataState: string;
|
||||
authState: AuthState;
|
||||
@@ -101,9 +106,8 @@ export interface IStore {
|
||||
routesModalVisible: boolean;
|
||||
currentStation: SceneryRowItem | null;
|
||||
selectedStationName: string;
|
||||
token: string | null;
|
||||
user: { name: string; id: string } | null;
|
||||
isAuthorized: boolean;
|
||||
// token: string | null;
|
||||
user: IUser | null;
|
||||
notifyDiscord: boolean;
|
||||
alertMessage: string;
|
||||
confirmMessage: string;
|
||||
@@ -117,8 +121,3 @@ export interface ILoginResponse {
|
||||
token: string;
|
||||
user: IUser;
|
||||
}
|
||||
|
||||
export interface IUser {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
+23
-16
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="login" v-if="store.authState == AuthState.UNAUTHORIZED">
|
||||
<div class="login">
|
||||
<div class="login-header">
|
||||
<img src="/icon-logo.svg" alt="logo" />
|
||||
<h1>Stacjownik Station Manager</h1>
|
||||
</div>
|
||||
|
||||
<form @submit="signIn">
|
||||
<form @submit.prevent="signIn">
|
||||
<label for="name">Nick</label>
|
||||
<br />
|
||||
<input type="text" id="name" v-model="name" />
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../store';
|
||||
import { useStore, baseURL } from '../store';
|
||||
import { AuthState } from '../types/types';
|
||||
import axios, { HttpStatusCode } from 'axios';
|
||||
|
||||
enum LoginState {
|
||||
INITIALIZED = 0,
|
||||
@@ -52,27 +53,33 @@ export default defineComponent({
|
||||
|
||||
methods: {
|
||||
async signIn(e: Event) {
|
||||
e.preventDefault();
|
||||
this.loginState = LoginState.LOADING;
|
||||
// this.loginState = LoginState.LOADING;
|
||||
|
||||
try {
|
||||
const loginData = (await this.store.login(this.name, this.password)).data;
|
||||
// const loginData = (await this.store.login(this.name, this.password)).data;
|
||||
const response = await axios.post(
|
||||
'auth/login',
|
||||
{ username: this.name, password: this.password },
|
||||
{
|
||||
baseURL,
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
|
||||
this.store.authState = AuthState.AUTHORIZED;
|
||||
this.loginState = LoginState.LOADED;
|
||||
// this.store.authState = AuthState.AUTHORIZED;
|
||||
// this.loginState = LoginState.LOADED;
|
||||
|
||||
this.store.token = loginData.token;
|
||||
this.store.user = loginData.user;
|
||||
// this.store.token = loginData.token;
|
||||
// this.store.user = loginData.user;
|
||||
|
||||
window.localStorage.setItem('auth-token', this.store.token);
|
||||
window.localStorage.setItem('user', JSON.stringify(this.store.user));
|
||||
// window.localStorage.setItem('auth-token', this.store.token);
|
||||
// window.localStorage.setItem('user', JSON.stringify(this.store.user));
|
||||
|
||||
this.store.user = response.data;
|
||||
this.$router.push('/');
|
||||
|
||||
this.store.fetchSceneriesData();
|
||||
} catch (e: any) {
|
||||
this.store.authState = AuthState.UNAUTHORIZED;
|
||||
this.loginState = LoginState.LOADED;
|
||||
|
||||
if (!e.response || e.response.status === undefined) {
|
||||
this.errorMessage = 'Wystąpił błąd podczas łączenia z serwerem!';
|
||||
return false;
|
||||
@@ -81,7 +88,7 @@ export default defineComponent({
|
||||
const response = e.response;
|
||||
const status: number = response.status;
|
||||
|
||||
if (status == 401) {
|
||||
if (status == 400) {
|
||||
this.errorMessage = 'Nieprawidłowe dane!';
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="manager" v-if="store.authState == AuthState.AUTHORIZED">
|
||||
<div class="manager">
|
||||
<RoutesModal v-if="store.currentStation" />
|
||||
<UpdateCard v-if="store.changesResponse.length > 0" />
|
||||
|
||||
|
||||
+10
-4
@@ -1,7 +1,13 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()]
|
||||
})
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
commonjsOptions: {
|
||||
esmExternals: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user