forked from mirrors/amnezia-wg-easy
		
	Add Remember me
This commit is contained in:
		
							parent
							
								
									4e79d0ee03
								
							
						
					
					
						commit
						3e6ded18a5
					
				
					 7 changed files with 49 additions and 3 deletions
				
			
		| 
						 | 
					@ -120,6 +120,7 @@ These options can be configured by setting environment variables using `-e KEY="
 | 
				
			||||||
| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi).                                        |
 | 
					| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi).                                        |
 | 
				
			||||||
| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI                                                                                                       |
 | 
					| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI                                                                                                       |
 | 
				
			||||||
| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart                           |
 | 
					| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart                           |
 | 
				
			||||||
 | 
					| `MAX_AGE` | `0` | `1440` | The maximum age of Web UI sessions in minutes. `0` means that the session will exist until the browser is closed.                                  |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> If you change `WG_PORT`, make sure to also change the exposed port.
 | 
					> If you change `WG_PORT`, make sure to also change the exposed port.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ module.exports.RELEASE = version;
 | 
				
			||||||
module.exports.PORT = process.env.PORT || '51821';
 | 
					module.exports.PORT = process.env.PORT || '51821';
 | 
				
			||||||
module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0';
 | 
					module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0';
 | 
				
			||||||
module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH;
 | 
					module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH;
 | 
				
			||||||
 | 
					module.exports.MAX_AGE = parseInt(process.env.MAX_AGE, 10) * 1000 * 60 || 0;
 | 
				
			||||||
module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
 | 
					module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
 | 
				
			||||||
module.exports.WG_DEVICE = process.env.WG_DEVICE || 'eth0';
 | 
					module.exports.WG_DEVICE = process.env.WG_DEVICE || 'eth0';
 | 
				
			||||||
module.exports.WG_HOST = process.env.WG_HOST;
 | 
					module.exports.WG_HOST = process.env.WG_HOST;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ const {
 | 
				
			||||||
  WEBUI_HOST,
 | 
					  WEBUI_HOST,
 | 
				
			||||||
  RELEASE,
 | 
					  RELEASE,
 | 
				
			||||||
  PASSWORD_HASH,
 | 
					  PASSWORD_HASH,
 | 
				
			||||||
 | 
					  MAX_AGE,
 | 
				
			||||||
  LANG,
 | 
					  LANG,
 | 
				
			||||||
  UI_TRAFFIC_STATS,
 | 
					  UI_TRAFFIC_STATS,
 | 
				
			||||||
  UI_CHART_TYPE,
 | 
					  UI_CHART_TYPE,
 | 
				
			||||||
| 
						 | 
					@ -82,6 +83,11 @@ module.exports = class Server {
 | 
				
			||||||
        return `"${LANG}"`;
 | 
					        return `"${LANG}"`;
 | 
				
			||||||
      }))
 | 
					      }))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .get('/api/remember-me', defineEventHandler((event) => {
 | 
				
			||||||
 | 
					        setHeader(event, 'Content-Type', 'application/json');
 | 
				
			||||||
 | 
					        return MAX_AGE > 0;
 | 
				
			||||||
 | 
					      }))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      .get('/api/ui-traffic-stats', defineEventHandler((event) => {
 | 
					      .get('/api/ui-traffic-stats', defineEventHandler((event) => {
 | 
				
			||||||
        setHeader(event, 'Content-Type', 'application/json');
 | 
					        setHeader(event, 'Content-Type', 'application/json');
 | 
				
			||||||
        return `"${UI_TRAFFIC_STATS}"`;
 | 
					        return `"${UI_TRAFFIC_STATS}"`;
 | 
				
			||||||
| 
						 | 
					@ -104,7 +110,7 @@ module.exports = class Server {
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }))
 | 
					      }))
 | 
				
			||||||
      .post('/api/session', defineEventHandler(async (event) => {
 | 
					      .post('/api/session', defineEventHandler(async (event) => {
 | 
				
			||||||
        const { password } = await readBody(event);
 | 
					        const { password, remember } = await readBody(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!requiresPassword) {
 | 
					        if (!requiresPassword) {
 | 
				
			||||||
          // if no password is required, the API should never be called.
 | 
					          // if no password is required, the API should never be called.
 | 
				
			||||||
| 
						 | 
					@ -122,6 +128,9 @@ module.exports = class Server {
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (MAX_AGE && remember) {
 | 
				
			||||||
 | 
					          event.node.req.session.cookie.maxAge = MAX_AGE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        event.node.req.session.authenticated = true;
 | 
					        event.node.req.session.authenticated = true;
 | 
				
			||||||
        event.node.req.session.save();
 | 
					        event.node.req.session.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -563,6 +563,24 @@
 | 
				
			||||||
          <input type="password" name="password" :placeholder="$t('password')" v-model="password" autocomplete="current-password"
 | 
					          <input type="password" name="password" :placeholder="$t('password')" v-model="password" autocomplete="current-password"
 | 
				
			||||||
            class="px-3 py-2 text-sm dark:bg-neutral-700 text-gray-500 dark:text-gray-500 mb-5 border-2 border-gray-100 dark:border-neutral-800 rounded-lg w-full focus:border-red-800 dark:focus:border-red-800 dark:placeholder:text-neutral-400 outline-none" />
 | 
					            class="px-3 py-2 text-sm dark:bg-neutral-700 text-gray-500 dark:text-gray-500 mb-5 border-2 border-gray-100 dark:border-neutral-800 rounded-lg w-full focus:border-red-800 dark:focus:border-red-800 dark:placeholder:text-neutral-400 outline-none" />
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
 | 
					          <!-- Remember me -->
 | 
				
			||||||
 | 
					          <label v-if="rememberMeEnabled"
 | 
				
			||||||
 | 
					            class="inline-block mb-5 cursor-pointer whitespace-nowrap" :title="$t('titleRememberMe')">
 | 
				
			||||||
 | 
					            <input type="checkbox" class="sr-only" v-model="remember">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            <div v-if="remember"
 | 
				
			||||||
 | 
					              class="inline-block align-middle rounded-full w-10 h-6 mr-1 bg-red-800 cursor-pointer hover:bg-red-700 transition-all">
 | 
				
			||||||
 | 
					              <div class="rounded-full w-4 h-4 m-1 ml-5 bg-white"></div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div v-if="!remember"
 | 
				
			||||||
 | 
					              class="inline-block align-middle rounded-full w-10 h-6 mr-1 bg-gray-200 dark:bg-neutral-400 cursor-pointer hover:bg-gray-300 dark:hover:bg-neutral-500 transition-all">
 | 
				
			||||||
 | 
					              <div class="rounded-full w-4 h-4 m-1 bg-white"></div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <span class="text-sm">{{$t("rememberMe")}}</span>
 | 
				
			||||||
 | 
					          </label>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
          <button v-if="authenticating"
 | 
					          <button v-if="authenticating"
 | 
				
			||||||
            class="bg-red-800 dark:bg-red-800 w-full rounded shadow py-2 text-sm text-white dark:text-white cursor-not-allowed">
 | 
					            class="bg-red-800 dark:bg-red-800 w-full rounded shadow py-2 text-sm text-white dark:text-white cursor-not-allowed">
 | 
				
			||||||
            <svg class="w-5 animate-spin mx-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
 | 
					            <svg class="w-5 animate-spin mx-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,13 @@ class API {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getRememberMeEnabled() {
 | 
				
			||||||
 | 
					    return this.call({
 | 
				
			||||||
 | 
					      method: 'get',
 | 
				
			||||||
 | 
					      path: '/remember-me',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async getuiTrafficStats() {
 | 
					  async getuiTrafficStats() {
 | 
				
			||||||
    return this.call({
 | 
					    return this.call({
 | 
				
			||||||
      method: 'get',
 | 
					      method: 'get',
 | 
				
			||||||
| 
						 | 
					@ -64,11 +71,11 @@ class API {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async createSession({ password }) {
 | 
					  async createSession({ password, remember }) {
 | 
				
			||||||
    return this.call({
 | 
					    return this.call({
 | 
				
			||||||
      method: 'post',
 | 
					      method: 'post',
 | 
				
			||||||
      path: '/session',
 | 
					      path: '/session',
 | 
				
			||||||
      body: { password },
 | 
					      body: { password, remember },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,8 @@ new Vue({
 | 
				
			||||||
    authenticating: false,
 | 
					    authenticating: false,
 | 
				
			||||||
    password: null,
 | 
					    password: null,
 | 
				
			||||||
    requiresPassword: null,
 | 
					    requiresPassword: null,
 | 
				
			||||||
 | 
					    remember: false,
 | 
				
			||||||
 | 
					    rememberMeEnabled: false,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clients: null,
 | 
					    clients: null,
 | 
				
			||||||
    clientsPersist: {},
 | 
					    clientsPersist: {},
 | 
				
			||||||
| 
						 | 
					@ -239,6 +241,7 @@ new Vue({
 | 
				
			||||||
      this.authenticating = true;
 | 
					      this.authenticating = true;
 | 
				
			||||||
      this.api.createSession({
 | 
					      this.api.createSession({
 | 
				
			||||||
        password: this.password,
 | 
					        password: this.password,
 | 
				
			||||||
 | 
					        remember: this.remember,
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
        .then(async () => {
 | 
					        .then(async () => {
 | 
				
			||||||
          const session = await this.api.getSession();
 | 
					          const session = await this.api.getSession();
 | 
				
			||||||
| 
						 | 
					@ -362,6 +365,11 @@ new Vue({
 | 
				
			||||||
        alert(err.message || err.toString());
 | 
					        alert(err.message || err.toString());
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.api.getRememberMeEnabled()
 | 
				
			||||||
 | 
					      .then((rememberMeEnabled) => {
 | 
				
			||||||
 | 
					        this.rememberMeEnabled = rememberMeEnabled;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setInterval(() => {
 | 
					    setInterval(() => {
 | 
				
			||||||
      this.refresh({
 | 
					      this.refresh({
 | 
				
			||||||
        updateCharts: this.updateCharts,
 | 
					        updateCharts: this.updateCharts,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,8 @@ const messages = { // eslint-disable-line no-unused-vars
 | 
				
			||||||
    backup: 'Backup',
 | 
					    backup: 'Backup',
 | 
				
			||||||
    titleRestoreConfig: 'Restore your configuration',
 | 
					    titleRestoreConfig: 'Restore your configuration',
 | 
				
			||||||
    titleBackupConfig: 'Backup your configuration',
 | 
					    titleBackupConfig: 'Backup your configuration',
 | 
				
			||||||
 | 
					    rememberMe: 'Remember me',
 | 
				
			||||||
 | 
					    titleRememberMe: 'Stay logged after closing the browser',
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  ua: {
 | 
					  ua: {
 | 
				
			||||||
    name: 'Ім`я',
 | 
					    name: 'Ім`я',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue