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 @@
+
+
+