isomorfeus-empowerment 2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8b9ca78286e54574f0295388fc69058dff4697173d544a215957aaf628d1f195
4
+ data.tar.gz: 4f8c8204a4fd01c1e778b5ab66b38d76f3fa41fb1640f98b9e685a6f09878f52
5
+ SHA512:
6
+ metadata.gz: 8271f0a513146ae534ba5c8303f83659d1f245a32bfc11423559e32de2f54db68bf1cf4e3b700d99433dcef43c7f3014c37d751d80ad7e79b7a38b4e3b3b7979
7
+ data.tar.gz: 408395a706c07e5af963d750187b617ff00aa3e7898146a59ac15337ac25f6807f9c0a8fc7a53931a85fc0e2795cc1551f9f8da7744cf826ba7ad87410809821
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Jan Biedermann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # isomorfeus-empowerment
2
+
3
+ Users, Authorization and Authentication for Isomorfeus.
4
+
5
+ ### Community and Support
6
+ At the [Isomorfeus Framework Project](https://isomorfeus.com)
7
+
8
+ ## Installation
9
+ isomorfeus-empowerment is usually installed with the installer.
10
+ Otherwise add to your Gemfile:
11
+ ```ruby
12
+ gem 'isomorfeus-empowerment'
13
+ ```
14
+ and bundle install/update
15
+
16
+ ## Usage
17
+
18
+ isomorfeus-empowerment provides severel helpful classes and infrastructure for users, authentication and sessions.
19
+
20
+ - [LucidUser](docs/user.md)
21
+ - [Authentication and Current User](docs/authentication.md)
22
+
23
+ Sessions are managed automatically and regularly cleaned up.
@@ -0,0 +1,11 @@
1
+ class Anonymous
2
+ include LucidUser::Authorization
3
+
4
+ def anonymous?
5
+ true
6
+ end
7
+
8
+ def key
9
+ 'anonymous'
10
+ end
11
+ end
@@ -0,0 +1,60 @@
1
+ module Isomorfeus
2
+ # available settings
3
+ class << self
4
+ if RUBY_ENGINE == 'opal'
5
+ def current_user
6
+ @current_user ||= init_current_user
7
+ end
8
+
9
+ def init_current_user
10
+ if Isomorfeus.current_user_sid
11
+ Isomorfeus.instance_from_sid(Isomorfeus.current_user_sid)
12
+ else
13
+ Anonymous.new
14
+ end
15
+ end
16
+
17
+ def set_current_user(user)
18
+ if user
19
+ @current_user = user
20
+ Isomorfeus.current_user_sid = user.sid
21
+ else
22
+ @current_user = Anonymous.new
23
+ Isomorfeus.current_user_sid = nil
24
+ end
25
+ end
26
+ else
27
+ attr_reader :session_class
28
+
29
+ def valid_user_class_names
30
+ @valid_user_class_names ||= Set.new
31
+ end
32
+
33
+ def valid_user_class_name?(class_name)
34
+ valid_user_class_names.include?(class_name)
35
+ end
36
+
37
+ def add_valid_user_class(klass)
38
+ valid_user_class_names << raw_class_name(klass)
39
+ end
40
+
41
+ def cached_user_classes
42
+ @cached_user_classes ||= {}
43
+ end
44
+
45
+ def cached_user_class(class_name)
46
+ return "::#{class_name}".constantize if Isomorfeus.development?
47
+ return cached_user_classes[class_name] if cached_user_classes.key?(class_name)
48
+ cached_user_classes[class_name] = "::#{class_name}".constantize
49
+ end
50
+
51
+ def current_user
52
+ Thread.current[:isomorfeus_user] ||= Anonymous.new
53
+ end
54
+
55
+ def session_class
56
+ @session_class ||= Isomorfeus::Empowerment::Session
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ Isomorfeus.operation_timer_tasks[:sessions] = Concurrent::TimerTask.new(execution_interval: 600, timeout_interval: 3600) do |timer_task|
2
+ Isomorfeus::Operation::RunTask.new(Isomorfeus::Empowerment::SessionTask, timer_task: timer_task, interval: 600, recurring: true).run
3
+ end
4
+
5
+ Isomorfeus.operation_timer_tasks[:sessions].execute
@@ -0,0 +1,11 @@
1
+ class LocalSystem
2
+ include LucidUser::Authorization
3
+
4
+ def anonymous?
5
+ false
6
+ end
7
+
8
+ def key
9
+ 'local_system'
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ class LocalSystemPolicy < LucidPolicy::Base
2
+ allow all
3
+ end
@@ -0,0 +1,63 @@
1
+ module Isomorfeus
2
+ module Empowerment
3
+ class Session < LucidObject::Base
4
+ # :key is the session_id
5
+ attribute :user_class_name, required: true
6
+ attribute :user_key, required: true
7
+ attribute :accessor, index: :value
8
+ attribute :cookie
9
+ attribute :ctime, required: true
10
+ attribute :atime, required: true # only updated when the last access is more than 10 minutes ago
11
+
12
+ class << self
13
+ def add(session_id:, cookie:, user:, accessor:)
14
+ t = Time.now
15
+ self.create(key: session_id, attributes: { user_class_name: user.class.name, user_key: user.key, cookie: cookie, accessor: accessor, ctime: t, atime: t })
16
+ end
17
+
18
+ def take_cookie(accessor:)
19
+ s = self.search(:accessor, accessor).first
20
+ if s
21
+ cookie = s.cookie
22
+ if cookie
23
+ session_info = cookie.split('; ').first
24
+ session_id = session_info.split('=').last.strip
25
+ s.cookie = nil
26
+ s.save
27
+ cookie
28
+ else
29
+ # asked for the same cookie a second time
30
+ # can probably only be due to session hijacking
31
+ # so delete session associated with that accessor
32
+ s.destroy
33
+ nil
34
+ end
35
+ end
36
+ end
37
+
38
+ def get_user(session_id:)
39
+ s = touch(session_id: session_id)
40
+ s.user_class_name.constantize.load(key: s.user_key) if s
41
+ rescue
42
+ nil
43
+ end
44
+
45
+ def touch(session_id:)
46
+ s = self.load(key: session_id)
47
+ return nil unless s
48
+ t = Time.now
49
+ if (t - s.atime) > 600
50
+ s.atime = t
51
+ s.save
52
+ end
53
+ s
54
+ end
55
+ alias_method :get_session, :touch
56
+
57
+ def remove(session_id:)
58
+ self.destroy(key: session_id)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,46 @@
1
+ module Isomorfeus
2
+ module Empowerment
3
+ class SessionCleanup < LucidSimpleOperation::Base
4
+ def self.sessions_cleaned
5
+ @sessions_cleaned
6
+ end
7
+
8
+ def self.sessions_cleaned=(v)
9
+ @sessions_cleaned = v
10
+ end
11
+
12
+ def self.sessions_counted
13
+ @sessions_counted
14
+ end
15
+
16
+ def self.sessions_counted=(v)
17
+ @sessions_counted = v
18
+ end
19
+
20
+ def self.reset_counters
21
+ @sessions_cleaned = 0
22
+ @sessions_counted = 0
23
+ end
24
+
25
+ op do
26
+ self.class.reset_counters
27
+ t = Time.now
28
+ # need to collect the sessions and then delete each individually to avoid a longstanding
29
+ # blocking transaction, that could potentially prevent new logins
30
+ sessions_to_cleanup = []
31
+ Isomorfeus::Empowerment::Session.each(readonly: true) do |session|
32
+ # cleanup sessions that have last been accessed more than 20 minutes ago
33
+ self.class.sessions_counted += 1
34
+ if (t - session.atime) > 1200
35
+ sessions_to_cleanup << session.key
36
+ end
37
+ end
38
+ sessions_to_cleanup.each do |key|
39
+ Isomorfeus::Empowerment::Session.destroy(key: key)
40
+ self.class.sessions_cleaned += 1
41
+ sleep 0.001 # sleep one millisecond to favor other transactions
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ module Isomorfeus
2
+ module Empowerment
3
+ class SessionTask < LucidObject::Base
4
+ STATES = %w[ready running failed]
5
+ # when the task is added to the queue its added as ready
6
+ # when its running, its running
7
+ # when it failes, it failed, the exception attribute is filled
8
+ # when it was successful, its removed from the queue
9
+ attribute :operation_class_name, class: String, required: true, validate_block: proc { |v| raise 'Invalid Operation class!' unless Isomorfeus.valid_operation_class_name?(v) }
10
+ attribute :props
11
+ attribute :user_class_name, class: String, default: 'Anonymous'
12
+ attribute :user_key, class: String, default: 'anonymous'
13
+ attribute :state, class: String, required: true, index: :value, ensure: proc { |v| Isomorfeus::Empowerment::SessionTask::STATES.include?(v) ? v : 'ready' }
14
+ attribute :exception
15
+ attribute :rtime
16
+ attribute :fail, default: false
17
+
18
+ def get_exception
19
+ Marshal.load(exception) if exception
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ module Isomorfeus
2
+ module Empowerment
3
+ VERSION = '2.3.0'
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ require 'isomorfeus-policy'
2
+ require 'isomorfeus-transport'
3
+ require 'isomorfeus-data'
4
+ require 'isomorfeus-operation'
5
+ require 'lucid_user/authentication'
6
+ require 'lucid_user/authorization'
7
+ require 'lucid_user/mixin'
8
+ require 'lucid_user/base'
9
+ require 'isomorfeus/empowerment/anonymous'
10
+ require 'isomorfeus/empowerment/config'
11
+
12
+ if RUBY_ENGINE != 'opal'
13
+ require 'active_support'
14
+ require 'isomorfeus/empowerment/session'
15
+ require 'isomorfeus/empowerment/session_cleanup'
16
+ require 'isomorfeus/empowerment/local_system'
17
+ require 'isomorfeus/empowerment/local_system_policy'
18
+ require 'isomorfeus/empowerment/session_task'
19
+ require 'isomorfeus/empowerment/init_timer_task'
20
+
21
+ # register daily session cleanup task
22
+ Isomorfeus::Empowerment::SessionTask.create(key: 'isomorfeus_empowerment_session_cleanup',
23
+ attributes: { operation_class_name: 'Isomorfeus::Empowerment::SessionCleanup',
24
+ props: {}, user_class_name: 'LocalSystem', user_key: 'local_system', state: 'ready', fail: false })
25
+
26
+ require 'iso_opal'
27
+ Opal.append_path(__dir__.untaint) unless IsoOpal.paths_include?(__dir__.untaint)
28
+ end
@@ -0,0 +1,123 @@
1
+ module LucidUser
2
+ module Authentication
3
+ def anonymous?
4
+ self.class == Anonymous
5
+ end
6
+
7
+ if RUBY_ENGINE == 'opal'
8
+ def self.included(base)
9
+ base.instance_exec do
10
+ def execute_login(&block)
11
+ end
12
+
13
+ def promise_login(user: nil, pass: nil, scheme: :isomorfeus, &block)
14
+ send("promise_authentication_with_#{scheme}", user: user, pass: pass, &block)
15
+ end
16
+
17
+ def promise_authentication_with_isomorfeus(user: nil, pass: nil, &block)
18
+ if Isomorfeus.production?
19
+ Isomorfeus.raise_error(message: "Connection not secure, can't login!") unless Isomorfeus::Transport.socket.url.start_with?('wss:')
20
+ else
21
+ `console.warn("Connection not secure, ensure a secure connection in production, otherwise login will fail!")` unless Isomorfeus::Transport.socket.url.start_with?('wss:')
22
+ end
23
+ Isomorfeus::Transport.promise_send_path('Isomorfeus::Transport::Handler::AuthenticationHandler', 'login', self.name, user, pass).then do |agent|
24
+ if agent.processed
25
+ agent.result
26
+ else
27
+ agent.processed = true
28
+ if agent.response.key?(:success)
29
+ Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: agent.response[:data])
30
+ class_name = agent.response[:data].keys.first
31
+ key = agent.response[:data][class_name].keys.first
32
+ logged_in_user = Isomorfeus.cached_data_class(class_name).new(key: key)
33
+ cookie_accessor = agent.response[:session_cookie_accessor]
34
+ begin
35
+ target = if block_given?
36
+ block.call(logged_in_user)
37
+ else
38
+ `window.location.pathname`
39
+ end
40
+ unless target.class == String && target.start_with?('/')
41
+ Isomorfeus.raise_error(message: "A path must be returned as string starting with '/', returned was #{target}!")
42
+ end
43
+ rescue
44
+ target = `window.location.pathname`
45
+ end
46
+ cookie_query = "#{Isomorfeus.cookie_eater_path}?#{cookie_accessor}=#{target}"
47
+ `window.location = cookie_query` # doing page load and redirect
48
+ nil
49
+ else
50
+ Isomorfeus.raise_error(message: "Login failed with '#{agent.response[:error]}'!") # triggers .fail
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def promise_logout(scheme: :isomorfeus)
59
+ send("promise_deauthentication_with_#{scheme}")
60
+ end
61
+
62
+ def promise_deauthentication_with_isomorfeus
63
+ cookie = `document.cookie`
64
+ p = Promise.new
65
+ begin
66
+ logout_query = Isomorfeus.api_logout_path
67
+ `window.location = logout_query`
68
+ rescue
69
+ p.reject
70
+ end
71
+ end
72
+ else
73
+ def self.included(base)
74
+ Isomorfeus.add_valid_user_class(base)
75
+
76
+ base.instance_exec do
77
+ def execute_login(&block)
78
+ @execute_login_block = block
79
+ end
80
+
81
+ def promise_login(user: nil, pass: nil, scheme: :isomorfeus, &block)
82
+ send("promise_authentication_with_#{scheme}", user: user, pass: pass, &block)
83
+ end
84
+
85
+ def promise_authentication_with_isomorfeus(user: nil, pass: nil, &block)
86
+ promise_or_user = @execute_login_block.call(user: user, pass: pass)
87
+ if promise_or_user.class == Promise
88
+ if block_given?
89
+ promise_or_user.then do |user|
90
+ block.call(user)
91
+ user
92
+ end
93
+ else
94
+ promise_or_user
95
+ end
96
+ else
97
+ block.call(user) if block_given?
98
+ Promise.new.resolve(promise_or_user)
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def encrypt_password(password, password_confirmation)
105
+ raise "Password and confirmation don't match!" unless password == password_confirmation
106
+ BCrypt::Password.create(password).to_s
107
+ end
108
+
109
+ def passwords_match?(encrypted_password, given_password)
110
+ bcrypt_pass = BCrypt::Password.new(encrypted_password)
111
+ bcrypt_pass == given_password
112
+ end
113
+
114
+ def promise_logout(scheme: :isomorfeus)
115
+ send("promise_deauthentication_with_#{scheme}")
116
+ end
117
+
118
+ def promise_deauthentication_with_isomorfeus
119
+ Promise.new.resolve(true)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,42 @@
1
+ module LucidUser
2
+ module Authorization
3
+ def record_authorization_reason
4
+ @_isomorfeus_record_authorization_reason = true
5
+ end
6
+
7
+ def stop_to_record_authorization_reason
8
+ @_isomorfeus_record_authorization_reason = false
9
+ @_isomorfeus_authorization_reason = nil
10
+ end
11
+
12
+ def authorization_reason
13
+ @_isomorfeus_authorization_reason
14
+ end
15
+
16
+ def authorized?(target_class, target_method = nil, props = nil)
17
+ begin
18
+ class_name = self.class.name
19
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
20
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
21
+ rescue ::NameError
22
+ policy_class = nil
23
+ end
24
+ return false unless policy_class
25
+ policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
26
+ result = policy_instance.authorized?(target_class, target_method, props)
27
+ @_isomorfeus_authorization_reason = policy_instance.reason
28
+ result
29
+ end
30
+
31
+ def authorized!(target_class, target_method = nil, props = nil)
32
+ class_name = self.class.name
33
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
34
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
35
+ Isomorfeus.raise_error(error_class: LucidPolicy::Exception, message: "#{self}: policy class #{class_name}Policy not found!") unless policy_class
36
+ policy_instance = policy_class.new(self, @_isomorfeus_record_authorization_reason)
37
+ result = policy_instance.authorized!(target_class, target_method, props)
38
+ @_isomorfeus_authorization_reason = policy_instance.reason
39
+ result
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ module LucidUser
2
+ class Base
3
+ def self.inherited(base)
4
+ base.include LucidUser::Mixin
5
+ if RUBY_ENGINE != 'opal'
6
+ Isomorfeus.add_valid_data_class(base)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module LucidUser
2
+ module Mixin
3
+ def self.included(base)
4
+ base.include(LucidObject::Mixin)
5
+ base.include(LucidUser::Authentication)
6
+ base.include(LucidUser::Authorization)
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: isomorfeus-empowerment
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Biedermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: isomorfeus-asset-manager
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.14.21
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.14.21
41
+ - !ruby/object:Gem::Dependency
42
+ name: isomorfeus-data
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 2.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: isomorfeus-operation
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.3.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: isomorfeus-policy
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 2.3.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 2.3.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: isomorfeus-transport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 2.3.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 2.3.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: isomorfeus
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 2.3.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 2.3.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.11.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.11.0
139
+ description: Users, Authorization and Authentication for Isomorfeus.
140
+ email: jan@kursator.de
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - LICENSE
146
+ - README.md
147
+ - lib/isomorfeus-empowerment.rb
148
+ - lib/isomorfeus/empowerment/anonymous.rb
149
+ - lib/isomorfeus/empowerment/config.rb
150
+ - lib/isomorfeus/empowerment/init_timer_task.rb
151
+ - lib/isomorfeus/empowerment/local_system.rb
152
+ - lib/isomorfeus/empowerment/local_system_policy.rb
153
+ - lib/isomorfeus/empowerment/session.rb
154
+ - lib/isomorfeus/empowerment/session_cleanup.rb
155
+ - lib/isomorfeus/empowerment/session_task.rb
156
+ - lib/isomorfeus/empowerment/version.rb
157
+ - lib/lucid_user/authentication.rb
158
+ - lib/lucid_user/authorization.rb
159
+ - lib/lucid_user/base.rb
160
+ - lib/lucid_user/mixin.rb
161
+ homepage: https://isomorfeus.com
162
+ licenses:
163
+ - MIT
164
+ metadata:
165
+ github_repo: ssh://github.com/isomorfeus/gems
166
+ source_code_uri: https://github.com/isomorfeus/isomorfeus-project/isomorfeus-empowerment
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubygems_version: 3.3.7
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Users, Authorization and Authentication for Isomorfeus.
186
+ test_files: []