Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/api_keys/models/api_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,17 @@ def within_key_type_limit
# Use pessimistic locking to prevent race conditions.
# Lock the owner's existing keys of this type/environment while counting.
# This ensures atomic check-then-create semantics.
# Note: .lock(true) generates "FOR UPDATE" in SQL but is the Rails-idiomatic approach.
#
# Note: We use .ids.size instead of .count because PostgreSQL doesn't allow
# FOR UPDATE with aggregate functions (COUNT). By selecting IDs with the
# lock and counting in Ruby, we achieve the same race condition protection.
existing_count = owner.api_keys
.lock(true)
.active
.where(key_type: key_type.to_s)
.where(environment: environment.to_s)
.count
.lock(true)
.ids
.size

if existing_count >= limit
errors.add(:base, "Maximum number of #{key_type} keys (#{limit}) reached for #{environment} environment")
Expand Down