propel_authentication 0.2.1 → 0.3.1
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/CHANGELOG.md +60 -0
- data/lib/generators/propel_authentication/install_generator.rb +190 -228
- data/lib/generators/propel_authentication/templates/auth/passwords_controller.rb.tt +10 -13
- data/lib/generators/propel_authentication/templates/auth/signup_controller.rb.tt +6 -9
- data/lib/generators/propel_authentication/templates/auth/tokens_controller.rb.tt +4 -7
- data/lib/generators/propel_authentication/templates/core/configuration_methods.rb +38 -1
- data/lib/generators/propel_authentication/templates/db/migrate/create_agencies.rb +4 -2
- data/lib/generators/propel_authentication/templates/db/migrate/create_agents.rb +6 -1
- data/lib/generators/propel_authentication/templates/db/migrate/create_organizations.rb +4 -2
- data/lib/generators/propel_authentication/templates/db/migrate/create_users.rb +4 -2
- data/lib/generators/propel_authentication/templates/db/propel_seeds.rb.tt +145 -0
- data/lib/generators/propel_authentication/templates/doc/signup_flow.md +9 -4
- data/lib/generators/propel_authentication/templates/fixtures/agencies.yml.erb +23 -0
- data/lib/generators/propel_authentication/templates/fixtures/agents.yml.erb +71 -0
- data/lib/generators/propel_authentication/templates/fixtures/invitations.yml.erb +9 -0
- data/lib/generators/propel_authentication/templates/fixtures/organizations.yml.erb +21 -0
- data/lib/generators/propel_authentication/templates/fixtures/users.yml.erb +77 -0
- data/lib/generators/propel_authentication/templates/models/agency.rb.tt +8 -2
- data/lib/generators/propel_authentication/templates/models/agent.rb.tt +13 -2
- data/lib/generators/propel_authentication/templates/models/invitation.rb.tt +3 -1
- data/lib/generators/propel_authentication/templates/models/organization.rb.tt +15 -2
- data/lib/generators/propel_authentication/templates/models/user.rb.tt +18 -2
- data/lib/generators/propel_authentication/templates/propel_authentication.rb.tt +33 -6
- data/lib/generators/propel_authentication/templates/test/controllers/auth/lockable_integration_test.rb.tt +2 -2
- data/lib/generators/propel_authentication/templates/test/controllers/auth/password_reset_integration_test.rb.tt +9 -9
- data/lib/generators/propel_authentication/templates/test/controllers/auth/signup_controller_test.rb.tt +6 -6
- data/lib/generators/propel_authentication/templates/test/controllers/auth/tokens_controller_test.rb.tt +4 -4
- data/lib/generators/propel_authentication/test/generators/authentication/controllers/tokens_controller_test.rb +1 -1
- data/lib/generators/propel_authentication/test/generators/authentication/install_generator_test.rb +1 -1
- data/lib/generators/propel_authentication/test/integration/multi_version_generator_test.rb +12 -13
- data/lib/propel_authentication.rb +1 -1
- metadata +30 -5
- data/lib/generators/propel_authentication/templates/db/seeds.rb +0 -75
|
@@ -44,7 +44,9 @@ module PropelAuthentication
|
|
|
44
44
|
:support_email,
|
|
45
45
|
:enable_email_notifications,
|
|
46
46
|
:enable_sms_notifications,
|
|
47
|
-
:
|
|
47
|
+
:tenancy_enabled,
|
|
48
|
+
:organization_required,
|
|
49
|
+
:agency_required,
|
|
48
50
|
:require_organization_id,
|
|
49
51
|
:require_user_id,
|
|
50
52
|
:namespace,
|
|
@@ -105,9 +107,13 @@ module PropelAuthentication
|
|
|
105
107
|
@enable_email_notifications = true
|
|
106
108
|
@enable_sms_notifications = false # Requires SMS provider configuration
|
|
107
109
|
|
|
108
|
-
# Tenancy configuration
|
|
109
|
-
#
|
|
110
|
-
@
|
|
110
|
+
# Tenancy configuration - hierarchical structure
|
|
111
|
+
# Master switch: enables/disables entire multi-tenancy system
|
|
112
|
+
@tenancy_enabled = <%= tenancy_enabled? %> # <%= tenancy_enabled? ? 'Enable' : 'Disable' %> multi-tenancy system
|
|
113
|
+
|
|
114
|
+
# Individual tenancy model requirements (only effective when tenancy_enabled = true)
|
|
115
|
+
@organization_required = <%= organization_required? %> # <%= organization_required? ? 'Require' : 'Optional' %> organization association
|
|
116
|
+
@agency_required = <%= agency_required? %> # <%= agency_required? ? 'Enable' : 'Disable' %> agency-level tenancy
|
|
111
117
|
|
|
112
118
|
# API tenancy requirements (for PropelApi integration)
|
|
113
119
|
# Controls whether APIs require explicit tenancy context in requests
|
|
@@ -120,6 +126,19 @@ module PropelAuthentication
|
|
|
120
126
|
@version = nil
|
|
121
127
|
@auth_scope = nil
|
|
122
128
|
end
|
|
129
|
+
|
|
130
|
+
# Helper methods for template conditionals
|
|
131
|
+
def tenancy_enabled?
|
|
132
|
+
@tenancy_enabled
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def organization_required?
|
|
136
|
+
@tenancy_enabled && @organization_required
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def agency_required?
|
|
140
|
+
@tenancy_enabled && @agency_required
|
|
141
|
+
end
|
|
123
142
|
end
|
|
124
143
|
end
|
|
125
144
|
|
|
@@ -141,11 +160,19 @@ PropelAuthentication.configure do |config|
|
|
|
141
160
|
# User registration settings
|
|
142
161
|
config.allow_registration = true
|
|
143
162
|
|
|
144
|
-
# Multi-tenancy settings
|
|
163
|
+
# Multi-tenancy settings - hierarchical configuration
|
|
164
|
+
# Master switch: enables/disables entire multi-tenancy system
|
|
165
|
+
# When false: Single-tenant mode (no tenancy models required)
|
|
166
|
+
config.tenancy_enabled = <%= tenancy_enabled? %>
|
|
167
|
+
|
|
168
|
+
# Individual tenancy model requirements (only effective when tenancy_enabled = true)
|
|
169
|
+
# Controls whether users must belong to organizations
|
|
170
|
+
config.organization_required = <%= organization_required? %>
|
|
171
|
+
|
|
145
172
|
# Controls whether agency-level tenancy is enabled within organizations
|
|
146
173
|
# When true: Organization -> Agency -> Resources structure
|
|
147
174
|
# When false: Organization -> Resources structure (simpler)
|
|
148
|
-
config.
|
|
175
|
+
config.agency_required = <%= agency_required? %>
|
|
149
176
|
|
|
150
177
|
# API tenancy requirements (for PropelApi integration)
|
|
151
178
|
# Controls whether clients must provide explicit tenancy context in API requests
|
|
@@ -11,7 +11,7 @@ class <%= controller_namespace('tokens') %>LockableIntegrationTest < ActionDispa
|
|
|
11
11
|
organization: @organization
|
|
12
12
|
)
|
|
13
13
|
# Create agent association for agency access (required for real-time agency lookup)
|
|
14
|
-
Agent.create!(user: @user, agency: @agency, role: "member")
|
|
14
|
+
Agent.create!(user: @user, agency: @agency, organization: @organization, role: "member")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# CRITICAL: Real API integration with lockable functionality
|
|
@@ -148,7 +148,7 @@ class <%= controller_namespace('tokens') %>LockableIntegrationTest < ActionDispa
|
|
|
148
148
|
|
|
149
149
|
post '<%= auth_route_prefix %>/unlock', params: {}
|
|
150
150
|
|
|
151
|
-
assert_response :
|
|
151
|
+
assert_response :unprocessable_content, "Missing token should return 422"
|
|
152
152
|
|
|
153
153
|
json = JSON.parse(response.body)
|
|
154
154
|
assert_match(/token.*required/i, json['error'], "Should indicate token is required")
|
|
@@ -13,7 +13,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
13
13
|
last_name: "User"
|
|
14
14
|
)
|
|
15
15
|
# Create agent association for agency access (required for real-time agency lookup)
|
|
16
|
-
Agent.create!(user: @user, agency: @agency, role: "member")
|
|
16
|
+
Agent.create!(user: @user, agency: @agency, organization: @organization, role: "member")
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# POST <%= auth_route_prefix %>/reset - Request Password Reset Tests
|
|
@@ -39,7 +39,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
39
39
|
post '<%= auth_route_prefix %>/reset', params: { email_address: "invalid-email-format" }
|
|
40
40
|
|
|
41
41
|
# VERIFY VALIDATION ERROR: Should return validation error
|
|
42
|
-
assert_response :
|
|
42
|
+
assert_response :unprocessable_content, "Invalid email_address format should be rejected"
|
|
43
43
|
|
|
44
44
|
response_json = JSON.parse(response.body)
|
|
45
45
|
assert_match(/email.*invalid/i, response_json['error'], "Should indicate email_address format error")
|
|
@@ -65,7 +65,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
65
65
|
post '<%= auth_route_prefix %>/reset', params: {}
|
|
66
66
|
|
|
67
67
|
# VERIFY PARAMETER VALIDATION: Should return parameter error
|
|
68
|
-
assert_response :
|
|
68
|
+
assert_response :unprocessable_content, "Missing email_address should return validation error"
|
|
69
69
|
|
|
70
70
|
response_json = JSON.parse(response.body)
|
|
71
71
|
assert_match(/email.*required/i, response_json['error'], "Should indicate email_address is required")
|
|
@@ -181,7 +181,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
# VERIFY VALIDATION: Should return validation error
|
|
184
|
-
assert_response :
|
|
184
|
+
assert_response :unprocessable_content, "Mismatched passwords should be rejected"
|
|
185
185
|
|
|
186
186
|
response_json = JSON.parse(response.body)
|
|
187
187
|
assert_match(/password.*confirmation.*match/i, response_json['error'], "Should indicate password mismatch")
|
|
@@ -205,7 +205,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
# VERIFY VALIDATION: Should return validation error
|
|
208
|
-
assert_response :
|
|
208
|
+
assert_response :unprocessable_content, "Weak password should be rejected"
|
|
209
209
|
|
|
210
210
|
response_json = JSON.parse(response.body)
|
|
211
211
|
assert_match(/password.*too short/i, response_json['error'], "Should indicate password strength issue")
|
|
@@ -226,7 +226,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
226
226
|
password_confirmation: "newpassword123"
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
assert_response :
|
|
229
|
+
assert_response :unprocessable_content, "Missing token should be rejected"
|
|
230
230
|
|
|
231
231
|
# TEST MISSING PASSWORD
|
|
232
232
|
patch '<%= auth_route_prefix %>/reset', params: {
|
|
@@ -234,7 +234,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
234
234
|
password_confirmation: "newpassword123"
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
assert_response :
|
|
237
|
+
assert_response :unprocessable_content, "Missing password should be rejected"
|
|
238
238
|
|
|
239
239
|
# TEST MISSING CONFIRMATION
|
|
240
240
|
patch '<%= auth_route_prefix %>/reset', params: {
|
|
@@ -242,7 +242,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
242
242
|
password: "newpassword123"
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
assert_response :
|
|
245
|
+
assert_response :unprocessable_content, "Missing password confirmation should be rejected"
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
test "should clear failed login attempts on successful password reset" do
|
|
@@ -356,7 +356,7 @@ class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < Act
|
|
|
356
356
|
get '<%= auth_route_prefix %>/reset', params: {}
|
|
357
357
|
|
|
358
358
|
# VERIFY PARAMETER VALIDATION: Should return parameter error
|
|
359
|
-
assert_response :
|
|
359
|
+
assert_response :unprocessable_content, "Missing token should return validation error"
|
|
360
360
|
|
|
361
361
|
response_json = JSON.parse(response.body)
|
|
362
362
|
assert_match(/token.*required/i, response_json['error'], "Should indicate token is required")
|
|
@@ -111,7 +111,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
111
111
|
params: invalid_params,
|
|
112
112
|
as: :json
|
|
113
113
|
|
|
114
|
-
assert_response :
|
|
114
|
+
assert_response :unprocessable_content
|
|
115
115
|
response_body = JSON.parse(response.body)
|
|
116
116
|
assert_includes response_body.keys, 'error'
|
|
117
117
|
end
|
|
@@ -123,7 +123,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
123
123
|
params: invalid_params,
|
|
124
124
|
as: :json
|
|
125
125
|
|
|
126
|
-
assert_response :
|
|
126
|
+
assert_response :unprocessable_content
|
|
127
127
|
response_body = JSON.parse(response.body)
|
|
128
128
|
assert_includes response_body.keys, 'error'
|
|
129
129
|
end
|
|
@@ -136,7 +136,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
136
136
|
params: invalid_params,
|
|
137
137
|
as: :json
|
|
138
138
|
|
|
139
|
-
assert_response :
|
|
139
|
+
assert_response :unprocessable_content
|
|
140
140
|
response_body = JSON.parse(response.body)
|
|
141
141
|
assert_includes response_body.keys, 'details'
|
|
142
142
|
assert_includes response_body['details'].keys, 'email_address'
|
|
@@ -150,7 +150,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
150
150
|
params: invalid_params,
|
|
151
151
|
as: :json
|
|
152
152
|
|
|
153
|
-
assert_response :
|
|
153
|
+
assert_response :unprocessable_content
|
|
154
154
|
response_body = JSON.parse(response.body)
|
|
155
155
|
assert_includes response_body.keys, 'details'
|
|
156
156
|
end
|
|
@@ -172,7 +172,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
172
172
|
params: duplicate_params,
|
|
173
173
|
as: :json
|
|
174
174
|
|
|
175
|
-
assert_response :
|
|
175
|
+
assert_response :unprocessable_content
|
|
176
176
|
response_body = JSON.parse(response.body)
|
|
177
177
|
assert_includes response_body.keys, 'details'
|
|
178
178
|
assert_includes response_body['details'].keys, 'email_address'
|
|
@@ -186,7 +186,7 @@ class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch
|
|
|
186
186
|
params: @valid_signup_params,
|
|
187
187
|
as: :json
|
|
188
188
|
|
|
189
|
-
assert_response :
|
|
189
|
+
assert_response :unprocessable_content
|
|
190
190
|
response_body = JSON.parse(response.body)
|
|
191
191
|
assert_equal 'MISSING_AGENCY_DATA', response_body['code']
|
|
192
192
|
end
|
|
@@ -51,9 +51,9 @@ class <%= controller_namespace('tokens') %>TokensControllerTest < ActionDispatch
|
|
|
51
51
|
@agency = Agency.create!(name: "Main Agency", organization: @organization)
|
|
52
52
|
@rival_agency = Agency.create!(name: "Rival Agency", organization: @rival_organization)
|
|
53
53
|
|
|
54
|
-
Agent.create!(user: @valid_user, agency: @agency, role: "member")
|
|
55
|
-
Agent.create!(user: @other_user, agency: @rival_agency, role: "member")
|
|
56
|
-
Agent.create!(user: @inactive_user, agency: @agency, role: "member")
|
|
54
|
+
Agent.create!(user: @valid_user, agency: @agency, organization: @organization, role: "member")
|
|
55
|
+
Agent.create!(user: @other_user, agency: @rival_agency, organization: @rival_organization, role: "member")
|
|
56
|
+
Agent.create!(user: @inactive_user, agency: @agency, organization: @organization, role: "member")
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
test "POST <%= auth_route_prefix %>/login with valid credentials returns JWT token and user data" do
|
|
@@ -232,7 +232,7 @@ class <%= controller_namespace('tokens') %>TokensControllerTest < ActionDispatch
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
# VERIFY PARAMETER VALIDATION: Check required field enforcement
|
|
235
|
-
assert_response :
|
|
235
|
+
assert_response :bad_request, "Missing required parameters should return bad_request"
|
|
236
236
|
response_json = JSON.parse(response.body)
|
|
237
237
|
assert response_json["error"].present?, "Should return validation error message"
|
|
238
238
|
end
|
|
@@ -72,7 +72,7 @@ class TokensControllerTest < ActionDispatch::IntegrationTest
|
|
|
72
72
|
}
|
|
73
73
|
}, as: :json
|
|
74
74
|
|
|
75
|
-
assert_response :
|
|
75
|
+
assert_response :unprocessable_content
|
|
76
76
|
|
|
77
77
|
response_body = JSON.parse(response.body)
|
|
78
78
|
assert response_body.key?("error"), "Should return error message"
|
data/lib/generators/propel_authentication/test/generators/authentication/install_generator_test.rb
CHANGED
|
@@ -151,7 +151,7 @@ class Propel::Authentication::InstallGeneratorTest < Rails::Generators::TestCase
|
|
|
151
151
|
assert_match(/t\.references :organization/, migration)
|
|
152
152
|
|
|
153
153
|
# JSON fields for flexible data storage
|
|
154
|
-
assert_match(/t\.jsonb :
|
|
154
|
+
assert_match(/t\.jsonb :metadata, default: {}/, migration)
|
|
155
155
|
assert_match(/t\.jsonb :settings, default: {}/, migration)
|
|
156
156
|
|
|
157
157
|
# Proper indexes for JWT authentication performance
|
|
@@ -16,32 +16,31 @@ class MultiVersionGeneratorTest < Rails::Generators::TestCase
|
|
|
16
16
|
super
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
test "generator creates dynamic
|
|
20
|
-
run_generator ["--
|
|
19
|
+
test "generator creates dynamic API versioning structure" do
|
|
20
|
+
run_generator ["--configurable-versioning"]
|
|
21
21
|
|
|
22
|
-
# Verify
|
|
23
|
-
assert_file "app/controllers/api/
|
|
24
|
-
assert_match(/class Api::
|
|
25
|
-
assert_match(/POST \/api\/
|
|
22
|
+
# Verify base controllers are created
|
|
23
|
+
assert_file "app/controllers/api/auth/base_tokens_controller.rb" do |content|
|
|
24
|
+
assert_match(/class Api::Auth::BaseTokensController < ApplicationController/, content)
|
|
25
|
+
assert_match(/POST \/api\/\{version\}\/auth\/login/, content)
|
|
26
26
|
assert_match(/def create/, content)
|
|
27
27
|
assert_match(/def show/, content)
|
|
28
28
|
assert_match(/def destroy/, content)
|
|
29
29
|
assert_match(/def unlock/, content)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
assert_file "app/controllers/api/
|
|
33
|
-
assert_match(/class Api::
|
|
34
|
-
assert_match(/POST \/api\/
|
|
32
|
+
assert_file "app/controllers/api/auth/base_passwords_controller.rb" do |content|
|
|
33
|
+
assert_match(/class Api::Auth::BasePasswordsController < ApplicationController/, content)
|
|
34
|
+
assert_match(/POST \/api\/\{version\}\/auth\/reset/, content)
|
|
35
35
|
assert_match(/def create/, content)
|
|
36
36
|
assert_match(/def show/, content)
|
|
37
37
|
assert_match(/def update/, content)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
# Verify routes are created
|
|
40
|
+
# Verify runtime configurable routes are created
|
|
41
41
|
assert_file "config/routes.rb" do |content|
|
|
42
|
-
assert_match(
|
|
43
|
-
assert_match(/
|
|
44
|
-
assert_match(/post 'login', to: 'tokens#create', as: :login/, content)
|
|
42
|
+
assert_match(/# Runtime configurable API versioning routes/, content)
|
|
43
|
+
assert_match(/api_version = PropelAccess\.configuration\.api_version/, content)
|
|
45
44
|
assert_match(/namespace :api do/, content)
|
|
46
45
|
assert_match(/namespace api_version do/, content)
|
|
47
46
|
assert_match(/namespace :auth do/, content)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: propel_authentication
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Propel Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-09-
|
|
11
|
+
date: 2025-09-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -50,14 +50,34 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version:
|
|
53
|
+
version: 3.1.2
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
60
|
+
version: 3.1.2
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: noticed
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 2.0.0
|
|
68
|
+
- - "<"
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '3.0'
|
|
71
|
+
type: :runtime
|
|
72
|
+
prerelease: false
|
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 2.0.0
|
|
78
|
+
- - "<"
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '3.0'
|
|
61
81
|
description: A self-extracting generator that creates a JWT-based authentication system
|
|
62
82
|
with agencies, agents, password resets, email confirmation, and account locking
|
|
63
83
|
for Rails applications.
|
|
@@ -90,8 +110,13 @@ files:
|
|
|
90
110
|
- lib/generators/propel_authentication/templates/db/migrate/create_invitations.rb
|
|
91
111
|
- lib/generators/propel_authentication/templates/db/migrate/create_organizations.rb
|
|
92
112
|
- lib/generators/propel_authentication/templates/db/migrate/create_users.rb
|
|
93
|
-
- lib/generators/propel_authentication/templates/db/
|
|
113
|
+
- lib/generators/propel_authentication/templates/db/propel_seeds.rb.tt
|
|
94
114
|
- lib/generators/propel_authentication/templates/doc/signup_flow.md
|
|
115
|
+
- lib/generators/propel_authentication/templates/fixtures/agencies.yml.erb
|
|
116
|
+
- lib/generators/propel_authentication/templates/fixtures/agents.yml.erb
|
|
117
|
+
- lib/generators/propel_authentication/templates/fixtures/invitations.yml.erb
|
|
118
|
+
- lib/generators/propel_authentication/templates/fixtures/organizations.yml.erb
|
|
119
|
+
- lib/generators/propel_authentication/templates/fixtures/users.yml.erb
|
|
95
120
|
- lib/generators/propel_authentication/templates/models/agency.rb.tt
|
|
96
121
|
- lib/generators/propel_authentication/templates/models/agent.rb.tt
|
|
97
122
|
- lib/generators/propel_authentication/templates/models/invitation.rb.tt
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# This file should ensure the existence of records required to run the application in every environment (production,
|
|
2
|
-
# development, test). The code here should be idempotent so that it can be executed at any point in every environment.
|
|
3
|
-
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
|
|
4
|
-
#
|
|
5
|
-
# Example:
|
|
6
|
-
#
|
|
7
|
-
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
|
|
8
|
-
# MovieGenre.find_or_create_by!(name: genre_name)
|
|
9
|
-
# end
|
|
10
|
-
|
|
11
|
-
# Create comprehensive tenancy structure for authentication testing
|
|
12
|
-
puts "🏢 Creating test organization structure..."
|
|
13
|
-
|
|
14
|
-
organization = Organization.find_or_create_by!(name: 'Test Organization') do |org|
|
|
15
|
-
org.website = 'https://test.example.com'
|
|
16
|
-
org.time_zone = 'UTC'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Create agencies for proper tenancy structure
|
|
20
|
-
main_agency = Agency.find_or_create_by!(name: 'Main Department', organization: organization) do |agency|
|
|
21
|
-
agency.phone_number = '+1-555-0101'
|
|
22
|
-
agency.address = '123 Main Street'
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
support_agency = Agency.find_or_create_by!(name: 'Support Department', organization: organization) do |agency|
|
|
26
|
-
agency.phone_number = '+1-555-0102'
|
|
27
|
-
agency.address = '123 Support Street'
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Create test users with proper confirmations
|
|
31
|
-
user = User.find_or_create_by!(email_address: 'test@example.com') do |u|
|
|
32
|
-
u.username = 'testuser'
|
|
33
|
-
u.email_address = 'test@example.com'
|
|
34
|
-
u.password = 'password123'
|
|
35
|
-
u.password_confirmation = 'password123'
|
|
36
|
-
u.organization = organization
|
|
37
|
-
u.first_name = 'Test'
|
|
38
|
-
u.last_name = 'User'
|
|
39
|
-
u.confirmed_at = 1.week.ago # Confirmed user for easier testing
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
admin_user = User.find_or_create_by!(email_address: 'admin@example.com') do |u|
|
|
43
|
-
u.username = 'adminuser'
|
|
44
|
-
u.email_address = 'admin@example.com'
|
|
45
|
-
u.password = 'password123'
|
|
46
|
-
u.password_confirmation = 'password123'
|
|
47
|
-
u.organization = organization
|
|
48
|
-
u.first_name = 'Admin'
|
|
49
|
-
u.last_name = 'User'
|
|
50
|
-
u.confirmed_at = 1.week.ago # Confirmed admin for easier testing
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Create agent associations for agency access (CRITICAL for tenancy validation)
|
|
54
|
-
Agent.find_or_create_by!(user: user, agency: main_agency) do |agent|
|
|
55
|
-
agent.role = 'member'
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
Agent.find_or_create_by!(user: admin_user, agency: main_agency) do |agent|
|
|
59
|
-
agent.role = 'manager'
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
Agent.find_or_create_by!(user: admin_user, agency: support_agency) do |agent|
|
|
63
|
-
agent.role = 'admin'
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
puts "✅ Created test organization: #{organization.name}"
|
|
67
|
-
puts "✅ Created agencies: #{Agency.where(organization: organization).pluck(:name).join(', ')}"
|
|
68
|
-
puts "✅ Created test user: #{user.email_address} (password: password123)"
|
|
69
|
-
puts "✅ Created admin user: #{admin_user.email_address} (password: password123)"
|
|
70
|
-
puts "✅ Created agent associations for proper tenancy access"
|
|
71
|
-
puts ""
|
|
72
|
-
puts "🎯 Test user agency access: #{user.agency_ids}"
|
|
73
|
-
puts "🎯 Admin user agency access: #{admin_user.agency_ids}"
|
|
74
|
-
puts ""
|
|
75
|
-
puts "🚀 You can now test login with POST /api/v1/login"
|