super_auth 0.1.3 → 0.1.4
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +154 -10
- data/db/migrate/1_users.rb +1 -1
- data/db/migrate/2_groups.rb +2 -2
- data/db/migrate/3_permissions.rb +1 -1
- data/db/migrate/4_roles.rb +2 -2
- data/db/migrate/5_resources.rb +1 -1
- data/db/migrate/6_edge.rb +6 -6
- data/lib/basic_loader.rb +1 -0
- data/lib/super_auth/edge.rb +91 -91
- data/lib/super_auth/group.rb +1 -1
- data/lib/super_auth/nestable.rb +2 -2
- data/lib/super_auth/permission.rb +11 -11
- data/lib/super_auth/railtie.rb +12 -0
- data/lib/super_auth/resource.rb +1 -1
- data/lib/super_auth/role.rb +1 -1
- data/lib/super_auth/user.rb +10 -10
- data/lib/super_auth/version.rb +1 -1
- data/lib/super_auth.rb +12 -8
- data/lib/tasks/super_auth_tasks.rake +13 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a5da5e9ec945c0624514fb6b72471c934911dfa9e59271aeee08ef7e78e60c7
|
4
|
+
data.tar.gz: 6f96f6f911d939a4f4059081b45b68894c7ef1795d232df6f4646c854f4554a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f747d99cf64d276a95d7e3231885b37289b4e587e09be1febbe070ed416f206b7989bba7c32a64b9d5fddeed6afb2502ef871008e51b64395696d54e54887dd1
|
7
|
+
data.tar.gz: b580ce1942b4ce3334639e0ac20c579af0eb65d285beaa403a5c3540c3239d6582d2444fb88d7d67fdf05720e37b7291d104cb208bbc98d393b97e4280ab066e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,23 +1,167 @@
|
|
1
1
|
# SuperAuth
|
2
2
|
|
3
|
-
|
3
|
+
Super auth is turn-key authorization gem that makes unauthorized access unrepresentable. **Stop writing tests for authorization with confidence**
|
4
4
|
|
5
|
-
|
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
|
-
|
9
|
+
## Installation
|
10
10
|
|
11
|
-
|
11
|
+
gem "super_auth"
|
12
12
|
|
13
|
-
$ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
|
14
13
|
|
15
|
-
|
14
|
+
## Docs
|
16
15
|
|
17
|
-
|
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/
|
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 [
|
179
|
+
The gem is available as open source under the terms of the [GPL](https://www.gnu.org/licenses/quick-guide-gplv3.html).
|
data/db/migrate/1_users.rb
CHANGED
data/db/migrate/2_groups.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Sequel.migration do
|
2
2
|
change do
|
3
|
-
create_table(:
|
3
|
+
create_table?(:super_auth_groups) do
|
4
4
|
primary_key :id
|
5
5
|
String :name, null: false
|
6
|
-
foreign_key :parent_id, :
|
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
|
data/db/migrate/3_permissions.rb
CHANGED
data/db/migrate/4_roles.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Sequel.migration do
|
2
2
|
change do
|
3
|
-
create_table(:
|
3
|
+
create_table?(:super_auth_roles) do
|
4
4
|
primary_key :id
|
5
5
|
String :name, null: false
|
6
|
-
foreign_key :parent_id, :
|
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
|
data/db/migrate/5_resources.rb
CHANGED
data/db/migrate/6_edge.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Sequel.migration do
|
2
2
|
change do
|
3
|
-
create_table(:
|
3
|
+
create_table?(:super_auth_edges) do
|
4
4
|
primary_key :id
|
5
5
|
|
6
|
-
foreign_key :user_id, :
|
7
|
-
foreign_key :group_id, :
|
8
|
-
foreign_key :permission_id, :
|
9
|
-
foreign_key :role_id, :
|
10
|
-
foreign_key :resource_id, :
|
6
|
+
foreign_key :user_id, :super_auth_users, null: true
|
7
|
+
foreign_key :group_id, :super_auth_groups, null: true
|
8
|
+
foreign_key :permission_id, :super_auth_permissions, null: true
|
9
|
+
foreign_key :role_id, :super_auth_roles, null: true
|
10
|
+
foreign_key :resource_id, :super_auth_resources, null: true
|
11
11
|
|
12
12
|
DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
13
13
|
DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
data/lib/basic_loader.rb
CHANGED
data/lib/super_auth/edge.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class SuperAuth::Edge < Sequel::Model(:
|
1
|
+
class SuperAuth::Edge < Sequel::Model(:super_auth_edges)
|
2
2
|
many_to_one :user
|
3
3
|
many_to_one :group
|
4
4
|
many_to_one :permission
|
@@ -15,45 +15,45 @@ class SuperAuth::Edge < Sequel::Model(:edges)
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def users_groups_roles_permissions_resources
|
18
|
-
users_groups_roles_ds = SuperAuth::User.join(:
|
19
|
-
Sequel[:
|
20
|
-
Sequel[:
|
21
|
-
Sequel[:
|
22
|
-
Sequel[:
|
23
|
-
Sequel[:
|
18
|
+
users_groups_roles_ds = SuperAuth::User.join(:super_auth_edges, user_id: :id).select_all(:super_auth_users).join(SuperAuth::Group.from(SuperAuth::Group.trees).as(:groups), id: :group_id).select(
|
19
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
20
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
21
|
+
Sequel[:super_auth_users][:external_id].as(:user_external_id),
|
22
|
+
Sequel[:super_auth_users][:created_at].as(:user_created_at),
|
23
|
+
Sequel[:super_auth_users][:updated_at].as(:user_updated_at),
|
24
24
|
Sequel[:groups][:id].as(:group_id),
|
25
25
|
Sequel[:groups][:name].as(:group_name),
|
26
|
-
Sequel[:
|
27
|
-
Sequel[:
|
28
|
-
Sequel[:
|
29
|
-
Sequel[:
|
30
|
-
Sequel[:
|
26
|
+
Sequel[:super_auth_edges][:id].as(:edge_id),
|
27
|
+
Sequel[:super_auth_edges][:permission_id].as(:edge_permission_id),
|
28
|
+
Sequel[:super_auth_edges][:group_id].as(:edge_group_id),
|
29
|
+
Sequel[:super_auth_edges][:user_id].as(:edge_user_id),
|
30
|
+
Sequel[:super_auth_edges][:role_id].as(:edge_role_id),
|
31
31
|
Sequel[:groups][:group_path],
|
32
32
|
Sequel[:groups][:group_name_path],
|
33
33
|
Sequel[:groups][:parent_id],
|
34
34
|
Sequel[:groups][:created_at].as(:group_created_at),
|
35
35
|
Sequel[:groups][:updated_at].as(:group_updated_at),
|
36
|
-
).join(Sequel[:
|
36
|
+
).join(Sequel[:super_auth_edges].as(:group_role_edges), Sequel[:group_role_edges][:group_id] => Sequel[:groups][:id]).select_append(
|
37
37
|
Sequel[:group_role_edges][:id].as(:group_role_edge_id),
|
38
38
|
Sequel[:group_role_edges][:permission_id].as(:group_role_edge_permission_id),
|
39
39
|
Sequel[:group_role_edges][:group_id].as(:group_role_edge_group_id),
|
40
40
|
Sequel[:group_role_edges][:user_id].as(:group_role_edge_user_id),
|
41
41
|
Sequel[:group_role_edges][:role_id].as(:group_role_edge_role_id),
|
42
|
-
).join(:
|
42
|
+
).join(:super_auth_roles, id: Sequel[:group_role_edges][:role_id])
|
43
43
|
|
44
44
|
SuperAuth::Edge.from(
|
45
45
|
SuperAuth::Edge.from(
|
46
46
|
SuperAuth::Group.cte(SuperAuth::Group.where(id: users_groups_roles_ds.select(Sequel[:groups][:id])).select(:id)).select { [id.as(:group_id), name.as(:group_name), parent_id.as(:group_parent_id), group_path, group_name_path, created_at.as(:group_created_at), updated_at.as(:group_updated_at)] },
|
47
47
|
SuperAuth::Role.cte(users_groups_roles_ds.select(Sequel[:group_role_edges][:role_id])).select { [id.as(:role_id), name.as(:role_name), parent_id.as(:role_parent_id), role_path, role_name_path, created_at.as(:role_created_at), updated_at.as(:role_updated_at) ] }
|
48
48
|
).as(:users_groups_roles_permissions_resources)
|
49
|
-
).join(Sequel[:
|
50
|
-
.join(Sequel[:
|
49
|
+
).join(Sequel[:super_auth_edges].as(:user_edges), Sequel[:user_edges][:group_id] => Sequel[:users_groups_roles_permissions_resources][:group_id])
|
50
|
+
.join(Sequel[:super_auth_users], id: Sequel[:user_edges][:user_id])
|
51
51
|
.select(
|
52
|
-
Sequel[:
|
53
|
-
Sequel[:
|
54
|
-
Sequel[:
|
55
|
-
Sequel[:
|
56
|
-
Sequel[:
|
52
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
53
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
54
|
+
Sequel[:super_auth_users][:external_id].as(:user_external_id),
|
55
|
+
Sequel[:super_auth_users][:created_at].cast(:text).as(:user_created_at),
|
56
|
+
Sequel[:super_auth_users][:updated_at].cast(:text).as(:user_updated_at),
|
57
57
|
|
58
58
|
Sequel[:users_groups_roles_permissions_resources][:group_id],
|
59
59
|
Sequel[:users_groups_roles_permissions_resources][:group_name],
|
@@ -71,32 +71,32 @@ class SuperAuth::Edge < Sequel::Model(:edges)
|
|
71
71
|
Sequel[:users_groups_roles_permissions_resources][:role_created_at].cast(:text),
|
72
72
|
Sequel[:users_groups_roles_permissions_resources][:role_updated_at].cast(:text),
|
73
73
|
|
74
|
-
Sequel[:
|
75
|
-
Sequel[:
|
76
|
-
Sequel[:
|
77
|
-
Sequel[:
|
74
|
+
Sequel[:super_auth_permissions][:id].as(:permission_id),
|
75
|
+
Sequel[:super_auth_permissions][:name].as(:permission_name),
|
76
|
+
Sequel[:super_auth_permissions][:created_at].cast(:text).as(:permission_created_at),
|
77
|
+
Sequel[:super_auth_permissions][:updated_at].cast(:text).as(:permission_updated_at),
|
78
78
|
|
79
|
-
Sequel[:
|
80
|
-
Sequel[:
|
81
|
-
Sequel[:
|
79
|
+
Sequel[:super_auth_resources][:id].as(:resource_id),
|
80
|
+
Sequel[:super_auth_resources][:name].as(:resource_name),
|
81
|
+
Sequel[:super_auth_resources][:external_id].as(:resource_external_id)
|
82
82
|
)
|
83
|
-
.join(Sequel[:
|
84
|
-
.join(Sequel[:
|
85
|
-
.join(Sequel[:
|
86
|
-
.join(Sequel[:
|
83
|
+
.join(Sequel[:super_auth_edges].as(:permission_edges), Sequel[:permission_edges][:role_id] => Sequel[:users_groups_roles_permissions_resources][:role_id])
|
84
|
+
.join(Sequel[:super_auth_permissions], id: Sequel[:permission_edges][:permission_id])
|
85
|
+
.join(Sequel[:super_auth_edges].as(:resource_edges), Sequel[:resource_edges][:permission_id] => Sequel[:permission_edges][:permission_id])
|
86
|
+
.join(Sequel[:super_auth_resources], id: Sequel[:resource_edges][:resource_id])
|
87
87
|
.distinct
|
88
88
|
end
|
89
89
|
|
90
90
|
def users_groups_permissions_resources
|
91
91
|
SuperAuth::User.
|
92
|
-
join(Sequel[:
|
92
|
+
join(Sequel[:super_auth_edges].as(:user_edges), user_id: :id).
|
93
93
|
join(SuperAuth::Group.from(SuperAuth::Group.trees).as(:groups), id: :group_id).
|
94
94
|
select(
|
95
|
-
Sequel[:
|
96
|
-
Sequel[:
|
97
|
-
Sequel[:
|
98
|
-
Sequel[:
|
99
|
-
Sequel[:
|
95
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
96
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
97
|
+
Sequel[:super_auth_users][:external_id].as(:user_external_id),
|
98
|
+
Sequel[:super_auth_users][:created_at].cast(:text).as(:user_created_at),
|
99
|
+
Sequel[:super_auth_users][:updated_at].cast(:text).as(:user_updated_at),
|
100
100
|
|
101
101
|
Sequel[:groups][:id].as(:group_id),
|
102
102
|
Sequel[:groups][:name].as(:group_name),
|
@@ -114,40 +114,40 @@ class SuperAuth::Edge < Sequel::Model(:edges)
|
|
114
114
|
Sequel::NULL.as(:role_created_at), # Sequel[:roles][:created_at].as(:role_created_at),
|
115
115
|
Sequel::NULL.as(:role_updated_at), # Sequel[:roles][:updated_at].as(:role_updated_at),
|
116
116
|
|
117
|
-
Sequel[:
|
118
|
-
Sequel[:
|
119
|
-
Sequel[:
|
120
|
-
Sequel[:
|
117
|
+
Sequel[:super_auth_permissions][:id].as(:permission_id),
|
118
|
+
Sequel[:super_auth_permissions][:name].as(:permission_name),
|
119
|
+
Sequel[:super_auth_permissions][:created_at].cast(:text).as(:permission_created_at),
|
120
|
+
Sequel[:super_auth_permissions][:updated_at].cast(:text).as(:permission_updated_at),
|
121
121
|
|
122
|
-
Sequel[:
|
123
|
-
Sequel[:
|
124
|
-
Sequel[:
|
122
|
+
Sequel[:super_auth_resources][:id].as(:resource_id),
|
123
|
+
Sequel[:super_auth_resources][:name].as(:resource_name),
|
124
|
+
Sequel[:super_auth_resources][:external_id].as(:resource_external_id),
|
125
125
|
).
|
126
|
-
join(Sequel[:
|
127
|
-
join(Sequel[:
|
128
|
-
join(Sequel[:
|
129
|
-
join(Sequel[:
|
126
|
+
join(Sequel[:super_auth_edges].as(:permission_edges), Sequel[:permission_edges][:group_id] => Sequel[:groups][:id]).
|
127
|
+
join(Sequel[:super_auth_permissions], id: Sequel[:permission_edges][:permission_id]).
|
128
|
+
join(Sequel[:super_auth_edges].as(:resource_edges), Sequel[:resource_edges][:permission_id] => Sequel[:super_auth_permissions][:id]).
|
129
|
+
join(Sequel[:super_auth_resources], id: Sequel[:resource_edges][:resource_id]).
|
130
130
|
distinct
|
131
131
|
end
|
132
132
|
|
133
133
|
def users_roles_permissions_resources
|
134
134
|
SuperAuth::User.
|
135
|
-
join(Sequel[:
|
135
|
+
join(Sequel[:super_auth_edges].as(:user_edges), user_id: :id).
|
136
136
|
join(SuperAuth::Role.from(SuperAuth::Role.trees).as(:roles), id: :role_id).
|
137
137
|
select(
|
138
|
-
Sequel[:
|
139
|
-
Sequel[:
|
140
|
-
Sequel[:
|
141
|
-
Sequel[:
|
142
|
-
Sequel[:
|
143
|
-
|
144
|
-
Sequel.lit(%Q[0 as "group_id"]), # Sequel[:
|
145
|
-
Sequel::NULL.as(:group_name), # Sequel[:
|
146
|
-
Sequel::NULL.as(:group_path), # Sequel[:
|
147
|
-
Sequel::NULL.as(:group_name_path), # Sequel[:
|
148
|
-
Sequel.lit(%Q[0 as "group_parent_id"]), # Sequel[:
|
149
|
-
Sequel.lit(%Q['1970-01-01 00:00:00.000000-00' as "group_created_at"]), # Sequel[:
|
150
|
-
Sequel.lit(%Q['1970-01-01 00:00:00.000000-00' as "group_updated_at"]), # Sequel[:
|
138
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
139
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
140
|
+
Sequel[:super_auth_users][:external_id].as(:user_external_id),
|
141
|
+
Sequel[:super_auth_users][:created_at].cast(:text).as(:user_created_at),
|
142
|
+
Sequel[:super_auth_users][:updated_at].cast(:text).as(:user_updated_at),
|
143
|
+
|
144
|
+
Sequel.lit(%Q[0 as "group_id"]), # Sequel[:super_auth_groups][:group_id],
|
145
|
+
Sequel::NULL.as(:group_name), # Sequel[:super_auth_groups][:group_name],
|
146
|
+
Sequel::NULL.as(:group_path), # Sequel[:super_auth_groups][:group_path],
|
147
|
+
Sequel::NULL.as(:group_name_path), # Sequel[:super_auth_groups][:group_name_path],
|
148
|
+
Sequel.lit(%Q[0 as "group_parent_id"]), # Sequel[:super_auth_groups][:group_parent_id],
|
149
|
+
Sequel.lit(%Q['1970-01-01 00:00:00.000000-00' as "group_created_at"]), # Sequel[:super_auth_groups][:group_created_at],
|
150
|
+
Sequel.lit(%Q['1970-01-01 00:00:00.000000-00' as "group_updated_at"]), # Sequel[:super_auth_groups][:group_updated_at],
|
151
151
|
|
152
152
|
Sequel[:roles][:id].as(:role_id),
|
153
153
|
Sequel[:roles][:name].as(:role_name),
|
@@ -157,31 +157,31 @@ class SuperAuth::Edge < Sequel::Model(:edges)
|
|
157
157
|
Sequel[:roles][:created_at].cast(:text).as(:role_created_at),
|
158
158
|
Sequel[:roles][:updated_at].cast(:text).as(:role_updated_at),
|
159
159
|
|
160
|
-
Sequel[:
|
161
|
-
Sequel[:
|
162
|
-
Sequel[:
|
163
|
-
Sequel[:
|
160
|
+
Sequel[:super_auth_permissions][:id].as(:permission_id),
|
161
|
+
Sequel[:super_auth_permissions][:name].as(:permission_name),
|
162
|
+
Sequel[:super_auth_permissions][:created_at].cast(:text).as(:permission_created_at),
|
163
|
+
Sequel[:super_auth_permissions][:updated_at].cast(:text).as(:permission_updated_at),
|
164
164
|
|
165
|
-
Sequel[:
|
166
|
-
Sequel[:
|
167
|
-
Sequel[:
|
165
|
+
Sequel[:super_auth_resources][:id].as(:resource_id),
|
166
|
+
Sequel[:super_auth_resources][:name].as(:resource_name),
|
167
|
+
Sequel[:super_auth_resources][:external_id].as(:resource_external_id),
|
168
168
|
).
|
169
|
-
join(Sequel[:
|
170
|
-
join(Sequel[:
|
171
|
-
join(Sequel[:
|
172
|
-
join(Sequel[:
|
169
|
+
join(Sequel[:super_auth_edges].as(:permission_edges), Sequel[:permission_edges][:role_id] => Sequel[:roles][:id]).
|
170
|
+
join(Sequel[:super_auth_permissions], id: Sequel[:permission_edges][:permission_id]).
|
171
|
+
join(Sequel[:super_auth_edges].as(:resource_edges), Sequel[:resource_edges][:permission_id] => Sequel[:super_auth_permissions][:id]).
|
172
|
+
join(Sequel[:super_auth_resources], id: Sequel[:resource_edges][:resource_id]).
|
173
173
|
distinct
|
174
174
|
end
|
175
175
|
|
176
176
|
def users_permissions_resources
|
177
177
|
SuperAuth::User.
|
178
|
-
join(Sequel[:
|
178
|
+
join(Sequel[:super_auth_edges].as(:user_edges), user_id: :id).
|
179
179
|
select(
|
180
|
-
Sequel[:
|
181
|
-
Sequel[:
|
182
|
-
Sequel[:
|
183
|
-
Sequel[:
|
184
|
-
Sequel[:
|
180
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
181
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
182
|
+
Sequel[:super_auth_users][:external_id].as(:user_external_id),
|
183
|
+
Sequel[:super_auth_users][:created_at].cast(:text).as(:user_created_at),
|
184
|
+
Sequel[:super_auth_users][:updated_at].cast(:text).as(:user_updated_at),
|
185
185
|
|
186
186
|
Sequel.lit(%Q[0 as "group_id"]), # Sequel[:groups][:group_id],
|
187
187
|
Sequel::NULL.as(:group_name), # Sequel[:groups][:group_name],
|
@@ -200,19 +200,19 @@ class SuperAuth::Edge < Sequel::Model(:edges)
|
|
200
200
|
Sequel::NULL.as(:role_created_at), # Sequel[:roles][:role_created_at],
|
201
201
|
Sequel::NULL.as(:role_updated_at), # Sequel[:roles][:role_updated_at],
|
202
202
|
|
203
|
-
Sequel[:
|
204
|
-
Sequel[:
|
205
|
-
Sequel[:
|
206
|
-
Sequel[:
|
203
|
+
Sequel[:super_auth_permissions][:id].as(:permission_id),
|
204
|
+
Sequel[:super_auth_permissions][:name].as(:permission_name),
|
205
|
+
Sequel[:super_auth_permissions][:created_at].cast(:text).as(:permission_created_at),
|
206
|
+
Sequel[:super_auth_permissions][:updated_at].cast(:text).as(:permission_updated_at),
|
207
207
|
|
208
|
-
Sequel[:
|
209
|
-
Sequel[:
|
210
|
-
Sequel[:
|
208
|
+
Sequel[:super_auth_resources][:id].as(:resource_id),
|
209
|
+
Sequel[:super_auth_resources][:name].as(:resource_name),
|
210
|
+
Sequel[:super_auth_resources][:external_id].as(:resource_external_id)
|
211
211
|
).
|
212
|
-
join(Sequel[:
|
213
|
-
join(Sequel[:
|
214
|
-
join(Sequel[:
|
215
|
-
join(Sequel[:
|
212
|
+
join(Sequel[:super_auth_edges].as(:permission_edges), Sequel[:permission_edges][:user_id] => Sequel[:super_auth_users][:id]).
|
213
|
+
join(Sequel[:super_auth_permissions], id: Sequel[:permission_edges][:permission_id]).
|
214
|
+
join(Sequel[:super_auth_edges].as(:resource_edges), Sequel[:resource_edges][:permission_id] => Sequel[:super_auth_permissions][:id]).
|
215
|
+
join(Sequel[:super_auth_resources], id: Sequel[:resource_edges][:resource_id]).
|
216
216
|
distinct
|
217
217
|
end
|
218
218
|
end
|
data/lib/super_auth/group.rb
CHANGED
data/lib/super_auth/nestable.rb
CHANGED
@@ -110,7 +110,7 @@ module SuperAuth::Nestable
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def pluralize(base = self)
|
113
|
-
"#{demodularize(base).downcase}s".to_sym
|
113
|
+
"super_auth_#{demodularize(base).downcase}s".to_sym
|
114
114
|
end
|
115
115
|
|
116
116
|
def singularize(base = self)
|
@@ -118,7 +118,7 @@ module SuperAuth::Nestable
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def cte_name(base = self)
|
121
|
-
"#{pluralize(base)}_cte".to_sym
|
121
|
+
"super_auth_#{pluralize(base)}_cte".to_sym
|
122
122
|
end
|
123
123
|
|
124
124
|
def base_path(base = self)
|
@@ -1,23 +1,23 @@
|
|
1
|
-
class SuperAuth::Permission < Sequel::Model(:
|
1
|
+
class SuperAuth::Permission < Sequel::Model(:super_auth_permissions)
|
2
2
|
one_to_many :edges
|
3
3
|
|
4
4
|
dataset_module do
|
5
5
|
def with_edges
|
6
|
-
join(:
|
6
|
+
join(:super_auth_edges, permission_id: :id).select_all(:super_auth_permissions)
|
7
7
|
end
|
8
8
|
|
9
9
|
def with_roles
|
10
|
-
|
11
|
-
Sequel[:
|
12
|
-
Sequel[:
|
10
|
+
with_edges.join(Role.from(Role.trees).as(:roles), id: :role_id).select(
|
11
|
+
Sequel[:super_auth_permissions][:id].as(:id),
|
12
|
+
Sequel[:super_auth_permissions][:id].as(:permission_id),
|
13
13
|
Sequel[:roles][:id].as(:role_id),
|
14
|
-
Sequel[:
|
14
|
+
Sequel[:super_auth_permissions][:name].as(:permission_name),
|
15
15
|
Sequel[:roles][:name].as(:role_name),
|
16
|
-
Sequel[:
|
17
|
-
Sequel[:
|
18
|
-
Sequel[:
|
19
|
-
Sequel[:
|
20
|
-
Sequel[:
|
16
|
+
Sequel[:super_auth_edges][:id].as(:edge_id),
|
17
|
+
Sequel[:super_auth_edges][:permission_id].as(:edge_permission_id),
|
18
|
+
Sequel[:super_auth_edges][:group_id].as(:edge_group_id),
|
19
|
+
Sequel[:super_auth_edges][:user_id].as(:edge_user_id),
|
20
|
+
Sequel[:super_auth_edges][:role_id].as(:edge_role_id),
|
21
21
|
:role_path,
|
22
22
|
:role_name_path,
|
23
23
|
:parent_id
|
data/lib/super_auth/resource.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
class SuperAuth::Resource < Sequel::Model(:
|
1
|
+
class SuperAuth::Resource < Sequel::Model(:super_auth_resources)
|
2
2
|
end
|
data/lib/super_auth/role.rb
CHANGED
data/lib/super_auth/user.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
class SuperAuth::User < Sequel::Model(:
|
1
|
+
class SuperAuth::User < Sequel::Model(:super_auth_users)
|
2
2
|
one_to_many :edges
|
3
3
|
|
4
4
|
dataset_module do
|
5
5
|
def with_edges
|
6
|
-
join(:
|
6
|
+
join(:super_auth_edges, user_id: :id).select_all(:super_auth_users)
|
7
7
|
end
|
8
8
|
|
9
9
|
def with_groups
|
10
10
|
with_edges.join(Group.from(Group.trees).as(:groups), id: :group_id).select(
|
11
|
-
Sequel[:
|
12
|
-
Sequel[:
|
11
|
+
Sequel[:super_auth_users][:id].as(:id),
|
12
|
+
Sequel[:super_auth_users][:id].as(:user_id),
|
13
13
|
Sequel[:groups][:id].as(:group_id),
|
14
|
-
Sequel[:
|
14
|
+
Sequel[:super_auth_users][:name].as(:user_name),
|
15
15
|
Sequel[:groups][:name].as(:group_name),
|
16
|
-
Sequel[:
|
17
|
-
Sequel[:
|
18
|
-
Sequel[:
|
19
|
-
Sequel[:
|
20
|
-
Sequel[:
|
16
|
+
Sequel[:super_auth_edges][:id].as(:edge_id),
|
17
|
+
Sequel[:super_auth_edges][:permission_id].as(:edge_permission_id),
|
18
|
+
Sequel[:super_auth_edges][:group_id].as(:edge_group_id),
|
19
|
+
Sequel[:super_auth_edges][:user_id].as(:edge_user_id),
|
20
|
+
Sequel[:super_auth_edges][:role_id].as(:edge_role_id),
|
21
21
|
Sequel[:groups][:group_path],
|
22
22
|
Sequel[:groups][:group_name_path],
|
23
23
|
Sequel[:groups][:parent_id]
|
data/lib/super_auth/version.rb
CHANGED
data/lib/super_auth.rb
CHANGED
@@ -13,25 +13,29 @@ end
|
|
13
13
|
require 'sequel'
|
14
14
|
|
15
15
|
ENV["SUPER_AUTH_LOG_LEVEL"] = 'debug'
|
16
|
-
logger
|
17
|
-
|
18
|
-
Logger.new(STDOUT)
|
19
|
-
end
|
16
|
+
require 'logger'
|
17
|
+
logger = Logger.new(STDOUT)
|
20
18
|
|
21
|
-
require 'sequel'
|
22
19
|
Sequel::Model.plugin :timestamps, update_on_create: true
|
23
20
|
if !ENV['SUPER_AUTH_DATABASE_URL'].nil? && !ENV['SUPER_AUTH_DATABASE_URL'].empty?
|
24
21
|
Sequel::Model.db = Sequel.connect(ENV['SUPER_AUTH_DATABASE_URL'], logger: logger)
|
25
22
|
else
|
26
|
-
|
23
|
+
logger.warn "SUPER_AUTH_DATABASE_URL not set, using sqlite in memory database."
|
27
24
|
Sequel::Model.db = Sequel.sqlite(logger: logger)
|
28
|
-
Sequel.extension :migration
|
29
|
-
Sequel::Migrator.run(Sequel::Model.db, "db/migrate")
|
30
25
|
end
|
31
26
|
Sequel::Model.default_association_options = {:class_namespace=>'SuperAuth'}
|
32
27
|
|
28
|
+
# I don't love this, but I don't know how to do it better
|
29
|
+
unless Sequel::Model.db.table_exists?(:super_auth_edges)
|
30
|
+
Sequel.extension :migration
|
31
|
+
path = Pathname.new(__FILE__).parent.parent.join("db", "migrate")
|
32
|
+
Sequel::Migrator.run(Sequel::Model.db, path)
|
33
|
+
end
|
33
34
|
require 'basic_loader' unless defined?(SuperAuth::AUTOLOADERS)
|
34
35
|
|
36
|
+
|
35
37
|
module SuperAuth
|
36
38
|
class Error < StandardError; end
|
37
39
|
end
|
40
|
+
|
41
|
+
require "super_auth/railtie" if defined?(Rails::Railtie)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :super_auth do
|
2
|
+
desc "Run the super_auth database migrations"
|
3
|
+
task migrate: :environment do
|
4
|
+
# TODO: Make this work properly without auto applying migrations, which is silly
|
5
|
+
#
|
6
|
+
# raise "ENV variable SUPER_AUTH_DATABASE_URL is not set" if ENV['SUPER_AUTH_DATABASE_URL'].nil? || ENV['SUPER_AUTH_DATABASE_URL'].empty?
|
7
|
+
# Sequel::Model.db = Sequel.connect(ENV['SUPER_AUTH_DATABASE_URL'])
|
8
|
+
# Sequel.extension :migration
|
9
|
+
# binding.irb
|
10
|
+
# path = Pathname.new(__FILE__).parent.parent.join("db", "migrate")
|
11
|
+
# Sequel::Migrator.run(Sequel::Model.db, path)
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: super_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Frias
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -64,10 +64,12 @@ files:
|
|
64
64
|
- lib/super_auth/group.rb
|
65
65
|
- lib/super_auth/nestable.rb
|
66
66
|
- lib/super_auth/permission.rb
|
67
|
+
- lib/super_auth/railtie.rb
|
67
68
|
- lib/super_auth/resource.rb
|
68
69
|
- lib/super_auth/role.rb
|
69
70
|
- lib/super_auth/user.rb
|
70
71
|
- lib/super_auth/version.rb
|
72
|
+
- lib/tasks/super_auth_tasks.rake
|
71
73
|
homepage: https://github.com/JonathanFrias/super_auth
|
72
74
|
licenses:
|
73
75
|
- MIT
|
@@ -90,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
92
|
- !ruby/object:Gem::Version
|
91
93
|
version: '0'
|
92
94
|
requirements: []
|
93
|
-
rubygems_version: 3.
|
95
|
+
rubygems_version: 3.4.19
|
94
96
|
signing_key:
|
95
97
|
specification_version: 4
|
96
98
|
summary: Make Unauthenticated State Unrepresentable
|