super_auth 0.1.5 → 0.3.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile +3 -7
  4. data/Gemfile.lock +25 -14
  5. data/LICENSE.txt +125 -21
  6. data/README.md +32 -1
  7. data/Rakefile +0 -2
  8. data/USAGE.md +619 -0
  9. data/VISUALIZATION.md +58 -0
  10. data/app/controllers/super_auth/graph_controller.rb +661 -0
  11. data/app/views/super_auth/graph/index.html.erb +1408 -0
  12. data/config/routes.rb +73 -0
  13. data/db/migrate/1_users.rb +1 -0
  14. data/db/migrate/2_groups.rb +8 -1
  15. data/db/migrate/4_roles.rb +8 -1
  16. data/db/migrate/5_resources.rb +1 -0
  17. data/db/migrate/7_authorization.rb +2 -0
  18. data/db/migrate/8_add_indexes_to_edges.rb +17 -0
  19. data/db/migrate/9_add_by_current_user_index.rb +12 -0
  20. data/db/migrate_activerecord/20250101000001_create_super_auth_users.rb +10 -0
  21. data/db/migrate_activerecord/20250101000002_create_super_auth_groups.rb +11 -0
  22. data/db/migrate_activerecord/20250101000003_create_super_auth_permissions.rb +8 -0
  23. data/db/migrate_activerecord/20250101000004_create_super_auth_roles.rb +11 -0
  24. data/db/migrate_activerecord/20250101000005_create_super_auth_resources.rb +10 -0
  25. data/db/migrate_activerecord/20250101000006_create_super_auth_edges.rb +12 -0
  26. data/db/migrate_activerecord/20250101000007_create_super_auth_authorizations.rb +41 -0
  27. data/db/migrate_activerecord/20250101000009_add_by_current_user_index_to_super_auth_authorizations.rb +7 -0
  28. data/db/seeds/sample_data.rb +193 -0
  29. data/lib/basic_loader.rb +0 -2
  30. data/lib/generators/super_auth/install/install_generator.rb +19 -0
  31. data/lib/generators/super_auth/install/templates/README +29 -0
  32. data/lib/generators/super_auth/install/templates/super_auth.rb +7 -0
  33. data/lib/super_auth/active_record/by_current_user.rb +26 -11
  34. data/lib/super_auth/active_record/edge.rb +45 -0
  35. data/lib/super_auth/active_record/group.rb +7 -0
  36. data/lib/super_auth/active_record/permission.rb +4 -0
  37. data/lib/super_auth/active_record/resource.rb +1 -0
  38. data/lib/super_auth/active_record/role.rb +7 -0
  39. data/lib/super_auth/active_record/user.rb +6 -0
  40. data/lib/super_auth/active_record.rb +17 -0
  41. data/lib/super_auth/edge.rb +190 -131
  42. data/lib/super_auth/group.rb +1 -0
  43. data/lib/super_auth/nestable.rb +17 -10
  44. data/lib/super_auth/permission.rb +1 -1
  45. data/lib/super_auth/railtie.rb +26 -25
  46. data/lib/super_auth/role.rb +2 -1
  47. data/lib/super_auth/user.rb +8 -8
  48. data/lib/super_auth/version.rb +1 -3
  49. data/lib/super_auth.rb +72 -40
  50. data/super_auth.gemspec +35 -0
  51. data/visualization.html +747 -0
  52. metadata +24 -6
@@ -1,4 +1,17 @@
1
1
  module SuperAuth
2
+ if defined? Rails::Engine
3
+ class Engine < Rails::Engine
4
+ isolate_namespace SuperAuth
5
+
6
+ config.paths.add 'app/controllers', eager_load: true
7
+
8
+ # Use ActiveRecord migrations when in a Rails environment
9
+ if defined?(ActiveRecord)
10
+ config.paths['db/migrate'] = 'db/migrate_activerecord'
11
+ end
12
+ end
13
+ end
14
+
2
15
  if defined? Rails::Railtie
3
16
  class Railtie < Rails::Railtie
4
17
  rake_tasks do
@@ -6,31 +19,19 @@ module SuperAuth
6
19
  end
7
20
 
8
21
  initializer "super_auth.initialize" do
9
- if defined?(Sequel) && Sequel.const_defined?("Model")
10
- require 'super_auth/authorization'
11
- require 'super_auth/edge'
12
- require 'super_auth/nestable'
13
- require 'super_auth/group'
14
- require 'super_auth/permission'
15
- require 'super_auth/resource'
16
- require 'super_auth/role'
17
- require 'super_auth/user'
18
- elsif defined?(ActiveRecord)
19
- require 'super_auth/active_record'
20
- require 'super_auth/active_record/authorization'
21
- require 'super_auth/active_record/edge'
22
- require 'super_auth/active_record/group'
23
- require 'super_auth/active_record/permission'
24
- require 'super_auth/active_record/resource'
25
- require 'super_auth/active_record/role'
26
- require 'super_auth/active_record/user'
27
- SuperAuth::Authorization = SuperAuth::ActiveRecord::Authorization
28
- SuperAuth::Edge = SuperAuth::ActiveRecord::Edge
29
- SuperAuth::Group = SuperAuth::ActiveRecord::Group
30
- SuperAuth::Permission = SuperAuth::ActiveRecord::Permission
31
- SuperAuth::Resource = SuperAuth::ActiveRecord::Resource
32
- SuperAuth::User = SuperAuth::ActiveRecord::User
33
- SuperAuth::Role = SuperAuth::ActiveRecord::Role
22
+ if defined?(ActiveRecord) && defined?(ActiveRecord::Base)
23
+ SuperAuth.db
24
+ begin
25
+ SuperAuth.load
26
+ rescue Sequel::DatabaseError => e
27
+ # Tables don't exist yet (e.g., before migrations are run)
28
+ # This is OK - models will be loaded when needed
29
+ Rails.logger.debug "SuperAuth Sequel models not loaded: #{e.message}" if defined?(Rails.logger)
30
+ end
31
+ require "super_auth/active_record"
32
+ elsif defined?(Sequel) && Sequel.const_defined?("Model")
33
+ SuperAuth.db
34
+ SuperAuth.load
34
35
  end
35
36
  end
36
37
  end
@@ -1,3 +1,4 @@
1
1
  class SuperAuth::Role < Sequel::Model(:super_auth_roles)
2
+ unrestrict_primary_key # For ActiveRecord
2
3
  include SuperAuth::Nestable
3
- end
4
+ end
@@ -30,16 +30,16 @@ class SuperAuth::User < Sequel::Model(:super_auth_users)
30
30
 
31
31
  def with_roles
