Merge pull request #658 from automatisch/discord/auth

feat(discord): add auth
This commit is contained in:
Ömer Faruk Aydın
2022-10-30 13:37:14 +01:00
committed by GitHub
13 changed files with 365 additions and 0 deletions

View File

@@ -0,0 +1 @@
export default [];

View File

@@ -0,0 +1,4 @@
<svg fill="#5865f2" aria-label="Discord" role="img" version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<rect width="512" height="512" rx="15%" fill="#fff"/>
<path d="m386 137c-24-11-49.5-19-76.3-23.7c-.5 0-1 0-1.2.6c-3.3 5.9-7 13.5-9.5 19.5c-29-4.3-57.5-4.3-85.7 0c-2.6-6.2-6.3-13.7-10-19.5c-.3-.4-.7-.7-1.2-.6c-23 4.6-52.4 13-76 23.7c-.2 0-.4.2-.5.4c-49 73-62 143-55 213c0 .3.2.7.5 1c32 23.6 63 38 93.6 47.3c.5 0 1 0 1.3-.4c7.2-9.8 13.6-20.2 19.2-31.2c.3-.6 0-1.4-.7-1.6c-10-4-20-8.6-29.3-14c-.7-.4-.8-1.5 0-2c2-1.5 4-3 5.8-4.5c.3-.3.8-.3 1.2-.2c61.4 28 128 28 188 0c.4-.2.9-.1 1.2.1c1.9 1.6 3.8 3.1 5.8 4.6c.7.5.6 1.6 0 2c-9.3 5.5-19 10-29.3 14c-.7.3-1 1-.6 1.7c5.6 11 12.1 21.3 19 31c.3.4.8.6 1.3.4c30.6-9.5 61.7-23.8 93.8-47.3c.3-.2.5-.5.5-1c7.8-80.9-13.1-151-55.4-213c0-.2-.3-.4-.5-.4Zm-192 171c-19 0-34-17-34-38c0-21 15-38 34-38c19 0 34 17 34 38c0 21-15 38-34 38zm125 0c-19 0-34-17-34-38c0-21 15-38 34-38c19 0 34 17 34 38c0 21-15 38-34 38z" fill="#5865f2"/>
</svg>

After

Width:  |  Height:  |  Size: 993 B

View File

@@ -0,0 +1,27 @@
import { IField, IGlobalVariable } from '@automatisch/types';
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 searchParams = new URLSearchParams({
client_id: $.auth.data.consumerKey as string,
redirect_uri: callbackUrl,
response_type: 'code',
scope: scopes.join(' '),
});
const url = `${$.app.apiBaseUrl}/oauth2/authorize?${searchParams.toString()}`;
await $.auth.set({ url });
} catch (error) {
throw new Error(
`Error occured while verifying credentials: ${error}`
);
}
}

View File

@@ -0,0 +1,221 @@
import createAuthData from './create-auth-data';
import verifyCredentials from './verify-credentials';
import isStillVerified from './is-still-verified';
export default {
fields: [
{
key: 'oAuthRedirectUrl',
label: 'OAuth Redirect URL',
type: 'string' as const,
required: true,
readOnly: true,
value: '{WEB_APP_URL}/app/discord/connections/add',
placeholder: null,
description: 'When asked to input an OAuth callback or redirect URL in Discord OAuth, enter the URL above.',
docUrl: 'https://automatisch.io/docs/discord#oauth-redirect-url',
clickToCopy: true
},
{
key: 'consumerKey',
label: 'Consumer Key',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description: null,
docUrl: 'https://automatisch.io/docs/discord#consumer-key',
clickToCopy: false
},
{
key: 'consumerSecret',
label: 'Consumer Secret',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description: null,
docUrl: 'https://automatisch.io/docs/discord#consumer-secret',
clickToCopy: false
}
],
authenticationSteps: [
{
step: 1,
type: 'mutation' as const,
name: 'createConnection',
arguments: [
{
name: 'key',
value: '{key}'
},
{
name: 'formattedData',
value: null,
properties: [
{
name: 'consumerKey',
value: '{fields.consumerKey}'
},
{
name: 'consumerSecret',
value: '{fields.consumerSecret}'
}
]
}
]
},
{
step: 2,
type: 'mutation' as const,
name: 'createAuthData',
arguments: [
{
name: 'id',
value: '{createConnection.id}'
}
]
},
{
step: 3,
type: 'openWithPopup' as const,
name: 'openAuthPopup',
arguments: [
{
name: 'url',
value: '{createAuthData.url}'
}
]
},
{
step: 4,
type: 'mutation' as const,
name: 'updateConnection',
arguments: [
{
name: 'id',
value: '{createConnection.id}'
},
{
name: 'formattedData',
value: null,
properties: [
{
name: 'oauthVerifier',
value: '{openAuthPopup.code}'
}
]
}
]
},
{
step: 5,
type: 'mutation' as const,
name: 'verifyConnection',
arguments: [
{
name: 'id',
value: '{createConnection.id}'
}
]
}
],
reconnectionSteps: [
{
step: 1,
type: 'mutation' as const,
name: 'resetConnection',
arguments: [
{
name: 'id',
value: '{connection.id}'
}
]
},
{
step: 2,
type: 'mutation' as const,
name: 'updateConnection',
arguments: [
{
name: 'id',
value: '{connection.id}'
},
{
name: 'formattedData',
value: null,
properties: [
{
name: 'consumerKey',
value: '{fields.consumerKey}'
},
{
name: 'consumerSecret',
value: '{fields.consumerSecret}'
}
]
}
]
},
{
step: 3,
type: 'mutation' as const,
name: 'createAuthData',
arguments: [
{
name: 'id',
value: '{connection.id}'
}
]
},
{
step: 4,
type: 'openWithPopup' as const,
name: 'openAuthPopup',
arguments: [
{
name: 'url',
value: '{createAuthData.url}'
}
]
},
{
step: 5,
type: 'mutation' as const,
name: 'updateConnection',
arguments: [
{
name: 'id',
value: '{connection.id}'
},
{
name: 'formattedData',
value: null,
properties: [
{
name: 'oauthVerifier',
value: '{openAuthPopup.code}'
}
]
}
]
},
{
step: 6,
type: 'mutation' as const,
name: 'verifyConnection',
arguments: [
{
name: 'id',
value: '{connection.id}'
}
]
}
],
createAuthData,
verifyCredentials,
isStillVerified,
};

