super_auth 0.1.3 → 0.1.5

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: e1ea96c948511db2bcb65e7dc10b813ae6b5fddb1bbee785c7a3e59178c7b68f
4
- data.tar.gz: 3d5eb559c56948c9edb31f801f28636ee594578759f83c452d3a62987432394e
3
+ metadata.gz: d1c0609f1c31ed023cb42444655098f37468e92f4a24f960f520877f5cb152ed
4
+ data.tar.gz: 8c7f9334b2226727b52550581756d9d34c50524283ad89339e2d8f0bdfd3094b
5
5
  SHA512:
6
- metadata.gz: 272eba9bf5807006f956605eb927c7aaec6594fee0683c8ee155c7f4d614419dbd1927495860cfa73acc9b5973887d273605bdbbff58a8d0726f7f63a9ebdcd5
7
- data.tar.gz: 904ee67ef8c4b858bfec6ea2cfe39bdc692dba063edee0a76f769209301c3c9a8850df37bf8b65584bd5a15db9cbf1df3125429c2d4a43f8b18f49e25c8bf665
6
+ metadata.gz: c3781d17e40e003e7e361789e71d3c9048920b7d14023b1af83de968f1e0e05b4f829fa5e3fda172c141c1c8dceea75888e407bc5f5210cf2148f870954c36df
7
+ data.tar.gz: 6b9edf03113857abcf6e9246f40dbb3a5d36814380f09e1d86782aa1220a56397dc9b2918fb3f85cb23aeeed1acc103d81af2a24c2abd253eb5e4ca140b54e50
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.6
data/Gemfile CHANGED
@@ -12,10 +12,11 @@ gemspec
12
12
  gem "rake", "~> 13.0"
13
13
  gem "rspec", "~> 3.0"
14
14
  gem "zeitwerk", "~> 2.6"
15
+ gem "sequel"
15
16
 
16
-
17
- group :development do
17
+ group :development, :test do
18
18
  gem "pry"
19
19
  gem "pg"
20
20
  gem "sqlite3"
21
- end
21
+ gem "activerecord"
22
+ end
data/Gemfile.lock CHANGED
@@ -1,16 +1,44 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- super_auth (0.1.2)
4
+ super_auth (0.1.5)
5
5
  sequel
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ activemodel (8.0.2)
11
+ activesupport (= 8.0.2)
12
+ activerecord (8.0.2)
13
+ activemodel (= 8.0.2)
14
+ activesupport (= 8.0.2)
15
+ timeout (>= 0.4.0)
16
+ activesupport (8.0.2)
17
+ base64
18
+ benchmark (>= 0.3)
19
+ bigdecimal
20
+ concurrent-ruby (~> 1.0, >= 1.3.1)
21
+ connection_pool (>= 2.2.5)
22
+ drb
23
+ i18n (>= 1.6, < 2)
24
+ logger (>= 1.4.2)
25
+ minitest (>= 5.1)
26
+ securerandom (>= 0.3)
27
+ tzinfo (~> 2.0, >= 2.0.5)
28
+ uri (>= 0.13.1)
29
+ base64 (0.3.0)
30
+ benchmark (0.4.1)
10
31
  bigdecimal (3.1.4)
11
32
  coderay (1.1.3)
33
+ concurrent-ruby (1.3.5)
34
+ connection_pool (2.5.3)
12
35
  diff-lcs (1.5.0)
36
+ drb (2.2.3)
37
+ i18n (1.14.7)
38
+ concurrent-ruby (~> 1.0)
39
+ logger (1.7.0)
13
40
  method_source (1.0.0)
41
+ minitest (5.25.5)
14
42
  pg (1.5.4)
15
43
  pry (0.14.2)
16
44
  coderay (~> 1.1)
@@ -29,21 +57,30 @@ GEM
29
57
  diff-lcs (>= 1.2.0, < 2.0)
30
58
  rspec-support (~> 3.12.0)
31
59
  rspec-support (3.12.1)
60
+ securerandom (0.4.1)
32
61
  sequel (5.75.0)
33
62
  bigdecimal
34
- sqlite3 (1.7.0-arm64-darwin)
35
- sqlite3 (1.7.0-x86_64-linux)
63
+ sqlite3 (2.7.2-arm64-darwin)
64
+ sqlite3 (2.7.2-x86_64-linux-gnu)
65
+ timeout (0.4.3)
66
+ tzinfo (2.0.6)
67
+ concurrent-ruby (~> 1.0)
68
+ uri (1.0.3)
36
69
  zeitwerk (2.6.12)
37
70
 
38
71
  PLATFORMS
39
72
  arm64-darwin-22
73
+ arm64-darwin-23
74
+ arm64-darwin-24
40
75
  x86_64-linux
41
76
 
42
77
  DEPENDENCIES
78
+ activerecord
43
79
  pg
44
80
  pry
45
81
  rake (~> 13.0)
46
82
  rspec (~> 3.0)
83
+ sequel
47
84
  sqlite3
48
85
  super_auth!
49
86
  zeitwerk (~> 2.6)
data/README.md CHANGED
@@ -1,23 +1,167 @@
1
1
  # SuperAuth
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ Super auth is turn-key authorization gem that makes unauthorized access unrepresentable. **Stop writing tests for authorization with confidence**
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/super_auth`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ The intent is to use with ruby applications, as well as centralize authorization for multiple applications. If you look at the [OWASP top vulnerabilty](https://owasp.org/Top10/A01_2021-Broken_Access_Control/), broken
6
+ access control is the NUMBER 1 most common security risk in modern applications today. super_auth provides a authentication strategy that allows you to completely de-risk your application, solving this issue once confidently.
6
7
 
7
- ## Installation
8
8
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
9
+ ## Installation
10
10
 
11
- Install the gem and add to the application's Gemfile by executing:
11
+ gem "super_auth"
12
12
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
13
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
14
+ ## Docs
16
15
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
16
+ How `super_auth` stacks up against other authentication strategies:
17
+ [Do you really understand Authentication](https://dev.to/jonathanfrias/do-you-really-understand-authorization-1o5d)
18
18
 
19
19
  ## Usage
20
20
 
21
+ SuperAuth is a rules engine engine that works on 5 different authorization concepts:
22
+
23
+ - Users
24
+ - Groups
25
+ - Roles
26
+ - Permissions
27
+ - Resources
28
+
29
+ The basis for how this works is that the rules engine is trying to match a user with a resource to determine access.
30
+ The engine determines if it can find an authorization route betewen a user and a resource. It does so by looking at users, groups, roles, permissions.
31
+
32
+ +-------+ +------+
33
+ | Group |<----->| Role |
34
+ +-------+\ / +------+
35
+ ^ \ / ^
36
+ | \/ |
37
+ | /\ |
38
+ | / \ |
39
+ V / \ V
40
+ +---------------+ +------+/ \+------------+ +----------+ +-------------------+
41
+ | YourApp::User |<-->| User |<------>| Permission |<-->| Resource | <--> | YourApp::Resource |
42
+ +---------------+ +------+ +------------+ +----------+ +-------------------+
43
+ ^ ^
44
+ | |
45
+ +----------------------------------+
46
+
47
+
48
+ The lines between the boxes are called [edges](https://en.wikipedia.org/wiki/Glossary_of_graph_theory#edge).
49
+ Note that `Group` and `Role` trees.
50
+
51
+ In general the super_auth has 5 different pathing strategies to search for access.
52
+
53
+ 1. users <-> group[s] <-> role[s] <-> permission <-> resource
54
+ 2. users <-> role[s] <-> permission <-> resource
55
+ 3. users <-> group[s] <-> permission <-> resource
56
+ 4. users <-> permission <-> resource
57
+ 5. users <-> resource
58
+
59
+ Edges can be drawn between any 2 objects, allowing super_auth can seamlessly scale in complexity with you.
60
+ When `Group` and `Role` are used, the rules will apply to all descedants. If there are any edges
61
+ between the specified user and the resource, then access is granted.
62
+
63
+
64
+ You can see usage examples `spec/example_spec.rb`.
65
+
66
+ We're going to need some users:
67
+
68
+ Users:
69
+ - Peter
70
+ - Michael
71
+ - Bethany
72
+ - Eloise
73
+ - Anna
74
+ - Dillon
75
+ - Guest (Unknown User)
76
+
77
+ Let's see an example company structure:
78
+
79
+ Groups:
80
+ - Company
81
+ - Engineering_dept
82
+ - Backend
83
+ - Frontend
84
+ - Sales Department
85
+ - Marketing Department
86
+ - Customers
87
+ - CustomerA
88
+ - CustomerB
89
+ - Vendors
90
+ - VendorA
91
+ - VendorB
92
+
93
+ We're going to define a roles:
94
+
95
+ Roles:
96
+ - Employee
97
+ - Engineering
98
+ - Señor Software Developer
99
+ - Señor Designer
100
+ - Software Developer
101
+ - Production Support
102
+ - Sales and Marketing
103
+ - Marketing Manager
104
+ - Marketing Associate
105
+ - CustomerRole
106
+
107
+ We're going to define some permissions:
108
+
109
+ Permissions:
110
+ - create
111
+ - read
112
+ - update
113
+ - delete
114
+ - invoice
115
+ - login
116
+ - reboot
117
+ - deploy
118
+ - sign_contract
119
+ - subscribe
120
+ - unsubscribe
121
+ - publish_design
122
+
123
+ Finally, we need some resources:
124
+
125
+ Resources:
126
+ - app1
127
+ - app2
128
+ - staging
129
+ - db1
130
+ - db2
131
+ - core_design_template
132
+ - customer_profile
133
+ - marketing_website
134
+ - customer_post1
135
+ - customer_post2
136
+ - customer_post3
137
+
138
+ So we have sufficient prerequisite data to do some interesting authorizations. Let's draw some edges:
139
+
140
+ Peter <-> Frontend # Peter is on the Frontend team. (via Company->Engineering_dept->Frontend)
141
+ Engineering_dept <-> Engineering # Group "Engineering_dept" has the Role "Engineering"
142
+ Engineering <-> create # Engineering role can do basic CRUD operations
143
+ Engineering <-> read # Peter can CRUD too
144
+ Engineering <-> update
145
+ Engineering <-> delete
146
+ core_design_template <-> create # Now, those CRUD permissions apply to core_design_template resource
147
+ core_design_template <-> read
148
+ core_design_template <-> update
149
+ core_design_template <-> delete
150
+
151
+ With this, the following paths are created from Peter to the core_design_template:
152
+
153
+ Peter <-> Frontend <-> Engineering_dept <-> Engineering <-> create <-> core_design_template
154
+ Peter <-> Frontend <-> Engineering_dept <-> Engineering <-> read <-> core_design_template
155
+ Peter <-> Frontend <-> Engineering_dept <-> Engineering <-> update <-> core_design_template
156
+ Peter <-> Frontend <-> Engineering_dept <-> Engineering <-> delete <-> core_design_template
157
+
158
+ Which completes the circuit using the path
159
+ user <-> group <-> group <-> role <-> permission <-> resource
160
+
161
+
162
+ When you create/delete an edge new authorizations are generated and stored in the `super_auth` database table.
163
+ Since the path is stored with the record, it trivial to audit access permissions using basic SQL.
164
+
21
165
  TODO: Write usage instructions here
22
166
 
23
167
  ## Development
@@ -28,8 +172,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
172
 
29
173
  ## Contributing
30
174
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/super_auth.
175
+ Bug reports and pull requests are welcome on GitHub at https://github.com/JonathanFrias/super_auth.
32
176
 
33
177
  ## License
34
178
 
35
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
179
+ The gem is available as open source under the terms of the [GPL](https://www.gnu.org/licenses/quick-guide-gplv3.html).
@@ -1,13 +1,15 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:users) do
2
+ up do
3
+ create_table(:super_auth_users) do
4
4
  primary_key :id
5
-
6
5
  String :external_id # , null: false
7
6
  String :name
8
-
9
7
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
10
8
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
11
9
  end
12
10
  end
11
+
12
+ down do
13
+ drop_table(:super_auth_users)
14
+ end
13
15
  end
@@ -1,11 +1,15 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:groups) do
2
+ up do
3
+ create_table(:super_auth_groups) do
4
4
  primary_key :id
5
5
  String :name, null: false
6
- foreign_key :parent_id, :groups, deferrable: true, type: :integer
6
+ foreign_key :parent_id, :super_auth_groups, deferrable: true, type: :integer
7
7
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
8
8
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
9
9
  end
10
10
  end
11
+
12
+ down do
13
+ drop_table(:super_auth_groups)
14
+ end
11
15
  end
@@ -1,10 +1,14 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:permissions) do
2
+ up do
3
+ create_table(:super_auth_permissions) do
4
4
  primary_key :id
5
5
  String :name, null: false
6
6
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
7
7
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
8
8
  end
9
9
  end
10
+
11
+ down do
12
+ drop_table(:super_auth_permissions)
13
+ end
10
14
  end
@@ -1,11 +1,15 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:roles) do
2
+ up do
3
+ create_table(:super_auth_roles) do
4
4
  primary_key :id
5
5
  String :name, null: false
6
- foreign_key :parent_id, :roles, deferrable: true, type: :integer
6
+ foreign_key :parent_id, :super_auth_roles, deferrable: true, type: :integer
7
7
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
8
8
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
9
9
  end
10
10
  end
11
+
12
+ down do
13
+ drop_table(:super_auth_roles)
14
+ end
11
15
  end
@@ -1,13 +1,15 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:resources) do
2
+ up do
3
+ create_table(:super_auth_resources) do
4
4
  primary_key :id
5
-
6
5
  String :name
7
6
  String :external_id # , null: false
8
-
9
7
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
10
8
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
11
9
  end
12
10
  end
11
+
12
+ down do
13
+ drop_table(:super_auth_resources)
14
+ end
13
15
  end
data/db/migrate/6_edge.rb CHANGED
@@ -1,16 +1,18 @@
1
1
  Sequel.migration do
2
- change do
3
- create_table(:edges) do
2
+ up do
3
+ create_table(:super_auth_edges) do
4
4
  primary_key :id
5
-
6
- foreign_key :user_id, :users, null: true
7
- foreign_key :group_id, :groups, null: true
8
- foreign_key :permission_id, :permissions, null: true
9
- foreign_key :role_id, :roles, null: true
10
- foreign_key :resource_id, :resources, null: true
11
-
5
+ foreign_key :user_id, :super_auth_users, null: true
6
+ foreign_key :group_id, :super_auth_groups, null: true
7
+ foreign_key :permission_id, :super_auth_permissions, null: true
8
+ foreign_key :role_id, :super_auth_roles, null: true
9
+ foreign_key :resource_id, :super_auth_resources, null: true
12
10
  DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
13
11
  DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
14
12
  end
15
13
  end
14
+
15
+ down do
16
+ drop_table(:super_auth_edges)
17
+ end
16
18
  end
@@ -0,0 +1,39 @@
1
+ Sequel.migration do
2
+ up do
3
+ create_table(:super_auth_authorizations) do
4
+ Integer :user_id, null: true
5
+ String :user_name, null: true
6
+ String :user_external_id, null: true
7
+ DateTime :user_created_at, null: true
8
+ DateTime :user_updated_at, null: true
9
+ Integer :group_id, null: true
10
+ String :group_name, null: true
11
+ String :group_path, null: true
12
+ String :group_name_path, null: true
13
+ String :group_parent_name, null: true
14
+ String :group_parent_id, null: true
15
+ DateTime :group_created_at, null: true
16
+ DateTime :group_updated_at, null: true
17
+ Integer :role_id, null: true
18
+ String :role_name, null: true
19
+ String :role_path, null: true
20
+ String :role_name_path, null: true
21
+ String :role_parent_id, null: true
22
+ DateTime :role_created_at, null: true
23
+ DateTime :role_updated_at, null: true
24
+ Integer :permission_id, null: true
25
+ String :permission_name, null: true
26
+ DateTime :permission_created_at, null: true
27
+ DateTime :permission_updated_at, null: true
28
+ Integer :resource_id, null: true
29
+ String :resource_name, null: true
30
+ String :resource_external_id, null: true
31
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
32
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
33
+ end
34
+ end
35
+
36
+ down do
37
+ drop_table(:super_auth_authorizations)
38
+ end
39
+ end
data/lib/basic_loader.rb CHANGED
@@ -3,10 +3,21 @@
3
3
  # File generated automatically, do not edit
4
4
  # See https://blog.pawelpokrywka.com/p/gem-with-zeitwerk-as-development-only-dependency
5
5
 
6
+ require 'super_auth/active_record' if defined?(ActiveRecord::Base)
7
+ require 'super_auth/authorization'
6
8
  require 'super_auth/edge'
7
9
  require 'super_auth/nestable'
8
10
  require 'super_auth/group'
9
11
  require 'super_auth/permission'
12
+ require 'super_auth/railtie'
10
13
  require 'super_auth/resource'
11
14
  require 'super_auth/role'
12
15
  require 'super_auth/user'
16
+ require 'super_auth/active_record/authorization' if defined?(ActiveRecord::Base)
17
+ require 'super_auth/active_record/by_current_user' if defined?(ActiveRecord::Base)
18
+ require 'super_auth/active_record/edge' if defined?(ActiveRecord::Base)
19
+ require 'super_auth/active_record/group' if defined?(ActiveRecord::Base)
20
+ require 'super_auth/active_record/permission' if defined?(ActiveRecord::Base)
21
+ require 'super_auth/active_record/resource' if defined?(ActiveRecord::Base)
22
+ require 'super_auth/active_record/role' if defined?(ActiveRecord::Base)
23
+ require 'super_auth/active_record/user' if defined?(ActiveRecord::Base)
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Authorization < ActiveRecord::Base
2
+ self.table_name = 'super_auth_authorizations'
3
+ end
@@ -0,0 +1,24 @@
1
+ module SuperAuth::ActiveRecord::ByCurrentUser
2
+ def self.included(base)
3
+ base.has_many :super_auth_authorizations
4
+
5
+ base.send(:default_scope, **{all_queries: true}) do
6
+ raise "SuperAuth.current_user not set" if SuperAuth.current_user.blank?
7
+
8
+ if SuperAuth.current_user.system?
9
+ self
10
+ else
11
+ # Important:
12
+ # We use a subquery here instead of a inner join because we don't want
13
+ # to potentially affect break on queries issue count queries in their app.
14
+ where(id: SuperAuth::ActiveRecord::Authorization.where(super_auth_user_id: SuperAuth.current_user.id).select(:resource_id))
15
+ end
16
+ end
17
+ end
18
+
19
+ def system? = false
20
+
21
+ module ClassMethods
22
+ end
23
+
24
+ end
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Edge < ActiveRecord::Base
2
+ self.table_name = 'super_auth_edges'
3
+ end
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Group < ActiveRecord::Base
2
+ self.table_name = 'super_auth_groups'
3
+ end
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Permission < ActiveRecord::Base
2
+ self.table_name = 'super_auth_permissions'
3
+ end
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Resource < ActiveRecord::Base
2
+ self.table_name = 'super_auth_resources'
3
+ end
@@ -0,0 +1,3 @@
1
+ class SuperAuth::ActiveRecord::Role < ActiveRecord::Base
2
+ self.table_name = 'super_auth_roles'
3
+ end
@@ -0,0 +1,8 @@
1
+ class SuperAuth::ActiveRecord::User < ActiveRecord::Base
2
+ self.table_name = 'super_auth_users'
3
+
4
+ def model_name = ActiveModel::Name.new(:user)
5
+
6
+ def system? = self.class.system == self
7
+ def self.system = find_or_create_by(name: "system")
8
+ end
@@ -0,0 +1,3 @@
1
+ require "active_record"
2
+ module SuperAuth::ActiveRecord
3
+ end
@@ -0,0 +1,2 @@
1
+ class SuperAuth::Authorization < Sequel::Model(:super_auth_authorizations)
2
+ end