Update build for client and admin

This commit is contained in:
Donald Zou 2025-07-08 16:32:08 +08:00
parent db6976a06a
commit af045447e6
18 changed files with 93 additions and 91 deletions

View File

@ -132,7 +132,11 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
@client.get(f'{prefix}/api/settings/getClientProfile') @client.get(f'{prefix}/api/settings/getClientProfile')
@login_required @login_required
def ClientAPI_Settings_GetClientProfile(): def ClientAPI_Settings_GetClientProfile():
return ResponseObject(data=DashboardClients.GetClientProfile(session['ClientID'])) return ResponseObject(data={
"Email": session.get("Email"),
"SignInMethod": session.get("SignInMethod"),
"Profile": DashboardClients.GetClientProfile(session.get("ClientID"))
})
@client.post(f'{prefix}/api/settings/updatePassword') @client.post(f'{prefix}/api/settings/updatePassword')
@login_required @login_required

View File

@ -1265,7 +1265,7 @@ def InitWireguardConfigurationsList(startup: bool = False):
try: try:
if i in WireguardConfigurations.keys(): if i in WireguardConfigurations.keys():
if WireguardConfigurations[i].configurationFileChanged(): if WireguardConfigurations[i].configurationFileChanged():
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, i) WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i)
else: else:
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i, startup=startup) WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i, startup=startup)
except WireguardConfiguration.InvalidConfigurationFileException as e: except WireguardConfiguration.InvalidConfigurationFileException as e:

View File

@ -52,8 +52,7 @@ class DashboardClients:
self.dashboardClientsInfoTable = db.Table( self.dashboardClientsInfoTable = db.Table(
'DashboardClientsInfo', self.metadata, 'DashboardClientsInfo', self.metadata,
db.Column('ClientID', db.String(255), nullable=False, primary_key=True), db.Column('ClientID', db.String(255), nullable=False, primary_key=True),
db.Column('Firstname', db.String(500)), db.Column('Name', db.String(500)),
db.Column('Lastname', db.String(500)),
extend_existing=True, extend_existing=True,
) )
@ -127,7 +126,8 @@ class DashboardClients:
) )
conn.execute( conn.execute(
self.dashboardClientsInfoTable.insert().values({ self.dashboardClientsInfoTable.insert().values({
"ClientID": newClientUUID "ClientID": newClientUUID,
"Name": data.get("name")
}) })
) )
self.logger.log(Message=f"User {data.get('email', '')} from {data.get('iss', '')} signed up") self.logger.log(Message=f"User {data.get('email', '')} from {data.get('iss', '')} signed up")
@ -150,6 +150,7 @@ class DashboardClients:
if not status: if not status:
return False, "Sign in failed. Reason: " + data return False, "Sign in failed. Reason: " + data
existingClient = self.SignIn_OIDC_UserExistence(data) existingClient = self.SignIn_OIDC_UserExistence(data)
print(data)
if not existingClient: if not existingClient:
status, newClientUUID = self.SignUp_OIDC(data) status, newClientUUID = self.SignUp_OIDC(data)
session['ClientID'] = newClientUUID session['ClientID'] = newClientUUID

View File

@ -1,6 +1,6 @@
{ {
"name": "app", "name": "app",
"version": "4.2.3", "version": "4.3",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,8 +28,8 @@
} }
} }
</style> </style>
<script type="module" crossorigin src="/static/client/dist/assets/index-DFmEbKGG.js"></script> <script type="module" crossorigin src="/static/client/dist/assets/index-ChoUdvn1.js"></script>
<link rel="stylesheet" crossorigin href="/static/client/dist/assets/index-1THt9Piw.css"> <link rel="stylesheet" crossorigin href="/static/client/dist/assets/index-3kRNveDB.css">
</head> </head>
<body> <body>
<div id="app"> <div id="app">
@ -37,7 +37,6 @@
<div id="preloader_placeholder"> <div id="preloader_placeholder">
<img style="width: 100%" src="/static/client/dist/img/Logo-2-128x128.png" alt="WGDashboard Client" /> <img style="width: 100%" src="/static/client/dist/img/Logo-2-128x128.png" alt="WGDashboard Client" />
</div> </div>
</div> </div>
</div> </div>
</body> </body>

