1
0
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:
Donald Zou 2024-08-10 19:03:21 -04:00
parent 55e0d2695d
commit 54142b73fb
9 changed files with 246 additions and 62 deletions

View File

@ -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():

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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]`
}
}
}
}
}) })