mumukit-auth 7.10.0 → 7.13.0

Sign up to get free protection for your applications and to get access to all the features.
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