Skip to content

Notice Board Michael Krueger Group 3 - #129

Merged
kchandan merged 10 commits into
becloudready:masterfrom
MichaelRSK:master
Aug 18, 2026
Merged

Notice Board Michael Krueger Group 3#129
kchandan merged 10 commits into
becloudready:masterfrom
MichaelRSK:master

Conversation

@MichaelRSK

Copy link
Copy Markdown

Notice Board submission for the Full-Stack AWS 10-Aug-2026 cohort, Group 3.

Tiers 1-3 complete. Backend: FastAPI (models/services/controllers), Supabase
(Postgres), JWT authentication, ownership-based delete. Frontend: React +
Material-UI, protected routes, login/signup. USP feature: reactions (like/heart/
laugh) on notices, independently toggleable per user.

Deployment: backend on EC2 (systemd + nginx + Let's Encrypt HTTPS), frontend on
S3 + CloudFront (HTTPS). Backend redeploy is automated via a GitHub Actions
SSH-based workflow. Frontend deploy is currently manual (build, S3 upload,
CloudFront invalidation) due to this quicklab account's IAM restrictions blocking
all programmatic AWS credential creation (no IAM user/role/access-key creation is
possible); this is documented in the README and has been raised with the course
admin.

Postman collection included covering the full auth + notice + reaction flow,
including negative cases (401/403/404/422).

- Implemented FastAPI application with CORS middleware
- Created models for notice data handling
- Developed services for CRUD operations on notices
- Established database schema for Supabase with row-level security
- Added requirements for necessary dependencies
- Included .gitignore to manage environment files
Moved Notice Board deliverables from the shared Group3 folder into
projects/submission/michael-krueger/, per the individual submission
format required by the assignment.

Group folder was used for early development; submission path is now
correct per Chandan's issued assignment spec.
Moved Notice Board deliverables from the shared Group3 folder into
projects/submission/michael-krueger/, per the individual submission
format required by the assignment (each student submits their own
folder, PR contains only that folder, peer review required before merge).

Group folder was used for early development; submission path is now
correct per Chandan's issued assignment spec.
- Add UserCreate, UserLogin, UserOut, and TokenResponse models in user.py for request and response validation.
- Create auth_service.py to handle user signup, login, password hashing, and JWT token management.
- Implement API calls for signup and login in auth.js, including error handling for responses.
- Set up Axios client in client.js to manage API requests and handle token storage.
- Create ProtectedRoute component to guard routes that require authentication.
- Develop AuthContext to manage authentication state and provide login, signup, and logout functionalities.
- Build LoginPage and SignupPage components for user interaction with forms and error handling.
- Create NoticeBoardPage to display notices and handle refresh logic.
- Add utility functions in decodeToken.js to decode JWT and extract user information.
- Implemented reaction functionality for notices, allowing users to toggle reactions (like, heart, laugh).
- Created a new `reaction_controller` to handle reaction-related API endpoints.
- Added `reaction_service` to manage interactions with the `notice_reactions` table.
- Updated `NoticeOut` model to include a `reactions` field for displaying reaction summaries.
- Introduced `ReactionBar` component to render reaction buttons and counts for each notice.
- Enhanced `list_notices` service to fetch and attach reaction summaries to notices.
- Updated SQL schema to include `notice_reactions` table with necessary constraints and permissions.
- Refactored authentication dependencies to streamline user verification for reaction actions.

@QaysMukaddam QaysMukaddam left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really solid submission, Michael. A few things that stood out:

  • Clean separation in the backend (models/services/controllers) — makes the FastAPI + Supabase integration easy to follow, especially the JWT auth and ownership-based delete logic.

  • Nice touch on the reactions feature, going beyond a single "like" to like/heart/laugh, and having each one independently toggleable per user, is a thoughtful extension of the base requirements.

  • The Postman collection covering negative cases (401/403/404) is a good sign you actually tested authorization boundaries, not just the happy path.

Approved.

@oali1029 oali1029 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this project. I reviewed both the frontend and backend implementation, and everything is well organized and easy to follow. I especially liked the authentication, validation, and protected route handling. Everything looks good to me!

created = notice_service.create_notice(
client,
notice,
user_id=current_user.user_id,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of the authenticated user's ID here instead of accepting a user ID from the request. This makes sure users can't create notices under another account.

# message deliberately does not say which. Telling a caller that a
# username exists lets them work through a list of usernames before they
# start guessing passwords.
if token is None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that the same error message is returned for an incorrect username or password. This avoids revealing whether a specific username exists.

# This must stay in step with the CHECK constraint on
# notice_reactions.reaction_type. The database is the final word: a value
# that got past this would still be refused there.
ReactionType = Literal["like", "heart", "laugh"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of Literal here to restrict reactions to the supported values before they reach the service layer.

const { isAuthenticated } = useAuth();
const location = useLocation();

if (!isAuthenticated) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of a protected route here. I also like that the original location is saved so the user can be redirected back after logging in.

# on the signup route is what guarantees the hash cannot leak, because
# FastAPI filters the outgoing row down to exactly these two fields even
# though the service returns the whole database row.
class UserOut(BaseModel):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good choice keeping the password hash out of the response model. This ensures sensitive authentication data is never accidentally returned to the client.

@kchandan
kchandan merged commit 9cae62b into becloudready:master Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants