super_auth 0.2.0 → 0.3.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: 0e93633206ab371d51eb0519bc0afccf33a028bd1025d66ee2fc1fb17df19c20
4
- data.tar.gz: f99edcddc159742adee9fcf5888d8bc438beaad627d58f8576204e695a3436fa
3
+ metadata.gz: d7dd44cc4a7bc63bd611b41e4f4555896c61095a279a32640831d4ff22b11628
4
+ data.tar.gz: bb64fa3b4cbd5059a56ef8d3aa27b372f96c7d8df15c2a42efc84d9b2f78bac9
5
5
  SHA512:
6
- metadata.gz: cedd01d07d249b8b49840915eed87eb68a0f7a16a2900dad8f93168338efc12c457b8c86ea910d5fd99def2844945abd8f148bd5bb360b476b22a3942eda8b7d
7
- data.tar.gz: 6158c6a1b379d27364ae97f570899fe1690ac172a9bf16732932058bf62504fd03180719fdce24974571b262ec5dfd4444d1c6dd967408e08892491791a45a6d
6
+ metadata.gz: de44b731731d0e9d6f86d944306e67db639a7a768416ad96bbcb5956600f6f38bd12f253ca12e30592b5e29078cbdb56078a197d89d9242017043ac8fbd4679b
7
+ data.tar.gz: 77ef025662b6bc4ed8110d9dd6ef77347a1744a723cb4b56a4779262010b651ece3a65af605a9cf4cea9fcf850b8d2a6c784fa2a8814f7d06787453e02b3d727
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.1] - 2026-03-10
4
+
5
+ - Refactor: move authorization compilation logic into Authorization model (`compile!` and `from_graph` class methods)
6
+
7
+ ## [0.3.0]
8
+
9
+ - Fix: ByCurrentUser mixin — correct subquery column, add admin wildcard, remove dead code
10
+ - Remove unused tests
11
+
12
+ ## [0.2.0]
13
+
14
+ - Version bump with various improvements
15
+
3
16
  ## [0.1.0] - 2023-12-09
4
17
 
5
18
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,80 +1,88 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- super_auth (0.1.5)
4
+ super_auth (0.3.1)
5
5
  sequel
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (7.2.2.1)
11
- activesupport (= 7.2.2.1)
12
- activerecord (7.2.2.1)
13
- activemodel (= 7.2.2.1)
14
- activesupport (= 7.2.2.1)
10
+ activemodel (8.1.2)
11
+ activesupport (= 8.1.2)
12
+ activerecord (8.1.2)
13
+ activemodel (= 8.1.2)
14
+ activesupport (= 8.1.2)
15
15
  timeout (>= 0.4.0)
16
- activesupport (7.2.2.1)
16
+ activesupport (8.1.2)
17
17
  base64
18
- benchmark (>= 0.3)
19
18
  bigdecimal
20
19
  concurrent-ruby (~> 1.0, >= 1.3.1)
21
20
  connection_pool (>= 2.2.5)
22
21
  drb
23
22
  i18n (>= 1.6, < 2)
23
+ json
24
24
  logger (>= 1.4.2)
25
25
  minitest (>= 5.1)
26
26
  securerandom (>= 0.3)
27
27
  tzinfo (~> 2.0, >= 2.0.5)
28
+ uri (>= 0.13.1)
28
29
  after_commit_everywhere (1.6.0)
29
30
  activerecord (>= 4.2)
30
31
  activesupport
31
32
  base64 (0.3.0)
32
- benchmark (0.4.1)
33
- bigdecimal (3.2.2)
33
+ bigdecimal (4.0.1)
34
34
  coderay (1.1.3)
35
- concurrent-ruby (1.3.5)
36
- connection_pool (2.5.3)
37
- diff-lcs (1.5.0)
35
+ concurrent-ruby (1.3.6)
36
+ connection_pool (3.0.2)
37
+ diff-lcs (1.6.2)
38
38
  drb (2.2.3)
39
- i18n (1.14.7)
39
+ i18n (1.14.8)
40
40
  concurrent-ruby (~> 1.0)
41
+ io-console (0.8.2)
42
+ json (2.19.1)
41
43
  logger (1.7.0)
42
- method_source (1.0.0)
43
- minitest (6.0.1)
44
+ method_source (1.1.0)
45
+ minitest (6.0.2)
46
+ drb (~> 2.0)
44
47
  prism (~> 1.5)
45
48
  mysql2 (0.5.7)
46
49
  bigdecimal
47
- pg (1.5.4)
50
+ pg (1.6.3-arm64-darwin)
51
+ pg (1.6.3-x86_64-linux)
48
52
  prism (1.9.0)
49
- pry (0.14.2)
53
+ pry (0.16.0)
50
54
  coderay (~> 1.1)
