mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-06-28 01:06:58 +00:00
Update
This commit is contained in:
parent
6cb30bcd7f
commit
c6af129960
@ -81,7 +81,10 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
||||
if session.get('username') is None:
|
||||
return ResponseObject(False, "Sign in status is invalid", status_code=401)
|
||||
session['totpVerified'] = True
|
||||
return ResponseObject(True)
|
||||
return ResponseObject(True, data={
|
||||
"Email": session.get('username'),
|
||||
"Profile": DashboardClients.GetClientProfile(session.get("ClientID"))
|
||||
})
|
||||
return ResponseObject(status, msg)
|
||||
|
||||
@client.get(prefix)
|
||||
|
@ -59,7 +59,14 @@ class DashboardClients:
|
||||
).where(
|
||||
self.dashboardClientsTable.c.DeletedDate is None)
|
||||
).mappings().fetchall()
|
||||
|
||||
|
||||
def GetClientProfile(self, ClientID):
|
||||
with self.engine.connect() as conn:
|
||||
return dict(conn.execute(
|
||||
self.dashboardClientsInfoTable.select().where(
|
||||
self.dashboardClientsInfoTable.c.ClientID == ClientID
|
||||
)
|
||||
).mappings().fetchone())
|
||||
|
||||
def SignIn(self, Email, Password) -> tuple[bool, str]:
|
||||
if not all([Email, Password]):
|
||||
|
@ -74,10 +74,8 @@ class DashboardClientsPeerAssignment:
|
||||
|
||||
def GetAssignedPeers(self, ClientID):
|
||||
peers = []
|
||||
assigned = list(
|
||||
filter(lambda e:
|
||||
e['ClientID'] == ClientID, self.assignments)
|
||||
)
|
||||
assigned = filter(lambda e:
|
||||
e['ClientID'] == ClientID, self.assignments)
|
||||
|
||||
for a in assigned:
|
||||
peer = filter(lambda e : e.id == a['PeerID'],
|
||||
@ -97,6 +95,4 @@ class DashboardClientsPeerAssignment:
|
||||
'configuration_name': a['ConfigurationName'],
|
||||
'peer_configuration_data': p.downloadPeer()
|
||||
})
|
||||
|
||||
print(peers)
|
||||
return peers
|
@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import './assets/main.css'
|
||||
import NotificationList from "@/components/notification/notificationList.vue";
|
||||
import NotificationList from "@/components/Notification/notificationList.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -0,0 +1,82 @@
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import ConfigurationQRCode from "@/components/Configuration/configurationQRCode.vue";
|
||||
|
||||
const props = defineProps([
|
||||
'config'
|
||||
])
|
||||
|
||||
const showQRCode = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card shadow rounded-3">
|
||||
<div class="card-header d-flex align-items-center">
|
||||
<div>
|
||||
<small v-if="props.config.status === 'stopped'">
|
||||
<i class="bi bi-lightbulb text-secondary me-2"></i>
|
||||
</small>
|
||||
<small v-else>
|
||||
<i class="bi bi-lightbulb-fill text-success me-2"></i>
|
||||
</small>
|
||||
<small style="word-break: break-all">
|
||||
{{ props.config.name }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="ms-auto d-flex gap-2 button-group">
|
||||
<a role="button" class="px-2 py-1 text-white rounded-3" aria-label="Download Configuration">
|
||||
<i class="bi bi-download"></i>
|
||||
</a>
|
||||
<a role="button"
|
||||
@click="showQRCode = true"
|
||||
class="px-2 py-1 text-white rounded-3" aria-label="Display QR Code">
|
||||
<i class="bi bi-qr-code"></i>
|
||||
</a>
|
||||
<Transition name="app">
|
||||
<ConfigurationQRCode
|
||||
v-if="showQRCode"
|
||||
@back="showQRCode = false"
|
||||
:qrcode-data="config.peer_configuration_data.file"></ConfigurationQRCode>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<small class="d-block text-muted" style="font-size: 0.8rem">Public Key</small>
|
||||
<small>
|
||||
<samp style="word-break: break-word">{{ props.config.id }}</samp>
|
||||
</small>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<h6 class="text-center">Data Usage</h6>
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<small class="d-block text-muted">
|
||||
Total
|
||||
</small>
|
||||
<small>3.20 GB / 4GB</small>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<small class="d-block text-muted">
|
||||
Received
|
||||
</small>
|
||||
<small>3.20 GB</small>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<small class="d-block text-muted">
|
||||
Sent
|
||||
</small>
|
||||
<small>3.20 GB</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.button-group a:hover{
|
||||
background-color: #ffffff20;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
import * as uuid from "uuid";
|
||||
import {onMounted} from "vue";
|
||||
import QRCode from "qrcode";
|
||||
import Qrcode from "@/components/SignIn/qrcode.vue";
|
||||
|
||||
const props = defineProps([
|
||||
'qrcodeData'
|
||||
])
|
||||
|
||||
const emits = defineEmits([
|
||||
'back'
|
||||
])
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-2 position-fixed top-0 start-0 vw-100 vh-100 d-flex qrcodeContainer">
|
||||
<div class="m-auto d-flex gap-3 flex-column">
|
||||
<a role="button" @click="emits('back')">
|
||||
<i class="me-2 bi bi-chevron-left"></i> Back
|
||||
</a>
|
||||
<Qrcode :content="props.qrcodeData" ></Qrcode>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.qrcodeContainer{
|
||||
background-color: #00000050;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
import Notification from "@/components/notification/notification.vue";
|
||||
import Notification from "@/components/Notification/notification.vue";
|
||||
import {computed, onMounted} from "vue";
|
||||
const store = clientStore()
|
||||
const notifications = computed(() => {
|
@ -1,19 +1,21 @@
|
||||
<script setup>
|
||||
import {onMounted} from "vue";
|
||||
import QRCode from "qrcode";
|
||||
import * as uuid from "uuid";
|
||||
|
||||
const props = defineProps([
|
||||
"content"
|
||||
])
|
||||
const id = uuid.v4().toString()
|
||||
|
||||
onMounted(() => {
|
||||
QRCode.toCanvas(document.getElementById('qrcode'), props.content, function (error) {})
|
||||
QRCode.toCanvas(document.getElementById(`qrcode_${id}`), props.content, function (error) {})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<canvas id="qrcode" class="rounded-3 shadow"></canvas>
|
||||
<canvas :id="'qrcode_' + id" class="rounded-3 shadow"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup async>
|
||||
import {computed, onMounted, reactive, ref} from "vue";
|
||||
import {computed, onMounted, reactive, ref, watch} from "vue";
|
||||
import axios from "axios";
|
||||
import {axiosPost, requestURl} from "@/utilities/request.js";
|
||||
import {useRouter} from "vue-router";
|
||||
@ -45,13 +45,8 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const emits = defineEmits(['clearToken'])
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
|
||||
const verify = async (e) => {
|
||||
e.preventDefault()
|
||||
if (e) e.preventDefault()
|
||||
if (formFilled){
|
||||
loading.value = true
|
||||
const data = await axiosPost('/api/signin/totp', {
|
||||
@ -61,6 +56,7 @@ const verify = async (e) => {
|
||||
loading.value = false
|
||||
if (data){
|
||||
if (data.status){
|
||||
store.clientProfile = data.data
|
||||
router.push('/')
|
||||
}else{
|
||||
store.newNotification(data.message, "danger")
|
||||
@ -71,6 +67,10 @@ const verify = async (e) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(formFilled, () => {
|
||||
verify()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,11 +1,19 @@
|
||||
import {defineStore} from "pinia";
|
||||
import {ref} from "vue";
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import {v4} from "uuid"
|
||||
import dayjs from "dayjs";
|
||||
import {axiosGet} from "@/utilities/request.js";
|
||||
|
||||
|
||||
export const clientStore = defineStore('clientStore', () => {
|
||||
const notifications = ref([])
|
||||
const configurations = ref([])
|
||||
const clientProfile = reactive({
|
||||
Email: "",
|
||||
Profile: {}
|
||||
})
|
||||
|
||||
|
||||
function newNotification(content, status) {
|
||||
notifications.value.push({
|
||||
id: v4().toString(),
|
||||
@ -15,8 +23,16 @@ export const clientStore = defineStore('clientStore', () => {
|
||||
show: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
async function getConfigurations(){
|
||||
const data = await axiosGet("/api/configurations")
|
||||
if (data){
|
||||
configurations.value = data.data
|
||||
}else{
|
||||
newNotification("Failed to fetch configurations", "danger")
|
||||
}
|
||||
}
|
||||
return {
|
||||
notifications, newNotification
|
||||
notifications, newNotification, getConfigurations, configurations, clientProfile
|
||||
}
|
||||
})
|
@ -1,14 +1,26 @@
|
||||
<script setup>
|
||||
import {onMounted} from "vue";
|
||||
<script setup async>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {axiosGet} from "@/utilities/request.js";
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
import Configuration from "@/components/Configuration/configuration.vue";
|
||||
const store = clientStore()
|
||||
const loading = ref(true)
|
||||
|
||||
const loadConfigurations = async () => {
|
||||
|
||||
await store.getConfigurations()
|
||||
|
||||
}
|
||||
|
||||
const configurations = computed(() => {
|
||||
return store.configurations
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const data = await axiosGet("/api/configurations")
|
||||
if (data){
|
||||
console.log(data)
|
||||
}else{
|
||||
// loading.value = true;
|
||||
await loadConfigurations();
|
||||
loading.value = false;
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -33,13 +45,23 @@ onMounted(async () => {
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<div class="px-3 border-bottom py-4">
|
||||
<h6>Hi donaldzou@live.hk!</h6>
|
||||
<h5 class="mb-0">You have <strong>3</strong> configurations available</h5>
|
||||
<Transition name="app" mode="out-in">
|
||||
<div class="d-flex flex-column gap-3" v-if="!loading">
|
||||
<div class="px-3 border-bottom py-4">
|
||||
<h6>Hi donaldzou@live.hk!</h6>
|
||||
<h5 class="mb-0">You have <strong>
|
||||
{{ configurations.length }}
|
||||
</strong> configuration{{ configurations.length > 1 ? 's':''}} available</h5>
|
||||
</div>
|
||||
<div class="px-3">
|
||||
<Configuration v-for="config in configurations" :config="config"></Configuration>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div v-else class="d-flex py-4">
|
||||
<div class="spinner-border m-auto"></div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user