Skip to content

Commit

Permalink
Merge pull request #91 from panoratech/feat/finish-crm-add-contact
Browse files Browse the repository at this point in the history
feat: added GET
  • Loading branch information
naelob authored Nov 22, 2023
2 parents e8d63e2 + 0ea4931 commit f581d54
Show file tree
Hide file tree
Showing 36 changed files with 948 additions and 276 deletions.
16 changes: 13 additions & 3 deletions packages/api/src/@core/connections/connections.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ import { Controller, Get, Query, Res } from '@nestjs/common';
import { Response } from 'express'; // Importing the Express Response type for type checking
import { CrmConnectionsService } from './crm/services/crm-connection.service';
import { ProviderVertical, getProviderVertical } from '../utils/providers';
import { LoggerService } from '../logger/logger.service';
import { handleServiceError } from '../utils/errors';

@Controller('connections')
export class ConnectionsController {
constructor(private readonly crmConnectionsService: CrmConnectionsService) {}
constructor(
private readonly crmConnectionsService: CrmConnectionsService,
private logger: LoggerService,
) {
this.logger.setContext(ConnectionsController.name);
}

@Get('oauth/callback')
handleCallback(
@Res() res: Response,
Expand All @@ -14,7 +22,9 @@ export class ConnectionsController {
@Query('location') zohoLocation?: string,
) {
try {
if (!state || !code) throw new Error('no params found');
if (!state) throw new Error('No Callback Params found for state');
if (!code) throw new Error('No Callback Params found for code');

const stateData = JSON.parse(decodeURIComponent(state));
const { projectId, linkedUserId, providerName, returnUrl } = stateData;
//TODO; ADD VERIFICATION OF PARAMS
Expand Down Expand Up @@ -46,7 +56,7 @@ export class ConnectionsController {

res.redirect(returnUrl);
} catch (error) {
console.error('An error occurred', error.response?.data || error.message);
handleServiceError(error, this.logger);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { HubspotConnectionService } from './hubspot/hubspot.service';
import { PipedriveConnectionService } from './pipedrive/pipedrive.service';
import { ZendeskConnectionService } from './zendesk/zendesk.service';
import { FreshsalesConnectionService } from './freshsales/freshsales.service';
import { LoggerService } from 'src/@core/logger/logger.service';

@Injectable()
export class CrmConnectionsService {
Expand All @@ -15,7 +16,10 @@ export class CrmConnectionsService {
private pipedriveConnectionService: PipedriveConnectionService,
private zendeskConnectionService: ZendeskConnectionService,
private freshsalesConnectionService: FreshsalesConnectionService,
) {}
private logger: LoggerService,
) {
this.logger.setContext(CrmConnectionsService.name);
}
//STEP 1:[FRONTEND STEP]
//create a frontend SDK snippet in which an authorization embedded link is set up so when users click
// on it to grant access => they grant US the access and then when confirmed
Expand All @@ -37,59 +41,52 @@ export class CrmConnectionsService {
code: string,
zohoLocation?: string,
) {
try {
switch (providerName) {
case 'hubspot':
if (!code) {
throw new NotFoundError('no hubspot code found');
}
return this.hubspotConnectionService.handleHubspotCallback(
linkedUserId,
projectId,
code,
);
case 'zoho':
if (!code) {
throw new NotFoundError('no zoho code');
}
if (!zohoLocation) {
throw new NotFoundError('no zoho location');
}
return this.zohoConnectionService.handleZohoCallback(
linkedUserId,
projectId,
code,
zohoLocation,
);
case 'pipedrive':
if (!code) {
throw new NotFoundError('no pipedrive code found');
}
return this.pipedriveConnectionService.handlePipedriveCallback(
linkedUserId,
projectId,
code,
);
case 'freshsales':
//todo: LATER
break;
case 'zendesk':
if (!code) {
throw new NotFoundError('no zendesk code found');
}
return this.zendeskConnectionService.handleZendeskCallback(
linkedUserId,
projectId,
code,
);
default:
return;
}
} catch (error) {
if (error instanceof NotFoundError) {
console.log(error);
}
return error;
switch (providerName) {
case 'hubspot':
if (!code) {
throw new NotFoundError('no hubspot code found');
}
return this.hubspotConnectionService.handleHubspotCallback(
linkedUserId,
projectId,
code,
);
case 'zoho':
if (!code) {
throw new NotFoundError('no zoho code');
}
if (!zohoLocation) {
throw new NotFoundError('no zoho location');
}
return this.zohoConnectionService.handleZohoCallback(
linkedUserId,
projectId,
code,
zohoLocation,
);
case 'pipedrive':
if (!code) {
throw new NotFoundError('no pipedrive code found');
}
return this.pipedriveConnectionService.handlePipedriveCallback(
linkedUserId,
projectId,
code,
);
case 'freshsales':
//todo: LATER
break;
case 'zendesk':
if (!code) {
throw new NotFoundError('no zendesk code found');
}
return this.zendeskConnectionService.handleZendeskCallback(
linkedUserId,
projectId,
code,
);
default:
return;
}
}

Expand All @@ -99,40 +96,33 @@ export class CrmConnectionsService {
refresh_token: string,
account_url?: string,
) {
try {
switch (providerId) {
case 'hubspot':
return this.hubspotConnectionService.handleHubspotTokenRefresh(
connectionId,
refresh_token,
);
case 'zoho':
return this.zohoConnectionService.handleZohoTokenRefresh(
connectionId,
refresh_token,
account_url,
);
case 'pipedrive':
return this.pipedriveConnectionService.handlePipedriveTokenRefresh(
connectionId,
refresh_token,
);
case 'freshsales':
//todo: LATER
break;
case 'zendesk':
return this.zendeskConnectionService.handleZendeskTokenRefresh(
connectionId,
refresh_token,
);
default:
return;
}
} catch (error) {
if (error instanceof NotFoundError) {
console.log(error);
}
return error;
switch (providerId) {
case 'hubspot':
return this.hubspotConnectionService.handleHubspotTokenRefresh(
connectionId,
refresh_token,
);
case 'zoho':
return this.zohoConnectionService.handleZohoTokenRefresh(
connectionId,
refresh_token,
account_url,
);
case 'pipedrive':
return this.pipedriveConnectionService.handlePipedriveTokenRefresh(
connectionId,
refresh_token,
);
case 'freshsales':
//todo: LATER
break;
case 'zendesk':
return this.zendeskConnectionService.handleZendeskTokenRefresh(
connectionId,
refresh_token,
);
default:
return;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import config from 'src/@core/utils/config';
import { Prisma } from '@prisma/client';

Check warning on line 5 in packages/api/src/@core/connections/crm/services/hubspot/hubspot.service.ts

View workflow job for this annotation

GitHub Actions / build-api (16.x)

'Prisma' is defined but never used
import { HubspotOAuthResponse } from '../../types';
import { LoggerService } from 'src/@core/logger/logger.service';
import {
Action,
NotUniqueRecord,
handleServiceError,
} from 'src/@core/utils/errors';

@Injectable()
export class HubspotConnectionService {
Expand Down Expand Up @@ -51,7 +56,15 @@ export class HubspotConnectionService {
code: string,
) {
try {
//TODO: make sure no connections already exists for {linkedUserId, projectId}
const isNotUnique = await this.prisma.connections.findFirst({
where: {
id_linked_user: BigInt(linkedUserId),
},
});
if (isNotUnique)
throw new NotUniqueRecord(
`A connection already exists for userId ${linkedUserId} and the provider hubspot`,
);
//TMP STEP = first create a linked_user and a project id
await this.addLinkedUserAndProjectTest();
//reconstruct the redirect URI that was passed in the frontend it must be the same
Expand Down Expand Up @@ -99,21 +112,10 @@ export class HubspotConnectionService {
});
this.logger.log('Successfully added tokens inside DB ' + db_res);
} catch (error) {
if (axios.isAxiosError(error)) {
// Handle Axios-specific errors
//console.error('Error with Axios request:', error.response?.data);
this.logger.error('Error with Axios request:', error.response?.data);
}
if (error instanceof Prisma.PrismaClientKnownRequestError) {
//console.error('Error with Prisma request:', error);
this.logger.error('Error with Prisma request:', error.message);
}
this.logger.error(
'An error occurred...',
error.response?.data || error.message,
);
handleServiceError(error, this.logger, 'hubspot', Action.oauthCallback);
}
}

async handleHubspotTokenRefresh(connectionId: bigint, refresh_token: string) {
try {
const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; //tocheck
Expand Down Expand Up @@ -149,14 +151,7 @@ export class HubspotConnectionService {
});
console.log('OAuth credentials updated : hubspot ', data);
} catch (error) {
if (axios.isAxiosError(error)) {
// Handle Axios-specific errors
console.error('Error with Axios request:', error.response?.data);
}
if (error instanceof Prisma.PrismaClientKnownRequestError) {
console.error('Error with Prisma request:', error);
}
console.log(error);
handleServiceError(error, this.logger, 'hubspot', Action.oauthRefresh);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,34 @@ import axios from 'axios';
import config from 'src/@core/utils/config';
import { PipeDriveOAuthResponse } from '../../types';
import { Prisma } from '@prisma/client';

Check warning on line 6 in packages/api/src/@core/connections/crm/services/pipedrive/pipedrive.service.ts

View workflow job for this annotation

GitHub Actions / build-api (16.x)

'Prisma' is defined but never used
import {
Action,
NotUniqueRecord,
handleServiceError,
} from 'src/@core/utils/errors';
import { LoggerService } from 'src/@core/logger/logger.service';

@Injectable()
export class PipedriveConnectionService {
constructor(private prisma: PrismaService) {}
constructor(private prisma: PrismaService, private logger: LoggerService) {
this.logger.setContext(PipedriveConnectionService.name);
}

async handlePipedriveCallback(
linkedUserId: string,
projectId: string,
code: string,
) {
try {
const isNotUnique = await this.prisma.connections.findFirst({
where: {
id_linked_user: BigInt(linkedUserId),
},
});
if (isNotUnique)
throw new NotUniqueRecord(
`A connection already exists for userId ${linkedUserId} and the provider pipedrive`,
);
//reconstruct the redirect URI that was passed in the frontend it must be the same
const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`;

Expand Down Expand Up @@ -59,14 +76,7 @@ export class PipedriveConnectionService {
},
});
} catch (error) {
if (axios.isAxiosError(error)) {
// Handle Axios-specific errors
console.error('Error with Axios request:', error.response?.data);
}
if (error instanceof Prisma.PrismaClientKnownRequestError) {
console.error('Error with Prisma request:', error);
}
console.log(error);
handleServiceError(error, this.logger, 'pipedrive', Action.oauthCallback);
}
}

Expand Down Expand Up @@ -109,14 +119,7 @@ export class PipedriveConnectionService {
});
console.log('OAuth credentials updated : pipedrive ', data);
} catch (error) {
if (axios.isAxiosError(error)) {
// Handle Axios-specific errors
console.error('Error with Axios request:', error.response?.data);
}
if (error instanceof Prisma.PrismaClientKnownRequestError) {
console.error('Error with Prisma request:', error);
}
console.log(error);
handleServiceError(error, this.logger, 'pipedrive', Action.oauthRefresh);
}
}
}
Loading

0 comments on commit f581d54

Please sign in to comment.