Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/christenjack/auth #39

Merged
merged 36 commits into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0487161
move globals.css to /src/app from /src/app/(web app) and updates (web…
jackavh Apr 24, 2024
b4994b4
set up login form
jackavh Apr 24, 2024
df382d1
auth works
jackavh May 1, 2024
3158115
minor changes to LoginSection
jackavh May 8, 2024
2b7cfde
page redirects and user account icon with logout button
jackavh May 8, 2024
5f1c061
forgot password flow
jackavh May 8, 2024
db64c45
merge in my reactfire stuff
christen03 May 8, 2024
0346c35
Merge branch 'feature/christenjack/auth' of https://github.com/Triton…
christen03 May 8, 2024
811de16
merge in my reactfire stuff
christen03 May 8, 2024
a46d976
Merge branch 'main' into feature/christenjack/auth
jennymar May 13, 2024
b5952cc
Added UserIcon to NavigationBar
jennymar May 13, 2024
ba51a04
Backend package-lock update
jennymar May 13, 2024
97f0f55
Added email validation to forget password page, font fixes
jennymar May 13, 2024
0b09ea1
Frontend white background adjustment
jennymar May 13, 2024
3358c78
change to firebase 9.23.0 and everything still works
jackavh May 15, 2024
605e369
refactor firebase providers concealing firebaseConfig in .env
jackavh May 15, 2024
70a2694
lint fixes
jackavh May 15, 2024
a2163a4
move all firebase providers to /admin/layout.tsx
jackavh May 15, 2024
6484729
refactor to use reactfire for everything, also adds loading wheel whi…
jackavh May 16, 2024
9f7e36c
removes needless console.log statments
jackavh May 16, 2024
5043662
Merge branch 'main' into feature/christenjack/auth
jennymar May 16, 2024
8884655
Wrapped all admin portal pages with PrivatePage component (except login)
jennymar May 16, 2024
0561d60
Added prop to frontend pipeline run
jennymar May 16, 2024
a58380d
Updated frontend and backend validateEnv
jennymar May 16, 2024
90f13f1
Re-added --legacy-peer-deps
jennymar May 16, 2024
6721f0c
migrates from reactfire to react-firebase-hooks and firebase 9.23.0 t…
jackavh May 23, 2024
dfc760d
merge main into feature/christenjack/auth
jackavh May 23, 2024
c528bad
lint fixes and re-add firebase provider (messed with merge)
jackavh May 23, 2024
7c9c7fa
fix bug where PrivatePage would try to check auth state before auth l…
jackavh May 23, 2024
ec08b86
fix bug where suddenly useRouter stops working, use redirect() instead
jackavh May 23, 2024
a642ca7
Added env vars to workflow
jennymar Jun 1, 2024
f95a309
Changed env var from json to str
jennymar Jun 1, 2024
b394e55
Frontend linting
jennymar Jun 1, 2024
a62c2a9
Firebase settings env
jennymar Jun 1, 2024
131a71d
not secrets maybe env
jennymar Jun 1, 2024
857c478
not env maybe vars
jennymar Jun 1, 2024
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
5 changes: 5 additions & 0 deletions .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ jobs:
npm ci --legacy-peer-deps
npm run lint-check
npm run build
env:
NEXT_PUBLIC_BACKEND_URL: ${{ vars.NEXT_PUBLIC_BACKEND_URL }}
NEXT_PUBLIC_FIREBASE_SETTINGS: ${{ vars.NEXT_PUBLIC_FIREBASE_SETTINGS }}
NEXT_PUBLIC_PAYPAL_CLIENT_SECRET: ${{ vars.NEXT_PUBLIC_PAYPAL_CLIENT_SECRET }}
NEXT_PUBLIC_PAYPAL_CLIENT_ID: ${{ vars.NEXT_PUBLIC_PAYPAL_CLIENT_ID }}
8 changes: 4 additions & 4 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/nodemailer": "^6.4.14",
"@types/nodemailer": "^6.4.15",
"@typescript-eslint/eslint-plugin": "^6.18.0",
"@typescript-eslint/parser": "^6.18.0",
"eslint": "^8.56.0",
Expand Down
2 changes: 2 additions & 0 deletions backend/src/util/validateEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ export default cleanEnv(process.env, {
EMAIL_NOTIFICATIONS_RECIPIENT: email(), // Recipient of VSR notification emails
BACKEND_FIREBASE_SETTINGS: json(), // Firebase settings for backend, stored as a JSON string
SERVICE_ACCOUNT_KEY: json(), // Private service account key for backend, stored as a JSON string
PAYPAL_CLIENT_ID: str(), // Client ID credential for PayPal account
PAYPAL_CLIENT_SECRET: str(), // Client secret credential for PayPal account
});
586 changes: 308 additions & 278 deletions frontend/package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^7.1.1",
"@paypal/react-paypal-js": "^8.2.0",
"envalid": "^8.0.0",
"firebase": "^10.11.0",
"@paypal/react-paypal-js": "^8.2.0",
"html2canvas": "^1.4.1",
"html2pdf.js": "^0.9.3",
"jspdf": "^2.5.1",
Expand All @@ -30,6 +30,7 @@
"nodemailer": "^6.9.11",
"react": "^18",
"react-dom": "^18",
"react-firebase-hooks": "^5.1.1",
"react-material-symbols": "^4.3.1"
},
"devDependencies": {
Expand Down
Binary file added frontend/public/Checker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions frontend/public/admin/loginLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/app/(web app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Footer from "@/components/Footer";
import HeaderBar from "@/components/HeaderBar";
import HeaderBarSpace from "@/components/HeaderBarSpace";
import "./globals.css";
import "../globals.css";
import "react-material-symbols/rounded";

export default function Layout({ children }: { children: React.ReactNode }) {
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/app/(web app)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"use client";
import React, { useEffect, useState } from "react";

import "../globals.css";
import { getPageText } from "../../api/pageeditor";

import "./globals.css";
import BackgroundHeader from "../../components/BackgroundHeader";

import styles from "./page.module.css";
Expand Down Expand Up @@ -91,7 +90,7 @@
<Button text={see_more_text} link={"/upcoming-events"} />
</div>
<Description title={s2Subtitle} description={s2Text} />
<img className={styles.sponsor_image} src="/Sponsors.svg" alt="Sponsors" />

Check warning on line 93 in frontend/src/app/(web app)/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
<div className={styles.buttonContainer}>
<Button text={sponsor_us_text} link={"/contact"} />
</div>
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/app/admin/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Admin Dashboard landing page
"use client";

import styles from "./page.module.css";

import DashboardCard from "@/components/DashboardCard";
Expand All @@ -19,14 +20,12 @@ export default function Dashboard() {
title="Page Editor"
last_updated="Month XX, XXXX, XX:XX"
/>

<DashboardCard
imageURI="/dashboard_newsletter.png"
url="/newsletter-creator"
title="Newsletter"
last_updated="Month XX, XXXX, XX:XX"
/>

<DashboardCard
imageURI="/dashboard_mailinglist.png"
url="/mailing-list"
Expand Down
63 changes: 55 additions & 8 deletions frontend/src/app/admin/firebase/firebase.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,64 @@
import { FirebaseOptions, initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { FirebaseApp, FirebaseOptions, initializeApp } from "firebase/app";
import { Auth, getAuth, signInWithEmailAndPassword, signOut } from "firebase/auth";
import { FirebaseStorage, getStorage } from "firebase/storage";

import env from "@/app/admin/util/validateEnv";
import env from "../util/validateEnv";

export const initFirebase = () => {
export type FirebaseServices = { auth: Auth; storage: FirebaseStorage };

/**
* Initialize Firebase with the Firebase config
* @returns FirebaseServices array instance
*/
export const initFirebase = (): FirebaseServices => {
if (!env.NEXT_PUBLIC_FIREBASE_SETTINGS) {
throw new Error("Cannot get firebase settings");
throw new Error("Cannot get firebase settings. " + process.env.NEXT_PUBLIC_FIREBASE_SETTINGS);
}

const firebaseConfig = env.NEXT_PUBLIC_FIREBASE_SETTINGS as FirebaseOptions;

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const app: FirebaseApp = initializeApp(firebaseConfig);
const auth: Auth = getAuth(app);
const storage: FirebaseStorage = getStorage(app);

return { auth, storage };
};

/**
* Uses Firebase to login with email and password
* @param auth Firebase Auth instance. In components get with useFirebase()
* @param email email address
* @param password password
* @returns boolean true if sign in successful, false otherwise
*/
export const firebaseSignIn = async (auth: Auth, email: string, password: string) => {
try {
await signInWithEmailAndPassword(auth, email, password);
return true;
} catch (error) {
return false;
}
};

return { app, auth };
/**
* Sign out using Firebase and delete client data holding the JWT
* @param auth Firebase Auth instance. In components get with useFirebase()
*/
export const firebaseSignOut = async (auth: Auth) => {
try {
await signOut(auth);
} catch (error) {
alert(error);
}
};

/**
* Get's the firebase config for use with reactfire components
*
*/
export const getFirebaseConfig = (): FirebaseOptions => {
if (!env.NEXT_PUBLIC_FIREBASE_SETTINGS) {
throw new Error("Cannot get firebase settings");
}
return env.NEXT_PUBLIC_FIREBASE_SETTINGS as FirebaseOptions;
};
27 changes: 27 additions & 0 deletions frontend/src/app/admin/firebase/firebaseProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use client";

import { Auth } from "firebase/auth";
import { FirebaseStorage } from "firebase/storage";
import React, { FC, ReactNode, createContext, useContext } from "react";

import { FirebaseServices, initFirebase } from "./firebase";

const AuthContext = createContext<Auth | undefined>(undefined);
const StorageContext = createContext<FirebaseStorage | undefined>(undefined);

let firebaseServices: FirebaseServices | undefined;

export const FirebaseProvider: FC<{ children: ReactNode }> = ({ children }) => {
if (firebaseServices === undefined) {
firebaseServices = initFirebase();
}

return (
<AuthContext.Provider value={firebaseServices.auth}>
<StorageContext.Provider value={firebaseServices.storage}>{children}</StorageContext.Provider>
</AuthContext.Provider>
);
};

export const useAuth = () => useContext(AuthContext);
export const useStorage = () => useContext(StorageContext);
30 changes: 24 additions & 6 deletions frontend/src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
"use client";

import { usePathname } from "next/navigation";

import { FirebaseProvider } from "./firebase/firebaseProvider";

import "../globals.css";
import HeaderBarSpace from "@/components/HeaderBarSpace";
import NavigationBar from "@/components/NavigationBar";
import "./globals.css";
import PrivatePage from "@/components/admin/PrivatePage";

export default function AdminLayout({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const isLoginPage = pathname === "/admin";

return (
<section>
<NavigationBar />
<HeaderBarSpace />
{children}
</section>
<FirebaseProvider>
{!isLoginPage ? (
<PrivatePage>
<section>
<NavigationBar />
<HeaderBarSpace />
{children}
</section>
</PrivatePage>
) : (
children
)}
</FirebaseProvider>
);
}
1 change: 1 addition & 0 deletions frontend/src/app/admin/page.module.css
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/* Styles for admin login screen */
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Roboto+Slab:[email protected]&display=swap");
4 changes: 3 additions & 1 deletion frontend/src/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import React from "react";

import LoginSection from "@/components/admin/LoginSection";

export default function Login() {
return <div>Login</div>;
return <LoginSection />;
}
8 changes: 6 additions & 2 deletions frontend/src/app/admin/util/validateEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { cleanEnv } from "envalid";
import { json, str } from "envalid/dist/validators";
import { str, json } from "envalid/dist/validators";

Check warning on line 7 in frontend/src/app/admin/util/validateEnv.ts

View workflow job for this annotation

GitHub Actions / Frontend check

Member 'json' of the import declaration should be sorted alphabetically

/**
* NextJS only allows the frontend to access environment variables if they start with
Expand All @@ -14,9 +14,13 @@
{
NEXT_PUBLIC_BACKEND_URL: process.env.NEXT_PUBLIC_BACKEND_URL,
NEXT_PUBLIC_FIREBASE_SETTINGS: process.env.NEXT_PUBLIC_FIREBASE_SETTINGS,
NEXT_PUBLIC_PAYPAL_CLIENT_SECRET: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_SECRET,
NEXT_PUBLIC_PAYPAL_CLIENT_ID: process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,
},
{
NEXT_PUBLIC_BACKEND_URL: str(), // URL of our backend
NEXT_PUBLIC_FIREBASE_SETTINGS: json(), // Firebase settings for frontend, stored as a JSON string
NEXT_PUBLIC_FIREBASE_SETTINGS: json(), // Firebase settings for frontend
NEXT_PUBLIC_PAYPAL_CLIENT_SECRET: str(),
NEXT_PUBLIC_PAYPAL_CLIENT_ID: str(),
},
);
File renamed without changes.
9 changes: 1 addition & 8 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,7 @@ const robotoSlab = Roboto_Slab({

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html
lang="en"
className={`
${openSans.className} ${openSans.variable}
${inter.className} ${inter.variable}
${robotoSlab.className} ${robotoSlab.variable}
`}
>
<html lang="en" className={`${openSans.variable} ${inter.variable} ${robotoSlab.variable}`}>
<body>{children}</body>
</html>
);
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/components/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Link from "next/link";
import React, { useEffect, useState } from "react";

import styles from "./NavigationBar.module.css";
import UserIcon from "./UserIcon";

const NavigationBar = () => {
const [activeMenu, setActiveMenu] = useState<string>("");
Expand Down Expand Up @@ -83,9 +84,7 @@ const NavigationBar = () => {
)}
</div>
<div className={styles.user}>
<Image src={"/sampleUserPhoto.svg"} alt="userImage" width={36} height={36}></Image>
<p>John Doe</p>
<Image src={"/ic_caretdown.svg"} alt="upArrow" width={24} height={24}></Image>
<UserIcon />
</div>
</div>
<div className={styles.navBar}>
Expand Down
Loading
Loading