Manage group membership in Discourse with WP Discourse SSO

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

Holy :cow:! How’d you manage to find it!? Nice work.

By adding log statments to my development site. This should be an easy fix, but I’d rather not push the change to WordPress before I test it out some more.

3 Likes

Sure you have a reasonable development environment. Like a real developer. That I understand (in spite of my not having such!) But even thinking to try usernames that had changed… I guess the 2 was the clue.

Here’s a slightly different method to handle Paid Memberships Pro group sync. Pop this into your functions.php file. Expected behavior is add upon subscribe and remove upon cancellation. Thanks to @dfriestedt for sponsoring.

https://github.com/justindirose/dc-pmp-group-sync

8 Likes

Awesome, anything stopping this being wrapped into a plugin for customers who aren’t confident editing PHP?

1 Like

No, probably not, but PHP/WP development isn’t my forte, and I don’t plan on personally actively maintaining this code long-term.

3 Likes

I am implementing the PMPro code above and am hung up on something. My understanding is that this code only fires when users buy subscription or cancel a subscription.

Is there a way that I can auto-sync users as they are created on Discourse? In my case, I have some users who are subscribers but don’t have a Discourse accounts (will be created via SSO).

If wordpress is the SSO master then you can have it update groups at every login.

1 Like

Is there a code snippet that shows an example of updating groups on WP login?

The add_user_to_discourse_groups function will create a Discourse user if it doesn’t already exist. If that function is being called for your users, then you should be fine. Where you might run into problems will be for existing WordPress users who got their membership before the code was added to your site. If that is the case, you will probably need to add the users to Discourse groups through the SSO parameters that are passed to Discourse on login.

To pass additional SSO parameters with the WP Discourse plugin, you can hook into the 'wpdc_sso_params' filter. The parameter you need to use to add users to a Discourse group is called add_groups. You can use it with something like this:

add_filter( 'wpdc_sso_params', 'wpdc_custom_sso_params', 10, 2 );
function wpdc_custom_sso_params( $params, $user ) {
    if ( /* some condition that returns true if groups should be added for the user */ ) {
        $params['add_groups'] = 'comma,separated,group,names'; // Don't use spaces between names.
    }

    return $params;
}
7 Likes

I realise this is only sample code but it appears to have a pretty critical bug.

If the payment isn’t completed and the status of the membership is ā€œtokenā€

The group is still added to the discourse user :open_mouth:

I’ll look in to this at a later date but i think it’s worth mentioning


1 Like

I wish to use this code to restrict my Discourse community ONLY to paid members using Paid Memberships Pro. I have a free membership level and two paid membership levels.

How can I modify this code: Manage group membership in Discourse with WP Discourse SSO

so that ONLY the paid members are able to access the community. Otherwise, they will be redirected to the paid memberships sign-up page.

Thank you.

For my own reference, here’s the code you are wanting to modify:

add_action( 'wpdc_sso_provider_before_sso_redirect', 'wpdc_custom_check_user_membership', 10, 2 );
function wpdc_custom_check_user_membership( $user_id, $user ) {
    if ( /* some condition */ ) {
	    wp_safe_redirect( home_url() );

	    exit;
    }
}

What you need to do is replace the code’s /* some condition */ comment with a condition that will return true for users who do not have paid memberships. These users can then be redirected to your membership signup page.

I don’t currently have the Paid Memberships Pro plugin installed on my test site, but from their documentation, it looks like you can use their pmpro_hasMembershipLevel function to check if a user has a given membership level: https://www.paidmembershipspro.com/documentation/content-controls/require-membership-function/.

To use the pmpro_hasMembershipLevel function, you need to know the IDs (or the names) of your two paid membership levels. You can get those ids from the pmp ā€œMembership Levelsā€ admin page. For example, if the IDs of your two paid levels are 1 and 2, you could use the following condition:

if (! pmpro_hasMembershipLevel(array(1, 2), $user_id))

Substituted into the code, that would be:

add_action( 'wpdc_sso_provider_before_sso_redirect', 'wpdc_custom_check_user_membership', 10, 2 );
function wpdc_custom_check_user_membership( $user_id, $user ) {
    if (! pmpro_hasMembershipLevel( array( 1, 2 ), $user_id ) ) {
	    wp_safe_redirect( home_url() );

	    exit;
    }
}

The other line you will need to change is:

wp_safe_redirect( home_url() );

It is currently set to redirect users to the site’s homepage. You will need to change it to redirect to either the path or the full URL of your site’s sign-up page:

wp_safe_redirect( /* path_to_your_signup_page */ );

Note that I haven’t tested this code. If you are making changes directly to your live site’s functions.php file, make sure that you are able to access the site’s functions.php file from the site’s backend, just in case there are any mistakes or typos in the code.

4 Likes

Leaving myself a note here related to https://meta.discourse.org/t/manage-group-membership-in-discourse-with-wp-discourse-sso/74724#restricting-access-to-discourse-when-a-membership-doesnt-exist-4. If the WP Discourse Create or Sync Discourse Users on Login option is enabled, Discourse accounts will be automatically created for all users on the WordPress site, even if they are prevented from logging into Discourse via the method outlined in the OP. Details about how to prevent accounts from being automatically created for users who do not have the appropriate membership level are in the second part of this post: How to prevent some WP users from being able to login to Discourse - #2 by simon.

Basically:

add_filter( 'wpdc_bypass_sync_sso', 'wpdc_custom_bypass_sync_sso', 10, 3 );
function wpdc_custom_bypass_sync_sso( $bypass_sync, $user_id, $user ) {
    if ( /* Some condition that returns true if the user doesn't meet the membership requirement */  ) {

        $bypass_sync = true;
    }

    return $bypass_sync;
}

I’m setting myself a reminder to update the OP with those details.

2 Likes

Thank you, Simon. I was able to set this for my website using your instructions.

1 Like