Manage group membership in Discourse with WP Discourse SSO

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

A clarification.

No level (not a user) : 0
Free level = 1
I have two paid levels: 2,3

You said

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.

And

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))

Are these statements contradicting?

In my understanding :
I should use the following:

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

to redirect users who DO NOT have a paid membership to the member sign-up page.

Please correct me if I am wrong.

Thanks.

If the condition returns true, users will be redirected to your signup page.

I think the safest thing to do for your case would be to use a condition that returns true if the user doesn’t have either level 2 or 3:

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

1 Like

Thank you. I missed the “!” mark in your second snippet.

1 Like