51
55
  method_source (~> 1.0)
52
- rake (13.1.0)
53
- rspec (3.12.0)
54
- rspec-core (~> 3.12.0)
55
- rspec-expectations (~> 3.12.0)
56
- rspec-mocks (~> 3.12.0)
57
- rspec-core (3.12.2)
58
- rspec-support (~> 3.12.0)
59
- rspec-expectations (3.12.3)
56
+ reline (>= 0.6.0)
57
+ rake (13.3.1)
58
+ reline (0.6.3)
59
+ io-console (~> 0.5)
60
+ rspec (3.13.2)
61
+ rspec-core (~> 3.13.0)
62
+ rspec-expectations (~> 3.13.0)
63
+ rspec-mocks (~> 3.13.0)
64
+ rspec-core (3.13.6)
65
+ rspec-support (~> 3.13.0)
66
+ rspec-expectations (3.13.5)
60
67
  diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.12.0)
62
- rspec-mocks (3.12.6)
68
+ rspec-support (~> 3.13.0)
69
+ rspec-mocks (3.13.8)
63
70
  diff-lcs (>= 1.2.0, < 2.0)
64
- rspec-support (~> 3.12.0)
65
- rspec-support (3.12.1)
71
+ rspec-support (~> 3.13.0)
72
+ rspec-support (3.13.7)
66
73
  securerandom (0.4.1)
67
- sequel (5.94.0)
74
+ sequel (5.102.0)
68
75
  bigdecimal
69
- sequel-activerecord_connection (2.0.0)
70
- activerecord (>= 5.0, < 8.1)
76
+ sequel-activerecord_connection (2.0.1)
77
+ activerecord (>= 5.1)
71
78
  sequel (~> 5.38)
72
- sqlite3 (2.9.0-arm64-darwin)
73
- sqlite3 (2.9.0-x86_64-linux-gnu)
74
- timeout (0.4.3)
79
+ sqlite3 (2.9.1-arm64-darwin)
80
+ sqlite3 (2.9.1-x86_64-linux-gnu)
81
+ timeout (0.6.1)
75
82
  tzinfo (2.0.6)
76
83
  concurrent-ruby (~> 1.0)
77
- zeitwerk (2.6.12)
84
+ uri (1.1.1)
85
+ zeitwerk (2.7.5)
78
86
 
79
87
  PLATFORMS
80
88
  arm64-darwin-22
@@ -182,15 +182,8 @@ module SuperAuth
182
182
  end
183
183
 
184
184
  def compile_authorizations
185
- # Compile all authorization paths and populate the authorizations table
186
185
  begin
187
- authorization_class.delete_all
188
-
189
- # Call the authorizations method which compiles all paths
190
- authorizations = edge_class.authorizations
191
- authorizations.each(&:save!)
192
-
193
- count = authorizations.count
186
+ count = authorization_class.compile!
194
187
 
