mirror of
https://github.com/dadosfera/maestro.git
synced 2026-10-15 07:39:08 +00:00
Saving oauth connections
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
import { Controller, Get, Redirect, Req, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { InputsService } from '../inputs/inputs.service';
|
||||
import { Request } from 'express';
|
||||
import { ConnectionClientService } from '../connection/client.service';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
|
||||
@ApiTags('oauth')
|
||||
@Controller('oauth')
|
||||
export class OauthController {
|
||||
frontendRedirectUri = '';
|
||||
constructor(private inputService: InputsService) {
|
||||
constructor(
|
||||
private connectionService: ConnectionClientService,
|
||||
private logger: DadosferaLogger,
|
||||
) {
|
||||
switch (process.env.ENV) {
|
||||
case 'dev':
|
||||
case 'stg':
|
||||
@@ -31,7 +36,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('hubspot'))
|
||||
@Redirect()
|
||||
async oauthHubspotCallback(@Req() req) {
|
||||
return await this.callback(req, 'hubspot');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('googleads')
|
||||
@@ -44,7 +49,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('google'))
|
||||
@Redirect()
|
||||
async oauthGoogleAdsCallback(@Req() req) {
|
||||
return await this.callback(req, 'googleads');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('google-sheets')
|
||||
@@ -57,7 +62,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('google'))
|
||||
@Redirect()
|
||||
async oauthGoogleSheetsCallback(@Req() req) {
|
||||
return await this.callback(req, 'google-sheets');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('facebook')
|
||||
@@ -70,7 +75,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('facebook'))
|
||||
@Redirect()
|
||||
async oauthFacebookCallback(@Req() req) {
|
||||
return await this.callback(req, 'facebook');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('mailchimp')
|
||||
@@ -83,7 +88,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('mailchimp'))
|
||||
@Redirect()
|
||||
async oauthMailchimpCallback(@Req() req) {
|
||||
return await this.callback(req, 'mailchimp');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('salesforce')
|
||||
@@ -96,11 +101,11 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('salesforce'))
|
||||
@Redirect()
|
||||
async oauthSalesforceCallback(@Req() req) {
|
||||
return await this.callback(req, 'salesforce');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
async callback(@Req() req: Request, plugin) {
|
||||
const { error, state: customer_id } = req.query;
|
||||
async callback(@Req() req: Request) {
|
||||
const { error, state } = req.query;
|
||||
|
||||
if (error)
|
||||
return {
|
||||
@@ -116,12 +121,33 @@ export class OauthController {
|
||||
|
||||
const { accessToken: access_token, refreshToken: refresh_token } = authInfo;
|
||||
|
||||
const response = await this.inputService.create({
|
||||
info: { customer_id, customer: 'customer', user_id: 'empty' },
|
||||
plugin,
|
||||
credentials: { access_token, refresh_token },
|
||||
});
|
||||
let connectionInfo: any;
|
||||
try {
|
||||
connectionInfo = jwt.verify(state as string, process.env.JWT_PRIVATE_KEY);
|
||||
} catch (error) {
|
||||
return {
|
||||
url: `${this.frontendRedirectUri}?error=invalid_state`,
|
||||
};
|
||||
}
|
||||
|
||||
return { url: `${this.frontendRedirectUri}?input_id=${response.input.id}` };
|
||||
connectionInfo.properties.access_token = access_token;
|
||||
connectionInfo.properties.refresh_token = refresh_token;
|
||||
|
||||
const { customer_id, customer_name, user_id } = connectionInfo;
|
||||
|
||||
try {
|
||||
const response = await this.connectionService.createConnection(
|
||||
connectionInfo,
|
||||
{ customer_id, customer_name, user_id },
|
||||
);
|
||||
return {
|
||||
url: `${this.frontendRedirectUri}?connection_id=${response.connection.id}`,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
return {
|
||||
url: `${this.frontendRedirectUri}?error=internal`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { InputsModule } from '../inputs/inputs.module';
|
||||
import { OauthController } from './oauth.controller';
|
||||
|
||||
import { getOauthSecrets } from '../../utils/OauthSecrets';
|
||||
@@ -9,17 +8,22 @@ import { FacebookStrategy } from './passport-strategies/facebook-strategy';
|
||||
import { GoogleStrategy } from './passport-strategies/google-strategy';
|
||||
import { MailChimpStrategy } from './passport-strategies/mailchimp-strategy';
|
||||
import { SalesforceStrategy } from './passport-strategies/salesforce-strategy';
|
||||
import { ConnectionModule } from '../connection/connection.module';
|
||||
import { OauthService } from './oauth.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
DadosferaLogger,
|
||||
{ provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() },
|
||||
HubspotStrategy,
|
||||
FacebookStrategy,
|
||||
GoogleStrategy,
|
||||
MailChimpStrategy,
|
||||
SalesforceStrategy,
|
||||
OauthService,
|
||||
],
|
||||
controllers: [OauthController],
|
||||
imports: [InputsModule],
|
||||
imports: [ConnectionModule],
|
||||
})
|
||||
export class OauthModule {}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConnectionDto } from '../connection/dtos/connection';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
|
||||
class PartialConnection extends PartialType(ConnectionDto) {}
|
||||
|
||||
@Injectable()
|
||||
export class OauthService {
|
||||
generateStateFromRequest(req, type): string {
|
||||
const plugin: string = req.route.path
|
||||
.replace('/oauth/', '')
|
||||
.replace('/callback', '');
|
||||
|
||||
const { query } = req;
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
connector_id,
|
||||
connector_name,
|
||||
image_url,
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
} = query;
|
||||
|
||||
const properties = { plugin, credentials_type: 'oauth' };
|
||||
for (const key in query) {
|
||||
if (key.includes('properties.')) {
|
||||
const propertyKey = key.split('.')[1];
|
||||
properties[propertyKey] = query[key];
|
||||
}
|
||||
}
|
||||
|
||||
const newConnection: PartialConnection = {
|
||||
name,
|
||||
description,
|
||||
connector_id,
|
||||
connector_name,
|
||||
image_url,
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
type,
|
||||
properties,
|
||||
};
|
||||
return jwt.sign({ ...newConnection }, process.env.JWT_PRIVATE_KEY);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { Profile, Strategy, StrategyOptions } from 'passport-google-oauth20';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
@@ -9,6 +10,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options: StrategyOptions = {
|
||||
clientID: oauthSecrets.google.client_id,
|
||||
@@ -44,23 +46,25 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
const plugin: string = req.route.path
|
||||
.replace('/oauth/', '')
|
||||
.replace('/callback', '');
|
||||
|
||||
const { customer_id } = req.query;
|
||||
options.scope = ['https://www.googleapis.com/auth/userinfo.email'];
|
||||
options.callbackURL = `${this.redirect_uri}/${plugin}/callback`;
|
||||
|
||||
switch (plugin) {
|
||||
case 'googleads':
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
options.scope.push('https://www.googleapis.com/auth/adwords');
|
||||
break;
|
||||
case 'google-sheets':
|
||||
options.state = this.oauthService.generateStateFromRequest(req, 'file');
|
||||
options.scope.push(
|
||||
'https://www.googleapis.com/auth/drive.metadata.readonly',
|
||||
'https://www.googleapis.com/auth/spreadsheets.readonly',
|
||||
);
|
||||
break;
|
||||
}
|
||||
options.state = customer_id;
|
||||
options.accessType = 'offline';
|
||||
options.prompt = 'consent';
|
||||
super.authenticate(req, options);
|
||||
|
||||
@@ -2,12 +2,14 @@ import { Strategy } from 'passport-hubspot-oauth2';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
super(
|
||||
{
|
||||
@@ -25,8 +27,10 @@ export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
}
|
||||
|
||||
authenticate(req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ import { Strategy } from 'passport-mailchimp';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable, Req } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class MailChimpStrategy extends PassportStrategy(Strategy, 'mailchimp') {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options = {
|
||||
clientID: oauthSecrets.mailchimp.client_id,
|
||||
@@ -28,8 +30,10 @@ export class MailChimpStrategy extends PassportStrategy(Strategy, 'mailchimp') {
|
||||
}
|
||||
|
||||
authenticate(@Req() req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Strategy } from 'passport-forcedotcom';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class SalesforceStrategy extends PassportStrategy(
|
||||
@@ -11,6 +12,7 @@ export class SalesforceStrategy extends PassportStrategy(
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options = {
|
||||
clientID: oauthSecrets.salesforce.client_id,
|
||||
@@ -40,8 +42,7 @@ export class SalesforceStrategy extends PassportStrategy(
|
||||
}
|
||||
|
||||
authenticate(req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(req, 'file');
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user