QUAL: API contract: RestException update, check if thirdparty exists before creating/updating contract (#36007)
* QUAL: API contract: RestException update, check if thirdparty exists before creating contract * also checking if socid exists during put * using the entity of this contract * also fixing entity during post * some hurl tests of contract api * check if contract id is 0, because that is not possible * check (un)activate permissions and getEntity() --------- Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
parent
7655c259f8
commit
20a428e2de
2 changed files with 196 additions and 8 deletions
|
|
@ -21,6 +21,7 @@
|
|||
use Luracast\Restler\RestException;
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
|
||||
|
||||
/**
|
||||
* API class for contracts
|
||||
|
|
@ -64,14 +65,19 @@ class Contracts extends DolibarrApi
|
|||
* @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
|
||||
* @param bool $withLines true or false to display or hide lines
|
||||
* @return Object Object with cleaned properties
|
||||
* @throws RestException
|
||||
*
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 503 Error
|
||||
*/
|
||||
public function get($id, $properties = '', $withLines = true)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
if ($id == 0) {
|
||||
throw new RestException(400, 'No contract with id=0 can exist');
|
||||
}
|
||||
$result = $this->contract->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contract not found');
|
||||
|
|
@ -108,7 +114,8 @@ class Contracts extends DolibarrApi
|
|||
* @phan-return Contrat[]|array{data:Contrat[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||
* @phpstan-return Contrat[]|array{data:Contrat[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||
*
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 400 Bad Request
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 503 Error
|
||||
*/
|
||||
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false, $withLines = true)
|
||||
|
|
@ -217,6 +224,11 @@ class Contracts extends DolibarrApi
|
|||
* @phan-param ?array<string,string> $request_data
|
||||
* @phpstan-param ?array<string,string> $request_data
|
||||
* @return int ID of contrat
|
||||
*
|
||||
* @throws RestException 400 Bad Request
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 500 Error
|
||||
*/
|
||||
public function post($request_data = null)
|
||||
{
|
||||
|
|
@ -232,6 +244,20 @@ class Contracts extends DolibarrApi
|
|||
$this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
|
||||
continue;
|
||||
}
|
||||
if ($field == 'id') {
|
||||
throw new RestException(400, 'Creating with id field is forbidden');
|
||||
}
|
||||
if ($field == 'entity' && $value != getEntity('contrat')) {
|
||||
throw new RestException(403, 'Creating entity not the same as your API user is forbidden');
|
||||
}
|
||||
|
||||
if ($field == 'socid') {
|
||||
$thirdparty = new Societe($this->db);
|
||||
$result = $thirdparty->fetch((int) $value);
|
||||
if ($result < 1) {
|
||||
throw new RestException(404, 'Thirdparty with id='.((int) $value).' not found');
|
||||
}
|
||||
}
|
||||
|
||||
$this->contract->$field = $this->_checkValForAPI($field, $value, $this->contract);
|
||||
}
|
||||
|
|
@ -568,10 +594,13 @@ class Contracts extends DolibarrApi
|
|||
* @url PUT {id}/lines/{lineid}/activate
|
||||
*
|
||||
* @return Object|bool
|
||||
*
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
*/
|
||||
public function activateLine($id, $lineid, $datestart, $dateend = null, $comment = null)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'activer')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
|
|
@ -606,10 +635,13 @@ class Contracts extends DolibarrApi
|
|||
* @url PUT {id}/lines/{lineid}/unactivate
|
||||
*
|
||||
* @return Object|bool
|
||||
*
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
*/
|
||||
public function unactivateLine($id, $lineid, $datestart, $comment = null)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'desactiver')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
|
|
@ -680,13 +712,20 @@ class Contracts extends DolibarrApi
|
|||
* @phan-param ?array<string,string> $request_data
|
||||
* @phpstan-param ?array<string,string> $request_data
|
||||
* @return Object Updated object
|
||||
*
|
||||
* @throws RestException 400 Bad Request
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 500 Error
|
||||
*/
|
||||
public function put($id, $request_data = null)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
if ($id == 0) {
|
||||
throw new RestException(400, 'No contract with id=0 can exist');
|
||||
}
|
||||
$result = $this->contract->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contrat not found');
|
||||
|
|
@ -697,13 +736,25 @@ class Contracts extends DolibarrApi
|
|||
}
|
||||
foreach ($request_data as $field => $value) {
|
||||
if ($field == 'id') {
|
||||
continue;
|
||||
throw new RestException(400, 'Updating with id field is forbidden');
|
||||
}
|
||||
if ($field == 'entity' && $value != $this->contract->entity) {
|
||||
throw new RestException(400, 'Changing entity of a contract using the APIs is not possible');
|
||||
}
|
||||
if ($field === 'caller') {
|
||||
// Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
|
||||
$this->contract->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($field == 'socid') {
|
||||
$thirdparty = new Societe($this->db);
|
||||
$result = $thirdparty->fetch((int) $value);
|
||||
if ($result < 1) {
|
||||
throw new RestException(404, 'Thirdparty with id='.((int) $value).' not found');
|
||||
}
|
||||
}
|
||||
|
||||
if ($field == 'array_options' && is_array($value)) {
|
||||
foreach ($value as $index => $val) {
|
||||
$this->contract->array_options[$index] = $this->_checkValForAPI($field, $val, $this->contract);
|
||||
|
|
@ -729,12 +780,20 @@ class Contracts extends DolibarrApi
|
|||
* @return array
|
||||
* @phan-return array{success:array{code:int,message:string}}
|
||||
* @phpstan-return array{success:array{code:int,message:string}}
|
||||
*
|
||||
* @throws RestException 400 Bad Request
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 500 Error
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'supprimer')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
if ($id == 0) {
|
||||
throw new RestException(400, 'No contract with id=0 can exist');
|
||||
}
|
||||
$result = $this->contract->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contract not found');
|
||||
|
|
@ -774,12 +833,20 @@ class Contracts extends DolibarrApi
|
|||
* {
|
||||
* "notrigger": 0
|
||||
* }
|
||||
*
|
||||
* @throws RestException 304 Not Modified
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 500 Error
|
||||
*/
|
||||
public function validate($id, $notrigger = 0)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
if ($id == 0) {
|
||||
throw new RestException(400, 'No contract with id=0 can exist');
|
||||
}
|
||||
$result = $this->contract->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contract not found');
|
||||
|
|
@ -823,12 +890,20 @@ class Contracts extends DolibarrApi
|
|||
* {
|
||||
* "notrigger": 0
|
||||
* }
|
||||
*
|
||||
* @throws RestException 304 Not Modified
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Not found
|
||||
* @throws RestException 500 Error
|
||||
*/
|
||||
public function close($id, $notrigger = 0)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'creer')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
if ($id == 0) {
|
||||
throw new RestException(400, 'No contract with id=0 can exist');
|
||||
}
|
||||
$result = $this->contract->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contract not found');
|
||||
|
|
@ -879,7 +954,8 @@ class Contracts extends DolibarrApi
|
|||
*
|
||||
* @param ?array<string,string> $data Array with data to verify
|
||||
* @return array<string,string>
|
||||
* @throws RestException
|
||||
*
|
||||
* @throws RestException 400 Bad Request
|
||||
*/
|
||||
private function _validate($data)
|
||||
{
|
||||
|
|
|
|||
112
test/hurl/api/contracts/10_contracts.hurl
Normal file
112
test/hurl/api/contracts/10_contracts.hurl
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# GET contracts
|
||||
GET http://{{hostnport}}/api/index.php/contracts
|
||||
HTTP 200
|
||||
|
||||
# GET sorted contracts
|
||||
GET http://{{hostnport}}/api/index.php/contracts?sortfield=t.rowid&sortorder=ASC
|
||||
HTTP 200
|
||||
|
||||
# GET sorted contracts
|
||||
GET http://{{hostnport}}/api/index.php/contracts?sortfield=t.rowid&sortorder=DSC
|
||||
HTTP 200
|
||||
|
||||
# GET with limit and page
|
||||
GET http://{{hostnport}}/api/index.php/contracts?limit=100&page=1
|
||||
HTTP 200
|
||||
|
||||
# GET with fk_user
|
||||
GET http://{{hostnport}}/api/index.php/contracts?fk_user=0
|
||||
HTTP 200
|
||||
|
||||
# GET with properties=id%2Cstatus
|
||||
GET http://{{hostnport}}/api/index.php/contracts?properties=id%2Cstatus
|
||||
HTTP 200
|
||||
|
||||
# GET with pagination_data=false
|
||||
GET http://{{hostnport}}/api/index.php/contracts?pagination_data=false
|
||||
HTTP 200
|
||||
|
||||
# GET with pagination_data=true
|
||||
GET http://{{hostnport}}/api/index.php/contracts?pagination_data=true
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.data" exists
|
||||
jsonpath "$.pagination.total" >= 0
|
||||
jsonpath "$.pagination.page" >= 0
|
||||
jsonpath "$.pagination.page_count" >= 0
|
||||
jsonpath "$.pagination.limit" == 100
|
||||
|
||||
# GET contract with ID 0 - which should not exist
|
||||
GET http://{{hostnport}}/api/index.php/contracts/0
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: No contract with id=0 can exist"}}
|
||||
# POST {}
|
||||
POST http://{{hostnport}}/api/index.php/contracts
|
||||
{}
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: socid field missing"}}
|
||||
|
||||
# POST topic required
|
||||
POST http://{{hostnport}}/api/index.php/contracts
|
||||
{ "id" : 42, "socid" : "22"}
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: date_contrat field missing"}}
|
||||
|
||||
# POST type_template field required
|
||||
POST http://{{hostnport}}/api/index.php/contracts
|
||||
{ "id" : 42, "socid" : "22", "date_contrat" : "873223122" }
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: commercial_signature_id field missing"}}
|
||||
|
||||
# POST No id in post request data
|
||||
POST http://{{hostnport}}/api/index.php/contracts
|
||||
{ "id" : 42, "socid" : "22", "date_contrat" : "873223122", "commercial_signature_id" : "1" }
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: commercial_suivi_id field missing"}}
|
||||
|
||||
# POST No id in post request data
|
||||
POST http://{{hostnport}}/api/index.php/contracts
|
||||
{ "id" : 42, "socid" : "22", "date_contrat" : "873223122", "commercial_signature_id" : "1", "commercial_suivi_id" : "1" }
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: Creating with id field is forbidden"}}
|
||||
|
||||
# DELETE
|
||||
DELETE http://{{hostnport}}/api/index.php/contracts/
|
||||
HTTP 405
|
||||
|
||||
# DELETE contract with ID 0 - which should not exist
|
||||
DELETE http://{{hostnport}}/api/index.php/contracts/0
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: No contract with id=0 can exist"}}
|
||||
|
||||
# PUT
|
||||
PUT http://{{hostnport}}/api/index.php/contracts/
|
||||
{}
|
||||
HTTP 405
|
||||
|
||||
# PUT
|
||||
PUT http://{{hostnport}}/api/index.php/contracts/0
|
||||
{}
|
||||
HTTP 400
|
||||
{"error":{"code":400,"message":"Bad Request: No contract with id=0 can exist"}}
|
||||
|
||||
|
||||
|
||||
# GET contracts DOLAPIENTITY: 1
|
||||
GET http://{{hostnport}}/api/index.php/contracts
|
||||
DOLAPIENTITY: 1
|
||||
HTTP 200
|
||||
|
||||
# GET contracts DOLAPIENTITY: 2
|
||||
GET http://{{hostnport}}/api/index.php/contracts
|
||||
DOLAPIENTITY: 2
|
||||
HTTP 401
|
||||
{"error":{"code":401,"message":"Unauthorized: Error user not valid (not found with api key or bad status or bad validity dates) (conf->entity=2)"}}
|
||||
|
||||
# http://localhost:8080/api/index.php/contracts?sortfield=t.rowid&sortorder=ASC&limit=1
|
||||
|
||||
# Capture a contract ID number
|
||||
GET http://{{hostnport}}/api/index.php/contracts?limit=1
|
||||
HTTP 200
|
||||
[Captures]
|
||||
contract_id: jsonpath "$[0]['id']"
|
||||
Loading…
Reference in a new issue