195
188
  render json: {
196
189
  success: true,
@@ -0,0 +1,12 @@
1
+ Sequel.migration do
2
+ up do
3
+ add_index :super_auth_authorizations,
4
+ [:user_external_id, :resource_external_type, :resource_external_id],
5
+ name: :idx_sa_auth_by_current_user
6
+ end
7
+ down do
8
+ drop_index :super_auth_authorizations,
9
+ [:user_external_id, :resource_external_type, :resource_external_id],
10
+ name: :idx_sa_auth_by_current_user
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class AddByCurrentUserIndexToSuperAuthAuthorizations < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_index :super_auth_authorizations,
4
+ [:user_external_id, :resource_external_type, :resource_external_id],
5
+ name: :idx_sa_auth_by_current_user
6
+ end
7
+ end
@@ -1,3 +1,20 @@
1
1
  class SuperAuth::ActiveRecord::Authorization < ActiveRecord::Base
2
2
  self.table_name = 'super_auth_authorizations'
3
+
4
+ class << self
5
+ # Returns all computed authorization paths as Authorization AR objects.
6
+ # These can be saved directly to the super_auth_authorizations table.
7
+ def from_graph
8
+ from("(#{SuperAuth::Edge.authorizations.sql}) as super_auth_authorizations".squish)
9
+ end
10
+
11
+ # Clears and repopulates the authorizations table from the current graph.
12
+ def compile!
13
+ transaction do
14
+ delete_all
15
+ from_graph.each { |auth| create!(auth.attributes.except("id")) }
16
+ end
17
+ count
18
+ end
19
+ end
3
20
  end
@@ -1,9 +1,7 @@
1
1
  module SuperAuth::ActiveRecord::ByCurrentUser
2
2
  def self.included(base)
3
- base.has_many :super_auth_authorizations
4
-
5
3
  base.send(:default_scope, **{all_queries: true}) do
6
- raise "SuperAuth.current_user not set" if SuperAuth.current_user.blank?
4
+ next none if SuperAuth.current_user.blank?
7
5
 
8
6
  if SuperAuth.current_user.respond_to?(:system?) && SuperAuth.current_user.system?
9
7
  self
@@ -15,25 +13,27 @@ module SuperAuth::ActiveRecord::ByCurrentUser
15
13
  { user_external_id: SuperAuth.current_user.id, user_external_type: SuperAuth.current_user.class.name }
16
14
  end
17
15
 
18
- resource_where =
19
- if try(:id)
20
- { resource_external_id: self.id, resource_external_type: self.class.name }
16
+ resource_type = self.model.name
17
+
18
+ # Type-level authorization (resource_external_id IS NULL) acts as wildcard:
19
+ # user has access to ALL records of this type (e.g., admin with ADMIN_ACCESS).
20
+ type_level = SuperAuth::ActiveRecord::Authorization
21
+ .where(**user_where, resource_external_type: resource_type, resource_external_id: nil)
22
+
23
+ if type_level.exists?
24
+ self
21
25
  else
22
- { resource_external_type: self.model.name }
26
+ # Per-record authorization: filter to specific records the user can access.
27
+ where(
28
+ id: SuperAuth::ActiveRecord::Authorization
29
+ .where(**user_where, resource_external_type: resource_type)
30
+ .where.not(resource_external_id: nil)
31
+ .select(:resource_external_id))
23
32
  end
24
-
25
- # Important:
26
- # We use a subquery here instead of a inner join because we don't want
27
- # to potentially affect break on queries issue count queries in their app.
28
- where(
29
- id: SuperAuth::ActiveRecord::Authorization
30
- .where(**user_where, **resource_where)
31
- .select(:resource_id))
32
33
  end
33
34
  end
34
35
  end
35
36
 
36
37
  module ClassMethods
37
38
  end
38
-
39
39
  end
@@ -1,3 +1,3 @@
1
1
  module SuperAuth
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -0,0 +1,35 @@
1
+ require_relative "lib/super_auth/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "super_auth"
5
+ spec.version = SuperAuth::VERSION
6
+ spec.authors = ["Jonathan Frias"]
7
+ spec.email = ["jonathan@gofrias.com"]
8
+
9
+ spec.summary = "Make Unauthenticated State Unrepresentable"
10
+ spec.description = "Simple, yet super powerful authorization for you application"
11
+ spec.homepage = "https://github.com/JonathanFrias/super_auth"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 2.6.0"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/JonathanFrias/super_auth"
17
+ spec.metadata["changelog_uri"] = "https://github.com/JonathanFrias/super_auth/blob/main/CHANGELOG.md"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
24
+ end
25
+ end
26
+ spec.bindir = "bin"
27
+ spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ # Uncomment to register a new dependency of your gem
31
+ spec.add_dependency "sequel"
32
+ spec.add_development_dependency "sqlite3"
33
+ # For more information and examples about making a new gem, check out our
34
+ # guide at: https://bundler.io/guides/creating_gem.html
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: super_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Frias
@@ -65,6 +65,7 @@ files:
65
65
  - db/migrate/6_edge.rb
66
66
  - db/migrate/7_authorization.rb
67
67
  - db/migrate/8_add_indexes_to_edges.rb
68
+ - db/migrate/9_add_by_current_user_index.rb
68
69
  - db/migrate_activerecord/20250101000001_create_super_auth_users.rb
69
70
  - db/migrate_activerecord/20250101000002_create_super_auth_groups.rb
70
71
  - db/migrate_activerecord/20250101000003_create_super_auth_permissions.rb
@@ -72,6 +73,7 @@ files:
72
73
  - db/migrate_activerecord/20250101000005_create_super_auth_resources.rb
73
74
  - db/migrate_activerecord/20250101000006_create_super_auth_edges.rb
74
75
  - db/migrate_activerecord/20250101000007_create_super_auth_authorizations.rb
76
+ - db/migrate_activerecord/20250101000009_add_by_current_user_index_to_super_auth_authorizations.rb
75
77
  - db/seeds/sample_data.rb
76
78
  - lib/basic_loader.rb
77
79
  - lib/generators/super_auth/install/install_generator.rb
@@ -98,6 +100,7 @@ files:
98
100
  - lib/super_auth/user.rb
99
101
  - lib/super_auth/version.rb
100
102
  - lib/tasks/super_auth_tasks.rake
103
+ - super_auth.gemspec
101
104
  - visualization.html
102
105
  homepage: https://github.com/JonathanFrias/super_auth
103
106
  licenses: