Skip to content

Commit 52a3973

Browse files
authored
add env variable for frontend url to remove hardcoded references to i… (#94)
Main Things 1) Added a FRONTEND_URL env variable to remove hardcoded references to localhost:3000 in our backend. 2) In the welcome page, there was a "You can learn more about the program here" button that before didn't take us anywhere. Now it will take us to either 'https://www.bloodcancers.ca/first-connection-peer-support-program' or 'https://www.cancersdusang.ca/programme-de-soutien-par-les-pairs-premier-contact' depending on the user's language. 3) Added a ENV env variable that should be set to either development or production. Updated seeder so that when ENV=production, it won't seed our mock users and ranking preferences. 4) Updated list of allowed admins to include 5 ppl from LLSC (Megan, Caroline, 3 others) Please update your env files to have the new FRONTEND_URL and ENV environment variables. ## Notion ticket link <!-- Please replace with your ticket's URL --> [Ticket Name](https://www.notion.so/uwblueprintexecs/Task-Board-db95cd7b93f245f78ee85e3a8a6a316d) <!-- Give a quick summary of the implementation details, provide design justifications if necessary --> ## Implementation description * <!-- What should the reviewer do to verify your changes? Describe expected results and include screenshots when appropriate --> ## Steps to test 1. <!-- Draw attention to the substantial parts of your PR or anything you'd like a second opinion on --> ## What should reviewers focus on? * ## Checklist - [ ] My PR name is descriptive and in imperative tense - [ ] My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits - [ ] I have run the appropriate linter(s) - [ ] I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR
1 parent 0c57f7c commit 52a3973

File tree

13 files changed

+152
-53
lines changed

13 files changed

+152
-53
lines changed

.env.sample

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
POSTGRES_DATABASE=
2-
POSTGRES_USER=
3-
POSTGRES_PASSWORD=
4-
POSTGRES_DATABASE_URL=
5-
AWS_ACCESS_KEY_ID=
6-
AWS_SECRET_ACCESS_KEY=
7-
AWS_REGION=
8-
SES_EMAIL_FROM=
1+
ENV=development # set ENV=production in prod
2+
3+
POSTGRES_DATABASE=llsc
4+
POSTGRES_USER=postgres
5+
POSTGRES_PASSWORD=postgres
6+
POSTGRES_DATABASE_URL=postgresql+psycopg2://postgres:postgres@db:5432/llsc
7+
POSTGRES_TEST_DATABASE_URL=postgresql+psycopg2://postgres:postgres@db:5432/llsc_test
8+
9+
FIREBASE_WEB_API_KEY=
10+
11+
AWS_ACCESS_KEY=
12+
AWS_SECRET_KEY=
13+
AWS_REGION=ca-central-1
14+
SES_SOURCE_EMAIL=
15+
SES_SOURCE_EMAIL_FR=
16+
17+
FRONTEND_URL=http://localhost:3000

backend/.env.sample

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ENV=development # set ENV=production in prod
2+
3+
POSTGRES_DATABASE=llsc
4+
POSTGRES_USER=postgres
5+
POSTGRES_PASSWORD=postgres
6+
POSTGRES_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/llsc
7+
POSTGRES_TEST_DATABASE_URL=postgresql+psycopg2://postgres:postgres@localhost:5432/llsc_test
8+
9+
FIREBASE_WEB_API_KEY=
10+
11+
AWS_ACCESS_KEY=
12+
AWS_SECRET_KEY=
13+
AWS_REGION=ca-central-1
14+
SES_SOURCE_EMAIL=
15+
SES_SOURCE_EMAIL_FR=
16+
17+
FRONTEND_URL=http://localhost:3000

