From 4aa93ef41c2c0b1a8d405e3498259ef05eb4a3c5 Mon Sep 17 00:00:00 2001 From: Dan Popescu Date: Tue, 17 Sep 2019 18:28:10 +0300 Subject: [PATCH] feat(Cookies/Storage): Add reviverFn for getting values from Cookies and Local/SessionStorage #4338 - see [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter) - fix Cookies getAll to parse value - fix Cookies set on SSR to retrieve raw previous value for replacement --- ui/src/plugins/Cookies.js | 31 +++++----- ui/src/plugins/Cookies.json | 65 ++++++++++++++++++++ ui/src/utils/private/web-storage.js | 19 +++--- ui/src/utils/private/web-storage.json | 86 +++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 24 deletions(-) diff --git a/ui/src/plugins/Cookies.js b/ui/src/plugins/Cookies.js index 5f530843edc4..d3bc9c79f469 100644 --- a/ui/src/plugins/Cookies.js +++ b/ui/src/plugins/Cookies.js @@ -12,7 +12,7 @@ function stringifyCookieValue (value) { return encode(value === Object(value) ? JSON.stringify(value) : '' + value) } -function read (string) { +function read (string, reviverFn) { if (string === '') { return string } @@ -28,7 +28,7 @@ function read (string) { string = decode(string.replace(/\+/g, ' ')) try { - string = JSON.parse(string) + string = JSON.parse(string, reviverFn) } catch (e) {} @@ -110,12 +110,13 @@ function set (key, val, opts = {}, ssr) { let all = ssr.req.headers.cookie || '' if (expire !== void 0 && expireValue < 0) { - const val = get(key, ssr) - if (val !== void 0) { + const oldVal = get(key, ssr, void 0, true) + if (oldVal !== void 0) { + const replaceKeyValue = `${encode(key)}=${stringifyCookieValue(oldVal)}` all = all - .replace(`${key}=${val}; `, '') - .replace(`; ${key}=${val}`, '') - .replace(`${key}=${val}`, '') + .replace(`${replaceKeyValue}; `, '') + .replace(`; ${replaceKeyValue}`, '') + .replace(`${replaceKeyValue}`, '') } } else { @@ -131,7 +132,7 @@ function set (key, val, opts = {}, ssr) { } } -function get (key, ssr) { +function get (key, ssr, reviverFn, raw) { const cookieSource = ssr ? ssr.req.headers : document, cookies = cookieSource.cookie ? cookieSource.cookie.split('; ') : [], @@ -149,10 +150,10 @@ function get (key, ssr) { cookie = parts.join('=') if (!key) { - result[name] = cookie + result[name] = read(cookie, reviverFn) } else if (key === name) { - result = read(cookie) + result = raw === true ? cookie : read(cookie, reviverFn) break } } @@ -169,17 +170,17 @@ function remove (key, options, ssr) { ) } -function has (key, ssr) { - return get(key, ssr) !== null +function has (key, ssr, reviverFn) { + return get(key, ssr, reviverFn) !== null } export function getObject (ssr) { return { - get: key => get(key, ssr), + get: (key, reviverFn) => get(key, ssr, reviverFn), set: (key, val, opts) => set(key, val, opts, ssr), - has: key => has(key, ssr), + has: (key, reviverFn) => has(key, ssr, reviverFn), remove: (key, options) => remove(key, options, ssr), - getAll: () => get(null, ssr) + getAll: reviverFn => get(null, ssr, reviverFn) } } diff --git a/ui/src/plugins/Cookies.json b/ui/src/plugins/Cookies.json index bf42fdb2bbd5..78c2471a4bd9 100644 --- a/ui/src/plugins/Cookies.json +++ b/ui/src/plugins/Cookies.json @@ -15,6 +15,27 @@ "desc": "Cookie name", "required": true, "examples": [ "userId" ] + }, + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for values - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } } }, "returns": { @@ -26,6 +47,29 @@ "getAll": { "desc": "Get all cookies", + "params": { + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for values - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } + } + }, "returns": { "type": "Object", "desc": "Object with cookie names (as keys) and their values", @@ -104,6 +148,27 @@ "desc": "Cookie name", "required": true, "examples": [ "userId" ] + }, + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for values - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } } }, "returns": { diff --git a/ui/src/utils/private/web-storage.js b/ui/src/utils/private/web-storage.js index 38eed7015396..fc2c35534c2d 100644 --- a/ui/src/utils/private/web-storage.js +++ b/ui/src/utils/private/web-storage.js @@ -29,8 +29,9 @@ function encode (value) { return value } -function decode (value) { +function decode (value, reviverFn) { const length = value.length + if (length < 9) { // then it wasn't encoded by us return value @@ -56,7 +57,7 @@ function decode (value) { return '' + source case '__q_objt': - return JSON.parse(source) + return JSON.parse(source, reviverFn) default: // hmm, we reached here, we don't know the type, @@ -87,20 +88,20 @@ export function getEmptyStorage () { export function getStorage (type) { const webStorage = window[type + 'Storage'], - get = key => { + get = (key, reviverFn) => { const item = webStorage.getItem(key) return item - ? decode(item) + ? decode(item, reviverFn) : null } return { - has: key => webStorage.getItem(key) !== null, + has: (key, reviverFn) => webStorage.getItem(key, reviverFn) !== null, getLength: () => webStorage.length, getItem: get, - getIndex: index => { + getIndex: (index, reviverFn) => { return index < webStorage.length - ? get(webStorage.key(index)) + ? get(webStorage.key(index), reviverFn) : null }, getKey: index => { @@ -108,13 +109,13 @@ export function getStorage (type) { ? webStorage.key(index) : null }, - getAll: () => { + getAll: reviverFn => { let key const result = {}, len = webStorage.length for (let i = 0; i < len; i++) { key = webStorage.key(i) - result[key] = get(key) + result[key] = get(key, reviverFn) } return result diff --git a/ui/src/utils/private/web-storage.json b/ui/src/utils/private/web-storage.json index f9291c206a7c..181587158795 100644 --- a/ui/src/utils/private/web-storage.json +++ b/ui/src/utils/private/web-storage.json @@ -12,6 +12,27 @@ "desc": "Entry key", "required": true, "examples": [ "userId" ] + }, + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for objects - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } } }, "returns": { @@ -38,6 +59,27 @@ "desc": "Entry key", "required": true, "examples": [ "userId" ] + }, + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for objects - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } } }, "returns": { @@ -56,6 +98,27 @@ "desc": "Entry index", "required": true, "examples": [ 5 ] + }, + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for objects - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } } }, "returns": { @@ -86,6 +149,29 @@ "getAll": { "desc": "Retrieve all items in storage", + "params": { + "reviverFn": { + "type": "Function", + "desc": "Transformation function to be used for objects - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter", + "params": { + "key": { + "type": "Any", + "desc": "Key in object", + "__exemption": [ "examples" ] + }, + "value": { + "type": "Any", + "desc": "Value in that key", + "__exemption": [ "examples" ] + } + }, + "returns": { + "type": "Any", + "desc": "Transformed value", + "__exemption": [ "examples" ] + } + } + }, "returns": { "type": "Object", "desc": "Object syntax: item name as Object key and its value",