mumukit-auth 7.10.0 → 7.13.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 517de6c84d1b25e0b31a83da4dbf8f0d5c234eb05c9c23476d2e721fa19b6049
4
- data.tar.gz: 3e2ae789e5dff9857e63f298c126fffe69a815b63649fdf1b7346c18f583e29a
3
+ metadata.gz: 5a77054a911454b7372cadecd8bda02e894ff80bd24ee5d19eb4b9086fb17dcc
4
+ data.tar.gz: 69b57019319e45c0a2c49425fea3964d9e270c5452c61c3f20d374ee41077464
5
5
  SHA512:
6
- metadata.gz: c28eac074b926567be11f09700623e3fdbd9eb1379ba22c794f87f3b06fd901fb5bb9cb436e56fbbb0985a55bb708651a9632003e4ea3849cb43408d61038717
7
- data.tar.gz: 253cc4b87c062b9e97e4ba350fbcef2922c198c396cea345675b490532d7b1528ade0d257cc872cc663cf47cd374b9338a5c3a656b62daaea298bce5c7927892
6
+ metadata.gz: 36a9d0459ed2513e94851f01312aab4ed88e8abcf17707c2c9c7bb3a86a9be406e8b5d43ac6d7194d568118622bb2801125aba27996c4eff7b12dd6824c538f6
7
+ data.tar.gz: e16a35c4478a206125c1d489b24ea79c84e0ba5d0082057363deb0d653c44d09e1bf7cc6e86f31268fad9b76d66c3d240eaf1b6f5643121dd7930f4765963289
@@ -2,18 +2,15 @@ class Mumukit::Auth::Permissions
2
2
  include Mumukit::Auth::Roles
3
3
  include Mumukit::Auth::Protection
4
4
 
5
- delegate :empty?, to: :scopes
6
-
7
5
  attr_accessor :scopes
8
6
 
9
7
  def initialize(scopes={})
10
- raise 'invalid scopes' if scopes.any? { |key, value| value.class != Mumukit::Auth::Scope }
11
-
12
- @scopes = scopes.with_indifferent_access
8
+ @scopes = {}.with_indifferent_access
9
+ add_scopes! scopes
13
10
  end
14
11
 
15
12
  def has_permission?(role, resource_slug)
16
- Mumukit::Auth::Role.parse(role).allows?(resource_slug, self)
13
+ role.to_mumukit_role.allows?(resource_slug, self)
17
14
  end
18
15
 
19
16
  def role_allows?(role, resource_slug)
@@ -28,6 +25,21 @@ class Mumukit::Auth::Permissions
28
25
  self.scopes[role] ||= Mumukit::Auth::Scope.new
29
26
  end
30
27
 
28
+ def empty?
29
+ scopes.all? { |_, it| it.empty? }
30
+ end
31
+
32
+ def compact!
33
+ old_scopes = @scopes.dup
34
+ @scopes = {}.with_indifferent_access
35
+
36
+ old_scopes.each do |role, scope|
37
+ scope.grants.each do |grant|
38
+ push_and_compact! role, grant
39
+ end
40
+ end
41
+ end
42
+
31
43
  # Deprecated: use `student_granted_organizations` organizations instead
32
44
  def accessible_organizations
33
45
  warn "Don't use accessible_organizations, since this method is probably not doing what you would expect.\n" +
@@ -54,7 +66,13 @@ class Mumukit::Auth::Permissions
54
66
  end
55
67
 
56
68
  def add_permission!(role, *grants)
57
- scope_for(role).add_grant! *grants
69
+ role = role.to_mumukit_role
70
+ grants.each { |grant| push_and_compact! role, grant }
71
+ end
72
+
73
+ def add_scopes!(scopes)
74
+ raise 'invalid scopes' if scopes.any? { |key, value| value.class != Mumukit::Auth::Scope }
75
+ scopes.each { |role, scope| add_permission! role, *scope.grants }
58
76
  end
59
77
 
60
78
  def merge(other)
@@ -146,4 +164,19 @@ class Mumukit::Auth::Permissions
146
164
  scope.grants.all? { |grant| has_permission? role, grant }
147
165
  end
148
166
 
167
+ def push_and_compact!(role, grant)
168
+ role = role.to_mumukit_role
169
+ grant = grant.to_mumukit_grant
170
+
171
+ scopes.each do |other_role, other_scope|
172
+ other_role = other_role.to_mumukit_role
173
+
174
+ if other_role.narrower_than?(role)
175
+ other_scope.remove_narrower_grants!(grant)
176
+ elsif other_role.broader_than?(role) && other_scope.has_broader_grant?(grant)
177
+ return
178
+ end
179
+ end
180
+ scope_for(role.to_sym).add_grant! grant
181
+ end
149
182
  end
