Changing Category Permissions via API


(Marcos Conceição) #1

I’m trying to change a category permission via API, but returning error 400.

I created this function with the php api.

And calling on my script:
$r = $api->editCategoryPermissions(641, array(‘admins’ => 1));

But returning error 400.

Can anyone help me?


(Dean Taylor) #2

Probably call with something more like:

$r = $api->editCategoryPermissions(641, array(
  array('group_name' => 'admins', 'permission_type' => 1)
));

(Marcos Conceição) #3

Still giving error 400.


(Dean Taylor) #4

OK, this will likely be due to array handling for parameters in PHP:

Change the function to:

function editCategoryPermissions( $categoryId, $permissions, $username = 'system' ) {
  $params = array();
  foreach ( $permissions as $group => $permission ) {
    $params['permissions[' . $group . ']'] = $permission;
  }

  if ( empty( $params ) ) {
    // @todo consider throwing an exception here
    // sending empty parameters is most likely bad
  }
  return $this->_putRequest( '/categories/' . $categoryId, $params, $username );
}

And call as you did before:

$r = $api->editCategoryPermissions( 641, array( 'admins' => 1 ) );

(Marcos Conceição) #5

Thanks @DeanMarkTaylor, but still throwing 400


(Dean Taylor) #6

What does the body text of the 400 error say?

What does the implementation of _putRequest look like?


(Marcos Conceição) #7

Nothing :confused:

stdClass Object ( [http_code] => 400 [apiresult] => )
private function _putRequest($reqString, $paramArray, $apiUser = 'system')
    {
        return $this->_putpostRequest($reqString, $paramArray, $apiUser, true);
    }

private function _putpostRequest($reqString, $paramArray, $apiUser = 'system', $putMethod = false)
    {
        $ch = curl_init();
        $url = sprintf(
            '%s://%s%s?api_key=%s&api_username=%s',
            $this->_protocol, 
            $this->_dcHostname, 
            $reqString, 
            $this->_apiKey, 
            $apiUser
        );
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($paramArray));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if ($putMethod) {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
        }
        $body = curl_exec($ch);
        $rc = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $resObj = new \stdClass();
        $resObj->http_code = $rc;
        $resObj->apiresult = json_decode($body);
        return $resObj;
    }

(Dean Taylor) #8

Personally I always:

  1. get the existing properties for the category from Discourse first
  2. reduce the result properties down to a known whitelist of properties
  3. add the permissions
  4. then make the PUT request

It might be that one or more of the of the properties is required.

The category permissions editor built into Discourse follows a similar process, however it knows exactly what should be sent back without needing a whitelist.

Filtering by a whitelist could be risky if other properties are added (by a new version of Discourse, a plugin, or custom fields), I haven’t checked the Discourse code to see if it removes the property if not set.