diff options
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts')
-rw-r--r-- | src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts new file mode 100644 index 000000000..afff2ec6d --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts @@ -0,0 +1,80 @@ +import _ from 'lodash'; + +/** + * This decorator can be used in a class or method. + * It will encode all the string parameters of all the methods of a class + * or, if applied on a method, the specified method. + * + * @export + * @param {Function} [target=null] + * @returns {*} + */ +export function cdEncode(...args: any[]): any { + switch (args.length) { + case 1: + return encodeClass.apply(undefined, args); + case 3: + return encodeMethod.apply(undefined, args); + default: + throw new Error(); + } +} + +/** + * This decorator can be used in parameters only. + * It will exclude the parameter from being encode. + * This should be used in parameters that are going + * to be sent in the request's body. + * + * @export + * @param {Object} target + * @param {string} propertyKey + * @param {number} index + */ +export function cdEncodeNot(target: object, propertyKey: string, index: number) { + const metadataKey = `__ignore_${propertyKey}`; + if (Array.isArray(target[metadataKey])) { + target[metadataKey].push(index); + } else { + target[metadataKey] = [index]; + } +} + +function encodeClass(target: Function) { + for (const propertyName of Object.getOwnPropertyNames(target.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(target.prototype, propertyName); + + const isMethod = descriptor.value instanceof Function; + const isConstructor = propertyName === 'constructor'; + if (!isMethod || isConstructor) { + continue; + } + + encodeMethod(target.prototype, propertyName, descriptor); + Object.defineProperty(target.prototype, propertyName, descriptor); + } +} + +function encodeMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) { + if (descriptor === undefined) { + descriptor = Object.getOwnPropertyDescriptor(target, propertyKey); + } + const originalMethod = descriptor.value; + + descriptor.value = function () { + const metadataKey = `__ignore_${propertyKey}`; + const indices: number[] = target[metadataKey] || []; + const args = []; + + for (let i = 0; i < arguments.length; i++) { + if (_.isString(arguments[i]) && indices.indexOf(i) === -1) { + args[i] = encodeURIComponent(arguments[i]); + } else { + args[i] = arguments[i]; + } + } + + const result = originalMethod.apply(this, args); + return result; + }; +} |