mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-06 16:00:28 +01:00
Ohhhhh kay testing CORS :)
This commit is contained in:
parent
55e0d2695d
commit
54142b73fb
@ -47,7 +47,11 @@ UPDATE = None
|
|||||||
app = Flask("WGDashboard")
|
app = Flask("WGDashboard")
|
||||||
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
||||||
app.secret_key = secrets.token_urlsafe(32)
|
app.secret_key = secrets.token_urlsafe(32)
|
||||||
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
|
cors = CORS(app, resources={r"/api/*": {
|
||||||
|
"origins": "*",
|
||||||
|
"methods": "DELETE, POST, GET, OPTIONS",
|
||||||
|
"allow_headers": ["Content-Type", "wg-dashboard-apikey"]
|
||||||
|
}})
|
||||||
|
|
||||||
class ModelEncoder(JSONEncoder):
|
class ModelEncoder(JSONEncoder):
|
||||||
def default(self, o: Any) -> Any:
|
def default(self, o: Any) -> Any:
|
||||||
@ -1345,6 +1349,9 @@ API Routes
|
|||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def auth_req():
|
def auth_req():
|
||||||
|
if request.method.lower() == 'options':
|
||||||
|
return ResponseObject(True)
|
||||||
|
|
||||||
if "api" in request.path:
|
if "api" in request.path:
|
||||||
if str(request.method) == "GET":
|
if str(request.method) == "GET":
|
||||||
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=str(request.args))
|
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=str(request.args))
|
||||||
@ -1385,6 +1392,10 @@ def auth_req():
|
|||||||
response.status_code = 401
|
response.status_code = 401
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@app.route('/api/handshake', methods=["GET", "OPTIONS"])
|
||||||
|
def API_ValidateAPIKey():
|
||||||
|
return ResponseObject(True)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/validateAuthentication', methods=["GET"])
|
@app.route('/api/validateAuthentication', methods=["GET"])
|
||||||
def API_ValidateAuthentication():
|
def API_ValidateAuthentication():
|
||||||
|
4
src/static/app/dist/assets/index.css
vendored
4
src/static/app/dist/assets/index.css
vendored
File diff suppressed because one or more lines are too long
54
src/static/app/dist/assets/index.js
vendored
54
src/static/app/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
@ -1,7 +1,17 @@
|
|||||||
<script setup >
|
<script setup>
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import {watch} from "vue";
|
||||||
const store = DashboardConfigurationStore();
|
const store = DashboardConfigurationStore();
|
||||||
|
store.initCrossServerConfiguration();
|
||||||
|
|
||||||
|
watch(store.CrossServerConfiguration, () => {
|
||||||
|
store.syncCrossServerConfiguration()
|
||||||
|
}, {
|
||||||
|
deep: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
<script>
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "RemoteServer",
|
||||||
|
props: {
|
||||||
|
server: Object
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
active: false,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handshake(){
|
||||||
|
this.startTime = undefined;
|
||||||
|
this.endTime = undefined;
|
||||||
|
|
||||||
|
this.startTime = dayjs()
|
||||||
|
fetch(`//${this.server.host}/api/handshake`, {
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"wg-dashboard-apikey": this.server.apiKey
|
||||||
|
},
|
||||||
|
method: "GET",
|
||||||
|
signal: AbortSignal.timeout(5000)
|
||||||
|
}).then(res => res.json()).then(res => {
|
||||||
|
this.active = true;
|
||||||
|
this.endTime = dayjs()
|
||||||
|
}).catch((res) => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.handshake()
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getHandshakeTime(){
|
||||||
|
if (this.startTime && this.endTime){
|
||||||
|
return dayjs().subtract(this.startTime).millisecond()
|
||||||
|
}else{
|
||||||
|
return "N/A"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="card rounded-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex gap-3 w-100">
|
||||||
|
<div class="d-flex gap-3 align-items-center flex-grow-1">
|
||||||
|
<i class="bi bi-server"></i>
|
||||||
|
<input class="form-control form-control-sm"
|
||||||
|
v-model="this.server.host"
|
||||||
|
type="url">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-3 align-items-center flex-grow-1">
|
||||||
|
<i class="bi bi-key-fill"></i>
|
||||||
|
<input class="form-control form-control-sm"
|
||||||
|
v-model="this.server.apiKey"
|
||||||
|
type="text">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button
|
||||||
|
@click="this.$emit('delete')"
|
||||||
|
class="ms-auto btn btn-sm bg-danger-subtle text-danger-emphasis border-1 border-danger-subtle">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
<button class="ms-auto btn btn-sm bg-success-subtle text-success-emphasis border-1 border-success-subtle">
|
||||||
|
<i class="bi bi-arrow-right-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer gap-2 d-flex align-items-center">
|
||||||
|
<span class="dot ms-0 me-2" :class="[this.active ? 'active':'inactive']"></span>
|
||||||
|
{{this.getHandshakeTime}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dot.inactive{
|
||||||
|
background-color: #dc3545;
|
||||||
|
box-shadow: 0 0 0 0.2rem #dc354545;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,35 @@
|
|||||||
|
<script>
|
||||||
|
import RemoteServer from "@/components/signInComponents/RemoteServer.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "RemoteServerList",
|
||||||
|
setup(){
|
||||||
|
const store = DashboardConfigurationStore();
|
||||||
|
return {store}
|
||||||
|
},
|
||||||
|
components: {RemoteServer}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-100 mt-3">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<h5 class="mb-0">Server List</h5>
|
||||||
|
<button
|
||||||
|
@click="this.store.addCrossServerConfiguration()"
|
||||||
|
class="btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle shadow-sm ms-auto">
|
||||||
|
<i class="bi bi-plus-circle-fill me-2"></i>Server
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="w-100 py-3 d-flex gap-3 flex-column" style="height: 400px">
|
||||||
|
<RemoteServer v-for="(server, index) in this.store.CrossServerConfiguration.ServerList"
|
||||||
|
@delete="this.store.CrossServerConfiguration.ServerList.splice(index, 1)"
|
||||||
|
:server="server"></RemoteServer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -10,9 +10,31 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
|
|||||||
Peers: {
|
Peers: {
|
||||||
Selecting: false,
|
Selecting: false,
|
||||||
RefreshInterval: undefined
|
RefreshInterval: undefined
|
||||||
|
},
|
||||||
|
CrossServerConfiguration:{
|
||||||
|
Enable: false,
|
||||||
|
ServerList: []
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
|
initCrossServerConfiguration(){
|
||||||
|
const currentConfiguration = localStorage.getItem('CrossServerConfiguration');
|
||||||
|
|
||||||
|
if (currentConfiguration === null){
|
||||||
|
localStorage.setItem('CrossServerConfiguration', JSON.stringify(this.CrossServerConfiguration))
|
||||||
|
}else{
|
||||||
|
this.CrossServerConfiguration = JSON.parse(currentConfiguration)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
syncCrossServerConfiguration(){
|
||||||
|
localStorage.setItem('CrossServerConfiguration', JSON.stringify(this.CrossServerConfiguration))
|
||||||
|
},
|
||||||
|
addCrossServerConfiguration(){
|
||||||
|
this.CrossServerConfiguration.ServerList.push(
|
||||||
|
{host: "", apiKey: ""}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
async getConfiguration(){
|
async getConfiguration(){
|
||||||
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
|
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
|
||||||
if (res.status) this.Configuration = res.data
|
if (res.status) this.Configuration = res.data
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
import {fetchGet, fetchPost} from "../utilities/fetch.js";
|
import {fetchGet, fetchPost} from "../utilities/fetch.js";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import Message from "@/components/messageCentreComponent/message.vue";
|
import Message from "@/components/messageCentreComponent/message.vue";
|
||||||
|
import RemoteServerList from "@/components/signInComponents/RemoteServerList.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "signin",
|
name: "signin",
|
||||||
components: {Message},
|
components: {RemoteServerList, Message},
|
||||||
async setup(){
|
async setup(){
|
||||||
const store = DashboardConfigurationStore()
|
const store = DashboardConfigurationStore()
|
||||||
let theme = ""
|
let theme = ""
|
||||||
@ -83,7 +84,7 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid login-container-fluid d-flex main flex-column" :data-bs-theme="this.theme">
|
<div class="container-fluid login-container-fluid d-flex main flex-column" :data-bs-theme="this.theme">
|
||||||
<div class="login-box m-auto" style="width: 600px;">
|
<div class="login-box m-auto" style="width: 700px;">
|
||||||
<div class="m-auto">
|
<div class="m-auto">
|
||||||
<div class="card px-4 py-5 rounded-4 shadow-lg">
|
<div class="card px-4 py-5 rounded-4 shadow-lg">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -92,7 +93,8 @@ export default {
|
|||||||
<div class="alert alert-danger mt-2 mb-0" role="alert" v-if="loginError">
|
<div class="alert alert-danger mt-2 mb-0" role="alert" v-if="loginError">
|
||||||
{{this.loginErrorMessage}}
|
{{this.loginErrorMessage}}
|
||||||
</div>
|
</div>
|
||||||
<form @submit="(e) => {e.preventDefault(); this.auth();}">
|
<form @submit="(e) => {e.preventDefault(); this.auth();}"
|
||||||
|
v-if="!this.store.CrossServerConfiguration.Enable">
|
||||||
<div class="form-group text-body">
|
<div class="form-group text-body">
|
||||||
<label for="username" class="text-left" style="font-size: 1rem">
|
<label for="username" class="text-left" style="font-size: 1rem">
|
||||||
<i class="bi bi-person-circle"></i></label>
|
<i class="bi bi-person-circle"></i></label>
|
||||||
@ -128,6 +130,16 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<RemoteServerList v-else></RemoteServerList>
|
||||||
|
|
||||||
|
<div class="d-flex mt-3">
|
||||||
|
<div class="form-check form-switch ms-auto">
|
||||||
|
<input
|
||||||
|
v-model="this.store.CrossServerConfiguration.Enable"
|
||||||
|
class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckChecked">
|
||||||
|
<label class="form-check-label" for="flexSwitchCheckChecked">Access Remote Server</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,34 +6,7 @@ import vue from '@vitejs/plugin-vue'
|
|||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(({mode}) => {
|
export default defineConfig(({mode}) => {
|
||||||
if (mode === 'production'){
|
|
||||||
return {
|
|
||||||
base: "/static/app/dist",
|
|
||||||
plugins: [
|
|
||||||
vue(),
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
server:{
|
|
||||||
proxy: {
|
|
||||||
'/api': proxy
|
|
||||||
}
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
outDir: 'dist',
|
|
||||||
rollupOptions: {
|
|
||||||
output: {
|
|
||||||
entryFileNames: `assets/[name].js`,
|
|
||||||
chunkFileNames: `assets/[name].js`,
|
|
||||||
assetFileNames: `assets/[name].[ext]`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === 'electron'){
|
if (mode === 'electron'){
|
||||||
return {
|
return {
|
||||||
@ -64,4 +37,32 @@ export default defineConfig(({mode}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
base: "/static/app/dist",
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server:{
|
||||||
|
proxy: {
|
||||||
|
'/api': proxy
|
||||||
|
},
|
||||||
|
host: '0.0.0.0'
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
entryFileNames: `assets/[name].js`,
|
||||||
|
chunkFileNames: `assets/[name].js`,
|
||||||
|
assetFileNames: `assets/[name].[ext]`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user