diff --git a/packages/backend/src/apps/discord/auth/create-auth-data.ts b/packages/backend/src/apps/discord/auth/create-auth-data.ts index c4dab8b0..25b83887 100644 --- a/packages/backend/src/apps/discord/auth/create-auth-data.ts +++ b/packages/backend/src/apps/discord/auth/create-auth-data.ts @@ -3,26 +3,20 @@ import { URLSearchParams } from 'url'; import scopes from '../common/scopes'; export default async function createAuthData($: IGlobalVariable) { - try { - const oauthRedirectUrlField = $.app.auth.fields.find( - (field: IField) => field.key == 'oAuthRedirectUrl' - ); - const callbackUrl = oauthRedirectUrlField.value as string; + const oauthRedirectUrlField = $.app.auth.fields.find( + (field: IField) => field.key == 'oAuthRedirectUrl' + ); + const callbackUrl = oauthRedirectUrlField.value as string; - const searchParams = new URLSearchParams({ - client_id: $.auth.data.consumerKey as string, - redirect_uri: callbackUrl, - response_type: 'code', - permissions: '2146958591', - scope: scopes.join(' '), - }); + const searchParams = new URLSearchParams({ + client_id: $.auth.data.consumerKey as string, + redirect_uri: callbackUrl, + response_type: 'code', + permissions: '2146958591', + scope: scopes.join(' '), + }); - const url = `${ - $.app.apiBaseUrl - }/oauth2/authorize?${searchParams.toString()}`; + const url = `${$.app.apiBaseUrl}/oauth2/authorize?${searchParams.toString()}`; - await $.auth.set({ url }); - } catch (error) { - throw new Error(`Error occured while verifying credentials: ${error}`); - } + await $.auth.set({ url }); } diff --git a/packages/backend/src/apps/flickr/auth/create-auth-data.ts b/packages/backend/src/apps/flickr/auth/create-auth-data.ts index 54e7a200..383363bd 100644 --- a/packages/backend/src/apps/flickr/auth/create-auth-data.ts +++ b/packages/backend/src/apps/flickr/auth/create-auth-data.ts @@ -1,31 +1,21 @@ -import { IJSONObject, IField, IGlobalVariable } from '@automatisch/types'; +import { IField, IGlobalVariable } from '@automatisch/types'; import { URLSearchParams } from 'url'; export default async function createAuthData($: IGlobalVariable) { - try { - const oauthRedirectUrlField = $.app.auth.fields.find( - (field: IField) => field.key == 'oAuthRedirectUrl' - ); + const oauthRedirectUrlField = $.app.auth.fields.find( + (field: IField) => field.key == 'oAuthRedirectUrl' + ); - const callbackUrl = oauthRedirectUrlField.value; - const requestPath = '/oauth/request_token'; - const data = { oauth_callback: callbackUrl }; + const callbackUrl = oauthRedirectUrlField.value; + const requestPath = '/oauth/request_token'; + const data = { oauth_callback: callbackUrl }; - const response = await $.http.post(requestPath, data); - const responseData = Object.fromEntries(new URLSearchParams(response.data)); + const response = await $.http.post(requestPath, data); + const responseData = Object.fromEntries(new URLSearchParams(response.data)); - await $.auth.set({ - url: `${$.app.apiBaseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}&perms=delete`, - accessToken: responseData.oauth_token, - accessSecret: responseData.oauth_token_secret, - }); - } catch (error) { - const errorMessages = error.response.data.errors - .map((error: IJSONObject) => error.message) - .join(' '); - - throw new Error( - `Error occured while verifying credentials: ${errorMessages}` - ); - } + await $.auth.set({ + url: `${$.app.apiBaseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}&perms=delete`, + accessToken: responseData.oauth_token, + accessSecret: responseData.oauth_token_secret, + }); } diff --git a/packages/backend/src/apps/flickr/auth/verify-credentials.ts b/packages/backend/src/apps/flickr/auth/verify-credentials.ts index 160ada6e..4539dc26 100644 --- a/packages/backend/src/apps/flickr/auth/verify-credentials.ts +++ b/packages/backend/src/apps/flickr/auth/verify-credentials.ts @@ -2,25 +2,21 @@ import { IGlobalVariable } from '@automatisch/types'; import { URLSearchParams } from 'url'; const verifyCredentials = async ($: IGlobalVariable) => { - try { - const response = await $.http.post( - `/oauth/access_token?oauth_verifier=${$.auth.data.oauthVerifier}&oauth_token=${$.auth.data.accessToken}`, - null - ); + const response = await $.http.post( + `/oauth/access_token?oauth_verifier=${$.auth.data.oauthVerifier}&oauth_token=${$.auth.data.accessToken}`, + null + ); - const responseData = Object.fromEntries(new URLSearchParams(response.data)); + const responseData = Object.fromEntries(new URLSearchParams(response.data)); - await $.auth.set({ - consumerKey: $.auth.data.consumerKey, - consumerSecret: $.auth.data.consumerSecret, - accessToken: responseData.oauth_token, - accessSecret: responseData.oauth_token_secret, - userId: responseData.user_nsid, - screenName: responseData.fullname, - }); - } catch (error) { - throw new Error(error.response.data); - } + await $.auth.set({ + consumerKey: $.auth.data.consumerKey, + consumerSecret: $.auth.data.consumerSecret, + accessToken: responseData.oauth_token, + accessSecret: responseData.oauth_token_secret, + userId: responseData.user_nsid, + screenName: responseData.fullname, + }); }; export default verifyCredentials; diff --git a/packages/backend/src/apps/github/auth/verify-credentials.ts b/packages/backend/src/apps/github/auth/verify-credentials.ts index d2c2c33b..53950337 100644 --- a/packages/backend/src/apps/github/auth/verify-credentials.ts +++ b/packages/backend/src/apps/github/auth/verify-credentials.ts @@ -2,39 +2,35 @@ import { IGlobalVariable } from '@automatisch/types'; import getCurrentUser from '../common/get-current-user'; const verifyCredentials = async ($: IGlobalVariable) => { - try { - const response = await $.http.post( - `${$.app.baseUrl}/login/oauth/access_token`, - { - client_id: $.auth.data.consumerKey, - client_secret: $.auth.data.consumerSecret, - code: $.auth.data.oauthVerifier, + const response = await $.http.post( + `${$.app.baseUrl}/login/oauth/access_token`, + { + client_id: $.auth.data.consumerKey, + client_secret: $.auth.data.consumerSecret, + code: $.auth.data.oauthVerifier, + }, + { + headers: { + Accept: 'application/json', }, - { - headers: { - Accept: 'application/json', - }, - } - ); + } + ); - const data = response.data; + const data = response.data; - $.auth.data.accessToken = data.access_token; + $.auth.data.accessToken = data.access_token; - const currentUser = await getCurrentUser($); + const currentUser = await getCurrentUser($); - await $.auth.set({ - consumerKey: $.auth.data.consumerKey, - consumerSecret: $.auth.data.consumerSecret, - accessToken: data.access_token, - scope: data.scope, - tokenType: data.token_type, - userId: currentUser.id, - screenName: currentUser.login, - }); - } catch (error) { - throw new Error(error.response.data); - } + await $.auth.set({ + consumerKey: $.auth.data.consumerKey, + consumerSecret: $.auth.data.consumerSecret, + accessToken: data.access_token, + scope: data.scope, + tokenType: data.token_type, + userId: currentUser.id, + screenName: currentUser.login, + }); }; export default verifyCredentials; diff --git a/packages/backend/src/apps/salesforce/auth/create-auth-data.ts b/packages/backend/src/apps/salesforce/auth/create-auth-data.ts index de43a3b8..b38f422e 100644 --- a/packages/backend/src/apps/salesforce/auth/create-auth-data.ts +++ b/packages/backend/src/apps/salesforce/auth/create-auth-data.ts @@ -2,21 +2,17 @@ import { IField, IGlobalVariable } from '@automatisch/types'; import qs from 'qs'; export default async function createAuthData($: IGlobalVariable) { - try { - const oauthRedirectUrlField = $.app.auth.fields.find( - (field: IField) => field.key == 'oAuthRedirectUrl' - ); - const redirectUri = oauthRedirectUrlField.value; - const searchParams = qs.stringify({ - client_id: $.auth.data.consumerKey as string, - redirect_uri: redirectUri, - response_type: 'code', - }); + const oauthRedirectUrlField = $.app.auth.fields.find( + (field: IField) => field.key == 'oAuthRedirectUrl' + ); + const redirectUri = oauthRedirectUrlField.value; + const searchParams = qs.stringify({ + client_id: $.auth.data.consumerKey as string, + redirect_uri: redirectUri, + response_type: 'code', + }); - await $.auth.set({ - url: `${$.auth.data.oauth2Url}/authorize?${searchParams}`, - }); - } catch (error) { - throw new Error(`Error occured while verifying credentials: ${error}`); - } + await $.auth.set({ + url: `${$.auth.data.oauth2Url}/authorize?${searchParams}`, + }); } diff --git a/packages/backend/src/apps/salesforce/auth/verify-credentials.ts b/packages/backend/src/apps/salesforce/auth/verify-credentials.ts index 93a3879c..b8797368 100644 --- a/packages/backend/src/apps/salesforce/auth/verify-credentials.ts +++ b/packages/backend/src/apps/salesforce/auth/verify-credentials.ts @@ -3,39 +3,35 @@ import getCurrentUser from '../common/get-current-user'; import qs from 'qs'; const verifyCredentials = async ($: IGlobalVariable) => { - try { - const oauthRedirectUrlField = $.app.auth.fields.find( - (field) => field.key == 'oAuthRedirectUrl' - ); - const redirectUri = oauthRedirectUrlField.value; - const searchParams = qs.stringify({ - code: $.auth.data.code, - grant_type: 'authorization_code', - client_id: $.auth.data.consumerKey as string, - client_secret: $.auth.data.consumerSecret as string, - redirect_uri: redirectUri, - }); - const { data } = await $.http.post( - `${$.auth.data.oauth2Url}/token?${searchParams}` - ); + const oauthRedirectUrlField = $.app.auth.fields.find( + (field) => field.key == 'oAuthRedirectUrl' + ); + const redirectUri = oauthRedirectUrlField.value; + const searchParams = qs.stringify({ + code: $.auth.data.code, + grant_type: 'authorization_code', + client_id: $.auth.data.consumerKey as string, + client_secret: $.auth.data.consumerSecret as string, + redirect_uri: redirectUri, + }); + const { data } = await $.http.post( + `${$.auth.data.oauth2Url}/token?${searchParams}` + ); - await $.auth.set({ - accessToken: data.access_token, - tokenType: data.token_type, - instanceUrl: data.instance_url, - signature: data.signature, - userId: data.id, - screenName: data.instance_url, - }); + await $.auth.set({ + accessToken: data.access_token, + tokenType: data.token_type, + instanceUrl: data.instance_url, + signature: data.signature, + userId: data.id, + screenName: data.instance_url, + }); - const currentUser = await getCurrentUser($); + const currentUser = await getCurrentUser($); - await $.auth.set({ - screenName: `${currentUser.displayName} - ${data.instance_url}`, - }); - } catch (error) { - throw new Error(error.response.data); - } + await $.auth.set({ + screenName: `${currentUser.displayName} - ${data.instance_url}`, + }); }; export default verifyCredentials; diff --git a/packages/backend/src/apps/twilio/auth/verify-credentials.ts b/packages/backend/src/apps/twilio/auth/verify-credentials.ts index 8d7b8d53..df68bb88 100644 --- a/packages/backend/src/apps/twilio/auth/verify-credentials.ts +++ b/packages/backend/src/apps/twilio/auth/verify-credentials.ts @@ -1,15 +1,11 @@ import { IGlobalVariable } from '@automatisch/types'; const verifyCredentials = async ($: IGlobalVariable) => { - try { - await $.http.get('/2010-04-01/Accounts.json?PageSize=1'); + await $.http.get('/2010-04-01/Accounts.json?PageSize=1'); - await $.auth.set({ - screenName: $.auth.data.accountSid, - }); - } catch (error) { - throw new Error(JSON.stringify(error.response.data)); - } + await $.auth.set({ + screenName: $.auth.data.accountSid, + }); }; export default verifyCredentials; diff --git a/packages/backend/src/apps/twitter/auth/create-auth-data.ts b/packages/backend/src/apps/twitter/auth/create-auth-data.ts index effbd8a6..d7ea1571 100644 --- a/packages/backend/src/apps/twitter/auth/create-auth-data.ts +++ b/packages/backend/src/apps/twitter/auth/create-auth-data.ts @@ -1,31 +1,21 @@ -import { IJSONObject, IField, IGlobalVariable } from '@automatisch/types'; +import { IField, IGlobalVariable } from '@automatisch/types'; import { URLSearchParams } from 'url'; export default async function createAuthData($: IGlobalVariable) { - try { - const oauthRedirectUrlField = $.app.auth.fields.find( - (field: IField) => field.key == 'oAuthRedirectUrl' - ); + const oauthRedirectUrlField = $.app.auth.fields.find( + (field: IField) => field.key == 'oAuthRedirectUrl' + ); - const callbackUrl = oauthRedirectUrlField.value; - const requestPath = '/oauth/request_token'; - const data = { oauth_callback: callbackUrl }; + const callbackUrl = oauthRedirectUrlField.value; + const requestPath = '/oauth/request_token'; + const data = { oauth_callback: callbackUrl }; - const response = await $.http.post(requestPath, data); - const responseData = Object.fromEntries(new URLSearchParams(response.data)); + const response = await $.http.post(requestPath, data); + const responseData = Object.fromEntries(new URLSearchParams(response.data)); - await $.auth.set({ - url: `${$.app.baseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}`, - accessToken: responseData.oauth_token, - accessSecret: responseData.oauth_token_secret, - }); - } catch (error) { - const errorMessages = error.response.data.errors - .map((error: IJSONObject) => error.message) - .join(' '); - - throw new Error( - `Error occured while verifying credentials: ${errorMessages}` - ); - } + await $.auth.set({ + url: `${$.app.baseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}`, + accessToken: responseData.oauth_token, + accessSecret: responseData.oauth_token_secret, + }); } diff --git a/packages/backend/src/apps/twitter/auth/verify-credentials.ts b/packages/backend/src/apps/twitter/auth/verify-credentials.ts index 4d50b42d..583135fe 100644 --- a/packages/backend/src/apps/twitter/auth/verify-credentials.ts +++ b/packages/backend/src/apps/twitter/auth/verify-credentials.ts @@ -2,23 +2,19 @@ import { IGlobalVariable } from '@automatisch/types'; import { URLSearchParams } from 'url'; const verifyCredentials = async ($: IGlobalVariable) => { - try { - const response = await $.http.post( - `/oauth/access_token?oauth_verifier=${$.auth.data.oauthVerifier}&oauth_token=${$.auth.data.accessToken}`, - null - ); + const response = await $.http.post( + `/oauth/access_token?oauth_verifier=${$.auth.data.oauthVerifier}&oauth_token=${$.auth.data.accessToken}`, + null + ); - const responseData = Object.fromEntries(new URLSearchParams(response.data)); + const responseData = Object.fromEntries(new URLSearchParams(response.data)); - await $.auth.set({ - accessToken: responseData.oauth_token, - accessSecret: responseData.oauth_token_secret, - userId: responseData.user_id, - screenName: responseData.screen_name, - }); - } catch (error) { - throw new Error(error.response.data); - } + await $.auth.set({ + accessToken: responseData.oauth_token, + accessSecret: responseData.oauth_token_secret, + userId: responseData.user_id, + screenName: responseData.screen_name, + }); }; export default verifyCredentials; diff --git a/packages/backend/src/errors/base.ts b/packages/backend/src/errors/base.ts index 9a871982..2e3e9863 100644 --- a/packages/backend/src/errors/base.ts +++ b/packages/backend/src/errors/base.ts @@ -1,17 +1,32 @@ import { IJSONObject } from '@automatisch/types'; export default class BaseError extends Error { - error = {}; + details = {}; constructor(error?: string | IJSONObject) { - super(); - + let computedError: Record; try { - this.error = JSON.parse(error as string); + computedError = JSON.parse(error as string); } catch { - this.error = typeof error === 'string' ? { error } : error; + computedError = typeof error === 'string' ? { error } : error; } + let computedMessage: string; + try { + // challenge to input to see if it is stringified JSON + JSON.parse(error as string); + computedMessage = error as string; + } catch { + if (typeof error === 'string') { + computedMessage = error; + } else { + computedMessage = JSON.stringify(error, null, 2); + } + } + + super(computedMessage); + + this.details = computedError; this.name = this.constructor.name; } } diff --git a/packages/backend/src/errors/create-auth-data.ts b/packages/backend/src/errors/create-auth-data.ts new file mode 100644 index 00000000..871c44eb --- /dev/null +++ b/packages/backend/src/errors/create-auth-data.ts @@ -0,0 +1,14 @@ +import { IJSONObject } from '@automatisch/types'; +import BaseError from './base'; + +export default class CreateAuthDataError extends BaseError { + constructor(error: IJSONObject) { + const computedError = + ((error.response as IJSONObject)?.data as IJSONObject) || + (error.message as string); + + super(computedError); + + this.message = `Error occured while creating authorization URL!`; + } +} diff --git a/packages/backend/src/errors/http-error.ts b/packages/backend/src/errors/http-error.ts deleted file mode 100644 index 2e71ebeb..00000000 --- a/packages/backend/src/errors/http-error.ts +++ /dev/null @@ -1,3 +0,0 @@ -import BaseError from './base'; - -export default class HttpError extends BaseError {} diff --git a/packages/backend/src/errors/http.ts b/packages/backend/src/errors/http.ts new file mode 100644 index 00000000..d4396f50 --- /dev/null +++ b/packages/backend/src/errors/http.ts @@ -0,0 +1,12 @@ +import { IJSONObject } from '@automatisch/types'; +import BaseError from './base'; + +export default class HttpError extends BaseError { + constructor(error: IJSONObject) { + const computedError = + ((error.response as IJSONObject)?.data as IJSONObject) || + (error.message as string); + + super(computedError); + } +} diff --git a/packages/backend/src/graphql/mutations/create-auth-data.ts b/packages/backend/src/graphql/mutations/create-auth-data.ts index fd3e020b..ecf5737e 100644 --- a/packages/backend/src/graphql/mutations/create-auth-data.ts +++ b/packages/backend/src/graphql/mutations/create-auth-data.ts @@ -2,6 +2,7 @@ import Context from '../../types/express/context'; import axios from 'axios'; import globalVariable from '../../helpers/global-variable'; import App from '../../models/app'; +import CreateAuthDataError from '../../errors/create-auth-data'; type Params = { input: { @@ -30,12 +31,11 @@ const createAuthData = async ( const app = await App.findOneByKey(connection.key); const $ = await globalVariable({ connection, app }); - await authInstance.createAuthData($); - try { + await authInstance.createAuthData($); await axios.get(connection.formattedData.url as string); } catch (error) { - throw new Error('Error occured while creating authorization URL!'); + throw new CreateAuthDataError(error); } return connection.formattedData; diff --git a/packages/backend/src/helpers/graphql-instance.ts b/packages/backend/src/helpers/graphql-instance.ts index aa55fe71..d65fd83c 100644 --- a/packages/backend/src/helpers/graphql-instance.ts +++ b/packages/backend/src/helpers/graphql-instance.ts @@ -23,10 +23,7 @@ const graphQLInstance = graphqlHTTP({ customFormatErrorFn: (error) => { logger.error(error.path + ' : ' + error.message + '\n' + error.stack); - return { - message: error.message, - locations: error.locations, - }; + return error.originalError; }, }); diff --git a/packages/backend/src/helpers/http-client/index.ts b/packages/backend/src/helpers/http-client/index.ts index 611d5d9b..893996d9 100644 --- a/packages/backend/src/helpers/http-client/index.ts +++ b/packages/backend/src/helpers/http-client/index.ts @@ -2,7 +2,7 @@ import axios, { AxiosRequestConfig } from 'axios'; export { AxiosInstance as IHttpClient } from 'axios'; import { IHttpClientParams } from '@automatisch/types'; import { URL } from 'url'; -import HttpError from '../../errors/http-error'; +import HttpError from '../../errors/http'; const removeBaseUrlForAbsoluteUrls = ( requestConfig: AxiosRequestConfig @@ -40,7 +40,7 @@ export default function createHttpClient({ instance.interceptors.response.use( (response) => response, (error) => { - throw new HttpError(error.response.data); + throw new HttpError(error); } ); diff --git a/packages/backend/src/services/flow.ts b/packages/backend/src/services/flow.ts index 86301400..f6a256fe 100644 --- a/packages/backend/src/services/flow.ts +++ b/packages/backend/src/services/flow.ts @@ -1,7 +1,7 @@ import Flow from '../models/flow'; import globalVariable from '../helpers/global-variable'; import EarlyExitError from '../errors/early-exit'; -import HttpError from '../errors/http-error'; +import HttpError from '../errors/http'; type ProcessFlowOptions = { flowId: string; @@ -27,7 +27,7 @@ export const processFlow = async (options: ProcessFlowOptions) => { } catch (error) { if (error instanceof EarlyExitError === false) { if (error instanceof HttpError) { - $.triggerOutput.error = error.error; + $.triggerOutput.error = error.details; } else { try { $.triggerOutput.error = JSON.parse(error.message); diff --git a/packages/web/src/components/AddAppConnection/index.tsx b/packages/web/src/components/AddAppConnection/index.tsx index 44a35a6d..7b54e0fe 100644 --- a/packages/web/src/components/AddAppConnection/index.tsx +++ b/packages/web/src/components/AddAppConnection/index.tsx @@ -6,6 +6,7 @@ import DialogContentText from '@mui/material/DialogContentText'; import Dialog from '@mui/material/Dialog'; import LoadingButton from '@mui/lab/LoadingButton'; import { FieldValues, SubmitHandler } from 'react-hook-form'; +import { IJSONObject } from '@automatisch/types'; import useFormatMessage from 'hooks/useFormatMessage'; import computeAuthStepVariables from 'helpers/computeAuthStepVariables'; @@ -37,7 +38,7 @@ export default function AddAppConnection( const { application, connectionId, onClose } = props; const { name, authDocUrl, key, auth } = application; const formatMessage = useFormatMessage(); - const [errorMessage, setErrorMessage] = React.useState(null); + const [error, setError] = React.useState(null); const [inProgress, setInProgress] = React.useState(false); const hasConnection = Boolean(connectionId); const steps = hasConnection @@ -59,7 +60,7 @@ export default function AddAppConnection( if (!steps) return; setInProgress(true); - setErrorMessage(null); + setError(null); const response: Response = { key, @@ -79,9 +80,9 @@ export default function AddAppConnection( response[step.name] = stepResponse; } catch (err) { - const error = err as Error; + const error = err as IJSONObject; console.log(error); - setErrorMessage(error.message); + setError((error.graphQLErrors as IJSONObject[])?.[0]); setInProgress(false); break; @@ -116,9 +117,13 @@ export default function AddAppConnection( )} - {errorMessage && ( - - {errorMessage} + {error && ( + + {error.message} +
{JSON.stringify(error.details, null, 2)}
)}