Compare commits

..

3 Commits

Author SHA1 Message Date
Donald Zou
42f9460369 Update wgd.sh 2026-04-10 16:18:12 +08:00
Donald Zou
71f4449741 Fixed quotation marks 2026-04-10 15:45:26 +08:00
Donald Zou
081c63cd43 Merge pull request #1197 from WGDashboard/development
v4.3.3 Merge
2026-04-10 14:50:10 +08:00
15 changed files with 2458 additions and 1770 deletions

View File

@@ -100,7 +100,7 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
date = datetime.datetime.now(tz=datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC') date = datetime.datetime.now(tz=datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')
emailSender = EmailSender(dashboardConfig) emailSender = EmailSender(dashboardConfig)
if not emailSender.is_ready(): if not emailSender.ready():
return ResponseObject(False, "We can't send you an email due to your Administrator has not setup email service. Please contact your administrator.") return ResponseObject(False, "We can't send you an email due to your Administrator has not setup email service. Please contact your administrator.")
data = request.get_json() data = request.get_json()
@@ -244,4 +244,4 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
return ResponseObject(status, message) return ResponseObject(status, message)
return client return client

View File

@@ -116,5 +116,5 @@ class AmneziaPeer(Peer):
self.configuration.getPeers() self.configuration.getPeers()
return True, None return True, None
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
current_app.logger.error(f"Subprocess call failed:\n{exc.output.decode("UTF-8")}") current_app.logger.error(f"Subprocess call failed:\n{exc.output.decode('UTF-8')}")
return False, "Internal server error" return False, "Internal server error"

View File

@@ -51,8 +51,7 @@ class DashboardConfig:
"peer_display_mode": "grid", "peer_display_mode": "grid",
"remote_endpoint": GetRemoteEndpoint(), "remote_endpoint": GetRemoteEndpoint(),
"peer_MTU": "1420", "peer_MTU": "1420",
"peer_keep_alive": "21", "peer_keep_alive": "21"
"peer_preshared_key_default": "false"
}, },
"Other": { "Other": {
"welcome_session": "true" "welcome_session": "true"
@@ -147,17 +146,14 @@ class DashboardConfig:
if col_name not in existing_columns: if col_name not in existing_columns:
type_str = col_type().compile(dialect=self.engine.dialect) type_str = col_type().compile(dialect=self.engine.dialect)
current_app.logger.info(f"Adding missing column '{col_name}' to table '{table_name}'") current_app.logger.info(f"Adding missing column '{col_name}' to table '{table_name}'")
preparer = self.engine.dialect.identifier_preparer conn.execute(db.text(f'ALTER TABLE "{table_name}" ADD COLUMN "{col_name}" {type_str}'))
quoted_table = preparer.quote_identifier(table_name)
quoted_column = preparer.quote_identifier(col_name)
conn.execute(db.text(f"ALTER TABLE {quoted_table} ADD COLUMN {quoted_column} {type_str}"))
def getConnectionString(self, database) -> str or None: def getConnectionString(self, database) -> str or None:
sqlitePath = os.path.join(DashboardConfig.ConfigurationPath, "db") sqlitePath = os.path.join(DashboardConfig.ConfigurationPath, "db")
if not os.path.isdir(sqlitePath): if not os.path.isdir(sqlitePath):
os.mkdir(sqlitePath) os.mkdir(sqlitePath)
if self.GetConfig("Database", "type")[1] == "postgresql": if self.GetConfig("Database", "type")[1] == "postgresql":
cn = f'postgresql+psycopg2://{self.GetConfig("Database", "username")[1]}:{self.GetConfig("Database", "password")[1]}@{self.GetConfig("Database", "host")[1]}/{database}' cn = f'postgresql+psycopg2://{self.GetConfig("Database", "username")[1]}:{self.GetConfig("Database", "password")[1]}@{self.GetConfig("Database", "host")[1]}/{database}'
elif self.GetConfig("Database", "type")[1] == "mysql": elif self.GetConfig("Database", "type")[1] == "mysql":

View File

@@ -151,7 +151,7 @@ class Peer:
) )
return True, None return True, None
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
current_app.logger.error(f"Subprocess call failed:\n{exc.output.decode("UTF-8")}") current_app.logger.error(f"Subprocess call failed:\n{exc.output.decode('UTF-8')}")
return False, "Internal server error" return False, "Internal server error"
def downloadPeer(self) -> dict[str, str]: def downloadPeer(self) -> dict[str, str]:

View File

@@ -8,10 +8,10 @@ icmplib==3.0.4
gunicorn==25.0.3 gunicorn==25.0.3
requests==2.32.5 requests==2.32.5
tcconfig==0.30.1 tcconfig==0.30.1
sqlalchemy==2.0.49 sqlalchemy==2.0.46
sqlalchemy_utils==0.42.1 sqlalchemy_utils==0.42.1
psycopg[binary]==3.3.3 psycopg[binary]==3.3.3
PyMySQL==1.1.2 PyMySQL==1.1.2
tzlocal==5.3.1 tzlocal==5.3.1
python-jose==3.5.0 python-jose==3.5.0
pydantic==2.13.3 pydantic==2.12.5

File diff suppressed because it is too large Load Diff

View File

@@ -20,28 +20,28 @@
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"bootstrap": "^5.3.2", "bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.3", "bootstrap-icons": "^1.11.3",
"cidr-tools": "^11.3.3", "cidr-tools": "^11.3.2",
"css-color-converter": "^2.0.0", "css-color-converter": "^2.0.0",
"dayjs": "^1.11.19", "dayjs": "^1.11.19",
"electron-builder": "^26.7.0", "electron-builder": "^26.7.0",
"fuse.js": "^7.3.0", "fuse.js": "^7.0.0",
"i": "^0.3.7", "i": "^0.3.7",
"is-cidr": "^6.0.3", "is-cidr": "^6.0.3",
"npm": "^11.8.0", "npm": "^11.8.0",
"ol": "^10.8.0", "ol": "^10.7.0",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1", "pinia-plugin-persistedstate": "^4.7.1",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"qrcodejs": "^1.0.0", "qrcodejs": "^1.0.0",
"simple-code-editor": "^2.0.9", "simple-code-editor": "^2.0.9",
"uuid": "^13.0.0", "uuid": "^13.0.0",
"vue": "^3.5.32", "vue": "^3.5.31",
"vue-chartjs": "^5.3.3", "vue-chartjs": "^5.3.3",
"vue-router": "^5.0.4" "vue-router": "^5.0.4"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^6.0.4", "@vitejs/plugin-vue": "^6.0.4",
"vite": "^8.0.8" "vite": "^7.3.1"
}, },
"overrides": { "overrides": {
"tar": "^7.5.6" "tar": "^7.5.6"

View File

@@ -6,27 +6,18 @@ export default {
components: {LocaleText}, components: {LocaleText},
props: { props: {
data: Object, data: Object,
saving: Boolean, saving: Boolean
defaultEnabled: Boolean
}, },
data(){ data(){
return{ return{
enable: false enable: false
} }
}, },
mounted() {
const hasKey = !!(this.data && this.data.preshared_key && this.data.preshared_key.length > 0)
if (hasKey || this.defaultEnabled){
this.enable = true
}
},
watch:{ watch:{
enable(){ enable(){
if (this.enable) { if (this.enable){
if (!this.data.preshared_key){ this.data.preshared_key = window.wireguard.generateKeypair().presharedKey
this.data.preshared_key = window.wireguard.generateKeypair().presharedKey }else {
}
} else {
this.data.preshared_key = "" this.data.preshared_key = ""
} }
} }
@@ -57,4 +48,4 @@ export default {
<style scoped> <style scoped>
</style> </style>

View File

@@ -32,7 +32,7 @@ const peerData = ref({
keepalive: parseInt(dashboardStore.Configuration.Peers.peer_keep_alive), keepalive: parseInt(dashboardStore.Configuration.Peers.peer_keep_alive),
mtu: parseInt(dashboardStore.Configuration.Peers.peer_mtu), mtu: parseInt(dashboardStore.Configuration.Peers.peer_mtu),
preshared_key: "", preshared_key: "",
preshared_key_bulkAdd: Boolean(dashboardStore.Configuration.Peers.peer_preshared_key_default), preshared_key_bulkAdd: false,
allowed_ips_validation: true, allowed_ips_validation: true,
}) })
const availableIp = ref([]) const availableIp = ref([])
@@ -128,7 +128,7 @@ watch(() => {
<EndpointAllowedIps :saving="saving" :data="peerData"></EndpointAllowedIps> <EndpointAllowedIps :saving="saving" :data="peerData"></EndpointAllowedIps>
<div class="row gy-3"> <div class="row gy-3">
<div class="col-sm" v-if="!peerData.bulkAdd"> <div class="col-sm" v-if="!peerData.bulkAdd">
<PresharedKeyInput :saving="saving" :data="peerData" :bulk="peerData.bulkAdd" :defaultEnabled="Boolean(dashboardStore.Configuration.Peers.peer_preshared_key_default)"></PresharedKeyInput> <PresharedKeyInput :saving="saving" :data="peerData" :bulk="peerData.bulkAdd"></PresharedKeyInput>
</div> </div>
<div class="col-sm"> <div class="col-sm">
@@ -177,4 +177,4 @@ watch(() => {
<style scoped> <style scoped>
</style> </style>

View File

@@ -36,7 +36,7 @@ export default {
keepalive: parseInt(this.dashboardStore.Configuration.Peers.peer_keep_alive), keepalive: parseInt(this.dashboardStore.Configuration.Peers.peer_keep_alive),
mtu: parseInt(this.dashboardStore.Configuration.Peers.peer_mtu), mtu: parseInt(this.dashboardStore.Configuration.Peers.peer_mtu),
preshared_key: "", preshared_key: "",
preshared_key_bulkAdd: Boolean(this.dashboardStore.Configuration.Peers.peer_preshared_key_default), preshared_key_bulkAdd: false,
}, },
availableIp: undefined, availableIp: undefined,
availableIpSearchString: "", availableIpSearchString: "",
@@ -133,7 +133,7 @@ export default {
<hr class="mb-0 mt-2"> <hr class="mb-0 mt-2">
<div class="row gy-3"> <div class="row gy-3">
<div class="col-sm" v-if="!this.data.bulkAdd"> <div class="col-sm" v-if="!this.data.bulkAdd">
<PresharedKeyInput :saving="saving" :data="data" :bulk="this.data.bulkAdd" :defaultEnabled="Boolean(this.dashboardStore.Configuration.Peers.peer_preshared_key_default)"></PresharedKeyInput> <PresharedKeyInput :saving="saving" :data="data" :bulk="this.data.bulkAdd"></PresharedKeyInput>
</div> </div>
<div class="col-sm"> <div class="col-sm">
@@ -187,4 +187,4 @@ div{
.card{ .card{
max-height: 100%; max-height: 100%;
} }
</style> </style>

View File

@@ -22,8 +22,6 @@ import PeersDefaultSettingsInput from "@/components/settingsComponent/peersDefau
targetData="peer_mtu" title="MTU"></PeersDefaultSettingsInput> targetData="peer_mtu" title="MTU"></PeersDefaultSettingsInput>
<PeersDefaultSettingsInput <PeersDefaultSettingsInput
targetData="peer_keep_alive" title="Persistent Keepalive"></PeersDefaultSettingsInput> targetData="peer_keep_alive" title="Persistent Keepalive"></PeersDefaultSettingsInput>
<PeersDefaultSettingsInput
targetData="peer_preshared_key_default" title="Pre-Shared Key Default"></PeersDefaultSettingsInput>
<PeersDefaultSettingsInput <PeersDefaultSettingsInput
targetData="remote_endpoint" title="Peer Remote Endpoint" targetData="remote_endpoint" title="Peer Remote Endpoint"
:warning="true" warningText="This will be changed globally, and will be apply to all peer's QR code and configuration file." :warning="true" warningText="This will be changed globally, and will be apply to all peer's QR code and configuration file."
@@ -36,4 +34,4 @@ import PeersDefaultSettingsInput from "@/components/settingsComponent/peersDefau
<style scoped> <style scoped>
</style> </style>

View File

@@ -31,11 +31,6 @@ export default {
mounted() { mounted() {
this.value = this.store.Configuration.Peers[this.targetData]; this.value = this.store.Configuration.Peers[this.targetData];
}, },
computed: {
isBoolean(){
return typeof this.value === "boolean"
}
},
methods:{ methods:{
async useValidation(){ async useValidation(){
if(this.changed){ if(this.changed){
@@ -72,14 +67,7 @@ export default {
<LocaleText :t="this.title"></LocaleText> <LocaleText :t="this.title"></LocaleText>
</small></strong> </small></strong>
</label> </label>
<div v-if="isBoolean" class="form-check form-switch"> <input type="text" class="form-control"
<input class="form-check-input" type="checkbox" role="switch"
v-model="this.value"
:id="this.uuid"
@change="this.changed = true; useValidation()"
:disabled="this.updating">
</div>
<input v-else type="text" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}" :class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
:id="this.uuid" :id="this.uuid"
v-model="this.value" v-model="this.value"
@@ -100,4 +88,4 @@ export default {
<style scoped> <style scoped>
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -13,16 +13,16 @@
"bootstrap": "^5.3.6", "bootstrap": "^5.3.6",
"bootstrap-icons": "^1.13.1", "bootstrap-icons": "^1.13.1",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"oidc-client-ts": "^3.5.0", "oidc-client-ts": "^3.2.1",
"pinia": "^3.0.2", "pinia": "^3.0.2",
"qrcode": "^1.5.4", "qrcode": "^1.5.4",
"uuid": "^13.0.0", "uuid": "^11.1.0",
"vue": "^3.5.32", "vue": "^3.5.13",
"vue-router": "^4.5.1" "vue-router": "^4.5.1"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.2.3", "@vitejs/plugin-vue": "^5.2.3",
"vite": "^8.0.8", "vite": "^6.2.4",
"vite-plugin-vue-devtools": "^8.1.1" "vite-plugin-vue-devtools": "^7.7.2"
} }
} }

View File

@@ -247,27 +247,19 @@ _checkWireguard(){
_checkPythonVersion(){ _checkPythonVersion(){
version_pass=$($pythonExecutable -c 'import sys; print("1") if (sys.version_info.major == 3 and sys.version_info.minor >= 10) else print("0");') version_pass=$($pythonExecutable -c 'import sys; print("1") if (sys.version_info.major == 3 and sys.version_info.minor >= 12) else print("0");')
version=$($pythonExecutable --version) version=$($pythonExecutable --version)
if [ $version_pass == "1" ] if [ $version_pass == "1" ]
then then
printf "[WGDashboard] %s Found compatible version of Python. Will be using %s to install WGDashboard.\n" "$heavy_checkmark" "$($pythonExecutable --version)" printf "[WGDashboard] %s Found compatible version of Python. Will be using %s to install WGDashboard.\n" "$heavy_checkmark" "$($pythonExecutable --version)"
return; return;
elif python3.10 --version > /dev/null 2>&1
then
printf "[WGDashboard] %s Found Python 3.10. Will be using [python3.10] to install WGDashboard.\n" "$heavy_checkmark"
pythonExecutable="python3.10"
elif python3.11 --version > /dev/null 2>&1
then
printf "[WGDashboard] %s Found Python 3.11. Will be using [python3.11] to install WGDashboard.\n" "$heavy_checkmark"
pythonExecutable="python3.11"
elif python3.12 --version > /dev/null 2>&1 elif python3.12 --version > /dev/null 2>&1
then then
printf "[WGDashboard] %s Found Python 3.12. Will be using [python3.12] to install WGDashboard.\n" "$heavy_checkmark" printf "[WGDashboard] %s Found Python 3.12. Will be using [python3.12] to install WGDashboard.\n" "$heavy_checkmark"
pythonExecutable="python3.12" pythonExecutable="python3.12"
else else
printf "[WGDashboard] %s Could not find a compatible version of Python. Current Python is %s.\n" "$heavy_crossmark" "$version" printf "[WGDashboard] %s Could not find a compatible version of Python. Current Python is %s.\n" "$heavy_crossmark" "$version"
printf "[WGDashboard] WGDashboard required Python 3.10, 3.11 or 3.12. Halting install now.\n" printf "[WGDashboard] WGDashboard required Python 3.12 or above. Halting install now.\n"
kill $TOP_PID kill $TOP_PID
fi fi
} }