View File

@ -1,6 +1,6 @@
{ {
"name": "client", "name": "client",
"version": "0.0.0", "version": "v4.3",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@ -4,7 +4,9 @@ import NotificationList from "@/components/Notification/notificationList.vue";
import {clientStore} from "@/stores/clientStore.js"; import {clientStore} from "@/stores/clientStore.js";
const store = clientStore() const store = clientStore()
fetch("/client/api/serverInformation").then(res => res.json()).then(res => store.serverInformation = res.data) fetch("/client/api/serverInformation")
.then(res => res.json())
.then(res => store.serverInformation = res.data)
</script> </script>
<template> <template>

View File

@ -2,8 +2,7 @@
import {clientStore} from "@/stores/clientStore.js"; import {clientStore} from "@/stores/clientStore.js";
const store = clientStore() const store = clientStore()
const ProfileLabels = { const ProfileLabels = {
Firstname: "First Name", Name: "Name",
Lastname: "Last Name"
} }
</script> </script>
@ -13,13 +12,11 @@ const ProfileLabels = {
<h5> <h5>
Profile Profile
</h5> </h5>
<div class="row g-2"> <div v-for="(val, key) in store.clientProfile.Profile">
<div class="col-sm-6" v-for="(val, key) in store.clientProfile.Profile"> <label :for="key" class="text-muted form-label">
<label :for="key" class="text-muted form-label"> <small>{{ ProfileLabels[key] }}</small>
<small>{{ ProfileLabels[key] }}</small> </label>
</label> <input :id="key" class="form-control rounded-3" v-model="store.clientProfile.Profile[key]">
<input :id="key" class="form-control rounded-3" v-model="store.clientProfile.Profile[key]">
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -16,10 +16,22 @@ if (getProviders){
</script> </script>
<template> <template>
<div class="d-flex gap-2" v-if="providers"> <div v-if="providers">
<suspense> <hr>
<OidcBtn :provider="provider" :name="name" v-for="(provider, name) in providers"></OidcBtn> <h6 class="text-center text-muted mb-3">
</suspense> <small>Sign in with</small>
</h6>
<div class="d-flex gap-2">
<suspense>
<OidcBtn :provider="provider" :name="name" v-for="(provider, name) in providers"></OidcBtn>
<template #fallback>
<a class="btn btn-sm btn-outline-body rounded-3 w-100 disabled">
Loading...
</a>
</template>
</suspense>
</div>
<hr>
</div> </div>
</template> </template>

View File

@ -10,7 +10,7 @@ const params = new URLSearchParams({
redirect_uri: window.location.protocol + '//' + window.location.host + window.location.pathname, redirect_uri: window.location.protocol + '//' + window.location.host + window.location.pathname,
response_type: 'code', response_type: 'code',
state: props.name, state: props.name,
scope: 'openid email' scope: 'openid email profile'
}).toString() }).toString()
const authUrl = ref(undefined) const authUrl = ref(undefined)
@ -22,8 +22,6 @@ try{
console.log(providerConfiguration.value) console.log(providerConfiguration.value)
authUrl.value = new URL(providerConfiguration.value.authorization_endpoint) authUrl.value = new URL(providerConfiguration.value.authorization_endpoint)
authUrl.value.search = params authUrl.value.search = params
} catch (error){ } catch (error){
console.log("Provider not available", props.provider) console.log("Provider not available", props.provider)
} }

View File

@ -6,8 +6,6 @@ import router from "@/router/router.js";
import {createPinia} from "pinia"; import {createPinia} from "pinia";
import 'bootstrap/dist/js/bootstrap.bundle.js' import 'bootstrap/dist/js/bootstrap.bundle.js'
import {clientStore} from "@/stores/clientStore.js";
import {OIDCAuth} from "@/utilities/oidcAuth.js";
import {axiosPost} from "@/utilities/request.js"; import {axiosPost} from "@/utilities/request.js";
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)

View File

