Manage group membership in Discourse with WP Discourse SSO

If you are developing this on your local computer, you can create a debug.log file in your wp-content folder, and add the following to your wp-config.php file so that you can write to the file:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false );

I add this function in a plugin to write to the debug.log file:

function write_log( ...$log_items ) {
	if ( true === WP_DEBUG ) {
		foreach ( $log_items as $log_item ) {
			if ( is_array( $log_item ) || is_object( $log_item ) ) {
				error_log( print_r( $log_item, true ) );
			} else {
				error_log( $log_item );
			}
		}
	}
}

This will let you add calls to write_log to your code so that you can see what’s going on. For example, in the dcpmp_get_level_for_id function, you can add:

write_log( 'In the dcpmp_get_level_for_id function, called with the id argument set to: ',  $id );

That will let you know if the function is being called, and what argument is being passed to it. Make sure that write_log calls are removed before you add the code to your live site. It is usually possible to work through code in this way, to figure out where it is going wrong.

1 Like

I’ll be honest — I had to abandon use of these methods on my site because I couldn’t get them to work.

Are you calling the group add function from a hook that fires when group membership changes?

we have the sync working. Only NEW memebers are synced or that have changed there membership.

1 Like

Glad the sync is working now! Makes sense that it only applies for new / updated members — the way WordPress works, the code that syncs users to Discourse groups only fires when triggered by certain actions e.g. new member added or membership level changed.

To fill in missing data for existing members added before the syncing was configured, you’d basically want to run a simple script to get all users, loop through and check member level for each, and if applicable call the relevant Discourse group functions.

3 Likes

thanks!
The missing data we will fill by hand because that is not that much.

1 Like

I am working with someone who wants to connect WooCommerce Subscriptions with Discourse, but has Discourse as the SSO master.

It looks like when someone places the order they might not already have a Discourse account, so hooking into the “subscription changed” hooks can’t work.

My current notion is that it might be possible to add a hook to WordPress that gets called at a successful login to WordPress that would then push the group membership over to Discourse. Do you think that could work? Is there some better idea?

Maybe use the API to send a PM to the email address first, creating a staged user account? I’ve found the staged user functionality, probably undocumented and largely unintended, to be super handy - e.g. you can even set a staged user’s notification levels for topics and categories so they can participate by email even before they create their account.

2 Likes

When Discourse is used as the SSO provider, you can check if a WordPress user has a Discourse account by checking if the value returned by this statement is empty:

get_user_meta( $user_id, 'discourse_sso_user_id', true );

You’ll need to do something to handle the case where the user doesn’t yet have a Discourse account. Creating the user via the API and adding them to the appropriate groups is probably the right solution. It will take some work to set that up.

3 Likes

Hey, @simon. It looks like add_user_to_discourse_group works only when WordPress is the SSO Master?

When I call it (configured with Discourse as master) I get

"The add_user_to_discourse_group function can only be used when SSO is enabled."

(It’s taken me hours and hours to figure out how to get useful debugging info out of WordPress. And now this. :crying_cat_face: )

Yes, add_user_to_discourse_group is only for sites that are using WordPress as the SSO Provider. It calls the Discourse sync_sso route.

That’s a fairly good error message you’re getting though. It could be improved to indicate that it only works when WordPress is the SSO Provider.

1 Like

Yeah. The error message is fine (I guess it should mention “sso master”, but I knew right away). It’s just that it wasn’t what I expected, and it’s taken me forever to figure it out. (Not your fault.)

What I’m trying to do now is have a function called at login. I’m trying to get the Discourse username so that I can then do an old-school curl to an API call to add to the group.

		$user_meta= get_user_meta( $user_id, 'discourse_sso_user_id', true );

doesn’t seem to be finding the user. Is that not how it works?

That is the correct way to get the user’s Discourse id if it has been set. $user_id needs to be the WordPress user’s ID. If you’re getting an empty response, the user has not logged in via Discourse yet. Try making the call with a user you know has logged into WordPress from Discourse.

1 Like

Sorry. It turns out that the problem is me not knowing how to get debugging info out of php/wordpress.

I now have the discourse_user_id, so now I can construct a curl to add the user to the desired group. I hope.

Thanks for your help.

For debugging WordPress, see this post: https://meta.discourse.org/t/managing-discourse-group-membership-with-wp-discourse/74724/51.

1 Like

Yeah, writing to a log file is what I wanted to do, but it seems that the only way I have access to the log on this webhost is by getting it emailed to me. :frowning:

My solution is pushing stuff to https://pipedream.com/ . It’s quite painful, but better than anything else I’ve found today. My problem before is that I need to do something different to push an array to the pipedream webhook than I do for the integer that get_user_meta returned.

1 Like

Well, it seems that if I do a curl within a wp_login action, it interferes with the SSO connection. (OOps, I’m not passing the API key, but I don’t think that’s the problem.)

add_action( 'wp_login', 'wc_login_manage_group', 10, 2);

Is there maybe something that gets called immediately after SSO is complete?

Maybe

wpdc_sso_client_after_login_link

edit: I think that might do it. Now to see if I can add to group via user_id rather than username. . .

nope. Need to figure out how php will let me access user_nicename out of $user = wp_get_current_user(); It’s right there.

Well, of course, it’s $discourse_username = $user->data->user_nicename;

I don’t think that php had that -> syntax when I learned it in 1997. :slight_smile:

But now, the user_nicename changes. Sometimes it’s correct, and sometimes it’s got a -2 appended. I’m logging out and then clicking Login via your forum account in the same browser window. This doesn’t seem right.

It goes back and forth between these:

  • “usernames”: “pfaffman_delete_gmai”
  • “usernames”: “pfaffman_delete_gmai-2”
1 Like

You’re kind of in uncharted territory with this. It’s going to be hard to develop it on a live site. I’m not sure what’s going on with the nice_name, but I’m going to take a closer look at that tomorrow.

4 Likes

Yeah. That’s on me. Setting up a staging sites with SSO seemed like it’d be a bigger problem than fighting with what was already working. It was going to be simple. :wink: This is one more reason to finish my Ansible tooling to support WordPress. :wink:

I’m a Discourse Sysadmin, dammit, not a WordPress developer!

Thanks. Unlike pretty much every other question I’ve had in this exchange, that does seem like a :bug:. Thanks for all of your help!

1 Like

Yes, this is a bug. I can only reproduce it if a username is changed on Discourse after an account is created on WordPress. I’ll get this fixed by early next week.

3 Likes