UNPKG

ghost

Version:

The professional publishing platform

137 lines (136 loc) 5.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ActivityPubService = void 0; const bson_objectid_1 = __importDefault(require("bson-objectid")); const node_fetch_1 = __importDefault(require("node-fetch")); class ActivityPubService { knex; siteUrl; logging; identityTokenService; constructor(knex, siteUrl, logging, identityTokenService) { this.knex = knex; this.siteUrl = siteUrl; this.logging = logging; this.identityTokenService = identityTokenService; } getExpectedWebhooks(secret) { return [ { event: 'post.published', target_url: new URL('.ghost/activitypub/v1/webhooks/post/published', this.siteUrl), api_version: 'v5.100.0', secret }, { event: 'post.deleted', target_url: new URL('.ghost/activitypub/v1/webhooks/post/deleted', this.siteUrl), api_version: 'v5.100.0', secret }, { event: 'post.unpublished', target_url: new URL('.ghost/activitypub/v1/webhooks/post/unpublished', this.siteUrl), api_version: 'v5.100.0', secret }, { event: 'post.published.edited', target_url: new URL('.ghost/activitypub/v1/webhooks/post/updated', this.siteUrl), api_version: 'v5.100.0', secret } ]; } async checkWebhookState(expectedWebhooks, integration) { this.logging.info(`Checking ActivityPub Webhook state`); const webhooks = await this.knex .select('*') .from('webhooks') .where('integration_id', '=', integration.id); if (webhooks.length !== expectedWebhooks.length) { this.logging.warn(`Expected ${expectedWebhooks.length} webhooks for ActivityPub`); return false; } for (const expectedWebhook of expectedWebhooks) { const foundWebhook = webhooks.find((webhook) => { return webhook.event === expectedWebhook.event && webhook.target_url === expectedWebhook.target_url.href && webhook.secret === expectedWebhook.secret; }); if (!foundWebhook) { this.logging.error(`Could not find webhook for ${expectedWebhook.event} ${expectedWebhook.target_url}`); return false; } } return true; } async getWebhookSecret() { try { const ownerUser = await this.knex('users') .select('users.*') .join('roles_users', 'users.id', 'roles_users.user_id') .join('roles', 'roles.id', 'roles_users.role_id') .where('roles.name', 'Owner') .first(); const token = await this.identityTokenService.getTokenForUser(ownerUser.email, 'Owner'); const res = await (0, node_fetch_1.default)(new URL('.ghost/activitypub/v1/site', this.siteUrl), { headers: { Authorization: `Bearer ${token}` } }); const body = await res.json(); return body.webhook_secret; } catch (err) { this.logging.error(`Could not get webhook secret for ActivityPub ${err}`); return null; } } async initialiseWebhooks() { const integration = await this.knex .select('*') .from('integrations') .where('slug', '=', 'ghost-activitypub') .andWhere('type', '=', 'internal') .first(); if (!integration) { this.logging.error('No ActivityPub integration found - cannot initialise'); return; } const secret = await this.getWebhookSecret(); if (!secret) { this.logging.error('No webhook secret found - cannot initialise'); return; } const expectedWebhooks = this.getExpectedWebhooks(secret); const isInCorrectState = await this.checkWebhookState(expectedWebhooks, integration); if (isInCorrectState) { this.logging.info(`ActivityPub webhooks in correct state`); return; } this.logging.info(`ActivityPub webhooks in incorrect state, deleting all of them and starting fresh`); await this.knex .del() .from('webhooks') .where('integration_id', '=', integration.id); const webhooksToInsert = expectedWebhooks.map((expectedWebhook) => { return { id: (new bson_objectid_1.default).toHexString(), event: expectedWebhook.event, target_url: expectedWebhook.target_url.href, api_version: expectedWebhook.api_version, name: `ActivityPub ${expectedWebhook.event} Webhook`, secret: secret, integration_id: integration.id, created_at: this.knex.raw('current_timestamp'), created_by: '1' }; }); await this.knex .insert(webhooksToInsert) .into('webhooks'); } } exports.ActivityPubService = ActivityPubService;