otto 1.6.0 → 2.0.0.pre1
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/.github/workflows/ci.yml +1 -1
- data/.github/workflows/claude-code-review.yml +53 -0
- data/.github/workflows/claude.yml +49 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +24 -345
- data/CHANGELOG.rst +83 -0
- data/CLAUDE.md +56 -0
- data/Gemfile +10 -3
- data/Gemfile.lock +23 -28
- data/README.md +2 -0
- data/bin/rspec +4 -4
- data/changelog.d/20250911_235619_delano_next.rst +28 -0
- data/changelog.d/20250912_123055_delano_remove_ostruct.rst +21 -0
- data/changelog.d/20250912_175625_claude_delano_remove_ostruct.rst +21 -0
- data/changelog.d/README.md +120 -0
- data/changelog.d/scriv.ini +5 -0
- data/docs/.gitignore +1 -0
- data/docs/migrating/v2.0.0-pre1.md +276 -0
- data/examples/.gitignore +1 -0
- data/examples/advanced_routes/README.md +33 -0
- data/examples/advanced_routes/app/controllers/handlers/async.rb +9 -0
- data/examples/advanced_routes/app/controllers/handlers/dynamic.rb +9 -0
- data/examples/advanced_routes/app/controllers/handlers/static.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/auth.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/transformer.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/validator.rb +9 -0
- data/examples/advanced_routes/app/controllers/routes_app.rb +232 -0
- data/examples/advanced_routes/app/controllers/v2/admin.rb +9 -0
- data/examples/advanced_routes/app/controllers/v2/config.rb +9 -0
- data/examples/advanced_routes/app/controllers/v2/settings.rb +9 -0
- data/examples/advanced_routes/app/logic/admin/logic/manager.rb +27 -0
- data/examples/advanced_routes/app/logic/admin/panel.rb +27 -0
- data/examples/advanced_routes/app/logic/analytics_processor.rb +25 -0
- data/examples/advanced_routes/app/logic/complex/business/handler.rb +27 -0
- data/examples/advanced_routes/app/logic/data_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/data_processor.rb +25 -0
- data/examples/advanced_routes/app/logic/input_validator.rb +24 -0
- data/examples/advanced_routes/app/logic/nested/feature/logic.rb +27 -0
- data/examples/advanced_routes/app/logic/reports_generator.rb +27 -0
- data/examples/advanced_routes/app/logic/simple_logic.rb +25 -0
- data/examples/advanced_routes/app/logic/system/config/manager.rb +27 -0
- data/examples/advanced_routes/app/logic/test_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/transform_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/upload_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/v2/logic/dashboard.rb +27 -0
- data/examples/advanced_routes/app/logic/v2/logic/processor.rb +27 -0
- data/examples/advanced_routes/app.rb +33 -0
- data/examples/advanced_routes/config.rb +23 -0
- data/examples/advanced_routes/config.ru +7 -0
- data/examples/advanced_routes/puma.rb +20 -0
- data/examples/advanced_routes/routes +167 -0
- data/examples/advanced_routes/run.rb +39 -0
- data/examples/advanced_routes/test.rb +58 -0
- data/examples/authentication_strategies/README.md +32 -0
- data/examples/authentication_strategies/app/auth.rb +68 -0
- data/examples/authentication_strategies/app/controllers/auth_controller.rb +29 -0
- data/examples/authentication_strategies/app/controllers/main_controller.rb +28 -0
- data/examples/authentication_strategies/config.ru +24 -0
- data/examples/authentication_strategies/routes +37 -0
- data/examples/basic/README.md +29 -0
- data/examples/basic/app.rb +7 -35
- data/examples/basic/routes +0 -9
- data/examples/mcp_demo/README.md +87 -0
- data/examples/mcp_demo/app.rb +29 -34
- data/examples/mcp_demo/config.ru +9 -60
- data/examples/security_features/README.md +46 -0
- data/examples/security_features/app.rb +23 -24
- data/examples/security_features/config.ru +8 -10
- data/lib/otto/core/configuration.rb +167 -0
- data/lib/otto/core/error_handler.rb +86 -0
- data/lib/otto/core/file_safety.rb +61 -0
- data/lib/otto/core/middleware_stack.rb +157 -0
- data/lib/otto/core/router.rb +183 -0
- data/lib/otto/core/uri_generator.rb +44 -0
- data/lib/otto/design_system.rb +7 -5
- data/lib/otto/helpers/base.rb +3 -0
- data/lib/otto/helpers/request.rb +10 -8
- data/lib/otto/helpers/response.rb +5 -4
- data/lib/otto/helpers/validation.rb +9 -7
- data/lib/otto/mcp/auth/token.rb +10 -9
- data/lib/otto/mcp/protocol.rb +24 -27
- data/lib/otto/mcp/rate_limiting.rb +8 -3
- data/lib/otto/mcp/registry.rb +7 -2
- data/lib/otto/mcp/route_parser.rb +10 -15
- data/lib/otto/mcp/server.rb +21 -11
- data/lib/otto/mcp/validation.rb +14 -10
- data/lib/otto/response_handlers/auto.rb +39 -0
- data/lib/otto/response_handlers/base.rb +16 -0
- data/lib/otto/response_handlers/default.rb +16 -0
- data/lib/otto/response_handlers/factory.rb +39 -0
- data/lib/otto/response_handlers/json.rb +28 -0
- data/lib/otto/response_handlers/redirect.rb +25 -0
- data/lib/otto/response_handlers/view.rb +24 -0
- data/lib/otto/response_handlers.rb +9 -135
- data/lib/otto/route.rb +9 -9
- data/lib/otto/route_definition.rb +15 -18
- data/lib/otto/route_handlers/base.rb +121 -0
- data/lib/otto/route_handlers/class_method.rb +89 -0
- data/lib/otto/route_handlers/factory.rb +29 -0
- data/lib/otto/route_handlers/instance_method.rb +69 -0
- data/lib/otto/route_handlers/lambda.rb +59 -0
- data/lib/otto/route_handlers/logic_class.rb +93 -0
- data/lib/otto/route_handlers.rb +10 -405
- data/lib/otto/security/authentication/auth_strategy.rb +44 -0
- data/lib/otto/security/authentication/authentication_middleware.rb +123 -0
- data/lib/otto/security/authentication/failure_result.rb +36 -0
- data/lib/otto/security/authentication/strategies/api_key_strategy.rb +40 -0
- data/lib/otto/security/authentication/strategies/permission_strategy.rb +47 -0
- data/lib/otto/security/authentication/strategies/public_strategy.rb +19 -0
- data/lib/otto/security/authentication/strategies/role_strategy.rb +57 -0
- data/lib/otto/security/authentication/strategies/session_strategy.rb +41 -0
- data/lib/otto/security/authentication/strategy_result.rb +223 -0
- data/lib/otto/security/authentication.rb +28 -282
- data/lib/otto/security/config.rb +14 -12
- data/lib/otto/security/configurator.rb +219 -0
- data/lib/otto/security/csrf.rb +8 -143
- data/lib/otto/security/middleware/csrf_middleware.rb +151 -0
- data/lib/otto/security/middleware/rate_limit_middleware.rb +38 -0
- data/lib/otto/security/middleware/validation_middleware.rb +252 -0
- data/lib/otto/security/rate_limiter.rb +86 -0
- data/lib/otto/security/rate_limiting.rb +10 -105
- data/lib/otto/security/validator.rb +8 -253
- data/lib/otto/static.rb +3 -0
- data/lib/otto/utils.rb +14 -0
- data/lib/otto/version.rb +3 -1
- data/lib/otto.rb +142 -498
- data/otto.gemspec +2 -2
- metadata +89 -28
- data/examples/dynamic_pages/app.rb +0 -115
- data/examples/dynamic_pages/config.ru +0 -30
- data/examples/dynamic_pages/routes +0 -21
- data/examples/helpers_demo/app.rb +0 -244
- data/examples/helpers_demo/config.ru +0 -26
- data/examples/helpers_demo/routes +0 -7
- data/lib/concurrent_cache_store.rb +0 -68
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../auth_strategy'
|
4
|
+
|
5
|
+
class Otto
|
6
|
+
module Security
|
7
|
+
module Authentication
|
8
|
+
module Strategies
|
9
|
+
# Permission-based authentication strategy
|
10
|
+
class PermissionStrategy < AuthStrategy
|
11
|
+
def initialize(required_permissions, session_key: 'user_permissions')
|
12
|
+
@required_permissions = Array(required_permissions)
|
13
|
+
@session_key = session_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def authenticate(env, requirement)
|
17
|
+
session = env['rack.session']
|
18
|
+
return failure('No session available') unless session
|
19
|
+
|
20
|
+
user_permissions = session[@session_key] || []
|
21
|
+
user_permissions = Array(user_permissions)
|
22
|
+
|
23
|
+
# Create user data from session
|
24
|
+
user_data = { user_permissions: user_permissions, session: session }
|
25
|
+
|
26
|
+
# Extract permission from requirement (e.g., "permission:write" -> "write")
|
27
|
+
required_permission = requirement.split(':', 2).last
|
28
|
+
|
29
|
+
if user_permissions.include?(required_permission)
|
30
|
+
success(user: user_data, user_permissions: user_permissions, required_permission: required_permission)
|
31
|
+
else
|
32
|
+
failure("Insufficient privileges - requires permission: #{required_permission}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def user_context(env)
|
37
|
+
session = env['rack.session']
|
38
|
+
return {} unless session
|
39
|
+
|
40
|
+
user_permissions = session[@session_key] || []
|
41
|
+
{ user_permissions: Array(user_permissions) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../auth_strategy'
|
4
|
+
require_relative '../strategy_result'
|
5
|
+
|
6
|
+
class Otto
|
7
|
+
module Security
|
8
|
+
module Authentication
|
9
|
+
module Strategies
|
10
|
+
# Public access strategy - always allows access
|
11
|
+
class PublicStrategy < AuthStrategy
|
12
|
+
def authenticate(env, _requirement)
|
13
|
+
Otto::Security::Authentication::StrategyResult.anonymous(metadata: { ip: env['REMOTE_ADDR'] })
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../auth_strategy'
|
4
|
+
|
5
|
+
class Otto
|
6
|
+
module Security
|
7
|
+
module Authentication
|
8
|
+
module Strategies
|
9
|
+
# Role-based authentication strategy
|
10
|
+
class RoleStrategy < AuthStrategy
|
11
|
+
def initialize(allowed_roles, session_key: 'user_roles')
|
12
|
+
@allowed_roles = Array(allowed_roles)
|
13
|
+
@session_key = session_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def authenticate(env, requirement)
|
17
|
+
session = env['rack.session']
|
18
|
+
return failure('No session available') unless session
|
19
|
+
|
20
|
+
user_roles = session[@session_key] || []
|
21
|
+
user_roles = Array(user_roles)
|
22
|
+
|
23
|
+
# Create user data from session
|
24
|
+
user_data = { user_roles: user_roles, session: session }
|
25
|
+
|
26
|
+
# For requirements like "role:admin", extract the role part
|
27
|
+
if requirement.include?(':')
|
28
|
+
required_role = requirement.split(':', 2).last
|
29
|
+
if user_roles.include?(required_role)
|
30
|
+
success(user: user_data, user_roles: user_roles, required_role: required_role)
|
31
|
+
else
|
32
|
+
failure("Insufficient privileges - requires role: #{required_role}")
|
33
|
+
end
|
34
|
+
else
|
35
|
+
# For direct strategy matches, check if user has any of the allowed roles
|
36
|
+
matching_roles = user_roles & @allowed_roles
|
37
|
+
if matching_roles.any?
|
38
|
+
success(user: user_data, user_roles: user_roles, allowed_roles: @allowed_roles,
|
39
|
+
matching_roles: matching_roles)
|
40
|
+
else
|
41
|
+
failure("Insufficient privileges - requires one of roles: #{@allowed_roles.join(', ')}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def user_context(env)
|
47
|
+
session = env['rack.session']
|
48
|
+
return {} unless session
|
49
|
+
|
50
|
+
user_roles = session[@session_key] || []
|
51
|
+
{ user_roles: Array(user_roles) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../auth_strategy'
|
4
|
+
|
5
|
+
class Otto
|
6
|
+
module Security
|
7
|
+
module Authentication
|
8
|
+
module Strategies
|
9
|
+
# Session-based authentication strategy
|
10
|
+
class SessionStrategy < AuthStrategy
|
11
|
+
def initialize(session_key: 'user_id', session_store: nil)
|
12
|
+
@session_key = session_key
|
13
|
+
@session_store = session_store
|
14
|
+
end
|
15
|
+
|
16
|
+
def authenticate(env, _requirement)
|
17
|
+
session = env['rack.session']
|
18
|
+
return failure('No session available') unless session
|
19
|
+
|
20
|
+
user_id = session[@session_key]
|
21
|
+
return failure('Not authenticated') unless user_id
|
22
|
+
|
23
|
+
# Create a simple user hash for the generic strategy
|
24
|
+
user_data = { id: user_id, user_id: user_id }
|
25
|
+
success(session: session, user: user_data, auth_method: 'session')
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_context(env)
|
29
|
+
session = env['rack.session']
|
30
|
+
return {} unless session
|
31
|
+
|
32
|
+
user_id = session[@session_key]
|
33
|
+
return {} unless user_id
|
34
|
+
|
35
|
+
{ user_id: user_id }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/otto/security/authentication/strategy_result.rb
|
4
|
+
|
5
|
+
# StrategyResult is an immutable data structure that holds the result of an
|
6
|
+
# authentication strategy. It contains session, user, and metadata needed by
|
7
|
+
# Otto Logic classes.
|
8
|
+
#
|
9
|
+
# @example Basic usage
|
10
|
+
# result = StrategyResult.new(
|
11
|
+
# session: { id: 'abc123', user_id: 1 },
|
12
|
+
# user: user_model_instance, # Actual user model, not a hash
|
13
|
+
# auth_method: 'token',
|
14
|
+
# metadata: { ip: '127.0.0.1' }
|
15
|
+
# )
|
16
|
+
#
|
17
|
+
# result.authenticated? #=> true
|
18
|
+
# result.has_role?('admin') #=> true
|
19
|
+
# result.user.name #=> 'John' (assuming user model has name method)
|
20
|
+
#
|
21
|
+
class Otto
|
22
|
+
module Security
|
23
|
+
module Authentication
|
24
|
+
StrategyResult = Data.define(:session, :user, :auth_method, :metadata) do
|
25
|
+
# Create an anonymous (unauthenticated) result
|
26
|
+
# @return [StrategyResult] Anonymous result with empty session and nil user
|
27
|
+
def self.anonymous(metadata: {})
|
28
|
+
new(
|
29
|
+
session: {},
|
30
|
+
user: nil, # Changed from {} to nil - clearer semantics
|
31
|
+
auth_method: 'anonymous',
|
32
|
+
metadata: metadata
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Check if the request is authenticated (has a user)
|
37
|
+
# @return [Boolean] True if user is present, false otherwise
|
38
|
+
def authenticated?
|
39
|
+
!user.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check if the request is anonymous (no user)
|
43
|
+
# @return [Boolean] True if not authenticated
|
44
|
+
def anonymous?
|
45
|
+
user.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Success/failure methods for compatibility
|
49
|
+
def success?
|
50
|
+
true # If we have a StrategyResult, authentication succeeded
|
51
|
+
end
|
52
|
+
|
53
|
+
def failure?
|
54
|
+
false # Failures return nil, not a StrategyResult
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Check if the user has a specific role
|
59
|
+
# @param role [String, Symbol] Role to check
|
60
|
+
# @return [Boolean] True if user has the role
|
61
|
+
def has_role?(role)
|
62
|
+
return false unless authenticated?
|
63
|
+
|
64
|
+
# Try user model methods first, fall back to hash access for backward compatibility
|
65
|
+
if user.respond_to?(:role)
|
66
|
+
user.role.to_s == role.to_s
|
67
|
+
elsif user.respond_to?(:has_role?)
|
68
|
+
user.has_role?(role)
|
69
|
+
elsif user.is_a?(Hash)
|
70
|
+
user_role = user[:role] || user['role']
|
71
|
+
user_role.to_s == role.to_s
|
72
|
+
else
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Check if the user has a specific permission
|
78
|
+
# @param permission [String, Symbol] Permission to check
|
79
|
+
# @return [Boolean] True if user has the permission
|
80
|
+
def has_permission?(permission)
|
81
|
+
return false unless authenticated?
|
82
|
+
|
83
|
+
# Try user model methods first, fall back to hash access for backward compatibility
|
84
|
+
if user.respond_to?(:has_permission?)
|
85
|
+
user.has_permission?(permission)
|
86
|
+
elsif user.respond_to?(:permissions)
|
87
|
+
permissions = user.permissions || []
|
88
|
+
permissions = [permissions] unless permissions.is_a?(Array)
|
89
|
+
permissions.map(&:to_s).include?(permission.to_s)
|
90
|
+
elsif user.is_a?(Hash)
|
91
|
+
permissions = user[:permissions] || user['permissions'] || []
|
92
|
+
permissions = [permissions] unless permissions.is_a?(Array)
|
93
|
+
permissions.map(&:to_s).include?(permission.to_s)
|
94
|
+
else
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Check if the user has any of the specified roles
|
100
|
+
# @param roles [Array<String, Symbol>] Roles to check
|
101
|
+
# @return [Boolean] True if user has any of the roles
|
102
|
+
def has_any_role?(*roles)
|
103
|
+
roles.flatten.any? { |role| has_role?(role) }
|
104
|
+
end
|
105
|
+
|
106
|
+
# Check if the user has any of the specified permissions
|
107
|
+
# @param permissions [Array<String, Symbol>] Permissions to check
|
108
|
+
# @return [Boolean] True if user has any of the permissions
|
109
|
+
def has_any_permission?(*permissions)
|
110
|
+
permissions.flatten.any? { |permission| has_permission?(permission) }
|
111
|
+
end
|
112
|
+
|
113
|
+
# Get user ID from various possible locations
|
114
|
+
# @return [String, Integer, nil] User ID or nil
|
115
|
+
def user_id
|
116
|
+
return nil unless authenticated?
|
117
|
+
|
118
|
+
# Try user model methods first, fall back to hash access and session
|
119
|
+
if user.respond_to?(:id)
|
120
|
+
user.id
|
121
|
+
elsif user.respond_to?(:user_id)
|
122
|
+
user.user_id
|
123
|
+
elsif user.is_a?(Hash)
|
124
|
+
user[:id] || user['id'] || user[:user_id] || user['user_id']
|
125
|
+
end || session[:user_id] || session['user_id']
|
126
|
+
end
|
127
|
+
|
128
|
+
# Get user name from various possible locations
|
129
|
+
# @return [String, nil] User name or nil
|
130
|
+
def user_name
|
131
|
+
return nil unless authenticated?
|
132
|
+
|
133
|
+
# Try user model methods first, fall back to hash access
|
134
|
+
if user.respond_to?(:name)
|
135
|
+
user.name
|
136
|
+
elsif user.respond_to?(:username)
|
137
|
+
user.username
|
138
|
+
elsif user.is_a?(Hash)
|
139
|
+
user[:name] || user['name'] || user[:username] || user['username']
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Get session ID from various possible locations
|
144
|
+
# @return [String, nil] Session ID or nil
|
145
|
+
def session_id
|
146
|
+
session[:id] || session['id'] || session[:session_id] || session['session_id']
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get all user roles as an array
|
150
|
+
# @return [Array<String>] Array of roles (empty if none)
|
151
|
+
def roles
|
152
|
+
return [] unless authenticated?
|
153
|
+
|
154
|
+
roles_data = user[:roles] || user['roles']
|
155
|
+
if roles_data.is_a?(Array)
|
156
|
+
roles_data.map(&:to_s)
|
157
|
+
elsif roles_data
|
158
|
+
[roles_data.to_s]
|
159
|
+
else
|
160
|
+
role = user[:role] || user['role']
|
161
|
+
role ? [role.to_s] : []
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Get all user permissions as an array
|
166
|
+
# @return [Array<String>] Array of permissions (empty if none)
|
167
|
+
def permissions
|
168
|
+
return [] unless authenticated?
|
169
|
+
|
170
|
+
perms = user[:permissions] || user['permissions'] || []
|
171
|
+
perms = [perms] unless perms.is_a?(Array)
|
172
|
+
perms.map(&:to_s)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Create a string representation for debugging
|
176
|
+
# @return [String] Debug representation
|
177
|
+
def inspect
|
178
|
+
if authenticated?
|
179
|
+
"#<StrategyResult authenticated user=#{user_name || user_id} roles=#{roles} method=#{auth_method}>"
|
180
|
+
else
|
181
|
+
"#<StrategyResult anonymous method=#{auth_method}>"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Get user context - a hash containing user-specific information and metadata
|
186
|
+
# @return [Hash] User context hash
|
187
|
+
def user_context
|
188
|
+
if authenticated?
|
189
|
+
case auth_method
|
190
|
+
when 'session'
|
191
|
+
{ user_id: user_id, session: session }
|
192
|
+
else
|
193
|
+
metadata
|
194
|
+
end
|
195
|
+
else
|
196
|
+
case auth_method
|
197
|
+
when 'anonymous'
|
198
|
+
{}
|
199
|
+
else
|
200
|
+
metadata
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Create a hash representation
|
206
|
+
# @return [Hash] Hash representation of the context
|
207
|
+
def to_h
|
208
|
+
{
|
209
|
+
session: session,
|
210
|
+
user: user,
|
211
|
+
auth_method: auth_method,
|
212
|
+
metadata: metadata,
|
213
|
+
authenticated: authenticated?,
|
214
|
+
user_id: user_id,
|
215
|
+
user_name: user_name,
|
216
|
+
roles: roles,
|
217
|
+
permissions: permissions
|
218
|
+
}
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|