Skip to content

feat: implement device registration, admin-secured management, and rate limiting for push notifications - #6

Merged
Euler-B merged 1 commit into
mainfrom
feature/device-notifications-api
Aug 6, 2026
Merged

feat: implement device registration, admin-secured management, and rate limiting for push notifications#6
Euler-B merged 1 commit into
mainfrom
feature/device-notifications-api

Conversation

@Euler-B

@Euler-B Euler-B commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added web device registration using FCM tokens.
    • Added authenticated endpoints to list and delete registered devices.
    • Prevented duplicate registrations and restricted devices to the web platform.
    • Added administrative token authentication for device management.
    • Added rate limiting of five registration requests per minute per IP.
    • Enabled DELETE requests for device management endpoints.
  • Documentation

    • Documented device registration, management, authentication, responses, and rate limits.
    • Added the administrative token configuration placeholder.

@Euler-B Euler-B self-assigned this Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4689f107-1be6-4b9f-b2d1-6fcfdfc70a5b

📥 Commits

Reviewing files that changed from the base of the PR and between ee003ad and 6c1c422.

⛔ Files ignored due to path filters (1)
  • db/schema.rb is excluded by !db/schema.rb
📒 Files selected for processing (12)
  • .env.example
  • README.md
  • app/controllers/application_controller.rb
  • app/controllers/devices_controller.rb
  • app/models/device.rb
  • config/initializers/cors.rb
  • config/initializers/rack_attack.rb
  • config/routes.rb
  • db/migrate/20260805000000_create_devices.rb
  • test/controllers/devices_controller_test.rb
  • test/integration/rate_limiting_test.rb
  • test/models/device_test.rb

Walkthrough

The change adds a Device model and table, device registration and administration endpoints, admin-token authentication, CORS support for deletion, per-IP registration throttling, tests, documentation, and an ADMIN_TOKEN environment variable.

Changes

Device API

