Skip to content

Commit

Permalink
Added New workflow to clean Anon users, as well as updated sign in page
Browse files Browse the repository at this point in the history
To allow Anon users to sign in instead.
  • Loading branch information
Kalvin-Twitty committed Apr 13, 2024
1 parent b0f06b2 commit 4d90c62
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 39 deletions.
18 changes: 12 additions & 6 deletions .github/workflows/fetch-commits.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Fetch Commits and Store in Firestore
name: Fetch Commits and Store in Firestore and Cleanup Anonymous Users

on:
push:
branches:
- main

jobs:
fetch-commits:
fetch-commits-and-cleanup:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand All @@ -15,16 +15,22 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18' # Specify Node.js version
node-version: '18'

- name: Install dependencies
run: npm install

- name: Fetch Commits
env: # Define necessary environment variables here
env:
FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node Scripts/fetchCommits.js # Run the script to fetch and store commits

run: node Scripts/fetchCommits.js

- name: Cleanup Anonymous Users
env:
FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
run: node Scripts/cleanupAnonymousUsers.js
31 changes: 31 additions & 0 deletions Scripts/cleanupAnonymousUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import admin from 'firebase-admin';
import dotenv from 'dotenv';

dotenv.config();

admin.initializeApp({
credential: admin.credential.cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n')
})
});

const deleteAnonymousUsers = async () => {
let nextPageToken;
do {
const listUsersResult = await admin.auth().listUsers(1000, nextPageToken);
nextPageToken = listUsersResult.pageToken;

const uidsToDelete = listUsersResult.users
.filter(user => user.providerData.length === 0) // Filter anonymous users
.map(user => user.uid);

if (uidsToDelete.length > 0) {
await Promise.all(uidsToDelete.map(uid => admin.auth().deleteUser(uid)));
console.log(`Deleted ${uidsToDelete.length} anonymous users`);
}
} while (nextPageToken);
};

deleteAnonymousUsers().catch(console.error);
42 changes: 28 additions & 14 deletions src/context/AuthContext.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React, { createContext, useContext, useEffect, useState } from 'react';
import { getFirestore, doc, getDoc } from 'firebase/firestore';
import app from '../firebase/firebaseConfig';
import { signInWithGoogle, signOut, handleRedirectResult } from '../firebase/authService';
import { signInWithGoogle, signOut, handleRedirectResult, signInAnonymously as firebaseSignInAnonymously, auth } from '../firebase/authService'; // Import 'auth' here
import { addNewUserWithDisplayNameCheck } from '../firebase/userService';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [userDocumentId, setUserDocumentId] = useState(null);
const [isAdmin, setIsAdmin] = useState(false); // State to track if the current user is an admin
const [loading, setLoading] = useState(true); // Initialize loading state
const [isAdmin, setIsAdmin] = useState(false);
const [loading, setLoading] = useState(true);