@@ -1,3 +1,16 @@
1
+
2
+ class String
3
+ def to_mumukit_role
4
+ Mumukit::Auth::Role.parse self
5
+ end
6
+ end
7
+
8
+ class Symbol
9
+ def to_mumukit_role
10
+ Mumukit::Auth::Role.parse self
11
+ end
12
+ end
13
+
1
14
  module Mumukit::Auth
2
15
  class Role
3
16
  def initialize(symbol)
@@ -17,17 +30,36 @@ module Mumukit::Auth
17
30
  @symbol
18
31
  end
19
32
 
20
- private
33
+ def broader_than?(other)
34
+ other.narrower_than? self
35
+ end
36
+
37
+ def narrower_than?(other)
38
+ other.class != self.class && _narrower_than_other?(other)
39
+ end
21
40
 
22
- def self.parent(parent)
23
- define_method(:parent) { self.class.parse(parent) }
41
+ def to_mumukit_role
42
+ self
24
43
  end
25
44
 
26
- def self.parse(role)
27
- @roles ||= {}
28
- @roles[role] ||= "Mumukit::Auth::Role::#{role.to_s.camelize}".constantize.new(role.to_sym)
45
+ def _narrower_than_other?(other)
46
+ self.parent.class == other.class || self.parent._narrower_than_other?(other)
29
47
  end
30
48
 
49
+ class << self
50
+ def parent(parent)
51
+ define_method(:parent) { self.class.parse(parent) }
52
+ end
53
+
54
+ def parse(role)
55
+ @roles ||= {}
56
+ @roles[role.to_sym] ||= "Mumukit::Auth::Role::#{role.to_s.camelize}".constantize.new(role.to_sym)
57
+ end
58
+ end
59
+
60
+ class ExStudent < Role
61
+ parent :student
62
+ end
31
63
  class Student < Role
32
64
  parent :teacher
33
65
  end
@@ -61,6 +93,10 @@ module Mumukit::Auth
61
93
  def parent_allows?(*)
62
94
  false
63
95
  end
96
+
97
+ def _narrower_than_other?(*)
98
+ false
99
+ end
64
100
  end
65
101
  end
66
102
  end
@@ -1,6 +1,6 @@
1
1
  module Mumukit::Auth
2
2
  module Roles
3
- ROLES = [:student, :teacher, :headmaster, :writer, :editor, :janitor, :moderator, :forum_supervisor, :admin, :owner]
3
+ ROLES = [:ex_student, :student, :teacher, :headmaster, :writer, :editor, :janitor, :moderator, :forum_supervisor, :admin, :owner]
4
4
 
5
5
  ROLES.each do |role|
6
6
  define_method "#{role}?" do |scope = Mumukit::Auth::Slug.any|
@@ -20,6 +20,10 @@ module Mumukit::Auth
20
20
  self.grants.delete(grant)
21
21
  end
22
22
 
23
+ def empty?
24
+ grants.empty?
25
+ end
26
+
23
27
  def merge(other)
24
28
  self.class.new grants + other.grants
25
29
  end
@@ -54,6 +58,14 @@ module Mumukit::Auth
54
58
  to_s
55
59
  end
56
60
 
61
+ def remove_narrower_grants!(grant)
62
+ grants.reject! { |it| grant.allows? it }
63
+ end
64
+
65
+ def has_broader_grant?(grant)
66
+ grants.any? { |it| it.allows? grant }
67
+ end
68
+
57
69
  private
58
70
 
59
71
  def any_grant?(&block)
@@ -66,13 +78,5 @@ module Mumukit::Auth
66
78
  remove_narrower_grants! grant
67
79
  grants << grant
68
80
  end
69
-
70
- def remove_narrower_grants!(grant)
71
- grants.reject! { |it| grant.allows? it }
72
- end
73
-
74
- def has_broader_grant?(grant)
75
- grants.any? { |it| it.allows? grant }
76
- end
77
81
  end
78
82
  end
@@ -35,11 +35,11 @@ module Mumukit::Auth
35
35
  end
36
36
 
37
37
  def ==(o)
38
- self.class == o.class && self.normalize.eql?(o.normalize)
38
+ o.is_a?(Mumukit::Auth::Slug) && self.normalize.eql?(o.normalize)
39
39
  end
40
40
 
41
41
  def eql?(o)
42
- self.class == o.class && to_s == o.to_s
42
+ o.is_a?(Mumukit::Auth::Slug) && to_s == o.to_s
43
43
  end
44
44
 
45
45
  def hash
@@ -57,7 +57,15 @@ module Mumukit::Auth
57
57
  end
58
58
 
59
59
  def normalize
60
- dup.normalize!
60
+ Normalized.new(first, second)
61
+ end
62
+
63
+ def normalized_s
64
+ normalize.to_s
65
+ end
66
+
67
+ def normalized?
68
+ normalize.eql? self
61
69
  end