Layer / File(s) Summary
Device persistence contract
db/migrate/..., app/models/device.rb, test/models/device_test.rb
Adds the devices table and the Device model. FCM tokens are required, unique, whitespace-free, and limited to 255 characters. The platform defaults to and accepts web.
Device endpoints and admin access
app/controllers/application_controller.rb, app/controllers/devices_controller.rb, config/routes.rb, config/initializers/cors.rb, .env.example, test/controllers/devices_controller_test.rb, README.md
Adds device creation, listing, and deletion endpoints. Listing and deletion require ADMIN_TOKEN. Creation supports FCM-token upsert behavior, validation errors, and uniqueness-race recovery. CORS preflight requests allow DELETE.
Device registration throttling
config/initializers/rack_attack.rb, test/integration/rate_limiting_test.rb, README.md
Limits POST /v1/devices to five requests per minute per IP and tests that the sixth request returns HTTP 429.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RackAttack
  participant DevicesController
  participant Device
  participant DevicesDatabase
  Client->>RackAttack: POST /v1/devices
  alt within five requests per minute
    RackAttack->>DevicesController: allow request
    DevicesController->>Device: find or initialize by fcm_token
    Device->>DevicesDatabase: validate and save
    DevicesDatabase-->>DevicesController: device record
    DevicesController-->>Client: JSON response
  else sixth request
    RackAttack-->>Client: HTTP 429
  end
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes device registration, admin-secured management, and rate limiting added by the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/device-notifications-api

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/controllers/application_controller.rb`:
- Around line 4-11: Update authenticate_admin! so every unauthorized branch
renders a JSON response containing the error message "Unauthorized" with status
:unauthorized instead of calling head :unauthorized. Preserve the existing token
presence, byte-length, and secure comparison checks, and leave successful
authentication returning normally.

In `@app/controllers/devices_controller.rb`:
- Around line 4-6: Update DevicesController#index to paginate the ordered Device
relation with will_paginate before calling pluck, using the requested page and a
per-page value defaulting to 100 and capped at 1000. Add the corresponding
constants and private device_per_page helper, and include current_page,
total_entries, and per_page in the response pagination metadata.
- Around line 4-6: Update the DevicesController#index action to call no_store
before rendering the FCM token response, ensuring GET /v1/devices is not cached
while preserving the existing query and JSON structure.
- Around line 8-17: Update the create action in DevicesController to rescue
ActiveRecord::RecordNotUnique from concurrent device saves, reload the existing
device by device_params[:fcm_token], and return its id/type payload with HTTP
200; preserve the current created, successful update, and validation-error
responses.

In `@app/models/device.rb`:
- Around line 2-3: Define a service-specific maximum token length in the Device
model and add a maximum-length validation alongside presence and uniqueness
without restricting token characters or whitespace. In
db/migrate/20260805000000_create_devices.rb, enforce the same limit on the
fcm_token database column. In test/models/device_test.rb, add coverage
confirming a token exceeding the limit is invalid.

In `@test/models/device_test.rb`:
- Around line 4-22: Extend the Device model tests with a case covering invalid
FCM tokens: reject tokens containing whitespace, control characters such as
newlines, and values exceeding the database limit. Add these inputs to
test/models/device_test.rb alongside the existing fcm_token uniqueness coverage
and assert each new Device is invalid.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f25ae498-ec0a-4485-8c01-9e7c23bb0a92

📥 Commits

Reviewing files that changed from the base of the PR and between ee003ad and e3d839d.

⛔ Files ignored due to path filters (1)
  • db/schema.rb is excluded by !db/schema.rb
📒 Files selected for processing (11)
  • .env.example
  • README.md
  • app/controllers/application_controller.rb
  • app/controllers/devices_controller.rb
  • app/models/device.rb
  • config/initializers/rack_attack.rb
  • config/routes.rb
  • db/migrate/20260805000000_create_devices.rb
  • test/controllers/devices_controller_test.rb
  • test/integration/rate_limiting_test.rb
  • test/models/device_test.rb

Comment thread app/controllers/application_controller.rb Outdated
Comment thread app/controllers/devices_controller.rb
Comment thread app/controllers/devices_controller.rb
Comment thread app/models/device.rb Outdated
Comment thread test/models/device_test.rb
@Euler-B
Euler-B force-pushed the feature/device-notifications-api branch from e3d839d to 38dc75f Compare August 6, 2026 03:58
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/routes.rb`:
- Line 7: Add DELETE to the CORS configuration for the /v1/* resource while
leaving ALLOWED_ORIGIN unchanged, so the existing devices destroy route supports
browser preflight requests.

In `@db/migrate/20260805000000_create_devices.rb`:
- Around line 5-9: Add the requested check constraint in the migration alongside
the existing devices index, using the devices_platform_is_web name and
restricting platform to web. Keep the existing column definition and index
unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 27c0de70-131e-489f-adcb-f5cae3e3513a

📥 Commits

Reviewing files that changed from the base of the PR and between ee003ad and 38dc75f.

⛔ Files ignored due to path filters (1)
  • db/schema.rb is excluded by !db/schema.rb
📒 Files selected for processing (11)
  • .env.example
  • README.md
  • app/controllers/application_controller.rb
  • app/controllers/devices_controller.rb
  • app/models/device.rb
  • config/initializers/rack_attack.rb
  • config/routes.rb
  • db/migrate/20260805000000_create_devices.rb
  • test/controllers/devices_controller_test.rb
  • test/integration/rate_limiting_test.rb
  • test/models/device_test.rb

Comment thread config/routes.rb
Comment thread db/migrate/20260805000000_create_devices.rb
@Euler-B
Euler-B force-pushed the feature/device-notifications-api branch from 38dc75f to 6c1c422 Compare August 6, 2026 04:08
@Euler-B
Euler-B merged commit 894c928 into main Aug 6, 2026
1 check passed
@Euler-B
Euler-B deleted the feature/device-notifications-api branch August 6, 2026 04:09
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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.

1 participant