]> git.proxmox.com Git - proxmox-widget-toolkit.git/blobdiff - src/Utils.js
bump version to 2.3-7
[proxmox-widget-toolkit.git] / src / Utils.js
index 2163794fe9b7a881e267ef4acc8f0968dffe83e7..abbad36f67e276e15274ddd305fd47355481882d 100644 (file)
@@ -39,6 +39,10 @@ Ext.Ajax.on('beforerequest', function(conn, options) {
        }
        options.headers.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
     }
+    let storedAuth = Proxmox.Utils.getStoredAuth();
+    if (storedAuth.token) {
+       options.headers.Authorization = storedAuth.token;
+    }
 });
 
 Ext.define('Proxmox.Utils', { // a singleton
@@ -67,26 +71,28 @@ utilities: {
     language_map: {
        ar: 'Arabic',
        ca: 'Catalan',
+       zh_CN: 'Chinese (Simplified)',
+       zh_TW: 'Chinese (Traditional)',
        da: 'Danish',
-       de: 'German',
+       nl: 'Dutch',
        en: 'English',
-       es: 'Spanish',
        eu: 'Euskera (Basque)',
-       fa: 'Persian (Farsi)',
        fr: 'French',
+       de: 'German',
        he: 'Hebrew',
        it: 'Italian',
        ja: 'Japanese',
+       kr: 'Korean',
        nb: 'Norwegian (Bokmal)',
        nn: 'Norwegian (Nynorsk)',
+       fa: 'Persian (Farsi)',
        pl: 'Polish',
        pt_BR: 'Portuguese (Brazil)',
        ru: 'Russian',
        sl: 'Slovenian',
+       es: 'Spanish',
        sv: 'Swedish',
        tr: 'Turkish',
-       zh_CN: 'Chinese (Simplified)',
-       zh_TW: 'Chinese (Traditional)',
     },
 
     render_language: function(value) {
@@ -157,8 +163,8 @@ utilities: {
     format_duration_human: function(ut) {
        let seconds = 0, minutes = 0, hours = 0, days = 0;
 
-       if (ut <= 0) {
-           return '0s';
+       if (ut <= 0.1) {
+           return '<0.1s';
        }
 
        let remaining = ut;
@@ -238,22 +244,34 @@ utilities: {
        return min < width ? width : min;
     },
 
+    getStoredAuth: function() {
+       let storedAuth = JSON.parse(window.localStorage.getItem('ProxmoxUser'));
+       return storedAuth || {};
+    },
+
     setAuthData: function(data) {
-       Proxmox.CSRFPreventionToken = data.CSRFPreventionToken;
        Proxmox.UserName = data.username;
        Proxmox.LoggedOut = data.LoggedOut;
        // creates a session cookie (expire = null)
        // that way the cookie gets deleted after the browser window is closed
-       Ext.util.Cookies.set(Proxmox.Setup.auth_cookie_name, data.ticket, null, '/', null, true);
+       if (data.ticket) {
+           Proxmox.CSRFPreventionToken = data.CSRFPreventionToken;
+           Ext.util.Cookies.set(Proxmox.Setup.auth_cookie_name, data.ticket, null, '/', null, true);
+       }
+
+       if (data.token) {
+           window.localStorage.setItem('ProxmoxUser', JSON.stringify(data));
+       }
     },
 
     authOK: function() {
        if (Proxmox.LoggedOut) {
            return undefined;
        }
+       let storedAuth = Proxmox.Utils.getStoredAuth();
        let cookie = Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
-       if (Proxmox.UserName !== '' && cookie && !cookie.startsWith("PVE:tfa!")) {
-           return cookie;
+       if ((Proxmox.UserName !== '' && cookie && !cookie.startsWith("PVE:tfa!")) || storedAuth.token) {
+           return cookie || storedAuth.token;
        } else {
            return false;
        }
@@ -264,6 +282,7 @@ utilities: {
            return;
        }
        Ext.util.Cookies.clear(Proxmox.Setup.auth_cookie_name);
+       window.localStorage.removeItem("ProxmoxUser");
     },
 
     // comp.setLoading() is buggy in ExtJS 4.0.7, so we
@@ -432,32 +451,35 @@ utilities: {
     },
 
     checked_command: function(orig_cmd) {
-       Proxmox.Utils.API2Request({
-           url: '/nodes/localhost/subscription',
-           method: 'GET',
-           failure: function(response, opts) {
-               Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-           },
-           success: function(response, opts) {
-               let data = response.result.data;
-               if (data.status !== 'Active') {
-                   Ext.Msg.show({
-                       title: gettext('No valid subscription'),
-                       icon: Ext.Msg.WARNING,
-                       message: Proxmox.Utils.getNoSubKeyHtml(data.url),
-                       buttons: Ext.Msg.OK,
-                       callback: function(btn) {
-                           if (btn !== 'ok') {
-                               return;
-                           }
-                           orig_cmd();
-                       },
-                   });
-               } else {
-                   orig_cmd();
-               }
+       Proxmox.Utils.API2Request(
+           {
+               url: '/nodes/localhost/subscription',
+               method: 'GET',
+               failure: function(response, opts) {
+                   Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+               },
+               success: function(response, opts) {
+                   let res = response.result;
+                   if (res === null || res === undefined || !res || res
+                       .data.status.toLowerCase() !== 'active') {
+                       Ext.Msg.show({
+                           title: gettext('No valid subscription'),
+                           icon: Ext.Msg.WARNING,
+                           message: Proxmox.Utils.getNoSubKeyHtml(res.data.url),
+                           buttons: Ext.Msg.OK,
+                           callback: function(btn) {
+                               if (btn !== 'ok') {
+                                   return;
+                               }
+                               orig_cmd();
+                           },
+                       });
+                   } else {
+                       orig_cmd();
+                   }
+               },
            },
-       });
+       );
     },
 
     assemble_field_data: function(values, data) {
@@ -624,6 +646,7 @@ utilities: {
        stopall: ['', gettext('Stop all VMs and Containers')],
        migrateall: ['', gettext('Migrate all VMs and Containers')],
        dircreate: [gettext('Directory Storage'), gettext('Create')],
+       dirremove: [gettext('Directory'), gettext('Remove')],
        lvmcreate: [gettext('LVM Storage'), gettext('Create')],
        lvmthincreate: [gettext('LVM-Thin Storage'), gettext('Create')],
        zfscreate: [gettext('ZFS Storage'), gettext('Create')],
@@ -688,6 +711,65 @@ utilities: {
        return Proxmox.Utils.format_duration_long(uptime);
     },
 
+    systemd_unescape: function(string_value) {
+       const charcode_0 = '0'.charCodeAt(0);
+       const charcode_9 = '9'.charCodeAt(0);
+       const charcode_A = 'A'.charCodeAt(0);
+       const charcode_F = 'F'.charCodeAt(0);
+       const charcode_a = 'a'.charCodeAt(0);
+       const charcode_f = 'f'.charCodeAt(0);
+       const charcode_x = 'x'.charCodeAt(0);
+       const charcode_minus = '-'.charCodeAt(0);
+       const charcode_slash = '/'.charCodeAt(0);
+       const charcode_backslash = '\\'.charCodeAt(0);
+
+       let parse_hex_digit = function(d) {
+           if (d >= charcode_0 && d <= charcode_9) {
+               return d - charcode_0;
+           }
+           if (d >= charcode_A && d <= charcode_F) {
+               return d - charcode_A + 10;
+           }
+           if (d >= charcode_a && d <= charcode_f) {
+               return d - charcode_a + 10;
+           }
+           throw "got invalid hex digit";
+       };
+
+       let value = new TextEncoder().encode(string_value);
+       let result = new Uint8Array(value.length);
+
+       let i = 0;
+       let result_len = 0;
+
+       while (i < value.length) {
+           let c0 = value[i];
+           if (c0 === charcode_minus) {
+               result.set([charcode_slash], result_len);
+               result_len += 1;
+               i += 1;
+               continue;
+           }
+           if ((i + 4) < value.length) {
+               let c1 = value[i+1];
+               if (c0 === charcode_backslash && c1 === charcode_x) {
+                   let h1 = parse_hex_digit(value[i+2]);
+                   let h0 = parse_hex_digit(value[i+3]);
+                   let ord = h1*16+h0;
+                   result.set([ord], result_len);
+                   result_len += 1;
+                   i += 4;
+                   continue;
+               }
+           }
+           result.set([c0], result_len);
+           result_len += 1;
+           i += 1;
+       }
+
+       return new TextDecoder().decode(result.slice(0, result.len));
+    },
+
     parse_task_upid: function(upid) {
        let task = {};
 
@@ -703,7 +785,7 @@ utilities: {
        }
        task.starttime = parseInt(res[6], 16);
        task.type = res[7];
-       task.id = res[8];
+       task.id = Proxmox.Utils.systemd_unescape(res[8]);
        task.user = res[9];
 
        task.desc = Proxmox.Utils.format_task_description(task.type, task.id);
@@ -740,6 +822,31 @@ utilities: {
        return Ext.Date.format(servertime, 'Y-m-d H:i:s');
     },
 
+    render_zfs_health: function(value) {
+       if (typeof value === 'undefined') {
+           return "";
+       }
+       var iconCls = 'question-circle';
+       switch (value) {
+           case 'AVAIL':
+           case 'ONLINE':
+               iconCls = 'check-circle good';
+               break;
+           case 'REMOVED':
+           case 'DEGRADED':
+               iconCls = 'exclamation-circle warning';
+               break;
+           case 'UNAVAIL':
+           case 'FAULTED':
+           case 'OFFLINE':
+               iconCls = 'times-circle critical';
+               break;
+           default: //unknown
+       }
+
+       return '<i class="fa fa-' + iconCls + '"></i> ' + value;
+    },
+
     get_help_info: function(section) {
        let helpMap;
        if (typeof proxmoxOnlineHelpInfo !== 'undefined') {
@@ -751,7 +858,17 @@ utilities: {
            throw "no global OnlineHelpInfo map declared";
        }
 
-       return helpMap[section];
+       if (helpMap[section]) {
+           return helpMap[section];
+       }
+       // try to normalize - and _ separators, to support asciidoc and sphinx
+       // references at the same time.
+       let section_minus_normalized = section.replace(/_/, '-');
+       if (helpMap[section_minus_normalized]) {
+           return helpMap[section_minus_normalized];
+       }
+       let section_underscore_normalized = section.replace(/-/, '_');
+       return helpMap[section_underscore_normalized];
     },
 
     get_help_link: function(section) {
@@ -817,12 +934,12 @@ utilities: {
        me.IP64_match = new RegExp("^(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + ")$");
        me.IP64_cidr_match = new RegExp("^(?:" + IPV6_REGEXP + "/" + IPV6_CIDR_MASK + ")|(?:" + IPV4_REGEXP + "/" + IPV4_CIDR_MASK + ")$");
 
-       let DnsName_REGEXP = "(?:(([a-zA-Z0-9]([a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*([A-Za-z0-9]([A-Za-z0-9\\-]*[A-Za-z0-9])?))";
+       let DnsName_REGEXP = "(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*(?:[A-Za-z0-9](?:[A-Za-z0-9\\-]*[A-Za-z0-9])?))";
        me.DnsName_match = new RegExp("^" + DnsName_REGEXP + "$");
 
-       me.HostPort_match = new RegExp("^(" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")(:\\d+)?$");
-       me.HostPortBrackets_match = new RegExp("^\\[(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")\\](:\\d+)?$");
-       me.IP6_dotnotation_match = new RegExp("^" + IPV6_REGEXP + "(\\.\\d+)?$");
+       me.HostPort_match = new RegExp("^(" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")(?::(\\d+))?$");
+       me.HostPortBrackets_match = new RegExp("^\\[(" + IPV6_REGEXP + "|" + IPV4_REGEXP + "|" + DnsName_REGEXP + ")\\](?::(\\d+))?$");
+       me.IP6_dotnotation_match = new RegExp("^(" + IPV6_REGEXP + ")(?:\\.(\\d+))?$");
        me.Vlan_match = /^vlan(\\d+)/;
        me.VlanInterface_match = /(\\w+)\\.(\\d+)/;
     },