Skip to content

[N3] firebase auth and update apis#5

Open
1jeanpaul1 wants to merge 16 commits into
devfrom
N3_JP
Open

[N3] firebase auth and update apis#5
1jeanpaul1 wants to merge 16 commits into
devfrom
N3_JP

Conversation

@1jeanpaul1

@1jeanpaul1 1jeanpaul1 commented Dec 13, 2025

Copy link
Copy Markdown
Collaborator

Description

  • Changes Authorization from cognito to firebase
  • Adds missing APIs
  • Adds API Docs
  • Adds Email and Push Notification flow
  • When User is in User Service, Notification are also deleted - triggered by event bridge

API Docs: https://fridgefinder.github.io/CFM_Notification/

API

Base URLs:

  • Dev: https://notifications-api-dev.communityfridgefinder.com
  • Staging: https://notifications-api-staging.communityfridgefinder.com
  • Prod: https://notifications-api-prod.communityfridgefinder.com

Authentication: 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 identifier

Success 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 identifier

Request 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 identifier

Request 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-notifications

Retrieve 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 identifier

Success Response (204):

No content (empty response body)

Error Responses

All errors follow a standardized format with an error object containing a code and message.

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

foodLevel2: bool
foodLevel3: bool

class ContactTypePreferencesModel(BaseModel):

@1jeanpaul1 1jeanpaul1 Dec 13, 2025

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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

IMG_1912

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)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot 2026-02-06 at 3 13 56 PM

Preliminary design

Authorizers:
FirebaseAuthorizer:
JwtConfiguration:
issuer: !Sub "https://securetoken.google.com/${FirebaseProjectId}"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

firebase auth

## DynamoDB Tables ##
##########################

UserFridgeNotificationsTable:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Hash/PrimaryKey: userId
Range: fridgeId

@1jeanpaul1 1jeanpaul1 changed the title [N3] add firebase auth and update apis and add docs [N3] firebase auth and update apis Dec 13, 2025
Unsubscribe: {base_url}/unsubscribe?token=eyJhbGciOiJ
"""

ses.send_email(

@1jeanpaul1 1jeanpaul1 Jan 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot 2026-01-24 at 5 33 21 AM

Email Notification Preview
TODO: Add Mobile App links once launched on app stores

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

TODO: add app links
Screenshot 2026-01-25 at 2 02 01 AM

token=fcm_token,
)

response = messaging.send(message)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot 2026-01-24 at 3 42 39 AM

Tested on firebase web fcmtoken

TODO: confirm messagin

Comment thread docs/openapi.yaml

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewer: Confirm fields and structure

@mansoorsiddiqui mansoorsiddiqui 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.

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_EXISTS here vs USER_NOT_FOUND, USER_ALREADY_EXISTS in the user service. Should we align?

Comment thread user-fridge-notification-service/functions/fridge_notifications/user/app.py Outdated
logger.setLevel(logging.INFO)

# Initialize Firebase when module is loaded
initialize_firebase()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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?

Comment thread user-fridge-notification-service/functions/fridge_notifications/user/app.py Outdated
push:
branches:
- main
- N3_JP

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Same as the user service PR — N3_JP branch is still in the trigger list. Remove before merging.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes will remove before merging

@1jeanpaul1

Copy link
Copy Markdown
Collaborator Author

@mansoorsiddiqui

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.

  • Yes, the plan it to make it an API call. I think we have enough time now so I'll implement

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.

  • Yes sorry should've left a comment, was waiting on review before adding tests. I'll add them now, thank you :)

Error codes use NOT_FOUND, ALREADY_EXISTS here vs USER_NOT_FOUND, USER_ALREADY_EXISTS in the user service. Should we align?

  • Yes, thank you for catching :)

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.

2 participants