forked from mirrors/amnezia-wg-easy
		
	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
					
				
					 6 changed files with 61 additions and 7 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue