organizations 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3074b8343b80c07b277e1038a0181981274d1baaa7a52af85dd425edf09c5d3
4
- data.tar.gz: 8529247495ba8c215216cf4acea19e7764b3e20ac16d997a1ca3b1ecc49f86d7
3
+ metadata.gz: bd2f1f7295aa0ba982150d0f5917b5ad002b9115fabd0bb4b645e8c5d5c68f15
4
+ data.tar.gz: 6821a5a24efe57ef744118ea038f75fc04c703e5528bb3170ffa81536738a3f6
5
5
  SHA512:
6
- metadata.gz: cb91ccb8891c4a17c65a85698c13c15931505c3d32688bc075402fdc8582dbd0ecaf2a6a0e581696f471991cd23344998563f340206855c9532352da22086fc7
7
- data.tar.gz: 1e15480d1f104e0fddea00dd2509223a7b43707e9eccd8930461c24928c3c81338387ba6e95e6b093058ee1bed2741c15b8c2ba919d8ba2449cdd98388f54a62
6
+ metadata.gz: 376ad9c58f8888e9120f9232836b633ce847e1fb900dca2f1968b6052881eaa05039c3e606ad1a346e37ec5823b7c77dd2d70a5fe68f653de7c89b11b27e232e
7
+ data.tar.gz: 451933a3d39140138e7690c071c9d9becfa6b57fd79aded5bc6ec8eae88f4b7d37b3e718d10afd9709e68ed3ffb8a4037d313807f92f3f98d92f263b29132db1
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- ## [Unreleased]
1
+ ## [0.9.1] - 2026-11-09
2
+
3
+ ### Fixed
4
+
5
+ - `max_organizations` holds under concurrency. `create_organization!` counted the user's owned organizations before its transaction, so two creates at the same moment could both count below the limit and both insert, and a host that sells organization slots gave away an extra one. When the limit is set, the count now runs inside the transaction under a lock on the user's row (the gem's lock order: the user row first), so the second create waits and then raises `OrganizationLimitReached`. That count skips the query cache, so a count read earlier in the same request cannot stand in for it. Without a limit nothing changes and nothing is locked.
2
6
 
3
7
  ## [0.9.0] - 2026-10-25
4
8
 
@@ -488,15 +488,12 @@ module Organizations
488
488
  attributes = name_or_attributes.is_a?(Hash) ? name_or_attributes : { name: name_or_attributes }
489
489
  Organizations::Organization.ensure_personal_owner_is_owner!(attributes, self)
490
490
 
491
- # Check max organizations limit
492
491
  settings = self.class.organization_settings
493
492
  max = settings[:max_organizations]
494
- if max && owned_organizations.count >= max
495
- raise OrganizationLimitReached, Organizations.t(:"errors.organization_limit_reached", max: max)
496
- end
497
493
 
498
494
  org = nil
499
495
  ActiveRecord::Base.transaction do
496
+ ensure_below_organization_limit!(max) if max
500
497
  org = Organizations::Organization.create!(attributes)
501
498
 
502
499
  Organizations::Membership.create!(
@@ -757,6 +754,18 @@ module Organizations
757
754
 
758
755
  private
759
756
 
757
+ # The limit is counted under a lock on this user's row, so two
758
+ # concurrent creates cannot both count below it and both insert.
759
+ # A user row first keeps the gem's lock order (RowLocks). Uncached:
760
+ # a count read earlier in the request must not stand in for the one
761
+ # taken under the lock.
762
+ def ensure_below_organization_limit!(max)
763
+ self.class.unscoped.where(self.class.primary_key => id).lock.pick(self.class.primary_key)
764
+ return if ActiveRecord::Base.uncached { owned_organizations.count } < max
765
+
766
+ raise OrganizationLimitReached, Organizations.t(:"errors.organization_limit_reached", max: max)
767
+ end
768
+
760
769
  def create_personal_organization_if_configured
761
770
  # Check condition inside callback (not via `if:` option) to ensure
762
771
  # proper evaluation of instance state, including singleton methods
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Organizations
4
- VERSION = "0.9.0"
4
+ VERSION = "0.9.1"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: organizations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - rameerez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-10-25 00:00:00.000000000 Z
10
+ date: 2026-11-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties