[N3] firebase auth and update apis#5
Conversation
| foodLevel2: bool | ||
| foodLevel3: bool | ||
|
|
||
| class ContactTypePreferencesModel(BaseModel): |
There was a problem hiding this comment.
I think notifications could be laid out something like this in the future on web and mobile
on web:
if user clicks on phone -> redirects them to download mobile app
if user clicks on email -> updates user preference
note: The only notification that I can think of that would be email specific: Weekly/Monthly Digest which emails the user monthly stats about the fridge (not included yet)
| Authorizers: | ||
| FirebaseAuthorizer: | ||
| JwtConfiguration: | ||
| issuer: !Sub "https://securetoken.google.com/${FirebaseProjectId}" |
| ## DynamoDB Tables ## | ||
| ########################## | ||
|
|
||
| UserFridgeNotificationsTable: |
There was a problem hiding this comment.
Hash/PrimaryKey: userId
Range: fridgeId
| Unsubscribe: {base_url}/unsubscribe?token=eyJhbGciOiJ | ||
| """ | ||
|
|
||
| ses.send_email( |
| token=fcm_token, | ||
| ) | ||
|
|
||
| response = messaging.send(message) |
There was a problem hiding this comment.
API Docs: https://fridgefinder.github.io/CFM_Notification/
TODO: Review and Approve by others
| email: Optional[FridgePreferencesModel] = None | ||
| device: Optional[FridgePreferencesModel] = None | ||
|
|
||
| class UserFridgeNotificationModel(BaseModel): |
There was a problem hiding this comment.
Reviewer: Confirm fields and structure
mansoorsiddiqui
left a comment
There was a problem hiding this comment.
Good progress on the restructure. Left a few comments inline — the bigger picture stuff is around cross-service coupling and making sure we have a path to decouple the direct DB reads.
Cross-service concerns:
- The stream processor reads directly from the user table — schema changes in the user service could silently break notifications. I know there's a note about making this an API call — just want to make sure we're tracking it.
- Old tests were deleted but no new tests added. The new code has non-trivial logic (preference merging, condition mapping, stream processing) — are we planning to add tests in a follow-up? Would feel a lot more comfortable merging if at least the model and service layer had coverage.
- Error codes use
NOT_FOUND,ALREADY_EXISTShere vsUSER_NOT_FOUND,USER_ALREADY_EXISTSin the user service. Should we align?
| logger.setLevel(logging.INFO) | ||
|
|
||
| # Initialize Firebase when module is loaded | ||
| initialize_firebase() |
There was a problem hiding this comment.
initialize_firebase() runs at module load time. If this fails (bad credentials, network blip during cold start), the entire Lambda container is toast — every invocation will fail until AWS recycles it. Can we wrap this in a try/except, or do lazy init on first invocation?
There was a problem hiding this comment.
if this fails the lambda will do periodic retries until successful or 24 hours go by, though maybe I should decrease that time.
are you suggesting to silently fail if firebase doesn't initialize? So that emails go through at least?
| push: | ||
| branches: | ||
| - main | ||
| - N3_JP |
There was a problem hiding this comment.
Same as the user service PR — N3_JP branch is still in the trigger list. Remove before merging.
There was a problem hiding this comment.
yes will remove before merging
|
The stream processor reads directly from the user table — schema changes in the user service could silently break notifications. I know there's a note about making this an API call — just want to make sure we're tracking it.
Old tests were deleted but no new tests added. The new code has non-trivial logic (preference merging, condition mapping, stream processing) — are we planning to add tests in a follow-up? Would feel a lot more comfortable merging if at least the model and service layer had coverage.
Error codes use NOT_FOUND, ALREADY_EXISTS here vs USER_NOT_FOUND, USER_ALREADY_EXISTS in the user service. Should we align?
|




Description
API Docs: https://fridgefinder.github.io/CFM_Notification/
API
Base URLs:
https://notifications-api-dev.communityfridgefinder.comhttps://notifications-api-staging.communityfridgefinder.comhttps://notifications-api-prod.communityfridgefinder.comAuthentication: All endpoints (except health check) require Firebase JWT token in
Authorization: Bearer <token>header.Endpoints
Get Notification for Specific Fridge
GET /v1/users/{user_id}/fridge-notifications/{fridge_id}Retrieve notification preferences for a specific fridge.
Path Parameters:
user_id(string, required) - Firebase User ID (must match authenticated user)fridge_id(string, required) - Unique fridge identifierSuccess Response (200):
{ "userId": "abc123xyz456def789", "fridgeId": "fridge_123abc", "contactTypePreferences": { "email": { "good": true, ... } }, "createdAt": "2025-12-13T10:30:45.123Z", "updatedAt": "2025-12-13T15:20:30.456Z" }Create Notification Preferences
POST /v1/users/{user_id}/fridge-notifications/{fridge_id}Create new notification preferences for a fridge.
Path Parameters:
user_id(string, required) - Firebase User ID (must match authenticated user)fridge_id(string, required) - Unique fridge identifierRequest Body:
{ "contactTypePreferences": { "email": { "good": true, ... }, "device": { "good": false, ... } } }Success Response (201):
{ "userId": "abc123xyz456def789", "fridgeId": "fridge_123abc", "contactTypePreferences": { "email": { "good": true, ... }, "device": { "good": false, ... } }, "createdAt": "2025-12-13T10:30:45.123Z", "updatedAt": "2025-12-13T10:30:45.123Z" }Update Notification Preferences
PATCH /v1/users/{user_id}/fridge-notifications/{fridge_id}Update existing notification preferences for a fridge.
Path Parameters:
user_id(string, required) - Firebase User ID (must match authenticated user)fridge_id(string, required) - Unique fridge identifierRequest Body:
{ "contactTypePreferences": { "email": { "good": false, ... }, "device": { "good": true, ... } } }Success Response (200):
{ "userId": "abc123xyz456def789", "fridgeId": "fridge_123abc", "contactTypePreferences": { "email": { "good": false, ... }, "device": { "good": true, ... } }, "createdAt": "2025-12-13T10:30:45.123Z", "updatedAt": "2025-12-13T16:45:22.789Z" }Get All User Notifications
GET /v1/users/{user_id}/fridge-notificationsRetrieve all notification preferences for a user.
Path Parameters:
user_id(string, required) - Firebase User ID (must match authenticated user)Success Response (200):
{ "data": [ { "userId": "abc123xyz456def789", "fridgeId": "fridge_123abc", "contactTypePreferences": { "email": { "good": true, "dirty": true, "outOfOrder": true, "notAtLocation": false, "ghost": false, "foodLevel0": true, "foodLevel1": false, "foodLevel2": false, "foodLevel3": false }, "device": { "good": false, ... } }, "createdAt": "2025-12-13T10:30:45.123Z", "updatedAt": "2025-12-13T15:20:30.456Z" } ], "count": 1 }Delete Notification Preferences
DELETE /v1/users/{user_id}/fridge-notifications/{fridge_id}Remove notification preferences for a specific fridge.
Path Parameters:
user_id(string, required) - Firebase User ID (must match authenticated user)fridge_id(string, required) - Unique fridge identifierSuccess Response (204):
Error Responses
All errors follow a standardized format with an
errorobject containing acodeandmessage.Error Response Structure
{ "error": { "code": "ERROR_CODE", "message": "Human-readable error message" } }Error Examples
400 Bad Request - Validation Error
{ "error": { "code": "VALIDATION_ERROR", "message": "Input validation failed" } }404 Not Found
{ "error": { "code": "NOT_FOUND", "message": "Notification preference not found" } }409 Conflict
{ "error": { "code": "ALREADY_EXISTS", "message": "Notification preference already exists for this user and fridge" } }500 Internal Server Error
{ "error": { "code": "INTERNAL_SERVER_ERROR", "message": "An unexpected error occurred" } }401 Unauthorized
{ "message": "Unauthorized" }401 errors are returned from API Gateway if JWT token is not valid