Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions bsg-frontend/apps/extension/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Firebase Configuration
# Copy this file to .env.local and fill in your Firebase project values
# Get these values from Firebase Console > Project Settings

NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=
6 changes: 6 additions & 0 deletions bsg-frontend/apps/extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.*
!.gitignore
!.env.example
.env.local
.env
/out
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { app } from "../../../config";
import { getAuth, signInWithCredential, GoogleAuthProvider, User } from "firebase/auth";

const auth = getAuth(app);

export async function SignInWithChromeIdentity(): Promise<User> {
return new Promise((resolve, reject) => {
if (!chrome.identity) {
reject(new Error('Chrome identity API not available'));
return;
}

chrome.identity.getAuthToken({ interactive: true }, async (token) => {
if (chrome.runtime.lastError) {
reject(new Error(chrome.runtime.lastError.message));
return;
}

if (!token || typeof token !== 'string') {
reject(new Error('No valid token received'));
return;
}

try {
// Use the token to get user info from Google API
//const userInfo = await getUserInfoFromToken(token);

// Create a Firebase credential using the token
const credential = GoogleAuthProvider.credential(null, token);

// Sign in to Firebase with the credential
const result = await signInWithCredential(auth, credential);

resolve(result.user);
} catch (error) {
console.error('Firebase auth error:', error);
reject(error);
}
});
});
}

async function getUserInfoFromToken(token: string) {
const response = await fetch(`https://www.googleapis.com/oauth2/v2/userinfo?access_token=${token}`);
if (!response.ok) {
throw new Error('Failed to get user info');
}
return response.json();
}

export async function SignOutFromChrome(): Promise<void> {

return new Promise((resolve, reject) => {
if (!chrome.identity) {
reject(new Error('Chrome identity API not available'));
return;
}

chrome.identity.getAuthToken({ interactive: false }, (token) => {

const tokenToRevoke = token.toString();
const requestBody = new URLSearchParams({
token: tokenToRevoke,
}).toString();

fetch('https://oauth2.googleapis.com/revoke', {
method:'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded',
},
body: requestBody,

}).then(response =>{
if(response.ok){
console.log("Reached google servers")

chrome.identity.clearAllCachedAuthTokens(() => {
auth.signOut().then(resolve).catch(reject);
}
)

}
else {
console.error('Error revoking token', response.status, response.statusText)
reject(new Error(`Failed to revoke token: ${response.statusText}`))
}
}
).catch(error => {
console.error("Network Error during token revocation", error)
reject(error);
})


});


});


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { app } from "../../../config";
import { getAuth,
signInWithRedirect,
signInWithPopup,
getRedirectResult,
User,
} from "firebase/auth";

import { provider } from './googleSignIn';


const auth = getAuth(app);


export async function SignInWithGoogleRedirect(): Promise<void> {

try{
await signInWithRedirect(auth, provider);
}
catch(error){
console.error("Auth error: ", error);
console.error(error.message);
throw error;
}
}

export async function SignInWithGooglePopup(): Promise<User> {
try {
const result = await signInWithPopup(auth, provider);
return result.user;
} catch (error) {
console.error("Popup auth error: ", error);
throw error;
}
}

export async function HandleAuthRedirectedResult(): Promise<User>{

try{

const result = await getRedirectResult(auth, provider);

if(result){
return result.user;
}else {
throw new Error("User Does Not Exist");
}

}catch(error){
console.log(error)
console.log(error.message)

throw new Error("User Did Not Successfully Log In")


}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { GoogleAuthProvider } from 'firebase/auth';


export const provider = new GoogleAuthProvider();
console.log(provider)





19 changes: 19 additions & 0 deletions bsg-frontend/apps/extension/firebase/auth/signOut.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { signOut, getAuth } from "firebase/auth";
import { app } from "../config";


export async function signOutOfAccount(): Promise<void>{

const auth = getAuth(app);

try{
return await signOut(auth);

}catch(error){

console.log(error.code)
console.log(error.message)
throw error;
}

}
24 changes: 24 additions & 0 deletions bsg-frontend/apps/extension/firebase/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, setPersistence, browserSessionPersistence } from "firebase/auth";



const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
};

// Initialize Firebase
export const app = initializeApp(firebaseConfig);

// Initialize Auth with session persistence
export const auth = getAuth(app);
setPersistence(auth, browserSessionPersistence);


9 changes: 9 additions & 0 deletions bsg-frontend/apps/extension/hooks/useNewTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useCallback } from 'react';

export const useNewTab = () => {
const openInNewTab = useCallback((url: string) => {
chrome.tabs.create({ url });
}, []);

return { openInNewTab };
};
4 changes: 4 additions & 0 deletions bsg-frontend/apps/extension/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ module.exports = {
'@bsg/ui-styles',
],

//no need for this line extension does not user next/image components
// images: {
// unoptimized: true,
// },
}
1 change: 0 additions & 1 deletion bsg-frontend/apps/extension/out/404.html

This file was deleted.

1 change: 0 additions & 1 deletion bsg-frontend/apps/extension/out/defaultPopup.html

This file was deleted.

38 changes: 0 additions & 38 deletions bsg-frontend/apps/extension/out/manifest.json

This file was deleted.

This file was deleted.

Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions bsg-frontend/apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"clsx": "^2.0.0",
"eslint": "8.49.0",
"eslint-config-next": "13.5.1",
"firebase": "^11.10.0",
"lucide-react": "^0.298.0",
"next": "^13.5.6",
"next-transpile-modules": "^10.0.1",
Expand All @@ -55,6 +56,7 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@types/chrome": "^0.0.319",
"css-loader": "^7.1.2",
"postcss-loader": "^8.1.1",
"replace-in-file": "^8.3.0",
Expand Down
18 changes: 13 additions & 5 deletions bsg-frontend/apps/extension/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import type {AppProps} from 'next/app';
import '../../../packages/ui-styles/global.css'
import Logo from '@bsg/components/Logo'
import { useState, useRef, useEffect } from 'react'
import type { AppProps } from 'next/app'
import '@bsg/ui-styles/global.css';

import {Poppins} from 'next/font/google'
import { Button } from '@bsg/ui/button'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDiscord, faGithub, faGoogle } from '@fortawesome/free-brands-svg-icons'
import { faPaperPlane, faSmile } from '@fortawesome/free-solid-svg-icons'

const poppins = Poppins({weight: '400', subsets: ['latin'], variable: '--poppins'})

export default function MyApp({Component, pageProps}: AppProps) {
return (
export default function App({ Component, pageProps }: AppProps) {

return (
<div className={poppins.className}>
<Component {...pageProps} />
</div>
);

)
}
11 changes: 6 additions & 5 deletions bsg-frontend/apps/extension/pages/defaultPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import {Button} from "@bsg/ui/button";
import useDefaultPopup from "@/hooks/useDefaultPopup";
import React from "react";
import Logo from "@bsg/components/Logo";
import {useState} from 'react';

export default function DefaultPopup() {
const {redirectToLeetCode, isOnLeetCode} = useDefaultPopup();

if (isOnLeetCode === null) {
return <div className="p-4 text-sm">Loading...</div>;
}

const [showLogin, setShowLogin] = useState(false);


return (
<div className={'my-5 mx-7'}>
<Logo/>
Expand All @@ -29,3 +28,5 @@ export default function DefaultPopup() {
</div>
);
}


Loading