XF 2.1 Best way to add/remove usergroups dynamically?

We are developing an application along side our forums and we want to be able to grant people user-groups based on actions they do in our application. E.g if they purchase something, exceed some milestones in our application, etc...

What is the best way for us to do this? We were ideally hoping with the introduction of the REST API we could just send a post & delete request to the endpoint to add/remove user-groups, but seems like that doesn't work and the documentation for that section is currently incomplete.

Is this likely to ever be possible for the REST API, or are we better off developing our own plugin? (We did take a look into the plugin route but the internal code of adding/removing groups seems a bit nonsensical, requiring that you add a group and assign it a unique ID and then only being able to "undo" that rather than removing it from a body property. Overall this method doesn't suit our purpose very well so we'd like to explore other options before having to change fundamental parts of our application to accomodate this slightly unintuitive system.)

Any help is appreciated.
 
Seems like I do not fully understand your question:
Do you want to add/remove new usergroups or do you just want to add/remove users to existing Usergroup?
 
Seems like I do not fully understand your question:
Do you want to add/remove new usergroups or do you just want to add/remove users to existing Usergroup?

Add and Remove users to existing usergroups. :)
Ideally, say I wanted to add usergroup(s) to a user, I'd like to be able to post/put something like secondary_group_ids with an array of group ids like so;

POST/PUT /forum/api/users/1/
Code:
{
    "secondary_group_ids": [1, 2, 3]
}
And that would then set this users id's to that array if that makes sense?

EDIT:
Obviously the above is the ideal way we'd like, but we are open to other suggestions of course.
 
Last edited:
To clarify, have you seen the REST API setup documentation that's available here:


I didn't realize that the endpoint documentation for POST users/#/ was missing, so I'll need to adjust that. However, passing a list of secondary group IDs in is supported for that endpoint. I actually just tried it with a quick test script.

So a couple things come to mind.

First, you showed JSON below where you mentioned request method and endpoint URL. Parameters should be passed in like a standard browser request (application/x-www-form-urlencoded when in the body or in the query string).

Second, you need to pass the correct format for array-type values. I don't know what HTTP client you're using, so the approach may differ. For example, in Guzzle, I can just setup my post data like this:

PHP:
$postData = [
   'secondary_group_ids' => [1, 3]
];

And it works as expected. If you are manually building the request, you'd pass in secondary_group_ids[] as the name for each value:

Code:
secondary_group_ids[]=1&secondary_group_ids[]=3

Note that when passing in this parameter, you are defining all of the secondary groups the user should be a member of, so you do need to pass in existing values. We do not currently expose add- or remove-based parameters for this.

(Interestingly, it only just came to mind, but if you need to remove all groups for a member, the request may be a little weird, as if you don't pass a parameter along, we don't take action. In this case, passing secondary_group_ids[]=0 should work.)
 
To clarify, have you seen the REST API setup documentation that's available here:


I didn't realize that the endpoint documentation for POST users/#/ was missing, so I'll need to adjust that. However, passing a list of secondary group IDs in is supported for that endpoint. I actually just tried it with a quick test script.

So a couple things come to mind.

First, you showed JSON below where you mentioned request method and endpoint URL. Parameters should be passed in like a standard browser request (application/x-www-form-urlencoded when in the body or in the query string).

Second, you need to pass the correct format for array-type values. I don't know what HTTP client you're using, so the approach may differ. For example, in Guzzle, I can just setup my post data like this:

PHP:
$postData = [
   'secondary_group_ids' => [1, 3]
];

And it works as expected. If you are manually building the request, you'd pass in secondary_group_ids[] as the name for each value:

Code:
secondary_group_ids[]=1&secondary_group_ids[]=3

Note that when passing in this parameter, you are defining all of the secondary groups the user should be a member of, so you do need to pass in existing values. We do not currently expose add- or remove-based parameters for this.

(Interestingly, it only just came to mind, but if you need to remove all groups for a member, the request may be a little weird, as if you don't pass a parameter along, we don't take action. In this case, passing secondary_group_ids[]=0 should work.)

Thanks for this. That appears to work.

If it isn't too much to ask, can I ask if you will ever decide to support JSON? It seems to be the primary standard nowadays and to be honest, I completely forgot x-www-form-urlencoded even existed, since I've never really used it.

Is there any specific reasons why XF chose to use this over JSON?
IMO it seems like it would be a lot easier to pass a JSON body of;
Code:
{
    "secondary_group_ids": [1, 2, 3]
}

Than a huge list of ids in repetition like so;
Code:
secondary_group_ids[]=1&secondary_group_ids[]=2&secondary_group_ids[]=3...

Just an opinion anyway. Hopefully you guys can consider it.

Thank you anyway and we will use the form encoded method for now. :)
 
Is there any specific reasons why XF chose to use this over JSON?
Honestly, JSON encoding requests seems to be less common, though obviously it will vary from API to API. The few I looked at were all form encoding based.

I suspect the reason for this is really that it's generally the default of most HTTP request libraries (as it's what browsers use) and it also means a generally consistent encoding method between GET and POST requests; otherwise, you would need to encode the data you're sending differently depending on the method. The JSON encoding method also doesn't really handle situations where files are being uploaded, unless you encode them in the body, which likely causes issues with larger files (files do require a different encoding anyway, though again something that is supported within HTTP libraries, web servers, and PHP directly).
 
Maybe the API could optionally support JSON payload for POST if Content-type application/json is specified?
That would be nice :)
 
Top Bottom