useEffect(() => {
const processRedirect = async () => {
Expand All @@ -20,10 +19,7 @@ export const AuthProvider = ({ children }) => {
const db = getFirestore(app);
const userDocRef = doc(db, 'users', user.uid);
const userDoc = await getDoc(userDocRef);

console.log("User document exists:", userDoc.exists());
console.log("User admin status:", userDoc.data()?.admin);


if (!userDoc.exists()) {
await addNewUserWithDisplayNameCheck(user.uid, {
displayName: user.displayName,
Expand All @@ -35,22 +31,40 @@ export const AuthProvider = ({ children }) => {
} else {
setIsAdmin(false);
}

setCurrentUser(user);
setUserDocumentId(user.uid);
console.log("Current user:", user);
console.log("Is admin:", userDoc.data()?.admin === true);
} else {
console.log("No user from redirect, likely not logged in");
}
} catch (error) {
console.error("Error during auth redirect process:", error);
} finally {
setLoading(false); // Ensure loading is set to false after the process
setLoading(false);
}
};

processRedirect();
}, []);

const signInAnonymously = async () => {
setLoading(true);
try {
const result = await firebaseSignInAnonymously(auth); // Use 'auth' directly here
if (result && result.user) {
setCurrentUser(result.user);
setUserDocumentId(result.user.uid);
console.log("Signed in anonymously", result.user);
} else {
console.log("No user data returned on anonymous sign-in.");
}
} catch (error) {
console.error("Error signing in anonymously:", error);
} finally {
setLoading(false);
}
};

const signIn = async () => {
await signInWithGoogle();
};
Expand All @@ -61,16 +75,16 @@ export const AuthProvider = ({ children }) => {
setIsAdmin(false);
setUserDocumentId(null);
setLoading(true);
console.log("User signed out");
};

const value = {
currentUser,
userDocumentId,
isAdmin,
loading, // Include loading state in the context value
loading,
signIn,
signOut: handleSignOut,
signInAnonymously,
};

return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
Expand Down
55 changes: 38 additions & 17 deletions src/firebase/authService.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,56 @@
import { getAuth, signInWithPopup, GoogleAuthProvider, signInWithRedirect, getRedirectResult, signOut as firebaseSignOut } from 'firebase/auth'; // Added getRedirectResult and firebaseSignOut
import {
getAuth,
signInWithPopup,
GoogleAuthProvider,
signInWithRedirect,
getRedirectResult,
signOut as firebaseSignOut,
signInAnonymously as firebaseSignInAnonymously
} from 'firebase/auth';
import app from './firebaseConfig';

const provider = new GoogleAuthProvider();
const auth = getAuth(app); // Pass the Firebase app instance to getAuth
export const auth = getAuth(app); // Get and export the authentication object

// Initiates sign-in with Google using redirect
export const signInWithGoogle = () => {
// Initiates sign-in with redirect
signInWithRedirect(auth, provider);
};

// Handles the results from the redirect sign-in
export const handleRedirectResult = async () => {
try {
const result = await getRedirectResult(auth);
if (result) {
// This gives you a Google Access Token. You can use it to access Google APIs.
// The signed-in user info is now available
return result.user; // Return the user object for further processing
if (result && result.user) {
return result.user; // Returns the user object from Firebase Auth
} else {
// Handle the case where no user is returned
console.log("No user from redirect, likely not logged in");
return null;
}
} catch (error) {
// Handle Errors here.
console.error("Error handling redirect result:", error);
throw error; // Rethrow or handle errors appropriately
throw error;
}
};

export const signOut = () => {
firebaseSignOut(auth).then(() => {
// Sign-out successful.
// Update UI or redirect as needed
}).catch((error) => {
// An error happened during sign-out.
// Signs out the current user
export const signOut = async () => {
try {
await firebaseSignOut(auth);
console.log("Sign-out successful.");
} catch (error) {
console.error("Error during sign-out:", error);
});
};
}
};

// Signs in a user anonymously
export const signInAnonymously = async () => {
try {
const result = await firebaseSignInAnonymously(auth);
return result; // Assuming you want to return the result object
} catch (error) {
console.error("Error signing in anonymously:", error);
throw error;
}
};
18 changes: 16 additions & 2 deletions src/pages/SignInPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useEffect } from 'react';
import { useAuth } from '../context/AuthContext';

const SignInPage = () => {
const { signIn, currentUser } = useAuth();
const { signIn, signInAnonymously, currentUser } = useAuth();
const navigate = useNavigate();

useEffect(() => {
Expand All @@ -12,16 +12,30 @@ const SignInPage = () => {
}
}, [currentUser, navigate]);

const handleAnonymousSignIn = async () => {
try {
await signInAnonymously();
} catch (error) {
console.error("Error during anonymous sign-in:", error);
}
};

return (
<div className="min-h-screen flex items-center justify-center bg-gray-900">
<div className="text-center">
<h1 className="text-4xl text-white font-bold mb-8">Welcome to Codele</h1>
<button
onClick={signIn}
className="text-white bg-teal-500 hover:bg-teal-700 font-semibold py-2 px-4 border border-teal-700 rounded shadow"
className="text-white bg-teal-500 hover:bg-teal-700 font-semibold py-2 px-4 border border-teal-700 rounded shadow mb-4"
>
Sign in with Google
</button>
<button
onClick={handleAnonymousSignIn}
className="text-white bg-gray-700 hover:bg-gray-800 font-semibold py-2 px-4 border border-gray-800 rounded shadow"
>
Continue Anonymously
</button>
</div>
</div>
);
Expand Down

0 comments on commit 4d90c62

Please sign in to comment.