diff --git a/.vscode/launch.json b/.vscode/launch.json index d914b0d..4a48d93 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,11 +20,9 @@ "type": "debugpy", "request": "launch", "module": "uvicorn", - // --reload seems to cause issues with browser-use "args": ["podium.main:app", "--reload"], - // "args": ["podium.main:app"], "env": { - "ENV_FOR_DYNACONF": "development" + "PYTHON_ENV": "development" }, "cwd": "${workspaceFolder}/backend", "justMyCode": true diff --git a/backend/docker-compose.yaml b/backend/docker-compose.yaml index b14d661..f9c49ae 100644 --- a/backend/docker-compose.yaml +++ b/backend/docker-compose.yaml @@ -1,11 +1,11 @@ -version: '3.8' +version: "3.8" services: podium: container_name: podium build: . - # ports: - # - "8000:8000" + ports: + - "8000:8000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/docs"] interval: 30s @@ -15,5 +15,4 @@ services: volumes: - ./settings.toml:/app/settings.toml:ro - ./.secrets.toml:/app/.secrets.toml:ro - -# docker run --rm -it -v "$(pwd)/settings.toml:/app/settings.toml:ro" -v "$(pwd)/.secrets.toml:/app/.secrets.toml:ro" -p 8000:8000 podium \ No newline at end of file +# docker run --rm -it -v "$(pwd)/settings.toml:/app/settings.toml:ro" -v "$(pwd)/.secrets.toml:/app/.secrets.toml:ro" -p 8000:8000 podium diff --git a/backend/podium/__init__.py b/backend/podium/__init__.py index d5df040..6cc3c61 100644 --- a/backend/podium/__init__.py +++ b/backend/podium/__init__.py @@ -1 +1 @@ -from podium.config import settings as settings +from podium.config import settings as settings, environment as environment \ No newline at end of file diff --git a/backend/podium/config.py b/backend/podium/config.py index 58c8bf0..696e78d 100644 --- a/backend/podium/config.py +++ b/backend/podium/config.py @@ -5,7 +5,9 @@ # type: ignore -print(f"Using environment: {os.getenv('ENV_FOR_DYNACONF', '')}") +environment = os.getenv("PYTHON_ENV", "development") +print(f"Using environment: {environment}") + settings = Dynaconf( envvar_prefix="PODIUM", load_dotenv=True, diff --git a/backend/podium/db/migration.py b/backend/podium/db/migration.py index 504fd29..c49b274 100644 --- a/backend/podium/db/migration.py +++ b/backend/podium/db/migration.py @@ -1,5 +1,5 @@ # python -m podium.db.migration | Tee-Object -FilePath migration.txt -# $env:ENV_FOR_DYNACONF="production" +# $env:PYTHON_ENV="production" # $env:PYTHONIOENCODING="utf-8" from podium.db import users from podium.db.user import UserPrivate, UserSignupPayload diff --git a/backend/podium/main.py b/backend/podium/main.py index a1e47f6..facbfe8 100644 --- a/backend/podium/main.py +++ b/backend/podium/main.py @@ -1,5 +1,4 @@ import importlib -import os from pathlib import Path import uvicorn from fastapi import FastAPI @@ -9,11 +8,11 @@ from contextlib import asynccontextmanager from typing import AsyncIterator import sentry_sdk - +from podium.config import environment sentry_sdk.init( dsn="" - if os.getenv("ENV_FOR_DYNACONF") == "development" + if environment == "development" else "https://489f4a109d07aeadfd13387bcd3197ab@o4508979744210944.ingest.de.sentry.io/4508979747553360", # Add data like request headers and IP for users, # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info diff --git a/backend/podium/routers/auth.py b/backend/podium/routers/auth.py index 25d147e..8ddbeb4 100644 --- a/backend/podium/routers/auth.py +++ b/backend/podium/routers/auth.py @@ -1,10 +1,9 @@ from datetime import datetime, timedelta, timezone - # import smtplib # from email.mime.text import MIMEText from typing import Annotated -from podium import db, settings +from podium import db, settings, environment from fastapi import APIRouter, HTTPException, Query, Depends from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials @@ -23,7 +22,7 @@ ALGORITHM = str(settings.jwt_algorithm) ACCESS_TOKEN_EXPIRE_MINUTES: int = settings.jwt_expire_minutes # type: ignore MAGIC_LINK_EXPIRE_MINUTES = 15 - +magic_urls = [] DEBUG_EMAIL = "angad+debug@hackclub.com" @@ -48,6 +47,9 @@ def create_access_token( encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt +def get_mail(): + """ kinda like /letter_box but in python or smt.""" + return magic_urls async def send_magic_link(email: str, redirect: str = ""): token_data = {"sub": email} @@ -58,7 +60,8 @@ async def send_magic_link(email: str, redirect: str = ""): magic_link = f"{settings.production_url}/login?token={token}" if redirect: magic_link += f"&redirect={redirect}" - + if environment == "development": + magic_urls.append(MagicLink(email=email, magic_link=magic_link)) if settings.sendgrid_api_key: message = Mail( from_email=settings.sendgrid_from_email, @@ -81,6 +84,13 @@ async def send_magic_link(email: str, redirect: str = ""): ) +@router.get("/letter_box") +async def letter_box(): + """ + This is a temporary endpoint to get the magic links that have been sent. + """ + return get_mail() + @router.post("/request-login") # https://fastapi.tiangolo.com/tutorial/query-param-models/ async def request_login(user: UserLoginPayload, redirect: Annotated[str, Query()]): @@ -297,4 +307,4 @@ def magic_link_email_content(magic_link: str) -> dict: - Hack Club` """ - return {"html": html, "text": text} + return {"html": html, "text": text} \ No newline at end of file diff --git a/frontend/.env.development b/frontend/.env.development new file mode 100644 index 0000000..7f13e1b --- /dev/null +++ b/frontend/.env.development @@ -0,0 +1 @@ +PUBLIC_API_URL=http://localhost:8000 \ No newline at end of file diff --git a/frontend/src/lib/components/Admin/Button.svelte b/frontend/src/lib/components/Admin/Button.svelte new file mode 100644 index 0000000..b943c42 --- /dev/null +++ b/frontend/src/lib/components/Admin/Button.svelte @@ -0,0 +1,8 @@ + + + diff --git a/frontend/src/lib/components/CreateEvent.svelte b/frontend/src/lib/components/CreateEvent.svelte index 5c3aed7..2388667 100644 --- a/frontend/src/lib/components/CreateEvent.svelte +++ b/frontend/src/lib/components/CreateEvent.svelte @@ -23,6 +23,7 @@ // Clear the form eventName = ""; eventDescription = ""; + await goto('/events'); } diff --git a/frontend/src/lib/misc.ts b/frontend/src/lib/misc.ts index 0b933be..d9a2bdf 100644 --- a/frontend/src/lib/misc.ts +++ b/frontend/src/lib/misc.ts @@ -12,7 +12,7 @@ export function handleError( error: HTTPValidationError | ErrorWithDetail | Error | unknown, ) { // If it's a FastAPI HTTPException, it will have a detail field. Same with validation errors. - console.error("Error", error) + console.error("Error", error); if (error && typeof error === "object" && "detail" in error) { if (Array.isArray(error?.detail)) { // const invalidFields = error.detail.map((e) => e.msg); @@ -72,3 +72,62 @@ export async function customInvalidateAll() { await invalidateAll(); await invalidateUser(); } + +function randomFromArray(arr: T[]): T { + return arr[Math.floor(Math.random() * arr.length)]; +} + +function randomInt(min: number, max: number) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function randomId(length = 12) { + return [...Array(length)].map(() => Math.random().toString(36)[2]).join(""); +} + +export function generateUser() { + const firstNames = ["Alice", "Bob", "Charlie", "Dana", "Elliot", "Fiona"]; + const lastNames = ["Smith", "Johnson", "Lee", "Garcia", "Brown", "Taylor"]; + const streets = ["Main St", "Oak Ave", "Pine Rd", "Maple Blvd"]; + const cities = ["New York", "Los Angeles", "Chicago", "Seattle"]; + const states = ["NY", "CA", "IL", "WA"]; + const countries = ["USA", "Canada"]; + + const first_name = randomFromArray(firstNames); + const last_name = randomFromArray(lastNames); + const email = `${first_name.toLowerCase()}.${last_name.toLowerCase()}@example.com`; + const phone = `+1${randomInt(2000000000, 9999999999)}`; + + const street_1 = `${randomInt(100, 9999)} ${randomFromArray(streets)}`; + const street_2 = Math.random() < 0.5 ? `Apt ${randomInt(1, 999)}` : null; + const city = randomFromArray(cities); + const state = randomFromArray(states); + const zip_code = `${randomInt(10000, 99999)}`; + const country = randomFromArray(countries); + + const year = randomInt(2008, 2020); + const month = String(randomInt(1, 12)).padStart(2, "0"); + const day = String(randomInt(1, 28)).padStart(2, "0"); + const dob = `${year}-${month}-${day}`; + + return { + first_name, + last_name, + email, + phone, + street_1, + street_2, + city, + state, + zip_code, + country, + dob, + id: randomId(), + votes: [], + projects: [], + collaborations: [], + owned_events: [], + attending_events: [], + referral: [], + }; +} diff --git a/frontend/src/routes/letter_box/+page.svelte b/frontend/src/routes/letter_box/+page.svelte new file mode 100644 index 0000000..b3a2db8 --- /dev/null +++ b/frontend/src/routes/letter_box/+page.svelte @@ -0,0 +1,48 @@ + + +
+
+
+

Letter box

+ +
+ {#if data && data.length === 0} +

No letters found.

+ {:else} +
    + {#each data as letter} +
  • + {letter[0]}: + {#let url = new URL(letter[1])} + {letter[1]} +
  • + {/each} +
+ {/if} +
+
+
diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index bddc633..b6e3b09 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -1,22 +1,23 @@