From bdd0843d94d89007a41a8b583ffc0f644ded20b9 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 14 Oct 2021 15:17:58 +0200 Subject: [PATCH] feat: Implement createAuthLink mutation --- packages/backend/package.json | 1 + packages/backend/src/apps/twitter/index.ts | 24 +++++++++++++ packages/backend/src/apps/twitter/info.json | 13 ++++++- .../src/graphql/mutations/create-auth-link.ts | 35 +++++++++++++++++++ packages/backend/src/graphql/root-mutation.ts | 4 ++- .../backend/src/graphql/types/auth-link.ts | 10 ++++++ .../backend/src/graphql/types/credential.ts | 1 + packages/backend/src/models/credential.ts | 12 +++++++ packages/backend/src/models/user.ts | 14 +++++++- packages/backend/src/types/field.d.ts | 14 ++++++++ yarn.lock | 5 +++ 11 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 packages/backend/src/apps/twitter/index.ts create mode 100644 packages/backend/src/graphql/mutations/create-auth-link.ts create mode 100644 packages/backend/src/graphql/types/auth-link.ts create mode 100644 packages/backend/src/types/field.d.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index 2bd1c4a6..1a673317 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -26,6 +26,7 @@ "morgan": "^1.10.0", "objection": "^2.2.17", "pg": "^8.7.1", + "twitter-api-v2": "1.6.0", "winston": "^3.3.3" }, "contributors": [ diff --git a/packages/backend/src/apps/twitter/index.ts b/packages/backend/src/apps/twitter/index.ts new file mode 100644 index 00000000..79ab8444 --- /dev/null +++ b/packages/backend/src/apps/twitter/index.ts @@ -0,0 +1,24 @@ +import TwitterApi from 'twitter-api-v2'; +import App from '../../models/app'; +import Field from '../../types/field'; + +export default class Twitter { + client: any + appData: any + + constructor(credentialsData: any) { + this.client = new TwitterApi({ + appKey: credentialsData.consumerKey, + appSecret: credentialsData.consumerSecret + }); + + this.appData = App.findOneByName('twitter') + } + + async createAuthLink() { + const appFields = this.appData.fields.find((field: Field) => field.key == 'oAuthRedirectUrl') + const callbackUrl = appFields.value; + + return this.client.generateAuthLink(callbackUrl); + } +} diff --git a/packages/backend/src/apps/twitter/info.json b/packages/backend/src/apps/twitter/info.json index f2f7a6f9..a160134a 100644 --- a/packages/backend/src/apps/twitter/info.json +++ b/packages/backend/src/apps/twitter/info.json @@ -12,7 +12,7 @@ "type": "string", "required": true, "readOnly": true, - "value": "http://localhost:3000/sample", + "value": "http://localhost:3001/app/twitter/connections/add", "placeholder": null, "description": "When asked to input an OAuth callback or redirect URL in Twitter OAuth, enter the URL above.", "docUrl": "https://automatisch.io/docs/twitter#oauth-redirect-url", @@ -84,6 +84,17 @@ ] } ] + }, + { + "step": 2, + "type": "mutation", + "name": "createAuthLink", + "fields": [ + { + "name": "id", + "value": "{response.credentialId}" + } + ] } ] } diff --git a/packages/backend/src/graphql/mutations/create-auth-link.ts b/packages/backend/src/graphql/mutations/create-auth-link.ts new file mode 100644 index 00000000..103a12e0 --- /dev/null +++ b/packages/backend/src/graphql/mutations/create-auth-link.ts @@ -0,0 +1,35 @@ +import { GraphQLNonNull, GraphQLInt } from 'graphql'; +import Credential from '../../models/credential'; +import authLinkType from '../types/auth-link'; +import User from '../../models/user'; + +type Params = { + credentialId: number, +} +const createAuthLinkResolver = async (params: Params) => { + const user = await User.query().findOne({ + email: 'user@automatisch.com' + }) + + const credential = await Credential.query().findOne({ + user_id: user.id, + id: params.credentialId + }) + + const appClass = (await import(`../../apps/${credential.key}`)).default; + + const appInstance = new appClass(credential.data) + const authLink = await appInstance.createAuthLink(); + + return authLink; +} + +const createAuthLink = { + type: authLinkType, + args: { + credentialId: { type: GraphQLNonNull(GraphQLInt) }, + }, + resolve: (_: any, params: Params) => createAuthLinkResolver(params) +}; + +export default createAuthLink; diff --git a/packages/backend/src/graphql/root-mutation.ts b/packages/backend/src/graphql/root-mutation.ts index 1a54013b..3d0f4f8f 100644 --- a/packages/backend/src/graphql/root-mutation.ts +++ b/packages/backend/src/graphql/root-mutation.ts @@ -1,10 +1,12 @@ import { GraphQLObjectType } from 'graphql'; import createCredential from './mutations/create-credential'; +import createAuthLink from './mutations/create-auth-link'; const rootMutation = new GraphQLObjectType({ name: 'Mutation', fields: { - createCredential: createCredential + createCredential: createCredential, + createAuthLink: createAuthLink } }); diff --git a/packages/backend/src/graphql/types/auth-link.ts b/packages/backend/src/graphql/types/auth-link.ts new file mode 100644 index 00000000..fbc4a6f2 --- /dev/null +++ b/packages/backend/src/graphql/types/auth-link.ts @@ -0,0 +1,10 @@ +import { GraphQLObjectType, GraphQLString } from 'graphql'; + +const authLinkType = new GraphQLObjectType({ + name: 'authLink', + fields: { + url: { type: GraphQLString } + } +}) + +export default authLinkType; diff --git a/packages/backend/src/graphql/types/credential.ts b/packages/backend/src/graphql/types/credential.ts index 6bc3abb2..6a09df16 100644 --- a/packages/backend/src/graphql/types/credential.ts +++ b/packages/backend/src/graphql/types/credential.ts @@ -4,6 +4,7 @@ import twitterCredentialType from './twitter-credential'; const credentialType = new GraphQLObjectType({ name: 'credential', fields: { + id: { type: GraphQLString }, key: { type: GraphQLString }, displayName: { type: GraphQLString }, data: { type: twitterCredentialType }, diff --git a/packages/backend/src/models/credential.ts b/packages/backend/src/models/credential.ts index 3f55904a..4231c90b 100644 --- a/packages/backend/src/models/credential.ts +++ b/packages/backend/src/models/credential.ts @@ -1,4 +1,5 @@ import Base from './base' +import User from './user' class Credential extends Base { id!: number @@ -22,6 +23,17 @@ class Credential extends Base { verified: { type: 'boolean' }, } } + + static relationMappings = () => ({ + credentials: { + relation: Base.BelongsToOneRelation, + modelClass: User, + join: { + from: 'credentials.user_id', + to: 'users.id', + }, + } + }) } export default Credential; diff --git a/packages/backend/src/models/user.ts b/packages/backend/src/models/user.ts index 7b9df512..694ad0e8 100644 --- a/packages/backend/src/models/user.ts +++ b/packages/backend/src/models/user.ts @@ -1,5 +1,6 @@ import { QueryContext, ModelOptions } from 'objection'; -import Base from './base' +import Base from './base'; +import Credential from './credential'; import bcrypt from 'bcrypt'; class User extends Base { @@ -20,6 +21,17 @@ class User extends Base { } } + static relationMappings = () => ({ + credentials: { + relation: Base.HasManyRelation, + modelClass: Credential, + join: { + from: 'users.id', + to: 'credentials.user_id', + }, + } + }) + async generateHash() { this.password = await bcrypt.hash(this.password, 10); } diff --git a/packages/backend/src/types/field.d.ts b/packages/backend/src/types/field.d.ts new file mode 100644 index 00000000..b7d3f62e --- /dev/null +++ b/packages/backend/src/types/field.d.ts @@ -0,0 +1,14 @@ +type Field = { + key: string, + label: string, + type: string, + required: boolean, + readOnly: boolean, + value: string, + placeholder: string, + description: string, + docUrl: string, + clickToCopy: boolean +} + +export default Field; diff --git a/yarn.lock b/yarn.lock index 76aece98..fec5ec43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15110,6 +15110,11 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +twitter-api-v2@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/twitter-api-v2/-/twitter-api-v2-1.6.0.tgz#429a19aed338d2ccf17a0cd890e590b20bb6e768" + integrity sha512-MLpHYyw06Ch0FLYZ8JvX4HZethpXRRtUetYe4HtPhcQvJgukvS8xKc1CG1nSuNDVZyZ1KN9ps6W3nHRZVxm+qg== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"