From f440300085407d8893e535a7cafc72cb3534bb1a Mon Sep 17 00:00:00 2001 From: bryng001 Date: Fri, 27 Sep 2024 20:18:31 +0500 Subject: [PATCH] added google sigin in feature --- td.server/src/config/env.config.js | 3 + td.server/src/controllers/configcontroller.js | 1 + td.server/src/env/Google.js | 25 ++++++ td.server/src/providers/google.js | 82 +++++++++++++++++++ td.server/src/providers/index.js | 4 +- td.vue/src/i18n/ar.js | 4 + td.vue/src/i18n/de.js | 4 + td.vue/src/i18n/el.js | 4 + td.vue/src/i18n/en.js | 4 + td.vue/src/i18n/es.js | 4 + td.vue/src/i18n/fi.js | 4 + td.vue/src/i18n/fr.js | 4 + td.vue/src/i18n/hi.js | 4 + td.vue/src/i18n/id.js | 4 + td.vue/src/i18n/ja.js | 4 + td.vue/src/i18n/ms.js | 4 + td.vue/src/i18n/pt.js | 4 + td.vue/src/i18n/ru.js | 4 + td.vue/src/i18n/uk.js | 4 + td.vue/src/i18n/zh.js | 4 + td.vue/src/plugins/fontawesome-vue.js | 8 +- .../src/service/provider/google.provider.js | 26 ++++++ td.vue/src/service/provider/providerTypes.js | 1 + td.vue/src/service/provider/providers.js | 8 ++ td.vue/src/views/HomePage.vue | 3 + 25 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 td.server/src/env/Google.js create mode 100644 td.server/src/providers/google.js create mode 100644 td.vue/src/service/provider/google.provider.js diff --git a/td.server/src/config/env.config.js b/td.server/src/config/env.config.js index 20c688d2e..ad78728fe 100644 --- a/td.server/src/config/env.config.js +++ b/td.server/src/config/env.config.js @@ -4,6 +4,7 @@ import env from '../env/Env.js'; import GithubEnv from '../env/Github.js'; import GitlabEnv from "../env/Gitlab"; import ThreatDragonEnv from '../env/ThreatDragon.js'; +import GoogleEnv from '../env/Google.js'; const tryLoadDotEnv = () => { const github = new GithubEnv(); @@ -11,11 +12,13 @@ const tryLoadDotEnv = () => { const bitbucket = new BitbucketEnv(); const encryption = new EncryptionEnv(); const threatDragon = new ThreatDragonEnv(); + const google = new GoogleEnv(); env.get().addProvider(github); env.get().addProvider(gitlab); env.get().addProvider(encryption); env.get().addProvider(bitbucket); env.get().addProvider(threatDragon); + env.get().addProvider(google); env.get().hydrate(); }; diff --git a/td.server/src/controllers/configcontroller.js b/td.server/src/controllers/configcontroller.js index 56775366c..bc28ff577 100644 --- a/td.server/src/controllers/configcontroller.js +++ b/td.server/src/controllers/configcontroller.js @@ -10,6 +10,7 @@ export const getConfig = () => ({ bitbucketEnabled: env.get().config.BITBUCKET_CLIENT_ID !== undefined && env.get().config.BITBUCKET_CLIENT_ID !== null, githubEnabled: env.get().config.GITHUB_CLIENT_ID !== undefined && env.get().config.GITHUB_CLIENT_ID !== null, gitlabEnabled: env.get().config.GITLAB_CLIENT_ID !== undefined && env.get().config.GITLAB_CLIENT_ID !== null, + googleEnabled: env.get().config.GOOGLE_CLIENT_ID !== undefined && env.get().config.GOOGLE_CLIENT_ID !== null, localEnabled: true, }); diff --git a/td.server/src/env/Google.js b/td.server/src/env/Google.js new file mode 100644 index 000000000..c5183708d --- /dev/null +++ b/td.server/src/env/Google.js @@ -0,0 +1,25 @@ +import { Env } from './Env.js'; + +class GoogleEnv extends Env { + constructor () { + super('Google'); + } + + get prefix () { + return 'GOOGLE_'; + } + + // Note that the actual env var will be prepended with GOOGLE_ + get properties () { + return [ + { key: 'CLIENT_ID', required: false }, + { key: 'CLIENT_SECRET', required: false }, + { key: 'SCOPE', required: false, defaultValue: 'openid email profile' }, + { key: 'REDIRECT_URI', required: false, defaultValue: 'http://localhost:8080/oauth-return' }, + { key: 'TOKEN_URL', required: false, defaultValue: 'https://oauth2.googleapis.com/token' }, + { key: 'USER_INFO_URL', required: false, defaultValue: 'https://www.googleapis.com/oauth2/v1/userinfo' } + ]; + } +} + +export default GoogleEnv; diff --git a/td.server/src/providers/google.js b/td.server/src/providers/google.js new file mode 100644 index 000000000..fe0d0beaf --- /dev/null +++ b/td.server/src/providers/google.js @@ -0,0 +1,82 @@ +/** + * @name google + * @description Identity provider for Google OAuth + */ +import axios from 'axios'; +import env from '../env/Env.js'; + +const name = 'google'; + +/** + * Determines if the Google provider is configured + * @returns {Boolean} + */ +const isConfigured = () => Boolean(env.get().config.GOOGLE_CLIENT_ID); + +/** + * Gets the Google OAuth Login URL + * @returns {String} + */ +const getOauthRedirectUrl = () => { + const scope = env.get().config.GOOGLE_SCOPE || 'openid email profile'; + const redirectUri = env.get().config.GOOGLE_REDIRECT_URI; + return `https://accounts.google.com/o/oauth2/auth?response_type=code&scope=${scope}&client_id=${env.get().config.GOOGLE_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUri)}`; +}; + +/** + * Gets the return URL for our application, returning from Google + * @param {string} code + * @returns {String} + */ +const getOauthReturnUrl = (code) => { + let returnUrl = `/#/oauth-return?code=${code}`; + if (env.get().config.NODE_ENV === 'development') { + returnUrl = `http://localhost:8080${returnUrl}`; + } + return returnUrl; +}; + +/** + * Finishes the OAuth login, issues a JWT + * @param {String} code + * @returns {String} jwt + */ +const completeLoginAsync = async (code) => { + const url = `https://oauth2.googleapis.com/token`; + const body = { + client_id: env.get().config.GOOGLE_CLIENT_ID, + client_secret: env.get().config.GOOGLE_CLIENT_SECRET, + code, + grant_type: 'authorization_code', + redirect_uri: env.get().config.GOOGLE_REDIRECT_URI + }; + const options = { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }; + + const providerResp = await axios.post(url, new URLSearchParams(body), options); + + const tokenInfoUrl = `https://www.googleapis.com/oauth2/v1/userinfo?access_token=${providerResp.data.access_token}`; + const userInfo = await axios.get(tokenInfoUrl); + + const user = { + username: userInfo.data.name, + email: userInfo.data.email, + picture: userInfo.data.picture + }; + + return { + user, + opts: providerResp.data + }; +}; + +export default { + completeLoginAsync, + getOauthReturnUrl, + getOauthRedirectUrl, + isConfigured, + name +}; diff --git a/td.server/src/providers/index.js b/td.server/src/providers/index.js index ad8738d4e..0f37f634d 100644 --- a/td.server/src/providers/index.js +++ b/td.server/src/providers/index.js @@ -1,6 +1,7 @@ import bitbucket from './bitbucket.js'; import github from './github.js'; import gitlab from "./gitlab"; +import google from './google.js'; /** * An immutable object containing all @@ -10,7 +11,8 @@ import gitlab from "./gitlab"; const all = Object.freeze({ github, gitlab, - bitbucket + bitbucket, + google }); /** diff --git a/td.vue/src/i18n/ar.js b/td.vue/src/i18n/ar.js index 5bc0229b9..64193e88b 100644 --- a/td.vue/src/i18n/ar.js +++ b/td.vue/src/i18n/ar.js @@ -29,6 +29,10 @@ const ara = { displayName: 'Bitbucket', loginWith: 'تسجيل الدخول باستخدام' }, + google: { + displayName: 'Google', + loginWith: 'تسجيل الدخول باستخدام' + }, local: { displayName: 'جلسة محلية', loginWith: 'تسجيل الدخول إلى' diff --git a/td.vue/src/i18n/de.js b/td.vue/src/i18n/de.js index 524b99bec..36a41949a 100644 --- a/td.vue/src/i18n/de.js +++ b/td.vue/src/i18n/de.js @@ -29,6 +29,10 @@ const deu = { displayName: 'Bitbucket', loginWith: 'Anmelden mit' }, + google: { + displayName: 'Google', + loginWith: 'Anmelden mit' + }, local: { displayName: 'Lokale Sitzung', loginWith: 'Anmelden an' diff --git a/td.vue/src/i18n/el.js b/td.vue/src/i18n/el.js index 636fcd9aa..394b7fbbe 100644 --- a/td.vue/src/i18n/el.js +++ b/td.vue/src/i18n/el.js @@ -29,6 +29,10 @@ const ell = { displayName: 'Bitbucket', loginWith: 'Είσοδος με' }, + google: { + displayName: 'Google', + loginWith: 'Είσοδος με' + }, local: { displayName: 'Τοπική Συνεδρία', loginWith: 'Είσοδος με' diff --git a/td.vue/src/i18n/en.js b/td.vue/src/i18n/en.js index 550ced2f1..fd1400a6e 100644 --- a/td.vue/src/i18n/en.js +++ b/td.vue/src/i18n/en.js @@ -29,6 +29,10 @@ const eng = { displayName: 'Bitbucket', loginWith: 'Login with' }, + google: { + displayName: 'Google', + loginWith: 'Login with' + }, local: { displayName: 'Local Session', loginWith: 'Login to' diff --git a/td.vue/src/i18n/es.js b/td.vue/src/i18n/es.js index da79a8d83..c073d2fe8 100644 --- a/td.vue/src/i18n/es.js +++ b/td.vue/src/i18n/es.js @@ -29,6 +29,10 @@ const spa = { displayName: 'Bitbucket', loginWith: 'Conectarse con' }, + google: { + displayName: 'Google', + loginWith: 'Conectarse con' + }, local: { displayName: 'Sesión Local', loginWith: 'Conectarse con' diff --git a/td.vue/src/i18n/fi.js b/td.vue/src/i18n/fi.js index 2d0c7396a..a41fbb3da 100644 --- a/td.vue/src/i18n/fi.js +++ b/td.vue/src/i18n/fi.js @@ -29,6 +29,10 @@ const fin = { displayName: 'Bitbucketissa', loginWith: 'Kirjaudu sisään' }, + google: { + displayName: 'Google', + loginWith: 'Kirjaudu sisään' + }, local: { displayName: 'paikallisesti', loginWith: 'Kirjaudu sisään' diff --git a/td.vue/src/i18n/fr.js b/td.vue/src/i18n/fr.js index 7705d49f0..15ef54425 100644 --- a/td.vue/src/i18n/fr.js +++ b/td.vue/src/i18n/fr.js @@ -29,6 +29,10 @@ const fra = { displayName: 'Bitbucket', loginWith: 'Se connecter avec' }, + google: { + displayName: 'Google', + loginWith: 'Se connecter avec' + }, local: { displayName: 'une session locale', loginWith: 'Se connecter avec' diff --git a/td.vue/src/i18n/hi.js b/td.vue/src/i18n/hi.js index 4f0c11d0d..d05008e13 100644 --- a/td.vue/src/i18n/hi.js +++ b/td.vue/src/i18n/hi.js @@ -29,6 +29,10 @@ const hin = { displayName: 'Bitbucket', loginWith: 'से लोगिन करें' }, + google: { + displayName: 'Google', + loginWith: 'से लोगिन करें' + }, local: { displayName: 'स्थानीय सत्र', loginWith: 'से लोगिन करें' diff --git a/td.vue/src/i18n/id.js b/td.vue/src/i18n/id.js index d873429e8..7818fe554 100644 --- a/td.vue/src/i18n/id.js +++ b/td.vue/src/i18n/id.js @@ -29,6 +29,10 @@ const id = { displayName: 'Bitbucket', loginWith: 'Masuk dengan' }, + google: { + displayName: 'Google', + loginWith: 'Masuk dengan' + }, local: { displayName: 'Sesi Lokal', loginWith: 'Masuk ke' diff --git a/td.vue/src/i18n/ja.js b/td.vue/src/i18n/ja.js index 522faa18c..542c08421 100644 --- a/td.vue/src/i18n/ja.js +++ b/td.vue/src/i18n/ja.js @@ -25,6 +25,10 @@ const jpn = { displayName: 'Bitbucketで', loginWith: 'ログイン' }, + google: { + displayName: 'Google', + loginWith: 'ログイン' + }, local: { displayName: 'ローカルセッション', loginWith: 'ログイン' diff --git a/td.vue/src/i18n/ms.js b/td.vue/src/i18n/ms.js index 825d050c9..18ea82f24 100644 --- a/td.vue/src/i18n/ms.js +++ b/td.vue/src/i18n/ms.js @@ -29,6 +29,10 @@ const ms = { displayName: 'Bitbucket', loginWith: 'Log masuk dengan' }, + google: { + displayName: 'Google', + loginWith: 'Log masuk dengan' + }, local: { displayName: 'Sesi Tempatan', loginWith: 'Log masuk ke' diff --git a/td.vue/src/i18n/pt.js b/td.vue/src/i18n/pt.js index e8de8c502..60f58aee0 100644 --- a/td.vue/src/i18n/pt.js +++ b/td.vue/src/i18n/pt.js @@ -29,6 +29,10 @@ const por = { displayName: 'Bitbucket', loginWith: 'Login com' }, + google: { + displayName: 'Google', + loginWith: 'Login com' + }, local: { displayName: 'Sessão Local', loginWith: 'Login com' diff --git a/td.vue/src/i18n/ru.js b/td.vue/src/i18n/ru.js index b9301d778..c36074909 100644 --- a/td.vue/src/i18n/ru.js +++ b/td.vue/src/i18n/ru.js @@ -29,6 +29,10 @@ const rus = { displayName: 'Bitbucket', loginWith: 'Login with' }, + google: { + displayName: 'Google', + loginWith: 'Login with' + }, local: { displayName: 'Local Session', loginWith: 'Login to' diff --git a/td.vue/src/i18n/uk.js b/td.vue/src/i18n/uk.js index 93188a2c5..15081aba7 100644 --- a/td.vue/src/i18n/uk.js +++ b/td.vue/src/i18n/uk.js @@ -29,6 +29,10 @@ const ukr = { displayName: 'Bitbucket', loginWith: 'Login with' }, + google: { + displayName: 'Google', + loginWith: 'Login with' + }, local: { displayName: 'Local Session', loginWith: 'Login to' diff --git a/td.vue/src/i18n/zh.js b/td.vue/src/i18n/zh.js index 92c72ea7a..caa206250 100644 --- a/td.vue/src/i18n/zh.js +++ b/td.vue/src/i18n/zh.js @@ -29,6 +29,10 @@ const zho = { displayName: 'Bitbucket', loginWith: '登录' }, + google: { + displayName: 'Google', + loginWith: '登录' + }, local: { displayName: '本地', loginWith: '登录' diff --git a/td.vue/src/plugins/fontawesome-vue.js b/td.vue/src/plugins/fontawesome-vue.js index ceda0479c..8d95eab6b 100644 --- a/td.vue/src/plugins/fontawesome-vue.js +++ b/td.vue/src/plugins/fontawesome-vue.js @@ -30,10 +30,10 @@ import { faFolderOpen, faPrint, faProjectDiagram, - faDiagramProject + faDiagramProject, } from '@fortawesome/free-solid-svg-icons'; -import {faBitbucket, faGithub, faGitlab, faVuejs} from '@fortawesome/free-brands-svg-icons'; +import {faBitbucket, faGithub, faGitlab, faVuejs, faGoogle, faGoogleDrive} from '@fortawesome/free-brands-svg-icons'; // Add icons to the library for use library.add( @@ -67,7 +67,9 @@ library.add( faFolderOpen, faPrint, faProjectDiagram, - faDiagramProject + faDiagramProject, + faGoogle, + faGoogleDrive ); Vue.component('font-awesome-icon', FontAwesomeIcon); diff --git a/td.vue/src/service/provider/google.provider.js b/td.vue/src/service/provider/google.provider.js new file mode 100644 index 000000000..1b59c5f3a --- /dev/null +++ b/td.vue/src/service/provider/google.provider.js @@ -0,0 +1,26 @@ +import { providerTypes } from './providerTypes.js'; + +const providerType = providerTypes.google; + +const getDashboardActions = () => ([ + { + to: `/${providerType}/google/drive`, + key: 'openExisting', + icon: 'google-drive', + iconPreface: 'fab' + }, + { + to: `/${providerType}/google/drive?action=create`, + key: 'createNew', + icon: 'plus' + }, + { + to: '/demo/select', + key: 'readDemo', + icon: 'cloud-download-alt' + } +]); + +export default { + getDashboardActions +}; diff --git a/td.vue/src/service/provider/providerTypes.js b/td.vue/src/service/provider/providerTypes.js index 153c4d721..b6de07474 100644 --- a/td.vue/src/service/provider/providerTypes.js +++ b/td.vue/src/service/provider/providerTypes.js @@ -1,5 +1,6 @@ export const providerTypes = { desktop: 'desktop', git: 'git', + google: 'google', local: 'local' }; diff --git a/td.vue/src/service/provider/providers.js b/td.vue/src/service/provider/providers.js index 4fd02479c..cf923ab32 100644 --- a/td.vue/src/service/provider/providers.js +++ b/td.vue/src/service/provider/providers.js @@ -4,6 +4,7 @@ import desktopProvider from './desktop.provider.js'; import { providerTypes } from './providerTypes.js'; import bitbucketProvider from '@/service/provider/bitbucket.provider'; import gitlabProvider from '@/service/provider/gitlab.provider'; +import googleProvider from './google.provider.js'; const providers = { desktop: { @@ -34,6 +35,13 @@ const providers = { type: providerTypes.git, icon: ['fab', 'bitbucket'] }, + google: { + key: 'google', + displayName: 'Google', + provider: googleProvider, + type: providerTypes.google, + icon: ['fab', 'google'] + }, local: { key: 'local', displayName: 'Local Session', diff --git a/td.vue/src/views/HomePage.vue b/td.vue/src/views/HomePage.vue index b293c5350..0d1644494 100644 --- a/td.vue/src/views/HomePage.vue +++ b/td.vue/src/views/HomePage.vue @@ -83,6 +83,9 @@ export default { if (state.config.config.gitlabEnabled) { providers.gitlab = allProviders.gitlab; } + if (state.config.config.googleEnabled) { + providers.google = allProviders.google; + } if (state.config.config.localEnabled) { providers.local = allProviders.local; }