62
70
 
63
71
  def inspect
@@ -99,7 +107,7 @@ module Mumukit::Auth
99
107
  end
100
108
 
101
109
  def self.normalize(first, second)
102
- new(first, second).normalize!
110
+ Normalized.new(first, second)
103
111
  end
104
112
 
105
113
  private
@@ -117,11 +125,29 @@ module Mumukit::Auth
117
125
  raise Mumukit::Auth::InvalidSlugFormatError, "Invalid slug: #{slug}. It must be in first/second format"
118
126
  end
119
127
  end
128
+
129
+ class Normalized < Slug
130
+ alias_method :_normalize!, :normalize!
131
+
132
+ def initialize(*)
133
+ super
134
+ _normalize!
135
+ end
136
+
137
+ def normalize
138
+ self
139
+ end
140
+
141
+ def normalize!
142
+ self
143
+ end
144
+
145
+ def normalized?
146
+ true
147
+ end
148
+ end
120
149
  end
121
150
 
122
151
  class InvalidSlugFormatError < StandardError
123
152
  end
124
153
  end
125
-
126
-
127
-
@@ -2,7 +2,7 @@ module Mumukit::Auth
2
2
  class Token
3
3
  attr_reader :jwt, :client
4
4
 
5
- def initialize(jwt, client)
5
+ def initialize(jwt = {}, client = Mumukit::Auth::Client.new)
6
6
  @jwt = jwt
7
7
  @client = client
8
8
  end
@@ -15,6 +15,22 @@ module Mumukit::Auth
15
15
  @uid ||= jwt['uid'] || jwt['email'] || jwt['sub']
16
16
  end
17
17
 
18
+ def organization
19
+ @organization ||= jwt['org']
20
+ end
21
+
22
+ def expiration
23
+ @expiration ||= Time.at jwt['exp']
24
+ end
25
+
26
+ def subject_id
27
+ @subject_id ||= jwt['sbid']
28
+ end
29
+
30
+ def subject_type
31
+ @subject_type ||= jwt['sbt']
32
+ end
33
+
18
34
  def verify_client!
19
35
  raise Mumukit::Auth::InvalidTokenError.new('aud mismatch') if client.id != jwt['aud']
20
36
  end
@@ -23,12 +39,13 @@ module Mumukit::Auth
23
39
  client.encode jwt
24
40
  end
25
41
 
26
- def self.from_rack_env(env)
27
- new(env.dig('omniauth.auth', 'extra', 'raw_info') || {})
42
+ def encode_header
43
+ 'Bearer ' + encode
28
44
  end
29
45
 
30
46
  def self.encode(uid, metadata, client = Mumukit::Auth::Client.new)
31
- new({aud: client.id, metadata: metadata, uid: uid}, client).encode
47
+ warn "Deprecated: please use build and then encode"
48
+ build(uid, client, metadata: metadata).encode
32
49
  end
33
50
 
34
51
  def self.decode(encoded, client = Mumukit::Auth::Client.new)
@@ -38,7 +55,8 @@ module Mumukit::Auth
38
55
  end
39
56
 
40
57
  def self.encode_header(uid, metadata)
41
- 'Bearer ' + encode(uid, metadata)
58
+ warn "Deprecated: please use build and then encode_header"
59
+ 'Bearer ' + build(uid, metadata: metadata).encode_header
42
60
  end
43
61
 
44
62
  def self.decode_header(header, client = Mumukit::Auth::Client.new)
@@ -50,6 +68,30 @@ module Mumukit::Auth
50
68
  header.split(' ').last
51
69
  end
52
70
 
71
+ def self.build(uid, client = Mumukit::Auth::Client.new,
72
+ expiration: nil, organization: nil,
73
+ subject_id: nil, subject_type: nil,
74
+ metadata: {})
75
+ new({
76
+ 'uid' => uid,
77
+ 'aud' => client.id,
78
+ 'exp' => expiration&.to_i,
79
+ 'org' => organization,
80
+ 'metadata' => metadata,
81
+ 'sbid' => subject_id,
82
+ 'sbt' => subject_type
83
+ }.compact,
84
+ client)
85
+ end
86
+
87
+ def self.load(encoded)
88
+ if encoded.present?
89
+ decode encoded rescue nil
90
+ end
91
+ end
92
+
93
+ def self.dump(decoded)
94
+ decoded.encode
95
+ end
53
96
  end
54
97
  end
55
-
@@ -1,5 +1,5 @@
1
1
  module Mumukit
2
2
  module Auth
3
- VERSION = '7.10.0'
3
+ VERSION = '7.13.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumukit-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.10.0
4
+ version: 7.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Leonardo Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-20 00:00:00.000000000 Z
11
+ date: 2022-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler