Changing Category Permissions via API

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?

1 Like

Probably call with something more like:

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

Still giving error 400.

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 ) );
1 Like

Thanks @DeanMarkTaylor, but still throwing 400

What does the body text of the 400 error say?

What does the implementation of _putRequest look like?

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;
    }

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.

3 Likes