diff --git a/.gitignore b/.gitignore index fce2cec75..cce39c460 100644 --- a/.gitignore +++ b/.gitignore @@ -10,20 +10,21 @@ .docusaurus .cache-loader +# Generated env files +.env.local +.env.dev + # Misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +# .env.local +# .env.development.local +# .env.test.local +# .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* -# AWS Secrets -IAM_Automation/aws_creds.py - # Terraform Stack build files .terraform .terraform.lock.hcl diff --git a/README.md b/README.md index 73ff9858e..cef503285 100644 --- a/README.md +++ b/README.md @@ -217,10 +217,10 @@ Here are the steps: > 2. `sudo apt install mkcert` > 3. Confirm your installation: `mkcert --version` -Similarly, some local environment variables must be specified in order to ensure functionality: -1. Create a copy of the file called `env.template` -2. Within this file populate the provided variables using information available on the AWS Console for Cognito. -3. Once populated with the correct information, authentication should work correctly +Similarly, some local environment variables must be specified in order to ensure functionality with authenication: +- Use `npm run local` to develop locally **without** authentication enabled +- Use `npm start` to develop locally **with** authentication + - If environment variables are not configured, you will be prompted to provide them ## 🎉Acknowledgements Many thanks to the [UMass Lowell Cloud Computing Club](https://umasslowellclubs.campuslabs.com/engage/organization/cloudcomputingclub) members, our faculty advisor [Dr. Johannes Weis](https://www.uml.edu/sciences/computer-science/people/weis-johannes.aspx), and the [UMass Lowell Computer Science Department](https://www.uml.edu/Sciences/computer-science/) for their support and guidance. diff --git a/docs/schedule/2024Fall/2024Fall.md b/docs/schedule/2024Fall/2024Fall.md index a4185a2fb..70e4fef76 100644 --- a/docs/schedule/2024Fall/2024Fall.md +++ b/docs/schedule/2024Fall/2024Fall.md @@ -8,7 +8,7 @@ ogDescription: Explore the Fall 2024 meeting schedule for the UMass Lowell Cloud --- :::danger -This schedule is outdated and refers to a past semester. Please check the [latest schedule](../current-schedule) for current information. +This schedule is outdated and refers to a past semester. Please check the [latest schedule](../docs/current-schedule) for current information. ::: diff --git a/docusaurus.config.js b/docusaurus.config.js index f2238e80b..0d54ce928 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -9,6 +9,7 @@ import remarkMath from 'remark-math'; import rehypeKatex from 'rehype-katex'; const process = require('node:process'); +const env_type = process.env.ENV; /** @type {import('@docusaurus/types').Config} */ const config = { @@ -85,7 +86,8 @@ const config = { [ "docusaurus-plugin-dotenv", { - path: "./.env.local", + default: "./.env.local", + path: "./.env.dev", systemvars: true, }, // '@docusaurus/plugin-content-docs', @@ -118,14 +120,14 @@ const config = { disableSwitch: false, respectPrefersColorScheme: true, }, - announcementBar: { - id: 'announcement-bar', - content: - '☀️ Summer Meetings start Virtually on May 17th! ✍️', - backgroundColor: '#48a0ff', - textColor: '#fff', - isCloseable: false - }, + // announcementBar: { + // id: 'announcement-bar', + // content: + // '☀️ Summer Meetings start Virtually on May 17th! ✍️', + // backgroundColor: '#48a0ff', + // textColor: '#fff', + // isCloseable: false + // }, navbar: { title: 'UML Cloud Computing Club', logo: { diff --git a/env.template b/env.template deleted file mode 100644 index c59d71845..000000000 --- a/env.template +++ /dev/null @@ -1,34 +0,0 @@ -## .env.local - -## i.e: localhost, dev, prod -ENV="localhost" - -## AWS Cognito Region -REGION="us-east-1" - -## AWS Cognito User Pool ID -USER_POOL_ID="" - -## AWS Cognito User Pool App Client ID -USER_POOL_WEB_CLIENT_ID="" - -## AWS Cognito Domain -OAUTH_DOMAIN="" - -## Cognito redirect url after a successful sign-out -OAUTH_REDIRECT_SIGN_OUT="https://localhost:3000,https://umlcloudcomputing.org" - -## Cognito setup, no need to change it! -OAUTH_REDIRECT_SIGN_RESPONSE_TYPE="code" - -## OIDC Authority -AUTHORITY="" - -## Client ID -CLIENT_ID="" - -## Redirect URI -REDIRECT_URI="" - -## Scope -SCOPE="email openid phone" \ No newline at end of file diff --git a/env_config/.gt/dev.gt b/env_config/.gt/dev.gt new file mode 100644 index 000000000..43eb978e1 --- /dev/null +++ b/env_config/.gt/dev.gt @@ -0,0 +1,11 @@ +ENV +REGION +USER_POOL_ID +USER_POOL_WEB_CLIENT_ID +OAUTH_DOMAIN +OAUTH_REDIRECT_SIGN_OUT +OAUTH_REDIRECT_SIGN_RESPONSE_TYPE +AUTHORITY +CLIENT_ID +REDIRECT_URI +SCOPE diff --git a/env_config/.gt/local.gt b/env_config/.gt/local.gt new file mode 100644 index 000000000..fffbb8241 --- /dev/null +++ b/env_config/.gt/local.gt @@ -0,0 +1 @@ +ENV diff --git a/env_config/configure_dev.sh b/env_config/configure_dev.sh new file mode 100755 index 000000000..ce4a50913 --- /dev/null +++ b/env_config/configure_dev.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Prompt and read +clear +# echo "Select an environment type:" +# echo "--------------------------------" +# echo "1: Local (default)" +# echo "2: Dev" + +# read -p "Choose a number (1 or 2): " choice + +# case $choice in +# 1) ENV="local" ;; +# 2) ENV="dev" ;; +# *) echo "Invalid choice. Exiting..." +# exit 1;; +# esac +# echo "----------------------------------------------" + +# Determine file type based on choice + +# NEW: Changed to be exclusively for dev session with authentication +env_file=".env.dev" # Determines file name to source/create +gt_file="./env_config/.gt/dev.gt" # Determines the ground truth (gt) file to validate against + +declare -A env_vars + +# Check if the file exists +if [ -f "$env_file" ]; then + # If the file exists, source it and validate the contents + . ./env_config/validate_vars.sh "$gt_file" "$env_file" + +else + # If the file does not exist, prompt for and create it + . ./env_config/process_gt.sh "$gt_file" "$env_file" +fi + +set -a +source $env_file +export ENV + +echo -e "Environment variables set successfully!\n" diff --git a/env_config/process_gt.sh b/env_config/process_gt.sh new file mode 100755 index 000000000..bad735d14 --- /dev/null +++ b/env_config/process_gt.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Prompts environment variables as per ground truth file +# Exports environment variables to environment file + +# WARNING: Flushes env file before writing! + +# Args: +# 1: Ground truth file +# 2: Environment file to source +gt_file=$1 +env_file=$2 + +declare -A env_vars + +read_and_prompt() { + local line + # Read env vars from gt file + while IFS= read -r line; do + # Skip preprocessing, input is assumed to be in the correct format + local var_name="$line" + + # Check if variable name has not been asked for before (avoid duplicates) + if [[ ! ${env_vars[$var_name]} ]]; then + echo -n "$var_name: " + read value < /dev/tty + env_vars[$var_name]=$value + fi + + # Uncomment if implementing custom `gt` file format validation + # else + # echo "Error: Invalid format. Expected ..., found '$line'". Skipping..." + #fi + done +} + +# Read and prompt for env vars +read_and_prompt < "$gt_file" + +# Flush file +:> "$env_file" + +# Export environment variables to destination file +for key in "${!env_vars[@]}"; do + echo "$key=\"${env_vars[$key]}\"" >> "$env_file" +done + +echo -e "\nEnvironment variables exported to $env_file" +echo -e "---------------------------------------------\n" \ No newline at end of file diff --git a/env_config/validate_vars.sh b/env_config/validate_vars.sh new file mode 100755 index 000000000..54a02a6c1 --- /dev/null +++ b/env_config/validate_vars.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Validates environment variables against ground truth file + +# Args +# 1: Ground truth file +# 2: Environment file to source +gt_file=$1 +env_file=$2 +is_invalid=false + +declare -A env_vars +source $env_file + +validate_var() { + local var_name=$1 + # Return non-zero value if variable name is invalid + if [[ -z "$var_name" ]] || [[ -z "${!var_name}" ]]; then + return 1 + fi + return 0; +} + +# Read env vars from gt file +while IFS= read -r line; do + # Skip preprocessing, input is assumed to be in the correct format + variable_name=$line + + # Check if variable name has not been checked before (avoid duplicates) + if [[ ! ${env_vars[$variable_name]} ]]; then + if validate_var "$variable_name"; then + echo -e "+ $variable_name configured!" + else + echo -e "- $variable_name is not configured!" + is_invalid=true + fi + + fi +done < "$gt_file" + +# Conditionally set exit status +if [ "$is_invalid" = true ]; then + echo -e "Invalid configuration, please check if variables are configured as per $gt_file!\n" + exit 3 +else + echo -e "Environment variables validated against $gt_file" + echo -e "----------------------------------------------"; +fi \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2f53d1be3..ef34f857a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11162,9 +11162,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "version": "1.0.30001721", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", + "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", "funding": [ { "type": "opencollective", diff --git a/package.json b/package.json index 362e66978..00438c5de 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "scripts": { "import": "node stream.js && rm -rf temp_resources && rm -rf temp_activity && rm -rf temp_projects", "docusaurus": "docusaurus", - "start": "docusaurus start", + "local": "export NODE_ENV=test && docusaurus start", + "start": "./env_config/configure_dev.sh && docusaurus start", "build": "docusaurus build && cp CNAME build/", "swizzle": "docusaurus swizzle", "deploy": "gh-pages -d build", "clear": "docusaurus clear", - "serve": "docusaurus serve", + "serve": "export NODE_ENV=prod docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "predeploy": "npm run build" diff --git a/src/components/Auth/index.js b/src/components/Auth/index.js index 52793b4c3..b3234c2f5 100644 --- a/src/components/Auth/index.js +++ b/src/components/Auth/index.js @@ -1,10 +1,10 @@ // src/components/Auth/index.js import React from "react"; - import { useAuth } from "react-oidc-context"; import { Redirect, useLocation } from "@docusaurus/router"; import ReactLoading from 'react-loading'; +import { envType, getEnvVar } from "../../utils/utils.js"; import { // AUTHENTICATED, @@ -20,11 +20,19 @@ export function AuthCheck({ children }) { let from = location.pathname; const auth = useAuth(); + // If .env.local is missing, skip all auth logic and just render children + if (envType() === 'local') { + // If the path is protected, redirect to sign in + if (PROTECTED_PATHS.filter((x) => from.includes(x)).length) + return ; + return children; + } + const [local_logout_uri, prod_logout_uri] = process.env.OAUTH_REDIRECT_SIGN_OUT.split(","); - + const signOutRedirect = () => { const clientId = process.env.CLIENT_ID; - const logoutUri = process.env.ENV === "localhost" + const logoutUri = process.env.ENV === "local" ? local_logout_uri : prod_logout_uri; const cognitoDomain = process.env.OAUTH_DOMAIN; @@ -66,4 +74,5 @@ export function AuthCheck({ children }) { else if (from === LOGIN_PATH) auth.signinRedirect(); return children; } -} \ No newline at end of file +} + diff --git a/src/config/cognito-auth-config.js b/src/config/cognito-auth-config.js index 22b8be6b1..b5947c9c8 100644 --- a/src/config/cognito-auth-config.js +++ b/src/config/cognito-auth-config.js @@ -1,11 +1,13 @@ // src/config/cognito-auth-config.js +import { envType, getEnvVar } from '../utils/utils'; + const cognitoAuthConfig = { authority: process.env.AUTHORITY, client_id: process.env.CLIENT_ID, redirect_uri: process.env.REDIRECT_URI, response_type: process.env.OAUTH_REDIRECT_SIGN_RESPONSE_TYPE, - scope: process.env.SCOPE, + scope: process.env.SCOPE }; export default cognitoAuthConfig; diff --git a/src/config/cognito-configure.js b/src/config/cognito-configure.js index ca0291722..a8bff8eae 100644 --- a/src/config/cognito-configure.js +++ b/src/config/cognito-configure.js @@ -1,8 +1,14 @@ // src/config/cognito-config.js import cognitoAuthConfig from "./cognito-auth-config"; +import { envType } from '../utils/utils'; export function configure() { + if (envType() === 'local') { + console.log("Local mode detected, skipping authentication config"); + return {}; + } + // Assuming you have two redirect URIs, and the first is for localhost and // second is for production const [localRedirectURI, prodRedirectURI] = @@ -11,10 +17,19 @@ export function configure() { const updatedCognitoConfig = { ...cognitoAuthConfig, redirect_uri: - process.env.ENV === "localhost" + envType() === "dev" ? localRedirectURI : prodRedirectURI }; - return updatedCognitoConfig; + + if (envType() === 'dev') { + console.log("Dev mode detected, configuring for local development with authentication enabled"); + return updatedCognitoConfig; + } + + // Running in production + else { + return updatedCognitoConfig; + } } \ No newline at end of file diff --git a/src/pages/index.js b/src/pages/index.js index 1b3e1d73b..7da183cb7 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -158,12 +158,12 @@ const LandingPageUniBotiFrame = () => (
GitHub
-
+ {/*
-
+
*/} ); @@ -179,12 +179,12 @@ const LandingPageImmersion = () => (
Dashboard GitHub
-
+ {/*
-
+
*/} ); diff --git a/src/utils/constants.js b/src/utils/constants.js index 7d1788860..419279b89 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -8,5 +8,19 @@ export const BASE = "/"; export const LOGOUT_BUTTON = "Logout"; export const LOGIN_BUTTON = "Login"; +export const REQUIRED_ENV_VARS = [ + 'AUTHORITY', + 'CLIENT_ID', + 'REDIRECT_URI', + 'OAUTH_REDIRECT_SIGN_RESPONSE_TYPE', + 'SCOPE', + 'REGION', + 'USER_POOL_ID', + 'USER_POOL_WEB_CLIENT_ID', + 'OAUTH_DOMAIN', + 'OAUTH_REDIRECT_SIGN_OUT', + 'ENV', +]; + // Add the protected paths here export const PROTECTED_PATHS = ["docs/resources", "docs/activities", "/accountSettings"]; \ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js index b4c2a9901..69f932723 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -10,10 +10,42 @@ import { LOGIN_PATH, LOGOUT_BUTTON, LOGOUT_PATH, + REQUIRED_ENV_VARS, } from "./constants"; +export function envType() { + // Local, authentication disabled + if (process.env.NODE_ENV === "test") { + return 'local'; + } + + // Dev, authentication enabled, locally developed + else if (process.env.NODE_ENV === "development") { + return 'dev'; + } + + // Prod, authentication enabled, deployed on server + else { + if (REQUIRED_ENV_VARS.every((key) => (typeof process.env[key] === 'string') && (process.env[key] !== ''))) { + throw new Error('FATAL: Missing required environment variables for AUTHENTICATION\nENV: ' + process.env.ENV) + } else { + return 'prod'; + } + } + // If any required env var is missing, assume .env.* is not loaded +} + +export function getEnvVar(key) { + if (typeof process.env[key] === 'string' && process.env[key] !== '') { + return process.env[key]; + } +} + export function useNavbarItemsMobile() { - // const { route } = useAuthenticator((context) => [context.route]); + if (envType() === 'local') { + // If .env.local is missing, do not render auth-related navbar items + return useThemeConfig().navbar.items; + } const auth = useAuth(); let authElement; @@ -61,7 +93,10 @@ export function useNavbarItemsMobile() { } export function useNavbarItemsDesktop() { - // const { route } = useAuthenticator((context) => [context.route]); + if (envType() === 'local') { + // If .env.local is missing, do not render auth-related navbar items + return useThemeConfig().navbar.items; + } const auth = useAuth(); let authElement;