mirror of
https://github.com/ceph/ceph
synced 2025-01-19 09:32:00 +00:00
mgr/dashboard: Add decorator to skip parameter encoding
By enconding all parameters of api services we were also encoding parameters
that were being sent in the body of the request.
Those parameters don't need to be enconded and the server never decodes them.
With this new decorator you can specify if you don't want a parameter to be
enconded.
This is a regression introduced in f21d0da5a3
.
Fixes: http://tracker.ceph.com/issues/26856
Signed-off-by: Tiago Melo <tmelo@suse.com>
This commit is contained in:
parent
0feccf0ca9
commit
45e645b770
@ -126,12 +126,4 @@ describe('RbdService', () => {
|
||||
const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap/snapshotName');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
describe('Encode decorator', () => {
|
||||
it('should encode the imageName', () => {
|
||||
service.get('poolName', 'rbd/name').subscribe();
|
||||
const req = httpTesting.expectOne('api/block/image/poolName/rbd%2Fname');
|
||||
expect(req.request.method).toBe('GET');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { cdEncode } from '../decorators/cd-encode';
|
||||
import { cdEncode, cdEncodeNot } from '../decorators/cd-encode';
|
||||
import { ApiModule } from './api.module';
|
||||
|
||||
@cdEncode
|
||||
@ -47,7 +47,7 @@ export class RbdService {
|
||||
return this.http.get('api/block/image/default_features');
|
||||
}
|
||||
|
||||
createSnapshot(poolName, rbdName, snapshotName) {
|
||||
createSnapshot(poolName, rbdName, @cdEncodeNot snapshotName) {
|
||||
const request = {
|
||||
snapshot_name: snapshotName
|
||||
};
|
||||
@ -56,7 +56,7 @@ export class RbdService {
|
||||
});
|
||||
}
|
||||
|
||||
renameSnapshot(poolName, rbdName, snapshotName, newSnapshotName) {
|
||||
renameSnapshot(poolName, rbdName, snapshotName, @cdEncodeNot newSnapshotName) {
|
||||
const request = {
|
||||
new_snap_name: newSnapshotName
|
||||
};
|
||||
@ -65,7 +65,7 @@ export class RbdService {
|
||||
});
|
||||
}
|
||||
|
||||
protectSnapshot(poolName, rbdName, snapshotName, isProtected) {
|
||||
protectSnapshot(poolName, rbdName, snapshotName, @cdEncodeNot isProtected) {
|
||||
const request = {
|
||||
is_protected: isProtected
|
||||
};
|
||||
|
@ -0,0 +1,41 @@
|
||||
import { cdEncode, cdEncodeNot } from './cd-encode';
|
||||
|
||||
describe('cdEncode', () => {
|
||||
@cdEncode
|
||||
class ClassA {
|
||||
x2: string;
|
||||
y2: string;
|
||||
|
||||
methodA(x1: string, @cdEncodeNot y1: string) {
|
||||
this.x2 = x1;
|
||||
this.y2 = y1;
|
||||
}
|
||||
}
|
||||
|
||||
class ClassB {
|
||||
x2: string;
|
||||
y2: string;
|
||||
|
||||
@cdEncode
|
||||
methodB(x1: string, @cdEncodeNot y1: string) {
|
||||
this.x2 = x1;
|
||||
this.y2 = y1;
|
||||
}
|
||||
}
|
||||
|
||||
const word = 'a+b/c-d';
|
||||
|
||||
it('should encode all params of ClassA, with exception of y1', () => {
|
||||
const a = new ClassA();
|
||||
a.methodA(word, word);
|
||||
expect(a.x2).toBe('a%2Bb%2Fc-d');
|
||||
expect(a.y2).toBe(word);
|
||||
});
|
||||
|
||||
it('should encode all params of methodB, with exception of y1', () => {
|
||||
const b = new ClassB();
|
||||
b.methodB(word, word);
|
||||
expect(b.x2).toBe('a%2Bb%2Fc-d');
|
||||
expect(b.y2).toBe(word);
|
||||
});
|
||||
});
|
@ -9,58 +9,71 @@ import * as _ from 'lodash';
|
||||
* @param {Function} [target=null]
|
||||
* @returns {*}
|
||||
*/
|
||||
export function cdEncode(target: Function = null): any {
|
||||
if (target) {
|
||||
encodeClass(target);
|
||||
export function cdEncode(...args: any[]): any {
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
return encodeClass.apply(this, args);
|
||||
case 3:
|
||||
return encodeMethod.apply(this, 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 {
|
||||
return encodeMethod();
|
||||
target[metadataKey] = [index];
|
||||
}
|
||||
}
|
||||
|
||||
function encodeClass(target: Function) {
|
||||
for (const propertyName of Object.keys(target.prototype)) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(target.prototype, propertyName);
|
||||
|
||||
const isMethod = descriptor.value instanceof Function;
|
||||
if (!isMethod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const originalMethod = descriptor.value;
|
||||
descriptor.value = function(...args: any[]) {
|
||||
args.forEach((arg, i, argsArray) => {
|
||||
if (_.isString(arg)) {
|
||||
argsArray[i] = encodeURIComponent(arg);
|
||||
}
|
||||
});
|
||||
|
||||
const result = originalMethod.apply(this, args);
|
||||
return result;
|
||||
};
|
||||
|
||||
encodeMethod(target.prototype, propertyName, descriptor);
|
||||
Object.defineProperty(target.prototype, propertyName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
function encodeMethod() {
|
||||
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
if (descriptor === undefined) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
|
||||
}
|
||||
const originalMethod = descriptor.value;
|
||||
function encodeMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
if (descriptor === undefined) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
|
||||
}
|
||||
const originalMethod = descriptor.value;
|
||||
|
||||
descriptor.value = function() {
|
||||
const args = [];
|
||||
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])) {
|
||||
args[i] = encodeURIComponent(arguments[i]);
|
||||
} else {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
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;
|
||||
};
|
||||
const result = originalMethod.apply(this, args);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user