32
32
  with_edges.join(SuperAuth::Role.from(SuperAuth::Role.trees).as(:roles), id: :role_id).select(
33
- Sequel[:users][:id].as(:id),
34
- Sequel[:users][:id].as(:user_id),
33
+ Sequel[:super_auth_users][:id].as(:id),
34
+ Sequel[:super_auth_users][:id].as(:user_id),
35
35
  Sequel[:roles][:id].as(:role_id),
36
- Sequel[:users][:name].as(:user_name),
36
+ Sequel[:super_auth_users][:name].as(:user_name),
37
37
  Sequel[:roles][:name].as(:role_name),
38
- Sequel[:edges][:id].as(:edge_id),
39
- Sequel[:edges][:permission_id].as(:edge_permission_id),
40
- Sequel[:edges][:group_id].as(:edge_group_id),
41
- Sequel[:edges][:user_id].as(:edge_user_id),
42
- Sequel[:edges][:role_id].as(:edge_role_id),
38
+ Sequel[:super_auth_edges][:id].as(:edge_id),
39
+ Sequel[:super_auth_edges][:permission_id].as(:edge_permission_id),
40
+ Sequel[:super_auth_edges][:group_id].as(:edge_group_id),
41
+ Sequel[:super_auth_edges][:user_id].as(:edge_user_id),
42
+ Sequel[:super_auth_edges][:role_id].as(:edge_role_id),
43
43
  Sequel[:roles][:role_path],
44
44
  Sequel[:roles][:role_name_path],
45
45
  Sequel[:roles][:parent_id]
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module SuperAuth
4
- VERSION = "0.1.5"
2
+ VERSION = "0.3.0"
5
3
  end
data/lib/super_auth.rb CHANGED
@@ -1,17 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
1
  require_relative "super_auth/version"
4
-
5
- if defined? SuperAuth::AUTOLOADERS
6
- require 'zeitwerk'
7
- SuperAuth::AUTOLOADERS << Zeitwerk::Loader.for_gem.tap do |loader|
8
- loader.ignore("#{__dir__}/basic_loader.rb")
9
- loader.setup
10
- end
11
- require "sequel"
12
- else
13
- require 'basic_loader'
14
- end
2
+ require "sequel"
15
3
 
16
4
  module SuperAuth
17
5
  class Error < StandardError; end
@@ -20,29 +8,20 @@ module SuperAuth
20
8
  yield self if block_given?
21
9
  end
22
10
 
23
- def self.set_db
24
- logger =
25
- if defined?(Rails) && ENV["SUPER_AUTH_LOG_LEVEL"] == "debug"
26
- Rails.logger
27
- elsif ENV["SUPER_AUTH_LOG_LEVEL"] == "debug"
28
- require "logger"
29
- logger = Logger.new(STDOUT)
30
- else
31
- nil
32
- end
33
-
34
- if !ENV['SUPER_AUTH_DATABASE_URL'].nil? && !ENV['SUPER_AUTH_DATABASE_URL'].empty?
35
- SuperAuth.db = Sequel.connect(ENV['SUPER_AUTH_DATABASE_URL'], logger: logger)
36
- else
37
- puts "ENV SUPER_AUTH_DATABASE_URL not set, using sqlite."
38
- SuperAuth.db = Sequel.sqlite(logger: logger, database: "./tmp/test.db")
39
- install_migrations
40
- end
41
- Sequel::Model.default_association_options = {:class_namespace=>'SuperAuth'}
11
+ def self.load
12
+ require "super_auth/authorization"
13
+ require "super_auth/edge"
14
+ require "super_auth/nestable"
15
+ require "super_auth/group"
16
+ require "super_auth/permission"
17
+ require "super_auth/railtie"
18
+ require "super_auth/resource"
19
+ require "super_auth/role"
20
+ require "super_auth/user"
21
+ require "super_auth/active_record" if defined?(ActiveRecord::Base)
42
22
  end
43
23
 
44
24
  def self.install_migrations
45
- require "sequel"
46
25
  Sequel.extension :migration
47
26
  require "pathname"
48
27
  path = Pathname.new(__FILE__).parent.parent.join("db", "migrate")
@@ -51,7 +30,6 @@ module SuperAuth
51
30
 
52
31
  def self.uninstall_migrations
53
32
  require "sequel"
54
- set_db
55
33
  Sequel.extension :migration
56
34
  require "pathname"
57
35
 
@@ -64,19 +42,73 @@ module SuperAuth
64
42
  end
65
43
 
66
44
  def self.current_user=(user)
67
- @current_user = user
45
+ Thread.current[:super_auth_current_user] = user
68
46
  end
69
47
 
70
48
  def self.current_user
71
- @current_user
49
+ Thread.current[:super_auth_current_user]
72
50
  end
73
51
 
74
- def self.db=(db)
75
- @db = db
52
+ def self.db
53
+ return @db if !@db.nil?
54
+
55
+ if !Gem::Specification.find_all_by_name("activerecord").empty?
56
+ require "active_record"
57
+ extensions = Gem::Specification.find_all_by_name("sequel-activerecord_connection").any? ? { extensions: :activerecord_connection } : {}
58
+
59
+ if extensions.empty?
60
+ warn "[SuperAuth] WARNING: Found ActiveRecord but could not find the gem 'sequel-activerecord_connection' installed. SuperAuth may not always work as expected."
61
+ end
62
+
63
+ begin
64
+ ::ActiveRecord::Base.establish_connection
65
+ rescue ActiveRecord::AdapterNotSpecified
66
+ if defined?(Rails) && !Rails.env.local?
67
+ raise Error, "SuperAuth could not find a database configuration. " \
68
+ "Please configure ActiveRecord or set SUPER_AUTH_DATABASE_URL."
69
+ end
70
+ warn "[SuperAuth] WARNING: No database configured. Falling back to in-memory SQLite. " \
71
+ "All authorization data will be lost on restart."
72
+ ::ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
73
+ end
74
+
75
+ case ::ActiveRecord::Base.adapter_class.to_s
76
+ when "ActiveRecord::ConnectionAdapters::SQLite3Adapter"
77
+ SuperAuth.db = Sequel.sqlite(**extensions)
78
+ when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
79
+ SuperAuth.db = Sequel.postgres(**extensions)
80
+ when "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
81
+ SuperAuth.db = Sequel.mysql2(**extensions)
82
+ else
83
+ warn "[SuperAuth] WARNING: Unknown adapter: #{::ActiveRecord::Base.adapter_class}"
84
+ end
85
+ else
86
+ logger =
87
+ if defined?(Rails) && ENV["SUPER_AUTH_LOG_LEVEL"] == "debug"
88
+ { logger: Rails.logger }
89
+ elsif ENV["SUPER_AUTH_LOG_LEVEL"] == "debug"
90
+ require "logger"
91
+ { logger: Logger.new(STDOUT) }
92
+ else
93
+ {} # no logger
94
+ end
95
+
96
+ if !ENV['SUPER_AUTH_DATABASE_URL'].nil? && !ENV['SUPER_AUTH_DATABASE_URL'].empty?
97
+ SuperAuth.db = Sequel.connect(ENV['SUPER_AUTH_DATABASE_URL'], **logger)
98
+ else
99
+ if defined?(Rails) && !Rails.env.local?
100
+ raise Error, "SuperAuth could not find a database configuration. " \
101
+ "Please set SUPER_AUTH_DATABASE_URL or configure ActiveRecord."
102
+ end
103
+ warn "[SuperAuth] WARNING: SUPER_AUTH_DATABASE_URL not set. Falling back to in-memory SQLite. " \
104
+ "All authorization data will be lost on restart."
105
+ SuperAuth.db = Sequel.sqlite(**logger)
106
+ end
107
+ end
76
108
  end
77
109
 
78
- def self.db
79
- @db
110
+ def self.db=(db)
111
+ @db = db
80
112
  end
81
113
  end
82
114
 
@@ -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