feat: add Discourse group syncing on subscription state changes

This commit is contained in:
Matthew Lopez
2024-12-09 02:32:00 -05:00
parent 3a0f02104d
commit 5cde7c8f77
3 changed files with 52 additions and 1 deletions

View File

@@ -10,6 +10,10 @@ const PNIDSchema = new Schema({
server_access_level: String,
access_level: Number,
username: String,
mii: {
name: String,
image_url: String
},
connections: {
discord: {
id: String

View File

@@ -286,6 +286,15 @@ async function handleStripeEvent(event) {
}
}
}
try {
if (await util.discourseUserExists(pid)) {
const updatedPNID = await database.PNID.findOne({ pid });
await util.syncDiscourseSso(updatedPNID);
}
} catch (error) {
logger.error(`Error syncing user Discourse SSO | ${pid} | - ${error.message}`);
}
}
}

View File

@@ -306,6 +306,42 @@ function signDiscoursePayload(payload) {
return crypto.createHmac('sha256', config.discourse.sso.secret).update(payload).digest('hex');
}
async function discourseUserExists(pid) {
const response = await got.get(`${config.discourse.api.base_url}/users/by-external/${pid}.json`, {
throwHttpErrors: false,
responseType: 'json'
});
if (response.statusCode === 200) {
return true;
} else if (response.statusCode === 404) {
return false;
} else {
throw new Error(`Discourse API error while checking if user ${pid} exists: ${response.statusCode} - ${JSON.stringify(response.body)}`);
}
}
async function syncDiscourseSso(pnid) {
// * Documentation: https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route/84398
const headers = {
'Content-Type': 'multipart/form-data',
'Api-Username': config.discourse.api.username,
'Api-Key': config.discourse.api.key
};
const payload = createDiscoursePayload('', pnid);
const post_data = {
'sso': payload,
'sig': signDiscoursePayload(payload)
};
return got.post(`${config.discourse.api.base_url}/admin/users/sync_sso`, {
headers: headers,
form: post_data,
responseType: 'json'
});
}
module.exports = {
fullUrl,
getLocale,
@@ -327,5 +363,7 @@ module.exports = {
removeDiscordMemberSupporterRole,
removeDiscordMemberTesterRole,
createDiscoursePayload,
signDiscoursePayload
signDiscoursePayload,
discourseUserExists,
syncDiscourseSso
};