backend/app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def create_app():
3333
app.add_middleware(
3434
CORSMiddleware,
3535
allow_origins=[
36-
"http://localhost:3000",
36+
os.getenv("FRONTEND_URL", "http://localhost:3000"),
3737
"https://uw-blueprint-starter-code.firebaseapp.com",
3838
"https://uw-blueprint-starter-code.web.app",
3939
# TODO: create a separate middleware function to dynamically

backend/app/routes/auth.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,21 @@
1919
# TODO: ADD RATE LIMITING
2020
@router.post("/register", response_model=UserCreateResponse)
2121
async def register_user(user: UserCreateRequest, user_service: UserService = Depends(get_user_service)):
22-
allowed_Admins = [
22+
allowed_admins = {
2323
2424
2525
2626
2727
28-
]
28+
29+
30+
31+
32+
33+
}
2934
if user.role == UserRole.ADMIN:
30-
if user.email not in allowed_Admins:
35+
normalized_email = user.email.lower() if user.email else ""
36+
if normalized_email not in allowed_admins:
3137
raise HTTPException(status_code=403, detail="Access denied. Admin privileges required for admin portal")
3238

3339
try:

backend/app/seeds/runner.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,40 @@ def seed_database(verbose: bool = True) -> None:
4545
Args:
4646
verbose: Whether to print detailed output
4747
"""
48+
# Check environment to determine if we should seed test data
49+
env = os.getenv("ENV", "development").lower()
50+
is_production = env == "production"
51+
4852
if verbose:
4953
print("🌱 Starting database seeding...")
54+
if is_production:
55+
print("⚠️ Production mode: Skipping test data (Users, Ranking Preferences)")
56+
else:
57+
print(f"🔧 {env.capitalize()} mode: Including test data")
5058

5159
session = get_database_session()
5260

5361
try:
5462
# Run all seed functions in dependency order
63+
# Reference data - always seed these
5564
seed_functions = [
5665
("Roles", seed_roles),
5766
("Treatments", seed_treatments),
5867
("Experiences", seed_experiences),
5968
("Qualities", seed_qualities),
6069
("Forms", seed_forms),
61-
("Users", seed_users),
62-
("Ranking Preferences", seed_ranking_preferences),
6370
("Match Status", seed_match_status),
6471
]
6572

73+
# Test data - only seed in non-production environments
74+
if not is_production:
75+
seed_functions.extend(
76+
[
77+
("Users", seed_users),
78+
("Ranking Preferences", seed_ranking_preferences),
79+
]
80+
)
81+
6682
for name, seed_func in seed_functions:
6783
if verbose:
6884
print(f"\n📦 Seeding {name}...")

backend/app/server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import os
23
from contextlib import asynccontextmanager
34
from typing import Union
45

@@ -87,7 +88,7 @@ async def lifespan(_: FastAPI):
8788

8889
# Shutdown scheduler gracefully
8990
log.info("Shutting down scheduler...")
90-
scheduler.shutdown()
91+
scheduler.shutdown(wait=False) # Don't wait for running jobs to prevent interpreter shutdown race condition
9192

9293
# Dispose database engine to close all connection pools
9394
# This prevents async generator cleanup errors during shutdown
@@ -104,8 +105,7 @@ async def lifespan(_: FastAPI):
104105
app.add_middleware(
105106
CORSMiddleware,
106107
allow_origins=[
107-
"http://localhost:3000",
108-
"http://localhost:3002",
108+
os.getenv("FRONTEND_URL", "http://localhost:3000"),
109109
"https://uw-blueprint-starter-code.firebaseapp.com",
110110
"https://uw-blueprint-starter-code.web.app",
111111
# TODO: create a separate middleware function to dynamically

backend/app/services/implementations/auth_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def reset_password(self, email: str) -> None:
7979

8080
# Use Firebase Admin SDK to generate password reset link
8181
action_code_settings = firebase_admin.auth.ActionCodeSettings(
82-
url="http://localhost:3000/set-new-password",
82+
url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/set-new-password",
8383
handle_code_in_app=True,
8484
)
8585

@@ -152,7 +152,7 @@ def send_email_verification_link(self, email: str, language: str = None) -> None
152152

153153
# Use Firebase Admin SDK to generate email verification link
154154
action_code_settings = firebase_admin.auth.ActionCodeSettings(
155-
url="http://localhost:3000/action", # URL to redirect after verification
155+
url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/action", # URL to redirect after verification
156156
handle_code_in_app=True,
157157
)
158158

backend/app/services/implementations/match_service.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import os
23
from datetime import date, datetime, timedelta, timezone
34
from typing import List, Optional
45
from uuid import UUID
@@ -106,7 +107,7 @@ async def create_matches(self, req: MatchCreateRequest) -> MatchCreateResponse:
106107
language = volunteer.language.value if volunteer.language else "en"
107108

108109
first_name = volunteer.first_name if volunteer.first_name else None
109-
matches_url = "http://localhost:3000/volunteer/dashboard"
110+
matches_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard"
110111

111112
ses_service.send_matches_available_email(
112113
to_email=volunteer.email,
@@ -342,7 +343,7 @@ async def schedule_match(
342343
time=participant_time_str,
343344
timezone=participant_tz_abbr,
344345
first_name=participant.first_name,
345-
scheduled_calls_url="http://localhost:3000/participant/dashboard",
346+
scheduled_calls_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard",
346347
language=participant_language,
347348
)
348349

@@ -357,7 +358,7 @@ async def schedule_match(
357358
time=volunteer_time_str,
358359
timezone=volunteer_tz_abbr,
359360
first_name=volunteer.first_name,
360-
scheduled_calls_url="http://localhost:3000/volunteer/dashboard",
361+
scheduled_calls_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard",
361362
language=volunteer_language,
362363
)
363364

@@ -446,7 +447,7 @@ async def request_new_times(
446447
to_email=volunteer.email,
447448
participant_name=participant_name,
448449
first_name=volunteer.first_name,
449-
matches_url="http://localhost:3000/volunteer/dashboard",
450+
matches_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard",
450451
language=volunteer_language,
451452
)
452453
except Exception as e:
@@ -532,7 +533,7 @@ async def cancel_match_by_participant(
532533
time=volunteer_time_str,
533534
timezone=volunteer_tz_abbr,
534535
first_name=volunteer.first_name,
535-
dashboard_url="http://localhost:3000/volunteer/dashboard",
536+
dashboard_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard",
536537
language=volunteer_language,
537538
)
538539
except Exception as e:
@@ -623,7 +624,7 @@ async def cancel_match_by_volunteer(
623624
time=participant_time_str,
624625
timezone=participant_tz_abbr,
625626
first_name=participant.first_name,
626-
request_matches_url="http://localhost:3000/participant/dashboard",
627+
request_matches_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard",
627628
language=participant_language,
628629
)
629630
except Exception as e:
@@ -829,7 +830,7 @@ async def volunteer_accept_match(
829830
language = participant.language.value if participant.language else "en"
830831

831832
first_name = participant.first_name if participant.first_name else None
832-
matches_url = "http://localhost:3000/participant/dashboard"
833+
matches_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard"
833834

834835
ses_service = SESEmailService()
835836
ses_service.send_matches_available_email(

backend/app/utilities/ses_email_service.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def send_matches_available_email(
217217

218218
# Default to dashboard if no specific URL provided
219219
if not matches_url:
220-
matches_url = "http://localhost:3000/participant/dashboard"
220+
matches_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard"
221221

222222
template_data = {"first_name": first_name if first_name else "there", "matches_url": matches_url}
223223

@@ -260,7 +260,7 @@ def send_call_scheduled_email(
260260

261261
# Default to dashboard if no specific URL provided
262262
if not scheduled_calls_url:
263-
scheduled_calls_url = "http://localhost:3000/participant/dashboard"
263+
scheduled_calls_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard"
264264

265265
template_data = {
266266
"first_name": first_name if first_name else "there",
@@ -304,7 +304,7 @@ def send_participant_requested_new_times_email(
304304

305305
# Default to dashboard if no specific URL provided
306306
if not matches_url:
307-
matches_url = "http://localhost:3000/volunteer/dashboard"
307+
matches_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard"
308308

309309
template_data = {
310310
"first_name": first_name if first_name else "there",
@@ -351,7 +351,7 @@ def send_volunteer_accepted_new_times_email(
351351

352352
# Default to dashboard if no specific URL provided
353353
if not scheduled_calls_url:
354-
scheduled_calls_url = "http://localhost:3000/participant/dashboard"
354+
scheduled_calls_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard"
355355

356356
template_data = {
357357
"first_name": first_name if first_name else "there",
@@ -401,7 +401,7 @@ def send_participant_cancelled_email(
401401

402402
# Default to dashboard if no specific URL provided
403403
if not dashboard_url:
404-
dashboard_url = "http://localhost:3000/volunteer/dashboard"
404+
dashboard_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/volunteer/dashboard"
405405

406406
template_data = {
407407
"first_name": first_name if first_name else "there",
@@ -451,7 +451,7 @@ def send_volunteer_cancelled_email(
451451

452452
# Default to dashboard if no specific URL provided
453453
if not request_matches_url:
454-
request_matches_url = "http://localhost:3000/participant/dashboard"
454+
request_matches_url = f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/participant/dashboard"
455455

456456
template_data = {
457457
"first_name": first_name if first_name else "there",

frontend/.env.sample

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
POSTGRES_DATABASE=llsc
2+
POSTGRES_USER=postgres
3+
POSTGRES_PASSWORD=postgres
4+
POSTGRES_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/llsc
5+
6+
NEXT_PUBLIC_FIREBASE_WEB_API_KEY=
7+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
8+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
9+
NEXT_PUBLIC_FIREBASE_APP_ID=
10+
11+
REACT_APP_BACKEND_URL=http://localhost:8080

0 commit comments

Comments
 (0)