rework login to wor with authentik
rework env handling a runtime remove oketbase
This commit is contained in:
@@ -6,5 +6,7 @@ COPY . ./
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
|
ENV NGINX_ENVSUBST_OUTPUT_DIR=/usr/share/nginx/html
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
COPY nginx.conf.template /etc/nginx/templates/default.conf.template
|
RUN mv -rf /usr/share/nginx/html/index.html /etc/nginx/templates/index.html.template
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
9
nginx.conf
Normal file
9
nginx.conf
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
server {
|
||||||
|
listen 80 http2;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ $uri.html /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80 http2;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ $uri.html /index.html;
|
|
||||||
}
|
|
||||||
location /marbas/ {
|
|
||||||
proxy_pass https://${MARBAS_URL}/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
rewrite /marbas/(.*) /$1 break;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_set_header Host "${MARBAS_URL}";
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_set_header Accept-Encoding "";
|
|
||||||
sub_filter 'https://${MARBAS_URL}/' '/marbas/';
|
|
||||||
sub_filter 'http://${MARBAS_URL}/' '/marbas/';
|
|
||||||
sub_filter_once off;
|
|
||||||
sub_filter_types application/json;
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
error_page 301 302 307 = @handle_redirects;
|
|
||||||
}
|
|
||||||
location /pocketbase/ {
|
|
||||||
proxy_pass https://${POCKET_BASE_URL}/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
rewrite /pocketbase/(.*) /$1 break;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_set_header Host "${POCKET_BASE_URL}";
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
error_page 301 302 307 = @handle_redirects;
|
|
||||||
}
|
|
||||||
location /evepraisal/ {
|
|
||||||
proxy_pass https://${EVEPRAISAL_URL}/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
rewrite /evepraisal/(.*) /$1 break;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_set_header Host "${EVEPRAISAL_URL}";
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
error_page 301 302 307 = @handle_redirects;
|
|
||||||
}
|
|
||||||
location /fuzzwork/ {
|
|
||||||
proxy_pass https://${FUZZWORK_URL}/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
rewrite /fuzzwork/(.*) /$1 break;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_set_header Host "${FUZZWORK_URL}";
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
error_page 301 302 307 = @handle_redirects;
|
|
||||||
}
|
|
||||||
location /esi/ {
|
|
||||||
proxy_pass https://esi.evetech.net/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
rewrite /esi/(.*) /latest/$1 break;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_set_header Host "esi.evetech.net";
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_set_header User-Agent "${ESI_USER_AGENT}";
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
error_page 301 302 307 = @handle_redirects;
|
|
||||||
}
|
|
||||||
|
|
||||||
location @handle_redirects {
|
|
||||||
set $saved_redirect_location '$upstream_http_location';
|
|
||||||
proxy_pass $saved_redirect_location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1693
package-lock.json
generated
1693
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -10,26 +10,26 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/vue": "^2.0.18",
|
"@heroicons/vue": "^2.0.18",
|
||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
|
||||||
"@vueuse/components": "^10.5.0",
|
"@vueuse/components": "^10.5.0",
|
||||||
"@vueuse/core": "^10.2.1",
|
"@vueuse/core": "^10.2.1",
|
||||||
"@vueuse/integrations": "^10.2.1",
|
"@vueuse/integrations": "^10.2.1",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"loglevel-plugin-prefix": "^0.8.4",
|
"loglevel-plugin-prefix": "^0.8.4",
|
||||||
|
"oidc-client-ts": "^3.0.1",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"pocketbase": "^0.18.0",
|
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.2.4"
|
"vue-router": "^4.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.4.5",
|
"@types/node": "^20.4.5",
|
||||||
"@vitejs/plugin-vue": "^4.2.3",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.4.5",
|
"vite": "^5.2.11",
|
||||||
"vue-tsc": "^1.8.5"
|
"vite-plugin-runtime-env": "^0.1.1",
|
||||||
|
"vue-tsc": "^2.0.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterView, useRoute } from 'vue-router';
|
import { useAuthStore } from '@/auth';
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
import { Sidebar } from './sidebar';
|
import { Sidebar } from './sidebar';
|
||||||
|
|
||||||
const route = useRoute();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="route.name === 'login'">
|
<template v-if="!authStore.isLoggedIn">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|||||||
45
src/auth.ts
Normal file
45
src/auth.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import log from "loglevel";
|
||||||
|
import { Log, User, UserManager } from "oidc-client-ts";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
|
||||||
|
Log.setLogger(log);
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
|
const userManager = new UserManager({
|
||||||
|
authority: import.meta.env.VITE_AUTH_AUTHORITY,
|
||||||
|
client_id: import.meta.env.VITE_AUTH_CLIENT_ID,
|
||||||
|
client_secret: import.meta.env.VITE_AUTH_CLIENT_SECRET,
|
||||||
|
redirect_uri: import.meta.env.VITE_AUTH_REDIRECT_URI,
|
||||||
|
scope: import.meta.env.VITE_AUTH_SCOPE,
|
||||||
|
});
|
||||||
|
|
||||||
|
const user = ref<User>();
|
||||||
|
const isLoggedIn = computed(() => !!user.value);
|
||||||
|
const accessToken = computed(() => user.value?.access_token);
|
||||||
|
const username = computed(() => user.value?.profile.name ?? "");
|
||||||
|
|
||||||
|
const redirect = async () => {
|
||||||
|
await userManager.signinRedirect();
|
||||||
|
log.info("Redirecting to login page");
|
||||||
|
}
|
||||||
|
|
||||||
|
const login = async () => {
|
||||||
|
await userManager.signinCallback();
|
||||||
|
log.debug("Logged in");
|
||||||
|
}
|
||||||
|
|
||||||
|
const logout = async () => {
|
||||||
|
await userManager.signoutRedirect();
|
||||||
|
log.debug("Logged out");
|
||||||
|
}
|
||||||
|
|
||||||
|
userManager.events.addUserLoaded(u => {
|
||||||
|
user.value = u;
|
||||||
|
log.info("User loaded", u.profile.name);
|
||||||
|
});
|
||||||
|
userManager.events.addAccessTokenExpiring(() => {
|
||||||
|
log.debug("Access token expiring");
|
||||||
|
});
|
||||||
|
return { redirect, login, logout, isLoggedIn, accessToken, username };
|
||||||
|
});
|
||||||
15
src/main.ts
15
src/main.ts
@@ -1,4 +1,4 @@
|
|||||||
import { providePocketBase } from '@/pocketbase';
|
import { useAuthStore } from "@/auth";
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
@@ -10,22 +10,25 @@ import './style.css';
|
|||||||
initLogger();
|
initLogger();
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pb = providePocketBase(app);
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(pinia);
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
router.beforeEach(async to => {
|
router.beforeEach(async to => {
|
||||||
if (!pb.authStore.isValid && to.name !== 'login') {
|
if (to.name === 'callback') {
|
||||||
return { name: 'login' };
|
await authStore.login();
|
||||||
} else if (pb.authStore.isValid && to.name === 'login') {
|
|
||||||
return { name: 'home' };
|
return { name: 'home' };
|
||||||
|
} else if (!authStore.isLoggedIn) {
|
||||||
|
await authStore.redirect();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(pinia);
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { MarketType } from "../type";
|
|||||||
import { PriceGetter } from './MarketTypePrice';
|
import { PriceGetter } from './MarketTypePrice';
|
||||||
|
|
||||||
export const evepraisalAxiosInstance = axios.create({
|
export const evepraisalAxiosInstance = axios.create({
|
||||||
baseURL: '/evepraisal/',
|
baseURL: import.meta.env.VITE_EVEPRAISAL_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { MarketType } from "../type";
|
|||||||
import { PriceGetter } from './MarketTypePrice';
|
import { PriceGetter } from './MarketTypePrice';
|
||||||
|
|
||||||
export const fuzzworkAxiosInstance = axios.create({
|
export const fuzzworkAxiosInstance = axios.create({
|
||||||
baseURL: '/fuzzwork/',
|
baseURL: import.meta.env.VITE_FUZZWORK_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { MarketOrderHistory, MarketType, MarketTypePrice, getHistory, jitaId } from "@/market";
|
import { MarketOrderHistory, MarketType, MarketTypePrice, getHistory, jitaId } from "@/market";
|
||||||
import { usePocketBase, watchCollection } from "@/pocketbase";
|
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { RecordModel } from "pocketbase";
|
import { computed, ref } from "vue";
|
||||||
import { computed, onMounted, ref } from "vue";
|
|
||||||
|
|
||||||
export type ScanResult = {
|
export type ScanResult = {
|
||||||
type: MarketType;
|
type: MarketType;
|
||||||
@@ -12,7 +10,7 @@ export type ScanResult = {
|
|||||||
orderCount: number,
|
orderCount: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MarketScan extends RecordModel {
|
interface MarketScan {
|
||||||
owner: string;
|
owner: string;
|
||||||
types: number[];
|
types: number[];
|
||||||
};
|
};
|
||||||
@@ -20,16 +18,11 @@ interface MarketScan extends RecordModel {
|
|||||||
const marketScans = 'marketScans';
|
const marketScans = 'marketScans';
|
||||||
|
|
||||||
export const useMarketScanStore = defineStore(marketScans, () => {
|
export const useMarketScanStore = defineStore(marketScans, () => {
|
||||||
const pb = usePocketBase();
|
|
||||||
const marketScan = ref<MarketScan>();
|
const marketScan = ref<MarketScan>();
|
||||||
|
|
||||||
const types = computed(() => marketScan.value?.types ?? []);
|
const types = computed(() => marketScan.value?.types ?? []);
|
||||||
const setTypes = async (types: number[]) => {
|
const setTypes = async (_types: number[]) => {
|
||||||
if (marketScan.value?.id) {
|
|
||||||
marketScan.value = await pb.collection(marketScans).update(marketScan.value.id, { owner: pb.authStore.model!.id, types });
|
|
||||||
} else {
|
|
||||||
marketScan.value = await pb.collection(marketScans).create({ owner: pb.authStore.model!.id, types });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const addType = async (type: number) => {
|
const addType = async (type: number) => {
|
||||||
if (!types.value.includes(type)) {
|
if (!types.value.includes(type)) {
|
||||||
@@ -41,15 +34,6 @@ export const useMarketScanStore = defineStore(marketScans, () => {
|
|||||||
await setTypes(types.value.filter(t => t !== type));
|
await setTypes(types.value.filter(t => t !== type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchCollection<MarketScan>(marketScans, '*', data => {
|
|
||||||
if (data.action === 'delete') {
|
|
||||||
marketScan.value = undefined;
|
|
||||||
} else if (!marketScan.value || data.record.id === marketScan.value.id) {
|
|
||||||
marketScan.value = data.record;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onMounted(async () => marketScan.value = await pb.collection(marketScans).getFirstListItem<MarketScan>('').catch(() => undefined));
|
|
||||||
return { types, setTypes, addType, removeType };
|
return { types, setTypes, addType, removeType };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { usePocketBase } from '@/pocketbase';
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
const pb = usePocketBase();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const username = ref("");
|
|
||||||
const password = ref("");
|
|
||||||
|
|
||||||
const login = async () => {
|
|
||||||
await pb.collection('users').authWithPassword(username.value, password.value);
|
|
||||||
await router.push('/');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="p-4 mx-auto mt-10 grid justify-center gap-2 w-64">
|
|
||||||
<div class="grid">
|
|
||||||
Login:
|
|
||||||
<input type="text" name="username" v-model="username" @keyup.enter="login" />
|
|
||||||
</div>
|
|
||||||
<div class="grid">
|
|
||||||
Password:
|
|
||||||
<input type="password" name="password" v-model="password" @keyup.enter="login" />
|
|
||||||
</div>
|
|
||||||
<button class="justify-self-end" name="login" @click="login">Login</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -35,7 +35,7 @@ watch(() => acquiredItemStore.items, async itms => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<template v-if="items.length > 0">
|
<template v-if="items.length > 0">
|
||||||
<AcquisitionResultTable :items="items" @buy="(type, price, buy, sell) => buyModal?.open(type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="type => sellModal?.open(type)" />
|
<AcquisitionResultTable :items="items" @buy="(type, price, buy, sell) => buyModal?.open(type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="type => sellModal?.open(type)" />
|
||||||
<BuyModal ref="buyModal" />
|
<BuyModal ref="buyModal" />
|
||||||
<SellModal ref="sellModal" />
|
<SellModal ref="sellModal" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { MarketType, MarketTypeInput, MarketTypePrice, getHistory, getMarketTypes, jitaId, useApraisalStore } from "@/market";
|
import { MarketType, MarketTypeInput, MarketTypePrice, getHistory, getMarketTypes, jitaId, useApraisalStore } from "@/market";
|
||||||
import { BuyModal } from '@/market/acquisition';
|
import { BuyModal } from '@/market/acquisition';
|
||||||
import { ScanResult, ScanResultTable, useMarketScanStore } from '@/market/scan';
|
import { ScanResult, ScanResultTable, createResult, useMarketScanStore } from '@/market/scan';
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ClipboardButton } from '@/components';
|
import { ClipboardButton } from '@/components';
|
||||||
import { MarketType, MarketTypeInput, getMarketType, useApraisalStore } from "@/market";
|
import { MarketType, MarketTypeInput, getMarketType, useApraisalStore } from "@/market";
|
||||||
|
import { BuyModal } from '@/market/acquisition';
|
||||||
import { ScanResultTable, createResult, useMarketScanStore } from '@/market/scan';
|
import { ScanResultTable, createResult, useMarketScanStore } from '@/market/scan';
|
||||||
import { BuyModal } from '@/market/track';
|
|
||||||
import { BookmarkIcon, BookmarkSlashIcon, ShoppingCartIcon } from '@heroicons/vue/24/outline';
|
import { BookmarkIcon, BookmarkSlashIcon, ShoppingCartIcon } from '@heroicons/vue/24/outline';
|
||||||
import { computedAsync } from '@vueuse/core/index.cjs';
|
import { computedAsync } from '@vueuse/core/index.cjs';
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
|
|
||||||
import { usePocketBase } from "@/pocketbase";
|
|
||||||
import { RecordModel, RecordSubscription } from "pocketbase";
|
|
||||||
import { Ref, computed, onMounted, ref } from "vue";
|
|
||||||
|
|
||||||
export const watchCollection = <T extends RecordModel = RecordModel>(collection: string, topic: string, callback: (data: RecordSubscription<T>) => void) => {
|
|
||||||
const pb = usePocketBase();
|
|
||||||
|
|
||||||
onMounted(async () => await pb.collection(collection).subscribe<T>(topic, callback));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useCollection = <T extends RecordModel = RecordModel>(collection: string) => {
|
|
||||||
const pb = usePocketBase();
|
|
||||||
const list = ref<T[]>([]) as Ref<T[]>;
|
|
||||||
|
|
||||||
watchCollection<T>(collection, '*', data => {
|
|
||||||
if (data.action === 'delete') {
|
|
||||||
list.value = list.value.filter(i => i.id !== data.record.id);
|
|
||||||
} else if (data.action === 'update') {
|
|
||||||
list.value = list.value.map(i => i.id === data.record.id ? data.record : i);
|
|
||||||
} else if (data.action === 'create') {
|
|
||||||
list.value = [...list.value, data.record];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onMounted(async () => list.value = await pb.collection(collection).getFullList<T>().catch(() => [] as T[]));
|
|
||||||
return computed(() => list.value);
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './collection';
|
|
||||||
export * from './pocketbase';
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import PocketBase from 'pocketbase';
|
|
||||||
import { App, inject } from 'vue';
|
|
||||||
|
|
||||||
const pocketBaseSymbol = Symbol('pocketBase');
|
|
||||||
|
|
||||||
export const providePocketBase = (app: App) => {
|
|
||||||
const pb = new PocketBase('/pocketbase/');
|
|
||||||
|
|
||||||
app.provide(pocketBaseSymbol, pb);
|
|
||||||
return pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const usePocketBase = () => inject<PocketBase>(pocketBaseSymbol)!;
|
|
||||||
@@ -2,7 +2,7 @@ import { RouteRecordRaw } from 'vue-router';
|
|||||||
|
|
||||||
export const routes: RouteRecordRaw[] = [
|
export const routes: RouteRecordRaw[] = [
|
||||||
{ path: '/', name: 'home', component: () => import('@/pages/Index.vue') },
|
{ path: '/', name: 'home', component: () => import('@/pages/Index.vue') },
|
||||||
{ path: '/login', name: 'login', component: () => import('@/pages/Login.vue') },
|
{ path: '/callback', name: 'callback', component: () => import('@/pages/Index.vue') },
|
||||||
{ path: '/reprocess', component: () => import('@/pages/Reprocess.vue') },
|
{ path: '/reprocess', component: () => import('@/pages/Reprocess.vue') },
|
||||||
{ path: '/market', component: () => import('@/pages/Market.vue'), children: [
|
{ path: '/market', component: () => import('@/pages/Market.vue'), children: [
|
||||||
{ path: '', redirect: '/market/type' },
|
{ path: '', redirect: '/market/type' },
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useAuthStore } from '@/auth';
|
||||||
import axios, { AxiosInstance } from 'axios';
|
import axios, { AxiosInstance } from 'axios';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
|
|
||||||
@@ -13,9 +14,9 @@ export const logResource = (a: AxiosInstance) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const marbasAxiosInstance = axios.create({
|
export const marbasAxiosInstance = axios.create({
|
||||||
baseURL: '/marbas/',
|
baseURL: import.meta.env.VITE_MARBAS_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -42,12 +43,21 @@ marbasAxiosInstance.interceptors.response.use(async r => {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
})
|
})
|
||||||
|
marbasAxiosInstance.interceptors.request.use(r => {
|
||||||
|
const accessToken = useAuthStore().accessToken;
|
||||||
|
|
||||||
|
if (accessToken) {
|
||||||
|
r.headers.Authorization = `Bearer ${accessToken}`;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
})
|
||||||
|
|
||||||
export const esiAxiosInstance = axios.create({
|
export const esiAxiosInstance = axios.create({
|
||||||
baseURL: '/esi/',
|
baseURL: import.meta.env.VITE_ESI_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json",
|
||||||
|
"User-Agent": import.meta.env.VITE_ESI_USER_AGENT
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
logResource(esiAxiosInstance)
|
logResource(esiAxiosInstance)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { usePocketBase } from '@/pocketbase';
|
import { useAuthStore } from '@/auth';
|
||||||
import { RouterLink, useRouter } from 'vue-router';
|
import { RouterLink } from 'vue-router';
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{ name: "Market", path: "/market" },
|
{ name: "Market", path: "/market" },
|
||||||
@@ -8,12 +8,10 @@ const links = [
|
|||||||
{ name: "Tools", path: "/tools" }
|
{ name: "Tools", path: "/tools" }
|
||||||
];
|
];
|
||||||
|
|
||||||
const pb = usePocketBase();
|
const authStore = useAuthStore();
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
pb.authStore.clear();
|
await authStore.logout();
|
||||||
await router.push({ name: 'login' });
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import vue from '@vitejs/plugin-vue';
|
import vue from '@vitejs/plugin-vue';
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { defineConfig, loadEnv } from 'vite';
|
import { defineConfig, loadEnv } from 'vite';
|
||||||
import zlib from 'zlib';
|
import runtimeEnv from 'vite-plugin-runtime-env';
|
||||||
|
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const env = loadEnv(mode, process.cwd(), '');
|
const env = loadEnv(mode, process.cwd(), '');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins: [vue()],
|
plugins: [
|
||||||
|
runtimeEnv(),
|
||||||
|
vue(),
|
||||||
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'src': path.resolve(__dirname, './src/'),
|
'src': path.resolve(__dirname, './src/'),
|
||||||
@@ -21,74 +24,6 @@ export default defineConfig(({ mode }) => {
|
|||||||
watch: {
|
watch: {
|
||||||
usePolling: true
|
usePolling: true
|
||||||
},
|
},
|
||||||
proxy: {
|
|
||||||
'/marbas/': {
|
|
||||||
target: env.MARBAS_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
followRedirects: true,
|
|
||||||
rewrite: path => path.replace(/^\/marbas/, ''),
|
|
||||||
selfHandleResponse: true,
|
|
||||||
configure: proxy => {
|
|
||||||
proxy.on('proxyRes', (proxyRes, req, res) => {
|
|
||||||
const chunks = [];
|
|
||||||
|
|
||||||
proxyRes.on("data", (chunk) => chunks.push(chunk));
|
|
||||||
proxyRes.on("end", () => {
|
|
||||||
const buffer = Buffer.concat(chunks);
|
|
||||||
const encoding = proxyRes.headers["content-encoding"];
|
|
||||||
const relace = (b: Buffer) => {
|
|
||||||
let remoteBody = b.toString();
|
|
||||||
const modifiedBody = remoteBody.replace(env.MARBAS_URL, '/marbas/');
|
|
||||||
|
|
||||||
res.write(modifiedBody);
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!encoding) {
|
|
||||||
relace(buffer);
|
|
||||||
} else if (encoding === "gzip" || encoding === "deflate") {
|
|
||||||
zlib.unzip(buffer, (err, b) => {
|
|
||||||
if (!err) {
|
|
||||||
relace(b);
|
|
||||||
} else {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(`Unsupported encoding: ${encoding}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'/pocketbase/': {
|
|
||||||
target: env.POCKET_BASE_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
followRedirects: true,
|
|
||||||
rewrite: path => path.replace(/^\/pocketbase/, ''),
|
|
||||||
},
|
|
||||||
'/evepraisal/': {
|
|
||||||
target: env.EVEPRAISAL_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
followRedirects: true,
|
|
||||||
rewrite: path => path.replace(/^\/evepraisal/, ''),
|
|
||||||
},
|
|
||||||
'/fuzzwork/': {
|
|
||||||
target: env.FUZZWORK_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
followRedirects: true,
|
|
||||||
rewrite: path => path.replace(/^\/fuzzwork/, ''),
|
|
||||||
},
|
|
||||||
'/esi/': {
|
|
||||||
target: env.ESI_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
followRedirects: true,
|
|
||||||
rewrite: path => path.replace(/^\/esi/, ''),
|
|
||||||
headers: {
|
|
||||||
'User-Agent': env.ESI_USER_AGENT
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user