feat: Introduce generic auth steps

This commit is contained in:
Ali BARIN
2021-10-14 18:34:30 +02:00
parent 1fbc58e7e1
commit 9c529b6c6d
12 changed files with 399 additions and 313 deletions

View File

@@ -2,6 +2,7 @@
"name": "@automatisch/root",
"private": true,
"scripts": {
"start": "lerna run --stream --scope @*/{web,backend} dev",
"start:web": "lerna run --stream --scope @*/web start",
"start:backend": "lerna run --stream --scope @*/backend dev"
},

View File

@@ -55,7 +55,7 @@
},
{
"name": "data",
"value": "data",
"value": null,
"fields": [
{
"name": "consumerKey",
@@ -76,7 +76,7 @@
"fields": [
{
"name": "id",
"value": "{response.credentialId}"
"value": "{createCredential.id}"
}
]
}

View File

@@ -1,15 +1,15 @@
import { GraphQLNonNull, GraphQLInt } from 'graphql';
import { GraphQLNonNull, GraphQLString } from 'graphql';
import Credential from '../../models/credential';
import authLinkType from '../types/auth-link';
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
type Params = {
credentialId: number,
id: number,
}
const createAuthLinkResolver = async (params: Params, req: RequestWithCurrentUser) => {
const credential = await Credential.query().findOne({
user_id: req.currentUser.id,
id: params.credentialId
id: params.id
})
const appClass = (await import(`../../apps/${credential.key}`)).default;
@@ -23,7 +23,7 @@ const createAuthLinkResolver = async (params: Params, req: RequestWithCurrentUse
const createAuthLink = {
type: authLinkType,
args: {
credentialId: { type: GraphQLNonNull(GraphQLInt) },
id: { type: GraphQLNonNull(GraphQLString) },
},
resolve: (_: any, params: Params, req: RequestWithCurrentUser) => createAuthLinkResolver(params, req)
};

View File

@@ -12,12 +12,14 @@
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/lodash.template": "^4.5.0",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.3.0",
"clipboard-copy": "^4.0.1",
"graphql": "^15.6.0",
"lodash.template": "^4.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.17.2",
@@ -28,7 +30,7 @@
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"

View File

@@ -1,4 +1,4 @@
import { useMutation } from '@apollo/client';
import { useApolloClient, useMutation } from '@apollo/client';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
@@ -6,8 +6,9 @@ import Dialog from '@mui/material/Dialog';
import Button from '@mui/material/Button';
import { FieldValues, SubmitHandler } from 'react-hook-form';
import computeAuthStepVariables from 'helpers/computeAuthStepVariables';
import InputCreator from 'components/InputCreator';
import { CREATE_CREDENTIALS } from 'graphql/mutations/create-credentials';
import MUTATIONS from 'graphql/mutations';
import type { App } from 'types/app';
import { Form } from './style';
@@ -16,26 +17,33 @@ type AddAppConnectionProps = {
application: App;
};
type Response = {
[key: string]: any;
}
export default function AddAppConnection(props: AddAppConnectionProps){
const { application, onClose } = props;
const { name, fields } = application;
const { key, fields, authenticationSteps } = application;
const [createCredentials, { data: newCredentials }] = useMutation(CREATE_CREDENTIALS);
console.log('newCredentials', newCredentials)
const apollo = useApolloClient();
const submitHandler: SubmitHandler<FieldValues> = (data) => {
const variables = {
key: application.key,
displayName: data.displayName,
data: {
consumerKey: data.consumerKey,
consumerSecret: data.consumerSecret
}
const submitHandler: SubmitHandler<FieldValues> = async (data) => {
const response: Response = {
key,
fields: data,
};
createCredentials({ variables });
for await (const authenticationStep of authenticationSteps) {
const mutation = MUTATIONS[authenticationStep.name as string];
const variables = computeAuthStepVariables(authenticationStep, response);
onClose?.();
const mutationResponse: any = await apollo.mutate({
mutation,
variables,
});
response[authenticationStep.name] = mutationResponse.data[authenticationStep.name];
}
};
return (

View File

@@ -0,0 +1,9 @@
import { gql } from '@apollo/client';
export const CREATE_AUTH_LINK = gql`
mutation CreateAuthLink($id: String!) {
createAuthLink(id: $id) {
url
}
}
`;

View File

@@ -1,10 +1,10 @@
import { gql } from '@apollo/client';
export const CREATE_CREDENTIALS = gql`
mutation CreateCredentials($displayName: String!, $key: String!, $data: twitterCredentialInput!) {
createCredential(displayName: $displayName, key: $key, data: $data) {
export const CREATE_CREDENTIAL = gql`
mutation CreateCredential($key: String!, $data: twitterCredentialInput!) {
createCredential(key: $key, data: $data) {
key
displayName
id
data {
consumerKey
consumerSecret

View File

@@ -0,0 +1,13 @@
import { CREATE_CREDENTIAL } from './create-credentials';
import { CREATE_AUTH_LINK } from './create-auth-link';
type Mutations = {
[key: string]: any,
}
const mutations: Mutations = {
createCredential: CREATE_CREDENTIAL,
createAuthLink: CREATE_AUTH_LINK,
};
export default mutations;

View File

@@ -19,6 +19,19 @@ export const GET_APP = gql`
docUrl
clickToCopy
}
authenticationSteps {
step
type
name
fields {
name
value
fields {
name
value
}
}
}
}
}
`;

View File

@@ -0,0 +1,25 @@
import template from 'lodash.template';
const interpolate = /{([\s\S]+?)}/g;
type VARIABLES = {
[key: string]: any
}
const computeAuthStepVariables = (authStep: any, aggregatedData: any) => {
const variables: VARIABLES = {};
for (const field of authStep.fields) {
if (field.fields) {
variables[field.name] = computeAuthStepVariables(field, aggregatedData);
continue;
}
variables[field.name] = template(field.value, { interpolate })(aggregatedData);
}
return variables;
};
export default computeAuthStepVariables;

View File

@@ -17,6 +17,7 @@ type App = {
docUrl: string;
primaryColor: string;
fields: AppFields[];
authenticationSteps: any[];
};
export type { App, AppFields };

588
yarn.lock

File diff suppressed because it is too large Load Diff