@ -12,6 +12,7 @@ export const clientStore = defineStore('clientStore', {
configurations: [], configurations: [],
clientProfile: { clientProfile: {
Email: "", Email: "",
SignInMethod: "",
Profile: {} Profile: {}
} }
}), }),
@ -28,7 +29,7 @@ export const clientStore = defineStore('clientStore', {
async getClientProfile(){ async getClientProfile(){
const data = await axiosGet('/api/settings/getClientProfile') const data = await axiosGet('/api/settings/getClientProfile')
if (data){ if (data){
this.clientProfile.Profile = data.data this.clientProfile = data.data
}else{ }else{
this.newNotification("Failed to fetch client profile", "danger") this.newNotification("Failed to fetch client profile", "danger")
} }

View File

@ -1,6 +0,0 @@
export const OIDCAuth = async () => {
const params = new URLSearchParams(window.location.search)
const state = params.get('state')
const code = params.get('code')
}

View File

@ -12,7 +12,7 @@ const configurations = computed(() => {
return store.configurations return store.configurations
}); });
const refreshInterval = ref(undefined) const refreshInterval = ref(undefined)
await store.getClientProfile();
onMounted(async () => { onMounted(async () => {
await store.getConfigurations() await store.getConfigurations()
loading.value = false; loading.value = false;
@ -37,14 +37,15 @@ const signOut = async () => {
}); });
store.newNotification("Sign out successful", "success") store.newNotification("Sign out successful", "success")
} }
</script> </script>
<template> <template>
<div class="p-sm-3"> <div class="p-sm-3">
<div class="w-100 d-flex align-items-center"> <div class="w-100 d-flex align-items-center">
<a class="nav-link text-body border-start-0" aria-current="page" href="#"> <a class="nav-link text-body border-start-0" aria-current="page" href="#">
<strong>WGDashboard Client</strong> <strong>
Hi, {{ store.clientProfile.Profile.Name ? store.clientProfile.Profile.Name : store.clientProfile.Email}}
</strong>
</a> </a>
<div class="ms-auto px-3 d-flex gap-2 nav-links"> <div class="ms-auto px-3 d-flex gap-2 nav-links">
<RouterLink to="/settings" class=" text-body btn btn-outline-body rounded-3 ms-auto btn-sm" aria-current="page" href="#"> <RouterLink to="/settings" class=" text-body btn btn-outline-body rounded-3 ms-auto btn-sm" aria-current="page" href="#">
@ -64,15 +65,11 @@ const signOut = async () => {
<Transition name="app" mode="out-in"> <Transition name="app" mode="out-in">
<div class="d-flex flex-column gap-3" v-if="!loading"> <div class="d-flex flex-column gap-3" v-if="!loading">
<div class="p-3 d-flex flex-column gap-3"> <div class="p-3 d-flex flex-column gap-3" v-if="configurations.length > 0">
<Configuration v-for="config in configurations" :config="config"></Configuration> <Configuration v-for="config in configurations" :config="config"></Configuration>
<!-- <h6 class="mb-0 text-center text-muted">--> </div>
<!-- <small>--> <div class="text-center text-muted" v-else>
<!-- <strong>--> <small>No configuration available</small>
<!-- {{ configurations.length }}-->
<!-- </strong> configuration{{ configurations.length > 1 ? 's':''}}-->
<!-- </small>-->
<!-- </h6>-->
</div> </div>
</div> </div>
<div v-else class="d-flex py-4"> <div v-else class="d-flex py-4">

View File

@ -3,7 +3,6 @@ import {clientStore} from "@/stores/clientStore.js";
import Profile from "@/components/Settings/profile.vue"; import Profile from "@/components/Settings/profile.vue";
import UpdatePassword from "@/components/Settings/updatePassword.vue"; import UpdatePassword from "@/components/Settings/updatePassword.vue";
const store = clientStore() const store = clientStore()
await store.getClientProfile(); await store.getClientProfile();
</script> </script>
@ -17,7 +16,7 @@ await store.getClientProfile();
<strong class="ms-auto">Settings</strong> <strong class="ms-auto">Settings</strong>
</div> </div>
<Profile></Profile> <Profile></Profile>
<UpdatePassword></UpdatePassword> <UpdatePassword v-if="store.clientProfile.SignInMethod === 'local'"></UpdatePassword>
</div> </div>
</template> </template>