mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-06-28 09:16:55 +00:00
Update
This commit is contained in:
parent
68fae3b23c
commit
41bf9b8baa
@ -55,9 +55,9 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
||||
|
||||
@client.get(f'{prefix}/api/signout')
|
||||
def ClientAPI_SignOut():
|
||||
session.pop('username')
|
||||
session.pop('role')
|
||||
session.pop('totpVerified')
|
||||
session['username'] = None
|
||||
session['role'] = None
|
||||
session['totpVerified'] = None
|
||||
return ResponseObject(True)
|
||||
|
||||
@client.get(f'{prefix}/api/signin/totp')
|
||||
@ -81,7 +81,7 @@ 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, data=)
|
||||
return ResponseObject(True)
|
||||
return ResponseObject(status, msg)
|
||||
|
||||
@client.get(prefix)
|
||||
|
@ -6,6 +6,7 @@ import pyotp
|
||||
import sqlalchemy as db
|
||||
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardClientsPeerAssignment import DashboardClientsPeerAssignment
|
||||
from .DashboardClientsTOTP import DashboardClientsTOTP
|
||||
from .Utilities import ValidatePasswordStrength
|
||||
from .DashboardLogger import DashboardLogger
|
||||
@ -18,7 +19,6 @@ class DashboardClients:
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
|
||||
|
||||
self.dashboardClientsTable = db.Table(
|
||||
'DashboardClients', self.metadata,
|
||||
db.Column('ClientID', db.String(255), nullable=False, primary_key=True),
|
||||
@ -46,6 +46,7 @@ class DashboardClients:
|
||||
self.Clients = []
|
||||
self.__getClients()
|
||||
self.DashboardClientsTOTP = DashboardClientsTOTP()
|
||||
self.DashboardClientsPeerAssignment = DashboardClientsPeerAssignment()
|
||||
|
||||
def __getClients(self):
|
||||
with self.engine.connect() as conn:
|
||||
@ -76,6 +77,7 @@ class DashboardClients:
|
||||
|
||||
def SignIn_GetTotp(self, Token: str, UserProvidedTotp: str = None) -> tuple[bool, str] or tuple[bool, None, str]:
|
||||
status, data = self.DashboardClientsTOTP.GetTotp(Token)
|
||||
|
||||
if not status:
|
||||
return False, "TOTP Token is invalid"
|
||||
if UserProvidedTotp is None:
|
||||
@ -83,7 +85,7 @@ class DashboardClients:
|
||||
return True, pyotp.totp.TOTP(data.get('TotpKey')).provisioning_uri(name=data.get('Email'),
|
||||
issuer_name="WGDashboard Client")
|
||||
else:
|
||||
totpMatched = pyotp.TOTP(data.get('TotpKey')).verify(UserProvidedTotp)
|
||||
totpMatched = pyotp.totp.TOTP(data.get('TotpKey')).verify(UserProvidedTotp)
|
||||
if not totpMatched:
|
||||
return False, "TOTP is does not match"
|
||||
else:
|
||||
|
46
src/modules/DashboardClientsPeerAssignment.py
Normal file
46
src/modules/DashboardClientsPeerAssignment.py
Normal file
@ -0,0 +1,46 @@
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardLogger import DashboardLogger
|
||||
import sqlalchemy as db
|
||||
|
||||
|
||||
class DashboardClientsPeerAssignment:
|
||||
def __init__(self):
|
||||
self.logger = DashboardLogger()
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
|
||||
self.dashboardClientsPeerAssignmentTable = db.Table(
|
||||
'DashboardClientsPeerAssignment', self.metadata,
|
||||
db.Column('AssignmentID', db.String(255), nullable=False, primary_key=True),
|
||||
db.Column('ClientID', db.String(255), nullable=False, index=True),
|
||||
db.Column('ConfigurationName', db.String(255)),
|
||||
db.Column('PeerID', db.String(500)),
|
||||
db.Column('AssignedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('UnassignedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||
extend_existing=True
|
||||
)
|
||||
self.metadata.create_all(self.engine)
|
||||
self.assignments = []
|
||||
|
||||
def __getAssignments(self):
|
||||
with self.engine.connect() as conn:
|
||||
self.assignments = conn.execute(
|
||||
self.dashboardClientsPeerAssignmentTable.select().where(
|
||||
self.dashboardClientsPeerAssignmentTable.c.UnassignedDate is None
|
||||
)
|
||||
).mappings().fetchall()
|
||||
|
||||
def AssignClient(self, ClientID, ConfigurationName, PeerID):
|
||||
pass
|
||||
|
||||
def UnassignClient(self, AssignmentID):
|
||||
pass
|
||||
|
||||
def GetAssignedClient(self, ConfigurationName, PeerID):
|
||||
pass
|
||||
|
||||
def GetAssignedPeers(self, ClientID):
|
||||
pass
|
22
src/static/client/src/components/SignIn/qrcode.vue
Normal file
22
src/static/client/src/components/SignIn/qrcode.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<script setup>
|
||||
import {onMounted} from "vue";
|
||||
import QRCode from "qrcode";
|
||||
|
||||
const props = defineProps([
|
||||
"content"
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
QRCode.toCanvas(document.getElementById('qrcode'), props.content, function (error) {})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<canvas id="qrcode" class="rounded-3 shadow"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -2,7 +2,7 @@
|
||||
import {computed, reactive, ref} from "vue";
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
import axios from "axios";
|
||||
import {requestURl} from "@/utilities/request.js";
|
||||
import {axiosPost, requestURl} from "@/utilities/request.js";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
const loading = ref(false)
|
||||
const formData = reactive({
|
||||
@ -20,15 +20,14 @@ const signIn = async (e) => {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
await axios.post(requestURl("/api/signin"), formData).then(res => {
|
||||
let data = res.data;
|
||||
if (!data.status){
|
||||
store.newNotification(data.message, "danger")
|
||||
loading.value = false;
|
||||
}else{
|
||||
emits("totpToken", data.message)
|
||||
}
|
||||
})
|
||||
|
||||
const data = await axiosPost("/api/signin", formData)
|
||||
if (!data.status){
|
||||
store.newNotification(data.message, "danger")
|
||||
loading.value = false;
|
||||
}else{
|
||||
emits("totpToken", data.message)
|
||||
}
|
||||
}
|
||||
|
||||
const formFilled = computed(() => {
|
||||
|
@ -1,10 +1,10 @@
|
||||
<script setup async>
|
||||
import {computed, onMounted, reactive, ref} from "vue";
|
||||
import axios from "axios";
|
||||
import {requestURl} from "@/utilities/request.js";
|
||||
import {axiosPost, requestURl} from "@/utilities/request.js";
|
||||
import {useRouter} from "vue-router";
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
import QRCode from "qrcode";
|
||||
import Qrcode from "@/components/SignIn/qrcode.vue";
|
||||
|
||||
const props = defineProps([
|
||||
'totpToken'
|
||||
@ -47,30 +47,28 @@ onMounted(() => {
|
||||
const emits = defineEmits(['clearToken'])
|
||||
|
||||
onMounted(() => {
|
||||
if (totpKey.value){
|
||||
QRCode.toCanvas(document.getElementById('qrcode'), totpKey.value, function (error) {})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const verify = async (e) => {
|
||||
e.preventDefault()
|
||||
if (formFilled){
|
||||
loading.value = true
|
||||
await axios.post(requestURl('/api/signin/totp'), {
|
||||
const data = await axiosPost('/api/signin/totp', {
|
||||
Token: props.totpToken,
|
||||
UserProvidedTOTP: formData.TOTP
|
||||
}).then(res => {
|
||||
loading.value = false
|
||||
let data = res.data
|
||||
})
|
||||
loading.value = false
|
||||
if (data){
|
||||
if (data.status){
|
||||
router.push('/')
|
||||
}else{
|
||||
store.newNotification(data.message, "danger")
|
||||
}
|
||||
}).catch(() => {
|
||||
}else{
|
||||
store.newNotification("Sign in status is invalid", "danger")
|
||||
emits('clearToken')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -88,7 +86,7 @@ const verify = async (e) => {
|
||||
<div class="card-body d-flex gap-3 flex-column">
|
||||
<h2 class="mb-0">Initial Setup</h2>
|
||||
<p class="mb-0">Please scan the following QR Code to generate TOTP with your choice of authenticator</p>
|
||||
<canvas id="qrcode" class="rounded-3 shadow "></canvas>
|
||||
<Qrcode :content="totpKey"></Qrcode>
|
||||
<p class="mb-0">Or you can click the link below:</p>
|
||||
<div class="card rounded-3 ">
|
||||
<div class="card-body">
|
||||
|
@ -3,7 +3,7 @@ import Index from "@/views/index.vue";
|
||||
import SignIn from "@/views/signin.vue";
|
||||
import SignUp from "@/views/signup.vue";
|
||||
import axios from "axios";
|
||||
import {requestURl} from "@/utilities/request.js";
|
||||
import {axiosGet, requestURl} from "@/utilities/request.js";
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
|
||||
const router = createRouter({
|
||||
@ -37,6 +37,8 @@ router.beforeEach(async (to, from, next) => {
|
||||
const store = clientStore()
|
||||
|
||||
if (to.path === '/signout'){
|
||||
|
||||
|
||||
await axios.get(requestURl('/api/signout')).then(() => {
|
||||
next('/signin')
|
||||
}).catch(() => {
|
||||
@ -45,13 +47,13 @@ router.beforeEach(async (to, from, next) => {
|
||||
store.newNotification("Sign in session ended, please sign in again", "warning")
|
||||
}else{
|
||||
if (to.meta.auth){
|
||||
await axios.get(requestURl('/api/validateAuthentication')).then(res => {
|
||||
const status = await axiosGet('/api/validateAuthentication')
|
||||
if (status){
|
||||
next()
|
||||
}).catch(() => {
|
||||
|
||||
}else{
|
||||
store.newNotification("Sign in session ended, please sign in again", "warning")
|
||||
next('/signin')
|
||||
})
|
||||
}
|
||||
}else{
|
||||
next()
|
||||
}
|
||||
|
@ -1,5 +1,26 @@
|
||||
import axios from "axios";
|
||||
|
||||
export const requestURl = (url) => {
|
||||
return import.meta.env.MODE === 'development' ? '/client' + url
|
||||
: `${window.location.protocol}//${(window.location.host + window.location.pathname + url).replace(/\/\//g, '/')}`
|
||||
}
|
||||
|
||||
export const axiosPost = async (URL, body = {}) => {
|
||||
try{
|
||||
const res = await axios.post(requestURl(URL), body)
|
||||
return res.data
|
||||
} catch (error){
|
||||
console.log(error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export const axiosGet = async (URL, query = {}) => {
|
||||
try{
|
||||
const res = await axios.get(requestURl(URL), query)
|
||||
return res.data
|
||||
} catch (error){
|
||||
console.log(error)
|
||||
return undefined
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user