View File

@@ -0,0 +1,14 @@
import { IGlobalVariable } from '@automatisch/types';
import getCurrentUser from '../common/get-current-user';
const isStillVerified = async ($: IGlobalVariable) => {
try {
await getCurrentUser($);
return true;
} catch (error) {
return false;
}
};
export default isStillVerified;

View File

@@ -0,0 +1,50 @@
import { IGlobalVariable, IField } from '@automatisch/types';
import { URLSearchParams } from 'url';
import scopes from '../common/scopes';
import getCurrentUser from '../common/get-current-user';
const verifyCredentials = async ($: IGlobalVariable) => {
const oauthRedirectUrlField = $.app.auth.fields.find(
(field: IField) => field.key == 'oAuthRedirectUrl'
);
const callbackUrl = oauthRedirectUrlField.value as string;
const params = new URLSearchParams({
client_id: $.auth.data.consumerKey as string,
redirect_uri: callbackUrl,
response_type: 'code',
scope: scopes.join(' '),
client_secret: $.auth.data.consumerSecret as string,
code: $.auth.data.oauthVerifier as string,
grant_type: 'authorization_code',
});
const { data: verifiedCredentials } = await $.http.post(
'/oauth2/token',
params.toString()
);
const {
access_token: accessToken,
refresh_token: refreshToken,
expires_in: expiresIn,
scope: scope,
token_type: tokenType,
} = verifiedCredentials;
await $.auth.set({
accessToken,
refreshToken,
expiresIn,
scope,
tokenType,
})
const user = await getCurrentUser($);
await $.auth.set({
userId: user.id,
screenName: user.username,
email: user.email,
});
};
export default verifyCredentials;

View File

@@ -0,0 +1,12 @@
import { TBeforeRequest } from '@automatisch/types';
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
const { tokenType, accessToken } = $.auth.data;
if (tokenType && accessToken) {
requestConfig.headers.Authorization = `${tokenType} ${accessToken}`;
}
return requestConfig;
};
export default addAuthHeader;

View File

@@ -0,0 +1,10 @@
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
const getCurrentUser = async ($: IGlobalVariable): Promise<IJSONObject> => {
const response = await $.http.get('/users/@me');
const currentUser = response.data;
return currentUser;
};
export default getCurrentUser;

View File

@@ -0,0 +1,3 @@
const scopes = ['identify', 'email'];
export default scopes;

View File

View File

@@ -0,0 +1,20 @@
import defineApp from '../../helpers/define-app';
import addAuthHeader from './common/add-auth-header';
import auth from './auth';
import actions from './actions';
import triggers from './triggers';
export default defineApp({
name: 'Discord',
key: 'discord',
iconUrl: '{BASE_URL}/apps/discord/assets/favicon.svg',
authDocUrl: 'https://automatisch.io/docs/connections/discord',
supportsConnections: true,
baseUrl: 'https://discord.com',
apiBaseUrl: 'https://discord.com/api',
primaryColor: '5865f2',
beforeRequest: [addAuthHeader],
auth,
triggers,
actions,
});

View File

@@ -0,0 +1 @@
export default [];

View File

@@ -39,6 +39,8 @@ const globalVariable = async (
...args,
},
});
$.auth.data = connection.formattedData;
}
return null;