From 5cde7c8f778cfcdd25e65214006f29b27c054702 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 9 Dec 2024 02:32:00 -0500 Subject: [PATCH] feat: add Discourse group syncing on subscription state changes --- src/schema/pnid.js | 4 ++++ src/stripe.js | 9 +++++++++ src/util.js | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/schema/pnid.js b/src/schema/pnid.js index e613ceb..297e4e4 100644 --- a/src/schema/pnid.js +++ b/src/schema/pnid.js @@ -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 diff --git a/src/stripe.js b/src/stripe.js index eddb382..3880ac7 100644 --- a/src/stripe.js +++ b/src/stripe.js @@ -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}`); + } } } diff --git a/src/util.js b/src/util.js index f95e37b..efc0c09 100644 --- a/src/util.js +++ b/src/util.js @@ -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 };