Skip to content

Commit

Permalink
Merge pull request #375 from gitroomhq/feat/refresh
Browse files Browse the repository at this point in the history
hotfix: fix refresh mechanism
  • Loading branch information
nevo-david authored Oct 18, 2024
2 parents 581953b + b6da5b8 commit fbd977a
Show file tree
Hide file tree
Showing 19 changed files with 154 additions and 113 deletions.
45 changes: 35 additions & 10 deletions apps/backend/src/api/routes/integrations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { NotEnoughScopesFilter } from '@gitroom/nestjs-libraries/integrations/in
import { PostsService } from '@gitroom/nestjs-libraries/database/prisma/posts/posts.service';
import { IntegrationTimeDto } from '@gitroom/nestjs-libraries/dtos/integrations/integration.time.dto';
import { AuthService } from '@gitroom/helpers/auth/auth.service';
import { AuthTokenDetails } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';

@ApiTags('Integrations')
@Controller('/integrations')
Expand Down Expand Up @@ -156,7 +157,12 @@ export class IntegrationsController {
: undefined;

const { codeVerifier, state, url } =
await integrationProvider.generateAuthUrl(refresh, getExternalUrl);
await integrationProvider.generateAuthUrl(getExternalUrl);

if (refresh) {
await ioRedis.set(`refresh:${state}`, refresh, 'EX', 300);
}

await ioRedis.set(`login:${state}`, codeVerifier, 'EX', 300);
await ioRedis.set(
`external:${state}`,
Expand Down Expand Up @@ -311,6 +317,11 @@ export class IntegrationsController {
await ioRedis.del(`external:${body.state}`);
}

const refresh = await ioRedis.get(`refresh:${body.state}`);
if (refresh) {
await ioRedis.del(`refresh:${body.state}`);
}

const {
accessToken,
expiresIn,
Expand All @@ -319,14 +330,28 @@ export class IntegrationsController {
name,
picture,
username,
} = await integrationProvider.authenticate(
{
code: body.code,
codeVerifier: getCodeVerifier,
refresh: body.refresh,
},
details ? JSON.parse(details) : undefined
);
// eslint-disable-next-line no-async-promise-executor
} = await new Promise<AuthTokenDetails>(async (res) => {
const auth = await integrationProvider.authenticate(
{
code: body.code,
codeVerifier: getCodeVerifier,
refresh: body.refresh,
},
details ? JSON.parse(details) : undefined
);

if (refresh && integrationProvider.reConnect) {
const newAuth = await integrationProvider.reConnect(
auth.id,
refresh,
auth.accessToken
);
return res(newAuth);
}

return res(auth);
});

if (!id) {
throw new Error('Invalid api key');
Expand All @@ -343,7 +368,7 @@ export class IntegrationsController {
refreshToken,
expiresIn,
username,
integrationProvider.isBetweenSteps,
refresh ? false : integrationProvider.isBetweenSteps,
body.refresh,
+body.timezone,
details
Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/src/components/launches/launches.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,13 @@ export const LaunchesComponent = () => {
{sortedIntegrations.map((integration) => (
<div
{...(integration.refreshNeeded && {
onClick: refreshChannel(integration),
'data-tooltip-id': 'tooltip',
'data-tooltip-content':
'Channel disconnected, click to reconnect.',
})}
key={integration.id}
className="flex gap-[8px] items-center"
className={clsx("flex gap-[8px] items-center", integration.refreshNeeded && 'cursor-pointer')}
>
<div
className={clsx(
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/src/components/layout/continue.provider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useCallback, useEffect, useMemo } from 'react';
import React, { FC, useCallback, useMemo } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
import { continueProviderList } from '@gitroom/frontend/components/launches/providers/continue-provider/list';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export abstract class SocialAbstract {
let json = '{}';
try {
json = await request.text();
console.log(json);
} catch (err) {
json = '{}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider {
};
}

async generateAuthUrl(refresh?: string) {
async generateAuthUrl() {
const state = makeId(6);
return {
url: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,13 @@ export class DiscordProvider extends SocialAbstract implements SocialProvider {
username: '',
};
}
async generateAuthUrl(refresh?: string) {
async generateAuthUrl() {
const state = makeId(6);
return {
url: `https://discord.com/oauth2/authorize?client_id=${
process.env.DISCORD_CLIENT_ID
}&permissions=377957124096&response_type=code&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/discord${
refresh ? `?refresh=${refresh}` : ''
}`
`${process.env.FRONTEND_URL}/integrations/social/discord`
)}&integration_type=0&scope=bot+identify+guilds&state=${state}`,
codeVerifier: makeId(10),
state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,13 @@ export class DribbbleProvider extends SocialAbstract implements SocialProvider {
);
}

async generateAuthUrl(refresh?: string) {
async generateAuthUrl() {
const state = makeId(6);
return {
url: `https://dribbble.com/oauth/authorize?client_id=${
process.env.DRIBBBLE_CLIENT_ID
}&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/dribbble${
refresh ? `?refresh=${refresh}` : ''
}`
`${process.env.FRONTEND_URL}/integrations/social/dribbble`
)}&response_type=code&scope=${this.scopes.join('+')}&state=${state}`,
codeVerifier: makeId(10),
state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import dayjs from 'dayjs';
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
import { string } from 'yup';

export class FacebookProvider extends SocialAbstract implements SocialProvider {
identifier = 'facebook';
Expand All @@ -33,16 +34,14 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
};
}

async generateAuthUrl(refresh?: string) {
async generateAuthUrl() {
const state = makeId(6);
return {
url:
'https://www.facebook.com/v20.0/dialog/oauth' +
`?client_id=${process.env.FACEBOOK_APP_ID}` +
`&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/facebook${
refresh ? `?refresh=${refresh}` : ''
}`
`${process.env.FRONTEND_URL}/integrations/social/facebook`
)}` +
`&state=${state}` +
`&scope=${this.scopes.join(',')}`,
Expand All @@ -51,6 +50,27 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
};
}

async reConnect(
id: string,
requiredId: string,
accessToken: string
): Promise<AuthTokenDetails> {
const information = await this.fetchPageInformation(
accessToken,
requiredId
);

return {
id: information.id,
name: information.name,
accessToken: information.access_token,
refreshToken: information.access_token,
expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(),
picture: information.picture,
username: information.username,
};
}

async authenticate(params: {
code: string;
codeVerifier: string;
Expand Down Expand Up @@ -91,22 +111,6 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
.map((p: any) => p.permission);
this.checkScopes(this.scopes, permissions);

if (params.refresh) {
const information = await this.fetchPageInformation(
access_token,
params.refresh
);
return {
id: information.id,
name: information.name,
accessToken: information.access_token,
refreshToken: information.access_token,
expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(),
picture: information.picture,
username: information.username,
};
}

const {
id,
name,
Expand Down Expand Up @@ -174,7 +178,11 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
let finalId = '';
let finalUrl = '';
if ((firstPost?.media?.[0]?.url?.indexOf('mp4') || -2) > -1) {
const { id: videoId, permalink_url, ...all } = await (
const {
id: videoId,
permalink_url,
...all
} = await (
await this.fetch(
`https://graph.facebook.com/v20.0/${id}/videos?access_token=${accessToken}&fields=id,permalink_url`,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import { timer } from '@gitroom/helpers/utils/timer';
import dayjs from 'dayjs';
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
import { string } from 'yup';

export class InstagramProvider
extends SocialAbstract
Expand Down Expand Up @@ -39,16 +40,39 @@ export class InstagramProvider
};
}

async generateAuthUrl(refresh?: string) {
async reConnect(
id: string,
requiredId: string,
accessToken: string
): Promise<AuthTokenDetails> {
const findPage = (await this.pages(accessToken)).find(
(p) => p.id === requiredId
);

const information = await this.fetchPageInformation(accessToken, {
id: requiredId,
pageId: findPage?.pageId!,
});

return {
id: information.id,
name: information.name,
accessToken: information.access_token,
refreshToken: information.access_token,
expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(),
picture: information.picture,
username: information.username,
};
}

async generateAuthUrl() {
const state = makeId(6);
return {
url:
'https://www.facebook.com/v20.0/dialog/oauth' +
`?client_id=${process.env.FACEBOOK_APP_ID}` +
`&redirect_uri=${encodeURIComponent(
`${process.env.FRONTEND_URL}/integrations/social/instagram${
refresh ? `?refresh=${refresh}` : ''
}`
`${process.env.FRONTEND_URL}/integrations/social/instagram`
)}` +
`&state=${state}` +
`&scope=${encodeURIComponent(this.scopes.join(','))}`,
Expand Down Expand Up @@ -109,26 +133,6 @@ export class InstagramProvider
)
).json();

if (params.refresh) {
const findPage = (await this.pages(access_token)).find(
(p) => p.id === params.refresh
);
const information = await this.fetchPageInformation(access_token, {
id: params.refresh,
pageId: findPage?.pageId!,
});

return {
id: information.id,
name: information.name,
accessToken: information.access_token,
refreshToken: information.access_token,
expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(),
picture: information.picture,
username: information.username,
};
}

return {
id,
name,
Expand Down Expand Up @@ -187,6 +191,7 @@ export class InstagramProvider
)
).json();

console.log(id, name, profile_picture_url, username);
return {
id,
name,
Expand All @@ -206,7 +211,9 @@ export class InstagramProvider
const medias = await Promise.all(
firstPost?.media?.map(async (m) => {
const caption =
firstPost.media?.length === 1 ? `&caption=${encodeURIComponent(firstPost.message)}` : ``;
firstPost.media?.length === 1
? `&caption=${encodeURIComponent(firstPost.message)}`
: ``;
const isCarousel =
(firstPost?.media?.length || 0) > 1 ? `&is_carousel_item=true` : ``;
const mediaType =
Expand Down
Loading

0 comments on commit fbd977a

Please sign in to comment.