Skip to content

Conversation

@akshayutture-augment
Copy link

@akshayutture-augment akshayutture-augment commented Nov 14, 2025

Test 1


Replicated from ai-code-review-evaluation/grafana-cursor#1


Note

Adds a configurable anonymous device limit (auth.anonymous.device_limit), surfaces it to the frontend, and enforces it in the anonymous device store with a 30‑day window.

  • Backend:
    • Config: Read auth.anonymous.device_limit in setting.go; include AnonymousDeviceLimit in frontend settings DTOs and server response.
    • Anonymous Service Wiring: ProvideAnonymousDeviceService now constructs AnonDBStore with sqlStore and cfg.AnonymousDeviceLimit; API uses a shared 30‑day anonymousDeviceExpiration.
    • Auth Client: Authenticate now surfaces ErrDeviceLimitReached from device tagging; otherwise logs warning.
    • AnonDBStore:
      • Add deviceLimit, ErrDeviceLimitReached, and 30‑day expiration.
      • Enforce limit in CreateOrUpdateDevice (update-only when at limit) via new updateDevice method.
      • Change ProvideAnonDBStore(sqlStore, deviceLimit) signature; minor query/CRUD adjustments.
  • Frontend:
    • Types/Runtime: Add anonymousDeviceLimit to GrafanaConfig and default in runtime config.
  • Tests:
    • Update constructors to pass device limit; add coverage for limit enforcement (TestIntegrationBeyondDeviceLimit).

Written by Cursor Bugbot for commit 3647ba7. Configure here.

* Anonymous: Add device limiter

* break auth if limit reached

* fix typo

* refactored const to make it clearer with expiration

* anon device limit for config

---------

Co-authored-by: Eric Leijonmarck <[email protected]>
@akshayutture-augment
Copy link
Author

cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Early Cache Entry Creates False Success

The local cache is set before the database operation completes. If CreateOrUpdateDevice fails (e.g., with ErrDeviceLimitReached), the cache entry remains set, causing subsequent requests for the same device within 29 minutes to incorrectly return success without attempting the database operation, creating inconsistent behavior based on cache state.

pkg/services/anonymous/anonimpl/impl.go#L86-L94

a.localCache.SetDefault(key, struct{}{})
if setting.Env == setting.Dev {
a.log.Debug("Tagging device for UI", "deviceID", device.DeviceID, "device", device, "key", key)
}
if err := a.anonStore.CreateOrUpdateDevice(ctx, device); err != nil {
return err

Fix in Cursor Fix in Web



if count >= s.deviceLimit {
return s.updateDevice(ctx, device)
}
Copy link

Choose a reason for hiding this comment

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

Bug: Race Condition Bypasses Device Limit

Race condition in device limit enforcement: the check-then-act pattern between counting devices and inserting new ones allows multiple concurrent requests to bypass the limit. When the count is near the limit, concurrent requests can all pass the check and insert devices, exceeding the configured deviceLimit.

Fix in Cursor Fix in Web


args := []interface{}{device.ClientIP, device.UserAgent, device.UpdatedAt.UTC(), device.DeviceID,
device.UpdatedAt.UTC().Add(-anonymousDeviceExpiration), device.UpdatedAt.UTC().Add(time.Minute),
}
Copy link

Choose a reason for hiding this comment

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

Bug: Old Devices Cannot Update Due to Limit

The updateDevice function's WHERE clause restricts updates to devices modified within the last 30 days. When the device limit is reached, existing devices older than 30 days cannot be updated and incorrectly return ErrDeviceLimitReached, even though they should be updatable since they already exist in the database.

Fix in Cursor Fix in Web

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.

3 participants