From f0e8f070a89dbe3f730b20469fccfcd4e5e07e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C4=B1dvan=20Akca?= <43352493+ridvanakca@users.noreply.github.com> Date: Tue, 7 Nov 2023 13:30:26 +0300 Subject: [PATCH] feat(ghost): add ghost integration (#1401) --- .../backend/src/apps/ghost/assets/favicon.svg | 60 +++++++++++++++++++ packages/backend/src/apps/ghost/auth/index.ts | 32 ++++++++++ .../src/apps/ghost/auth/is-still-verified.ts | 9 +++ .../src/apps/ghost/auth/verify-credentials.ts | 16 +++++ .../src/apps/ghost/common/add-auth-header.ts | 23 +++++++ .../src/apps/ghost/common/set-base-url.ts | 12 ++++ packages/backend/src/apps/ghost/index.d.ts | 0 packages/backend/src/apps/ghost/index.ts | 17 ++++++ packages/docs/pages/.vitepress/config.js | 6 ++ packages/docs/pages/apps/ghost/connection.md | 13 ++++ packages/docs/pages/public/favicons/ghost.svg | 60 +++++++++++++++++++ 11 files changed, 248 insertions(+) create mode 100644 packages/backend/src/apps/ghost/assets/favicon.svg create mode 100644 packages/backend/src/apps/ghost/auth/index.ts create mode 100644 packages/backend/src/apps/ghost/auth/is-still-verified.ts create mode 100644 packages/backend/src/apps/ghost/auth/verify-credentials.ts create mode 100644 packages/backend/src/apps/ghost/common/add-auth-header.ts create mode 100644 packages/backend/src/apps/ghost/common/set-base-url.ts create mode 100644 packages/backend/src/apps/ghost/index.d.ts create mode 100644 packages/backend/src/apps/ghost/index.ts create mode 100644 packages/docs/pages/apps/ghost/connection.md create mode 100644 packages/docs/pages/public/favicons/ghost.svg diff --git a/packages/backend/src/apps/ghost/assets/favicon.svg b/packages/backend/src/apps/ghost/assets/favicon.svg new file mode 100644 index 00000000..e98fb6fd --- /dev/null +++ b/packages/backend/src/apps/ghost/assets/favicon.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + diff --git a/packages/backend/src/apps/ghost/auth/index.ts b/packages/backend/src/apps/ghost/auth/index.ts new file mode 100644 index 00000000..bdb9f338 --- /dev/null +++ b/packages/backend/src/apps/ghost/auth/index.ts @@ -0,0 +1,32 @@ +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + { + key: 'instanceUrl', + label: 'Instance URL', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + { + key: 'apiKey', + label: 'Admin API Key', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/ghost/auth/is-still-verified.ts b/packages/backend/src/apps/ghost/auth/is-still-verified.ts new file mode 100644 index 00000000..66bb963e --- /dev/null +++ b/packages/backend/src/apps/ghost/auth/is-still-verified.ts @@ -0,0 +1,9 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/ghost/auth/verify-credentials.ts b/packages/backend/src/apps/ghost/auth/verify-credentials.ts new file mode 100644 index 00000000..a8795d0b --- /dev/null +++ b/packages/backend/src/apps/ghost/auth/verify-credentials.ts @@ -0,0 +1,16 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + const site = await $.http.get('/admin/site/'); + const screenName = [site.data.site.title, site.data.site.url] + .filter(Boolean) + .join(' @ '); + + await $.auth.set({ + screenName, + }); + + await $.http.get('/admin/pages/'); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/ghost/common/add-auth-header.ts b/packages/backend/src/apps/ghost/common/add-auth-header.ts new file mode 100644 index 00000000..2a449e13 --- /dev/null +++ b/packages/backend/src/apps/ghost/common/add-auth-header.ts @@ -0,0 +1,23 @@ +import { TBeforeRequest } from '@automatisch/types'; +import jwt from 'jsonwebtoken'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + const key = $.auth.data?.apiKey as string; + + if (key) { + const [id, secret] = key.split(':'); + + const token = jwt.sign({}, Buffer.from(secret, 'hex'), { + keyid: id, + algorithm: 'HS256', + expiresIn: '1h', + audience: `/admin/`, + }); + + requestConfig.headers.Authorization = `Ghost ${token}`; + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/ghost/common/set-base-url.ts b/packages/backend/src/apps/ghost/common/set-base-url.ts new file mode 100644 index 00000000..1a769742 --- /dev/null +++ b/packages/backend/src/apps/ghost/common/set-base-url.ts @@ -0,0 +1,12 @@ +import { TBeforeRequest } from '@automatisch/types'; + +const setBaseUrl: TBeforeRequest = ($, requestConfig) => { + const instanceUrl = $.auth.data.instanceUrl as string; + if (instanceUrl) { + requestConfig.baseURL = `${instanceUrl}/ghost/api`; + } + + return requestConfig; +}; + +export default setBaseUrl; diff --git a/packages/backend/src/apps/ghost/index.d.ts b/packages/backend/src/apps/ghost/index.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/backend/src/apps/ghost/index.ts b/packages/backend/src/apps/ghost/index.ts new file mode 100644 index 00000000..b2e0de7d --- /dev/null +++ b/packages/backend/src/apps/ghost/index.ts @@ -0,0 +1,17 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; +import setBaseUrl from './common/set-base-url'; +import auth from './auth'; + +export default defineApp({ + name: 'Ghost', + key: 'ghost', + baseUrl: 'https://ghost.org', + apiBaseUrl: '', + iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/ghost/connection', + primaryColor: '15171A', + supportsConnections: true, + beforeRequest: [setBaseUrl, addAuthHeader], + auth, +}); diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index f8c5db37..74482c54 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -95,6 +95,12 @@ export default defineConfig({ { text: 'Connection', link: '/apps/formatter/connection' }, ], }, + { + text: 'Ghost', + collapsible: true, + collapsed: true, + items: [{ text: 'Connection', link: '/apps/ghost/connection' }], + }, { text: 'GitHub', collapsible: true, diff --git a/packages/docs/pages/apps/ghost/connection.md b/packages/docs/pages/apps/ghost/connection.md new file mode 100644 index 00000000..2de3528b --- /dev/null +++ b/packages/docs/pages/apps/ghost/connection.md @@ -0,0 +1,13 @@ +# Ghost + +:::info +This page explains the steps you need to follow to set up the Ghost connection in Automatisch. If any of the steps are outdated, please let us know! +::: + +1. Go to your Ghost Admin panel. +2. Click on the **Integrations** button. +3. Click on the **Add custom integration** button and create Admin API key. +4. Add your Admin API Key in the **Admin API Key** field on Automatisch. +5. Add your API URL in the **Instance URL** field on Automatisch. +6. Click **Submit** button on Automatisch. +7. Congrats! Start using your new Ghost connection within the flows. diff --git a/packages/docs/pages/public/favicons/ghost.svg b/packages/docs/pages/public/favicons/ghost.svg new file mode 100644 index 00000000..e98fb6fd --- /dev/null +++ b/packages/docs/pages/public/favicons/ghost.svg @@ -0,0 +1,60 @@ + + + + + + + + + + +