diff --git a/apps/backend/src/services/auth/providers/github.provider.ts b/apps/backend/src/services/auth/providers/github.provider.ts index dcfdb669..2d8b95ea 100644 --- a/apps/backend/src/services/auth/providers/github.provider.ts +++ b/apps/backend/src/services/auth/providers/github.provider.ts @@ -5,7 +5,7 @@ export class GithubProvider implements ProvidersInterface { return `https://github.com/login/oauth/authorize?client_id=${ process.env.GITHUB_CLIENT_ID }&scope=user:email&redirect_uri=${encodeURIComponent( - `${process.env.FRONTEND_URL}/settings?provider=github` + `${process.env.FRONTEND_URL}/settings` )}`; } diff --git a/apps/backend/src/services/auth/providers/google.provider.ts b/apps/backend/src/services/auth/providers/google.provider.ts new file mode 100644 index 00000000..d895b45a --- /dev/null +++ b/apps/backend/src/services/auth/providers/google.provider.ts @@ -0,0 +1,74 @@ +import { + AnalyticsData, + AuthTokenDetails, + PostDetails, + PostResponse, + SocialProvider, +} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; +import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; +import { google } from 'googleapis'; +import { OAuth2Client } from 'google-auth-library/build/src/auth/oauth2client'; +import { ProvidersInterface } from '@gitroom/backend/services/auth/providers.interface'; + +const clientAndYoutube = () => { + const client = new google.auth.OAuth2({ + clientId: process.env.YOUTUBE_CLIENT_ID, + clientSecret: process.env.YOUTUBE_CLIENT_SECRET, + redirectUri: `${process.env.FRONTEND_URL}/integrations/social/youtube`, + }); + + const youtube = (newClient: OAuth2Client) => + google.youtube({ + version: 'v3', + auth: newClient, + }); + + const youtubeAnalytics = (newClient: OAuth2Client) => + google.youtubeAnalytics({ + version: 'v2', + auth: newClient, + }); + + const oauth2 = (newClient: OAuth2Client) => + google.oauth2({ + version: 'v2', + auth: newClient, + }); + + return { client, youtube, oauth2, youtubeAnalytics }; +}; + +export class GoogleProvider implements ProvidersInterface { + generateLink() { + const state = makeId(7); + const { client } = clientAndYoutube(); + return client.generateAuthUrl({ + access_type: 'online', + prompt: 'consent', + state, + redirect_uri: `${process.env.FRONTEND_URL}/integrations/social/youtube`, + scope: [ + 'https://www.googleapis.com/auth/userinfo.profile', + 'https://www.googleapis.com/auth/userinfo.email', + ], + }); + } + + async getToken(code: string) { + const { client, oauth2 } = clientAndYoutube(); + const { tokens } = await client.getToken(code); + return tokens.access_token; + } + + async getUser(providerToken: string) { + const { client, oauth2 } = clientAndYoutube(); + client.setCredentials({ access_token: providerToken }); + const user = oauth2(client); + const { data } = await user.userinfo.get(); + + return { + id: data.id!, + email: data.email, + }; + } +} diff --git a/apps/backend/src/services/auth/providers/providers.factory.ts b/apps/backend/src/services/auth/providers/providers.factory.ts index 96af6adb..61048d50 100644 --- a/apps/backend/src/services/auth/providers/providers.factory.ts +++ b/apps/backend/src/services/auth/providers/providers.factory.ts @@ -1,12 +1,15 @@ -import {Provider} from "@prisma/client"; -import {GithubProvider} from "@gitroom/backend/services/auth/providers/github.provider"; -import {ProvidersInterface} from "@gitroom/backend/services/auth/providers.interface"; +import { Provider } from '@prisma/client'; +import { GithubProvider } from '@gitroom/backend/services/auth/providers/github.provider'; +import { ProvidersInterface } from '@gitroom/backend/services/auth/providers.interface'; +import { GoogleProvider } from '@gitroom/backend/services/auth/providers/google.provider'; export class ProvidersFactory { - static loadProvider(provider: Provider): ProvidersInterface { - switch (provider) { - case Provider.GITHUB: - return new GithubProvider(); - } + static loadProvider(provider: Provider): ProvidersInterface { + switch (provider) { + case Provider.GITHUB: + return new GithubProvider(); + case Provider.GOOGLE: + return new GoogleProvider(); } -} \ No newline at end of file + } +} diff --git a/apps/frontend/src/components/auth/login.tsx b/apps/frontend/src/components/auth/login.tsx index 91c0f3a8..5f101a37 100644 --- a/apps/frontend/src/components/auth/login.tsx +++ b/apps/frontend/src/components/auth/login.tsx @@ -8,7 +8,7 @@ import { Input } from '@gitroom/react/form/input'; import { useMemo, useState } from 'react'; import { classValidatorResolver } from '@hookform/resolvers/class-validator'; import { LoginUserDto } from '@gitroom/nestjs-libraries/dtos/auth/login.user.dto'; -import { GithubProvider } from '@gitroom/frontend/app/auth/providers/github.provider'; +import { GithubProvider } from '@gitroom/frontend/components/auth/providers/github.provider'; import interClass from '@gitroom/react/helpers/inter.font'; import { isGeneral } from '@gitroom/react/helpers/is.general'; diff --git a/apps/frontend/src/app/auth/providers/github.provider.tsx b/apps/frontend/src/components/auth/providers/github.provider.tsx similarity index 100% rename from apps/frontend/src/app/auth/providers/github.provider.tsx rename to apps/frontend/src/components/auth/providers/github.provider.tsx diff --git a/apps/frontend/src/components/auth/providers/google.provider.tsx b/apps/frontend/src/components/auth/providers/google.provider.tsx new file mode 100644 index 00000000..1bbb8a60 --- /dev/null +++ b/apps/frontend/src/components/auth/providers/google.provider.tsx @@ -0,0 +1,45 @@ +import { useCallback } from 'react'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import interClass from '@gitroom/react/helpers/inter.font'; + +export const GoogleProvider = () => { + const fetch = useFetch(); + const gotoLogin = useCallback(async () => { + const link = await (await fetch('/auth/oauth/GOOGLE')).text(); + window.location.href = link; + }, []); + + return ( +