diff --git a/packages/backend/package.json b/packages/backend/package.json index 000d831..584fe96 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@octokit/oauth-methods": "^1.2.6", + "@slack/oauth": "2.3.0", "axios": "0.24.0", "bcrypt": "^5.0.1", "cors": "^2.8.5", diff --git a/packages/backend/src/apps/slack/assets/favicon.svg b/packages/backend/src/apps/slack/assets/favicon.svg new file mode 100644 index 0000000..81629c7 --- /dev/null +++ b/packages/backend/src/apps/slack/assets/favicon.svg @@ -0,0 +1,6 @@ + diff --git a/packages/backend/src/apps/slack/index.ts b/packages/backend/src/apps/slack/index.ts new file mode 100644 index 0000000..0425e87 --- /dev/null +++ b/packages/backend/src/apps/slack/index.ts @@ -0,0 +1,54 @@ +import { InstallProvider } from '@slack/oauth'; +import App from '../../models/app'; +import Field from '../../types/field'; + +export default class Slack { + client: any + connectionData: any + appData: any + + scopes: string[] = [ + 'channels:read' + ] + + constructor(connectionData: any) { + this.client = new InstallProvider({ + clientId: connectionData.consumerKey, + clientSecret: connectionData.consumerSecret, + stateSecret: 'my-state-secret' + }); + + this.connectionData = connectionData; + this.appData = App.findOneByKey('slack'); + } + + async createAuthData() { + const url = await this.client.generateInstallUrl({ + scopes: this.scopes + }) + + return { url } + } + + async verifyCredentials() { + // const verifiedCredentials = await this.client.login(this.connectionData.oauthVerifier) + + // return { + // consumerKey: this.connectionData.consumerKey, + // consumerSecret: this.connectionData.consumerSecret, + // accessToken: verifiedCredentials.accessToken, + // accessSecret: verifiedCredentials.accessSecret, + // userId: verifiedCredentials.userId, + // screenName: verifiedCredentials.screenName + // } + } + + async isStillVerified() { + // try { + // await this.client.currentUser(); + // return true; + // } catch { + // return false + // } + } +} diff --git a/packages/backend/src/apps/slack/info.json b/packages/backend/src/apps/slack/info.json new file mode 100644 index 0000000..3aea4fd --- /dev/null +++ b/packages/backend/src/apps/slack/info.json @@ -0,0 +1,218 @@ +{ + "name": "Slack", + "key": "slack", + "iconUrl": "{BASE_URL}/apps/slack/assets/favicon.svg", + "docUrl": "https://automatisch.io/docs/slack", + "primaryColor": "2DAAE1", + "fields": [ + { + "key": "oAuthRedirectUrl", + "label": "OAuth Redirect URL", + "type": "string", + "required": true, + "readOnly": true, + "value": "https://localhost:3001/app/slack/connections/add", + "placeholder": null, + "description": "When asked to input an OAuth callback or redirect URL in Slack OAuth, enter the URL above.", + "docUrl": "https://automatisch.io/docs/slack#oauth-redirect-url", + "clickToCopy": true + }, + { + "key": "consumerKey", + "label": "Client ID", + "type": "string", + "required": true, + "readOnly": false, + "value": null, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/slack#client-id", + "clickToCopy": false + }, + { + "key": "consumerSecret", + "label": "Client Secret", + "type": "string", + "required": true, + "readOnly": false, + "value": null, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/slack#client-secret", + "clickToCopy": false + } + ], + "authenticationSteps": [ + { + "step": 1, + "type": "mutation", + "name": "createConnection", + "arguments": [ + { + "name": "key", + "value": "{key}" + }, + { + "name": "data", + "value": null, + "properties": [ + { + "name": "consumerKey", + "value": "{fields.consumerKey}" + }, + { + "name": "consumerSecret", + "value": "{fields.consumerSecret}" + } + ] + } + ] + }, + { + "step": 2, + "type": "mutation", + "name": "createAuthData", + "arguments": [ + { + "name": "id", + "value": "{createConnection.id}" + } + ] + }, + { + "step": 3, + "type": "openWithPopup", + "name": "openAuthPopup", + "arguments": [ + { + "name": "url", + "value": "{createAuthData.url}" + } + ] + }, + { + "step": 4, + "type": "mutation", + "name": "updateConnection", + "arguments": [ + { + "name": "id", + "value": "{createConnection.id}" + }, + { + "name": "data", + "value": null, + "properties": [ + { + "name": "oauthVerifier", + "value": "{openAuthPopup.oauth_verifier}" + } + ] + } + ] + }, + { + "step": 5, + "type": "mutation", + "name": "verifyConnection", + "arguments": [ + { + "name": "id", + "value": "{createConnection.id}" + } + ] + } + ], + "reconnectionSteps": [ + { + "step": 1, + "type": "mutation", + "name": "resetConnection", + "arguments": [ + { + "name": "id", + "value": "{connection.id}" + } + ] + }, + { + "step": 2, + "type": "mutation", + "name": "updateConnection", + "arguments": [ + { + "name": "id", + "value": "{connection.id}" + }, + { + "name": "data", + "value": null, + "properties": [ + { + "name": "consumerKey", + "value": "{fields.consumerKey}" + }, + { + "name": "consumerSecret", + "value": "{fields.consumerSecret}" + } + ] + } + ] + }, + { + "step": 3, + "type": "mutation", + "name": "createAuthData", + "arguments": [ + { + "name": "id", + "value": "{connection.id}" + } + ] + }, + { + "step": 4, + "type": "openWithPopup", + "name": "openAuthPopup", + "arguments": [ + { + "name": "url", + "value": "{createAuthData.url}" + } + ] + }, + { + "step": 5, + "type": "mutation", + "name": "updateConnection", + "arguments": [ + { + "name": "id", + "value": "{connection.id}" + }, + { + "name": "data", + "value": null, + "properties": [ + { + "name": "oauthVerifier", + "value": "{openAuthPopup.oauth_verifier}" + } + ] + } + ] + }, + { + "step": 6, + "type": "mutation", + "name": "verifyConnection", + "arguments": [ + { + "name": "id", + "value": "{connection.id}" + } + ] + } + ] +} diff --git a/packages/backend/src/apps/twitter/index.ts b/packages/backend/src/apps/twitter/index.ts index 9416dc2..34f21b1 100644 --- a/packages/backend/src/apps/twitter/index.ts +++ b/packages/backend/src/apps/twitter/index.ts @@ -23,12 +23,12 @@ export default class Twitter { const appFields = this.appData.fields.find((field: Field) => field.key == 'oAuthRedirectUrl') const callbackUrl = appFields.value; - const authLink = await this.client.generateAuthLink(callbackUrl); + const authData = await this.client.generateAuthLink(callbackUrl); return { - url: authLink.url, - accessToken: authLink.oauth_token, - accessSecret: authLink.oauth_token_secret, + url: authData.url, + accessToken: authData.oauth_token, + accessSecret: authData.oauth_token_secret, } } diff --git a/packages/backend/src/graphql/mutations/create-connection.ts b/packages/backend/src/graphql/mutations/create-connection.ts index cc97ab6..8ed4a65 100644 --- a/packages/backend/src/graphql/mutations/create-connection.ts +++ b/packages/backend/src/graphql/mutations/create-connection.ts @@ -10,6 +10,8 @@ type Params = { data: object } const createConnectionResolver = async (params: Params, req: RequestWithCurrentUser) => { + console.log('params :', params) + const app = App.findOneByKey(params.key); const connection = await Connection.query().insert({ key: params.key, diff --git a/yarn.lock b/yarn.lock index 64c9344..97f2d7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2815,6 +2815,47 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@slack/logger@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@slack/logger/-/logger-3.0.0.tgz#b736d4e1c112c22a10ffab0c2d364620aedcb714" + integrity sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA== + dependencies: + "@types/node" ">=12.0.0" + +"@slack/oauth@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@slack/oauth/-/oauth-2.3.0.tgz#733f583cc8733bfb8fe7884b5a33e86a64f1b33c" + integrity sha512-VcxxQ8rks7Vx9mCF7JtOT8QnksnfMsQmKP6S7l5fZ8BzptdqrhNjoBvnfzdmJLjG2qGFA5Ucua6xjNMNv6ZGZg== + dependencies: + "@slack/logger" "^3.0.0" + "@slack/web-api" "^6.3.0" + "@types/jsonwebtoken" "^8.3.7" + "@types/node" ">=12" + jsonwebtoken "^8.5.1" + lodash.isstring "^4.0.1" + +"@slack/types@^2.0.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@slack/types/-/types-2.2.0.tgz#fcc3648ee20c3fb92a076b23c35bca19158d9925" + integrity sha512-/yHEFvgp0UY/lfFvQqbq9BocW/pM4xnGycqGAx+plRgYp96dZp1y50Whz7yzOgasEUsy5TyQfBK07cj0RwUyIg== + +"@slack/web-api@^6.3.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@slack/web-api/-/web-api-6.4.0.tgz#fe8212e4aca50c4cbafe4dac3f4b81c84c527423" + integrity sha512-Hi0pq60d/zCqn1UQvuSyrMcoLGNbKUBL/Tmk1b1RPTZdVYiRK8zp337glvhxTBwiaGOu+58uO5yflpK1AAuoRw== + dependencies: + "@slack/logger" "^3.0.0" + "@slack/types" "^2.0.0" + "@types/is-stream" "^1.1.0" + "@types/node" ">=12.0.0" + axios "^0.21.1" + eventemitter3 "^3.1.0" + form-data "^2.5.0" + is-electron "^2.2.0" + is-stream "^1.1.0" + p-queue "^6.6.1" + p-retry "^4.0.0" + "@surma/rollup-plugin-off-main-thread@^1.1.1": version "1.4.2" resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz#e6786b6af5799f82f7ab3a82e53f6182d2b91a58" @@ -3142,6 +3183,13 @@ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.1.tgz#e81ad28a60bee0328c6d2384e029aec626f1ae67" integrity sha512-e+2rjEwK6KDaNOm5Aa9wNGgyS9oSZU/4pfSMMPYNOfjvFI0WVXm29+ITRFr6aKDvvKo7uU1jV68MW4ScsfDi7Q== +"@types/is-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1" + integrity sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg== + dependencies: + "@types/node" "*" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -3187,6 +3235,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/jsonwebtoken@^8.3.7": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.5.tgz#da5f2f4baee88f052ef3e4db4c1a0afb46cff22c" + integrity sha512-OGqtHQ7N5/Ap/TUwO6IgHDuLiAoTmHhGpNvgkCm/F4N6pKzx/RBSfr2OXZSwC6vkfnsEdb6+7DNZVtiXiwdwFw== + dependencies: + "@types/node" "*" + "@types/lodash.template@^4.5.0": version "4.5.0" resolved "https://registry.yarnpkg.com/@types/lodash.template/-/lodash.template-4.5.0.tgz#277654af717ed37ce2687c69f8f221c550276b7a" @@ -3226,6 +3281,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.9.tgz#8f1cdd517972f76a3b928298f4c0747cd6fef25a" integrity sha512-H9ReOt+yqIJPCutkTYjFjlyK6WEMQYT9hLZMlWtOjFQY2ItppsWZ6RJf8Aw+jz5qTYceuHvFgPIaKOHtLAEWBw== +"@types/node@>=12", "@types/node@>=12.0.0": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== + "@types/node@^12.0.0": version "12.20.33" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.33.tgz#24927446e8b7669d10abacedd16077359678f436" @@ -3336,6 +3396,11 @@ dependencies: "@types/node" "*" +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "@types/scheduler@*": version "0.16.2" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" @@ -4293,7 +4358,7 @@ axios@0.24.0: dependencies: follow-redirects "^1.14.4" -axios@^0.21.4: +axios@^0.21.1, axios@^0.21.4: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== @@ -7230,6 +7295,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + eventemitter3@^4.0.0, eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -7754,7 +7824,7 @@ fork-ts-checker-webpack-plugin@4.1.6: tapable "^1.0.0" worker-rpc "^0.1.0" -form-data@^2.3.1: +form-data@^2.3.1, form-data@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== @@ -9075,6 +9145,11 @@ is-docker@^2.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-electron@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0" + integrity sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q== + is-error@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" @@ -11918,6 +11993,14 @@ p-retry@^3.0.1: dependencies: retry "^0.12.0" +p-retry@^4.0.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + dependencies: + "@types/retry" "^0.12.0" + retry "^0.13.1" + p-timeout@^3.1.0, p-timeout@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" @@ -14090,6 +14173,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"