mirror of
https://we.phorge.it/source/phorge.git
synced 2025-03-12 04:15:00 +01:00
Conduit accept int/bool parameters as strings
Summary: Accept Conduit parameter values as strings (e.g. from `curl`) and convert to required type. Test Plan: Call conduit method with int/bool parameter iusing `curl` and make sure it does not result in validation error, e.g. ``` $ curl http://$PHABRICATOR_HOST/api/maniphest.search -d api.token=$CONDUIT_TOKEN -d constraints[modifiedEnd]=$(date +%s) -d constraints[hasParents]=true -d limit=1 ``` Fixes T10456. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin Maniphest Tasks: T10456 Differential Revision: https://secure.phabricator.com/D16694
This commit is contained in:
parent
636eaf231e
commit
c71bb0550c
21 changed files with 127 additions and 100 deletions
|
@ -15,7 +15,7 @@ final class ConduitCall extends Phobject {
|
|||
private $request;
|
||||
private $user;
|
||||
|
||||
public function __construct($method, array $params) {
|
||||
public function __construct($method, array $params, $strictly_typed = true) {
|
||||
$this->method = $method;
|
||||
$this->handler = $this->buildMethodHandler($method);
|
||||
|
||||
|
@ -41,7 +41,7 @@ final class ConduitCall extends Phobject {
|
|||
"'".implode("', '", array_keys($invalid_params))."'"));
|
||||
}
|
||||
|
||||
$this->request = new ConduitAPIRequest($params);
|
||||
$this->request = new ConduitAPIRequest($params, $strictly_typed);
|
||||
}
|
||||
|
||||
public function getAPIRequest() {
|
||||
|
|
|
@ -25,9 +25,11 @@ final class PhabricatorConduitAPIController
|
|||
|
||||
try {
|
||||
|
||||
list($metadata, $params) = $this->decodeConduitParams($request, $method);
|
||||
list($metadata, $params, $strictly_typed) = $this->decodeConduitParams(
|
||||
$request,
|
||||
$method);
|
||||
|
||||
$call = new ConduitCall($method, $params);
|
||||
$call = new ConduitCall($method, $params, $strictly_typed);
|
||||
$method_implementation = $call->getMethodImplementation();
|
||||
|
||||
$result = null;
|
||||
|
@ -638,7 +640,7 @@ final class PhabricatorConduitAPIController
|
|||
$metadata = idx($params, '__conduit__', array());
|
||||
unset($params['__conduit__']);
|
||||
|
||||
return array($metadata, $params);
|
||||
return array($metadata, $params, true);
|
||||
}
|
||||
|
||||
// Otherwise, look for a single parameter called 'params' which has the
|
||||
|
@ -659,7 +661,7 @@ final class PhabricatorConduitAPIController
|
|||
$metadata = idx($params, '__conduit__', array());
|
||||
unset($params['__conduit__']);
|
||||
|
||||
return array($metadata, $params);
|
||||
return array($metadata, $params, true);
|
||||
}
|
||||
|
||||
// If we do not have `params`, assume this is a simple HTTP request with
|
||||
|
@ -675,7 +677,7 @@ final class PhabricatorConduitAPIController
|
|||
}
|
||||
}
|
||||
|
||||
return array($metadata, $params);
|
||||
return array($metadata, $params, false);
|
||||
}
|
||||
|
||||
private function authorizeOAuthMethodAccess(
|
||||
|
|
|
@ -3,17 +3,9 @@
|
|||
final class ConduitBoolParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
|
||||
if (!is_bool($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected boolean (true or false), got something else.'));
|
||||
}
|
||||
|
||||
return $value;
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
return $this->parseBoolValue($request, $key, $value, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
final class ConduitColumnsParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
// We don't do any meaningful validation here because the transaction
|
||||
// itself validates everything and the input format is flexible.
|
||||
return parent::getParameterValue($request, $key);
|
||||
return parent::getParameterValue($request, $key, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -3,15 +3,9 @@
|
|||
final class ConduitEpochParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
|
||||
if (!is_int($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected epoch timestamp as integer, got something else.'));
|
||||
}
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
$value = $this->parseIntValue($request, $key, $value, $strict);
|
||||
|
||||
if ($value <= 0) {
|
||||
$this->raiseValidationException(
|
||||
|
|
|
@ -3,19 +3,11 @@
|
|||
final class ConduitIntListParameterType
|
||||
extends ConduitListParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$list = parent::getParameterValue($request, $key);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$list = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
foreach ($list as $idx => $item) {
|
||||
if (!is_int($item)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht(
|
||||
'Expected a list of integers, but item with index "%s" is '.
|
||||
'not an integer.',
|
||||
$idx));
|
||||
}
|
||||
$list[$idx] = $this->parseIntValue($request, $key.'['.$idx.']', $item);
|
||||
}
|
||||
|
||||
return $list;
|
||||
|
|
|
@ -3,17 +3,9 @@
|
|||
final class ConduitIntParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
|
||||
if (!is_int($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected integer, got something else.'));
|
||||
}
|
||||
|
||||
return $value;
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
return $this->parseIntValue($request, $key, $value, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -14,8 +14,8 @@ abstract class ConduitListParameterType
|
|||
return $this->allowEmptyList;
|
||||
}
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
if (!is_array($value)) {
|
||||
$this->raiseValidationException(
|
||||
|
@ -48,17 +48,18 @@ abstract class ConduitListParameterType
|
|||
return $value;
|
||||
}
|
||||
|
||||
protected function validateStringList(array $request, $key, array $list) {
|
||||
protected function parseStringList(
|
||||
array $request,
|
||||
$key,
|
||||
array $list,
|
||||
$strict) {
|
||||
|
||||
foreach ($list as $idx => $item) {
|
||||
if (!is_string($item)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht(
|
||||
'Expected a list of strings, but item with index "%s" is '.
|
||||
'not a string.',
|
||||
$idx));
|
||||
}
|
||||
$list[$idx] = $this->parseStringValue(
|
||||
$request,
|
||||
$key.'['.$idx.']',
|
||||
$item,
|
||||
$strict);
|
||||
}
|
||||
|
||||
return $list;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
final class ConduitPHIDListParameterType
|
||||
extends ConduitListParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$list = parent::getParameterValue($request, $key);
|
||||
return $this->validateStringList($request, $key, $list);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$list = parent::getParameterValue($request, $key, $strict);
|
||||
return $this->parseStringList($request, $key, $list, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
final class ConduitPHIDParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
if (!is_string($value)) {
|
||||
$this->raiseValidationException(
|
||||
|
|
|
@ -30,12 +30,12 @@ abstract class ConduitParameterType extends Phobject {
|
|||
}
|
||||
|
||||
|
||||
final public function getValue(array $request, $key) {
|
||||
final public function getValue(array $request, $key, $strict = true) {
|
||||
if (!$this->getExists($request, $key)) {
|
||||
return $this->getParameterDefault();
|
||||
}
|
||||
|
||||
return $this->getParameterValue($request, $key);
|
||||
return $this->getParameterValue($request, $key, $strict);
|
||||
}
|
||||
|
||||
final public function getKeys($key) {
|
||||
|
@ -85,7 +85,7 @@ abstract class ConduitParameterType extends Phobject {
|
|||
return array_key_exists($key, $request);
|
||||
}
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
return $request[$key];
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,53 @@ abstract class ConduitParameterType extends Phobject {
|
|||
return array($key);
|
||||
}
|
||||
|
||||
protected function parseStringValue(array $request, $key, $value, $strict) {
|
||||
if (!is_string($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected string, got something else.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function parseIntValue(array $request, $key, $value, $strict) {
|
||||
if (!$strict && is_string($value) && ctype_digit($value)) {
|
||||
$value = $value + 0;
|
||||
if (!is_int($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Integer overflow.'));
|
||||
}
|
||||
} else if (!is_int($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected integer, got something else.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function parseBoolValue(array $request, $key, $value, $strict) {
|
||||
$bool_strings = array(
|
||||
'0' => false,
|
||||
'1' => true,
|
||||
'false' => false,
|
||||
'true' => true,
|
||||
);
|
||||
|
||||
if (!$strict && is_string($value) && isset($bool_strings[$value])) {
|
||||
$value = $bool_strings[$value];
|
||||
} else if (!is_bool($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected boolean (true or false), got something else.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
abstract protected function getParameterTypeName();
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
final class ConduitPointsParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
if (($value !== null) && !is_numeric($value)) {
|
||||
$this->raiseValidationException(
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
final class ConduitProjectListParameterType
|
||||
extends ConduitListParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$list = parent::getParameterValue($request, $key);
|
||||
$list = $this->validateStringList($request, $key, $list);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$list = parent::getParameterValue($request, $key, $strict);
|
||||
$list = $this->parseStringList($request, $key, $list, $strict);
|
||||
return id(new PhabricatorProjectPHIDResolver())
|
||||
->setViewer($this->getViewer())
|
||||
->resolvePHIDs($list);
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
final class ConduitStringListParameterType
|
||||
extends ConduitListParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$list = parent::getParameterValue($request, $key);
|
||||
return $this->validateStringList($request, $key, $list);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$list = parent::getParameterValue($request, $key, $strict);
|
||||
return $this->parseStringList($request, $key, $list, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -3,17 +3,9 @@
|
|||
final class ConduitStringParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
|
||||
if (!is_string($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
$key,
|
||||
pht('Expected string, got something else.'));
|
||||
}
|
||||
|
||||
return $value;
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
return $this->parseStringValue($request, $key, $value, $strict);
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
final class ConduitUserListParameterType
|
||||
extends ConduitListParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$list = parent::getParameterValue($request, $key);
|
||||
$list = $this->validateStringList($request, $key, $list);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$list = parent::getParameterValue($request, $key, $strict);
|
||||
$list = $this->parseStringList($request, $key, $list, $strict);
|
||||
return id(new PhabricatorUserPHIDResolver())
|
||||
->setViewer($this->getViewer())
|
||||
->resolvePHIDs($list);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
final class ConduitUserParameterType
|
||||
extends ConduitParameterType {
|
||||
|
||||
protected function getParameterValue(array $request, $key) {
|
||||
$value = parent::getParameterValue($request, $key);
|
||||
protected function getParameterValue(array $request, $key, $strict) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
if ($value === null) {
|
||||
return null;
|
||||
|
|
|
@ -6,9 +6,11 @@ final class ConduitAPIRequest extends Phobject {
|
|||
private $user;
|
||||
private $isClusterRequest = false;
|
||||
private $oauthToken;
|
||||
private $isStrictlyTyped = true;
|
||||
|
||||
public function __construct(array $params) {
|
||||
public function __construct(array $params, $strictly_typed) {
|
||||
$this->params = $params;
|
||||
$this->isStrictlyTyped = $strictly_typed;
|
||||
}
|
||||
|
||||
public function getValue($key, $default = null) {
|
||||
|
@ -68,6 +70,10 @@ final class ConduitAPIRequest extends Phobject {
|
|||
return $this->isClusterRequest;
|
||||
}
|
||||
|
||||
public function getIsStrictlyTyped() {
|
||||
return $this->isStrictlyTyped;
|
||||
}
|
||||
|
||||
public function newContentSource() {
|
||||
return PhabricatorContentSource::newForSource(
|
||||
PhabricatorConduitContentSource::SOURCECONST);
|
||||
|
|
|
@ -1115,7 +1115,9 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject {
|
|||
continue;
|
||||
}
|
||||
|
||||
$value = $field->readValueFromConduitRequest($constraints);
|
||||
$value = $field->readValueFromConduitRequest(
|
||||
$constraints,
|
||||
$request->getIsStrictlyTyped());
|
||||
$saved_query->setParameter($field->getKey(), $value);
|
||||
}
|
||||
|
||||
|
|
|
@ -323,10 +323,14 @@ abstract class PhabricatorSearchField extends Phobject {
|
|||
$this->getConduitKey());
|
||||
}
|
||||
|
||||
public function readValueFromConduitRequest(array $constraints) {
|
||||
public function readValueFromConduitRequest(
|
||||
array $constraints,
|
||||
$strict = true) {
|
||||
|
||||
return $this->getConduitParameterType()->getValue(
|
||||
$constraints,
|
||||
$this->getConduitKey());
|
||||
$this->getConduitKey(),
|
||||
$strict);
|
||||
}
|
||||
|
||||
public function getValidConstraintKeys() {
|
||||
|
|
|
@ -1903,7 +1903,10 @@ abstract class PhabricatorEditEngine
|
|||
$parameter_type->setViewer($viewer);
|
||||
|
||||
try {
|
||||
$xaction['value'] = $parameter_type->getValue($xaction, 'value');
|
||||
$xaction['value'] = $parameter_type->getValue(
|
||||
$xaction,
|
||||
'value',
|
||||
$request->getIsStrictlyTyped());
|
||||
} catch (Exception $ex) {
|
||||
throw new PhutilProxyException(
|
||||
pht(
|
||||
|
|
Loading…
Add table
Reference in a new issue