Fix short link. Generate One Time Link (#1301)
Co-authored-by: Vadim Babadzhanyan <vadim.babadzhanyan@my.games>
This commit is contained in:
parent
352a022f30
commit
968d2b90a0
|
@ -132,14 +132,15 @@ module.exports = class Server {
|
||||||
authenticated,
|
authenticated,
|
||||||
};
|
};
|
||||||
}))
|
}))
|
||||||
.get('/:clientHash', defineEventHandler(async (event) => {
|
.get('/cnf/:clientOneTimeLink', defineEventHandler(async (event) => {
|
||||||
const clientHash = getRouterParam(event, 'clientHash');
|
const clientOneTimeLink = getRouterParam(event, 'clientOneTimeLink');
|
||||||
const clients = await WireGuard.getClients();
|
const clients = await WireGuard.getClients();
|
||||||
const client = clients.find((client) => client.hash === clientHash);
|
const client = clients.find((client) => client.oneTimeLink === clientOneTimeLink);
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
const clientId = client.id;
|
const clientId = client.id;
|
||||||
const config = await WireGuard.getClientConfiguration({ clientId });
|
const config = await WireGuard.getClientConfiguration({ clientId });
|
||||||
setHeader(event, 'Content-Disposition', `attachment; filename="${clientHash}.conf"`);
|
await WireGuard.eraseOneTimeLink({ clientId });
|
||||||
|
setHeader(event, 'Content-Disposition', `attachment; filename="${clientOneTimeLink}.conf"`);
|
||||||
setHeader(event, 'Content-Type', 'text/plain');
|
setHeader(event, 'Content-Type', 'text/plain');
|
||||||
return config;
|
return config;
|
||||||
}))
|
}))
|
||||||
|
@ -252,6 +253,14 @@ module.exports = class Server {
|
||||||
await WireGuard.enableClient({ clientId });
|
await WireGuard.enableClient({ clientId });
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}))
|
}))
|
||||||
|
.post('/api/wireguard/client/:clientId/generateOneTimeLink', defineEventHandler(async (event) => {
|
||||||
|
const clientId = getRouterParam(event, 'clientId');
|
||||||
|
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') {
|
||||||
|
throw createError({ status: 403 });
|
||||||
|
}
|
||||||
|
await WireGuard.generateOneTimeLink({ clientId });
|
||||||
|
return { success: true };
|
||||||
|
}))
|
||||||
.post('/api/wireguard/client/:clientId/disable', defineEventHandler(async (event) => {
|
.post('/api/wireguard/client/:clientId/disable', defineEventHandler(async (event) => {
|
||||||
const clientId = getRouterParam(event, 'clientId');
|
const clientId = getRouterParam(event, 'clientId');
|
||||||
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') {
|
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') {
|
||||||
|
|
|
@ -152,7 +152,7 @@ ${client.preSharedKey ? `PresharedKey = ${client.preSharedKey}\n` : ''
|
||||||
? new Date(client.expiredAt)
|
? new Date(client.expiredAt)
|
||||||
: null,
|
: null,
|
||||||
allowedIPs: client.allowedIPs,
|
allowedIPs: client.allowedIPs,
|
||||||
hash: Math.abs(CRC32.str(clientId)).toString(16),
|
oneTimeLink: client.oneTimeLink ? client.oneTimeLink : null,
|
||||||
downloadableConfig: 'privateKey' in client,
|
downloadableConfig: 'privateKey' in client,
|
||||||
persistentKeepalive: null,
|
persistentKeepalive: null,
|
||||||
latestHandshakeAt: null,
|
latestHandshakeAt: null,
|
||||||
|
@ -306,6 +306,21 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
|
||||||
await this.saveConfig();
|
await this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async generateOneTimeLink({ clientId }) {
|
||||||
|
const client = await this.getClient({ clientId });
|
||||||
|
const key = `${clientId}-${Math.floor(Math.random() * 1000)}`;
|
||||||
|
client.oneTimeLink = Math.abs(CRC32.str(key)).toString(16);
|
||||||
|
client.updatedAt = new Date();
|
||||||
|
await this.saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
async eraseOneTimeLink({ clientId }) {
|
||||||
|
const client = await this.getClient({ clientId });
|
||||||
|
client.oneTimeLink = null;
|
||||||
|
client.updatedAt = new Date();
|
||||||
|
await this.saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
async disableClient({ clientId }) {
|
async disableClient({ clientId }) {
|
||||||
const client = await this.getClient({ clientId });
|
const client = await this.getClient({ clientId });
|
||||||
|
|
||||||
|
|
|
@ -256,8 +256,8 @@
|
||||||
{{!uiTrafficStats ? " · " : ""}}{{new Date(client.latestHandshakeAt) | timeago}}
|
{{!uiTrafficStats ? " · " : ""}}{{new Date(client.latestHandshakeAt) | timeago}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="uiShowLinks" :ref="'client-' + client.id + '-hash'" class="text-gray-400 text-xs">
|
<div v-if="uiShowLinks && client.oneTimeLink !== null && client.oneTimeLink !== ''" :ref="'client-' + client.id + '-link'" class="text-gray-400 text-xs">
|
||||||
<a :href="'./' + client.hash + ''">{{document.location.protocol}}//{{document.location.host}}/{{client.hash}}</a>
|
<a :href="'./cnf/' + client.oneTimeLink + ''">{{document.location.protocol}}//{{document.location.host}}/cnf/{{client.oneTimeLink}}</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- Expire Date -->
|
<!-- Expire Date -->
|
||||||
<div v-show="enableExpireTime" class=" block md:inline-block pb-1 md:pb-0 text-gray-500 dark:text-neutral-400 text-xs">
|
<div v-show="enableExpireTime" class=" block md:inline-block pb-1 md:pb-0 text-gray-500 dark:text-neutral-400 text-xs">
|
||||||
|
@ -384,6 +384,22 @@
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<!-- Short OneTime Link -->
|
||||||
|
<button v-if="uiShowLinks" :disabled="!client.downloadableConfig"
|
||||||
|
class="align-middle inline-block bg-gray-100 dark:bg-neutral-600 dark:text-neutral-300 p-2 rounded transition"
|
||||||
|
:class="{
|
||||||
|
'hover:bg-red-800 dark:hover:bg-red-800 hover:text-white dark:hover:text-white': client.downloadableConfig,
|
||||||
|
'is-disabled': !client.downloadableConfig
|
||||||
|
}"
|
||||||
|
:title="!client.downloadableConfig ? $t('noPrivKey') : $t('OneTimeLink')"
|
||||||
|
@click="if(client.downloadableConfig) { showOneTimeLink(client); }">
|
||||||
|
<svg class="w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M13.213 9.787a3.391 3.391 0 0 0-4.795 0l-3.425 3.426a3.39 3.39 0 0 0 4.795 4.794l.321-.304m-.321-4.49a3.39 3.39 0 0 0 4.795 0l3.424-3.426a3.39 3.39 0 0 0-4.794-4.795l-1.028.961"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- Delete -->
|
<!-- Delete -->
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -132,6 +132,13 @@ class API {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async showOneTimeLink({ clientId }) {
|
||||||
|
return this.call({
|
||||||
|
method: 'post',
|
||||||
|
path: `/wireguard/client/${clientId}/generateOneTimeLink`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async enableClient({ clientId }) {
|
async enableClient({ clientId }) {
|
||||||
return this.call({
|
return this.call({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
|
|
@ -312,6 +312,11 @@ new Vue({
|
||||||
.catch((err) => alert(err.message || err.toString()))
|
.catch((err) => alert(err.message || err.toString()))
|
||||||
.finally(() => this.refresh().catch(console.error));
|
.finally(() => this.refresh().catch(console.error));
|
||||||
},
|
},
|
||||||
|
showOneTimeLink(client) {
|
||||||
|
this.api.showOneTimeLink({ clientId: client.id })
|
||||||
|
.catch((err) => alert(err.message || err.toString()))
|
||||||
|
.finally(() => this.refresh().catch(console.error));
|
||||||
|
},
|
||||||
enableClient(client) {
|
enableClient(client) {
|
||||||
this.api.enableClient({ clientId: client.id })
|
this.api.enableClient({ clientId: client.id })
|
||||||
.catch((err) => alert(err.message || err.toString()))
|
.catch((err) => alert(err.message || err.toString()))
|
||||||
|
|
|
@ -39,6 +39,7 @@ const messages = { // eslint-disable-line no-unused-vars
|
||||||
sort: 'Sort',
|
sort: 'Sort',
|
||||||
ExpireDate: 'Expire Date',
|
ExpireDate: 'Expire Date',
|
||||||
Permanent: 'Permanent',
|
Permanent: 'Permanent',
|
||||||
|
OneTimeLink: 'Generate short one time link',
|
||||||
},
|
},
|
||||||
ua: {
|
ua: {
|
||||||
name: 'Ім`я',
|
name: 'Ім`я',
|
||||||
|
@ -112,6 +113,7 @@ const messages = { // eslint-disable-line no-unused-vars
|
||||||
sort: 'Сортировка',
|
sort: 'Сортировка',
|
||||||
ExpireDate: 'Дата истечения срока',
|
ExpireDate: 'Дата истечения срока',
|
||||||
Permanent: 'Бессрочно',
|
Permanent: 'Бессрочно',
|
||||||
|
OneTimeLink: 'Создать короткую одноразовую ссылку',
|
||||||
},
|
},
|
||||||
tr: { // Müslüm Barış Korkmazer @babico
|
tr: { // Müslüm Barış Korkmazer @babico
|
||||||
name: 'İsim',
|
name: 'İsim',
|
||||||
|
|
Loading…
Reference in New Issue