propel_authentication 0.1.3 → 0.2.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 +4 -4
- data/CHANGELOG.md +128 -0
- data/README.md +254 -116
- data/lib/generators/{propel_auth → propel_authentication}/install_generator.rb +152 -170
- data/lib/generators/propel_authentication/templates/application_mailer.rb +6 -0
- data/lib/generators/propel_authentication/templates/auth/passwords_controller.rb.tt +132 -0
- data/lib/generators/propel_authentication/templates/auth/signup_controller.rb.tt +242 -0
- data/lib/generators/{propel_auth/templates → propel_authentication/templates/auth}/tokens_controller.rb.tt +39 -22
- data/lib/generators/{propel_auth → propel_authentication}/templates/auth_mailer.rb +3 -1
- data/lib/generators/{propel_auth → propel_authentication}/templates/authenticatable.rb +10 -4
- data/lib/generators/{propel_auth → propel_authentication}/templates/concerns/confirmable.rb +3 -3
- data/lib/generators/{propel_auth → propel_authentication}/templates/concerns/lockable.rb +10 -8
- data/lib/generators/{propel_auth/templates/concerns/propel_authentication.rb → propel_authentication/templates/concerns/propel_authentication_concern.rb} +33 -3
- data/lib/generators/{propel_auth → propel_authentication}/templates/concerns/recoverable.rb +21 -11
- data/lib/generators/propel_authentication/templates/core/configuration_methods.rb +191 -0
- data/lib/generators/propel_authentication/templates/db/seeds.rb +75 -0
- data/lib/generators/propel_authentication/templates/doc/signup_flow.md +315 -0
- data/lib/generators/propel_authentication/templates/models/agency.rb.tt +13 -0
- data/lib/generators/propel_authentication/templates/models/agent.rb.tt +13 -0
- data/lib/generators/{propel_auth/templates/invitation.rb → propel_authentication/templates/models/invitation.rb.tt} +8 -2
- data/lib/generators/propel_authentication/templates/models/organization.rb.tt +12 -0
- data/lib/generators/{propel_auth/templates/user.rb → propel_authentication/templates/models/user.rb.tt} +5 -0
- data/lib/generators/propel_authentication/templates/propel_authentication.rb.tt +218 -0
- data/lib/generators/propel_authentication/templates/routes/auth_routes.rb.tt +55 -0
- data/lib/generators/{propel_auth → propel_authentication}/templates/services/auth_notification_service.rb +3 -3
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/concerns/confirmable_test.rb.tt +34 -10
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/concerns/lockable_test.rb.tt +12 -12
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/concerns/propel_authentication_test.rb.tt +2 -2
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/concerns/recoverable_test.rb.tt +11 -11
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/controllers/auth/lockable_integration_test.rb.tt +18 -15
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/controllers/auth/password_reset_integration_test.rb.tt +38 -40
- data/lib/generators/propel_authentication/templates/test/controllers/auth/signup_controller_test.rb.tt +201 -0
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/controllers/auth/tokens_controller_test.rb.tt +33 -25
- data/lib/generators/{propel_auth → propel_authentication}/templates/test/mailers/auth_mailer_test.rb.tt +51 -36
- data/lib/generators/{propel_auth → propel_authentication}/templates/user_test.rb.tt +1 -1
- data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/email_confirmation.html.erb +2 -2
- data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/email_confirmation.text.erb +1 -1
- data/lib/generators/{propel_auth → propel_authentication}/test/generators/authentication/install_generator_test.rb +4 -4
- data/lib/generators/{propel_auth → propel_authentication}/test/generators/authentication/uninstall_generator_test.rb +1 -1
- data/lib/generators/{propel_auth → propel_authentication}/test/integration/generator_integration_test.rb +1 -1
- data/lib/generators/{propel_auth → propel_authentication}/test/integration/multi_version_generator_test.rb +13 -12
- data/lib/generators/{propel_auth → propel_authentication}/unpack_generator.rb +55 -38
- data/lib/propel_authentication.rb +3 -0
- metadata +101 -98
- data/lib/generators/propel_auth/core/configuration_methods.rb +0 -134
- data/lib/generators/propel_auth/pack_generator.rb +0 -277
- data/lib/generators/propel_auth/templates/agency.rb +0 -7
- data/lib/generators/propel_auth/templates/agent.rb +0 -7
- data/lib/generators/propel_auth/templates/auth/base_passwords_controller.rb.tt +0 -99
- data/lib/generators/propel_auth/templates/auth/base_tokens_controller.rb.tt +0 -90
- data/lib/generators/propel_auth/templates/auth/passwords_controller.rb.tt +0 -126
- data/lib/generators/propel_auth/templates/db/seeds.rb +0 -29
- data/lib/generators/propel_auth/templates/organization.rb +0 -7
- data/lib/generators/propel_auth/templates/propel_auth.rb.tt +0 -141
- data/lib/propel_auth.rb +0 -3
- /data/lib/generators/{propel_auth → propel_authentication}/templates/concerns/rack_session_disable.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/config/environments/development_email.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/db/migrate/create_agencies.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/db/migrate/create_agents.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/db/migrate/create_invitations.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/db/migrate/create_organizations.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/db/migrate/create_users.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/test/mailers/previews/auth_mailer_preview.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/account_unlock.html.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/account_unlock.text.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/password_reset.html.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/password_reset.text.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/user_invitation.html.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/templates/views/auth_mailer/user_invitation.text.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/Dockerfile +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/Gemfile +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/README.md +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/Rakefile +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/assets/stylesheets/application.css +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/controllers/application_controller.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/helpers/application_helper.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/jobs/application_job.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/mailers/application_mailer.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/models/application_record.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/views/layouts/application.html.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/views/layouts/mailer.html.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/views/layouts/mailer.text.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/views/pwa/manifest.json.erb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/app/views/pwa/service-worker.js +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/brakeman +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/dev +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/docker-entrypoint +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/rails +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/rake +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/rubocop +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/setup +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/bin/thrust +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/application.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/boot.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/cable.yml +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/credentials.yml.enc +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/database.yml +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/environment.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/environments/development.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/environments/production.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/environments/test.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/initializers/assets.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/initializers/content_security_policy.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/initializers/filter_parameter_logging.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/initializers/inflections.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/locales/en.yml +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/master.key +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/puma.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/routes.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config/storage.yml +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/config.ru +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/dummy/db/schema.rb +0 -0
- /data/lib/generators/{propel_auth → propel_authentication}/test/generators/authentication/controllers/tokens_controller_test.rb +0 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
|
-
class <%= controller_namespace
|
|
3
|
+
class <%= controller_namespace('tokens') %>LockableIntegrationTest < ActionDispatch::IntegrationTest
|
|
4
4
|
def setup
|
|
5
5
|
@organization = Organization.create!(name: "Test Organization")
|
|
6
|
+
@agency = Agency.create!(name: "Test Agency", organization: @organization)
|
|
6
7
|
@user = User.create!(
|
|
7
8
|
email_address: "lockable-integration@example.com",
|
|
8
9
|
username: "lockableintegration",
|
|
9
10
|
password: "correctpassword123",
|
|
10
11
|
organization: @organization
|
|
11
12
|
)
|
|
13
|
+
# Create agent association for agency access (required for real-time agency lookup)
|
|
14
|
+
Agent.create!(user: @user, agency: @agency, role: "member")
|
|
12
15
|
end
|
|
13
16
|
|
|
14
17
|
# CRITICAL: Real API integration with lockable functionality
|
|
@@ -16,7 +19,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
16
19
|
test "should track failed attempts during actual login API calls" do
|
|
17
20
|
# BEHAVIOR: Verify failed login attempts are tracked through real API
|
|
18
21
|
9.times do |i|
|
|
19
|
-
post <%=
|
|
22
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
20
23
|
user: { email_address: @user.email_address, password: "wrongpassword" }
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -32,14 +35,14 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
32
35
|
|
|
33
36
|
# First 9 attempts should not lock
|
|
34
37
|
9.times do
|
|
35
|
-
post <%=
|
|
38
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
36
39
|
user: { email_address: @user.email_address, password: "wrongpassword" }
|
|
37
40
|
}
|
|
38
41
|
assert_response :unauthorized
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
# 10th attempt should lock the account
|
|
42
|
-
post <%=
|
|
45
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
43
46
|
user: { email_address: @user.email_address, password: "wrongpassword" }
|
|
44
47
|
}
|
|
45
48
|
|
|
@@ -52,14 +55,14 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
52
55
|
# BEHAVIOR: Verify locked accounts return proper HTTP status and error
|
|
53
56
|
@user.lock_account!
|
|
54
57
|
|
|
55
|
-
post <%=
|
|
58
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
56
59
|
user: { email_address: @user.email_address, password: "correctpassword123" }
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
assert_response :locked, "Should return 423 locked status"
|
|
60
63
|
|
|
61
64
|
json = JSON.parse(response.body)
|
|
62
|
-
assert_match(/locked.*too many
|
|
65
|
+
assert_match(/locked.*too many.*failed.*attempts/i, json['error'], "Should return descriptive error message")
|
|
63
66
|
assert_nil json['token'], "Should not return authentication token"
|
|
64
67
|
assert_nil json['user'], "Should not return user data"
|
|
65
68
|
end
|
|
@@ -69,7 +72,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
69
72
|
@user.lock_account!
|
|
70
73
|
|
|
71
74
|
# Try with correct password
|
|
72
|
-
post <%=
|
|
75
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
73
76
|
user: { email_address: @user.email_address, password: "correctpassword123" }
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -85,7 +88,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
85
88
|
|
|
86
89
|
# Build up some failed attempts
|
|
87
90
|
5.times do
|
|
88
|
-
post <%=
|
|
91
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
89
92
|
user: { email_address: @user.email_address, password: "wrongpassword" }
|
|
90
93
|
}
|
|
91
94
|
end
|
|
@@ -94,7 +97,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
94
97
|
assert_equal 5, @user.failed_login_attempts, "Should have 5 failed attempts"
|
|
95
98
|
|
|
96
99
|
# Successful login should reset counter
|
|
97
|
-
post <%=
|
|
100
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
98
101
|
user: { email_address: @user.email_address, password: "correctpassword123" }
|
|
99
102
|
}
|
|
100
103
|
|
|
@@ -111,7 +114,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
111
114
|
@user.lock_account!
|
|
112
115
|
unlock_token = @user.generate_unlock_token
|
|
113
116
|
|
|
114
|
-
post <%=
|
|
117
|
+
post '<%= auth_route_prefix %>/unlock', params: { token: unlock_token }
|
|
115
118
|
|
|
116
119
|
assert_response :ok, "Valid unlock token should return 200"
|
|
117
120
|
|
|
@@ -128,7 +131,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
128
131
|
# API INTEGRATION: Verify unlock endpoint properly validates tokens
|
|
129
132
|
@user.lock_account!
|
|
130
133
|
|
|
131
|
-
post <%=
|
|
134
|
+
post '<%= auth_route_prefix %>/unlock', params: { token: "invalid_token_12345" }
|
|
132
135
|
|
|
133
136
|
assert_response :unauthorized, "Invalid token should return 401"
|
|
134
137
|
|
|
@@ -143,7 +146,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
143
146
|
# API VALIDATION: Verify unlock endpoint validates required parameters
|
|
144
147
|
@user.lock_account!
|
|
145
148
|
|
|
146
|
-
post <%=
|
|
149
|
+
post '<%= auth_route_prefix %>/unlock', params: {}
|
|
147
150
|
|
|
148
151
|
assert_response :unprocessable_entity, "Missing token should return 422"
|
|
149
152
|
|
|
@@ -153,7 +156,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
153
156
|
|
|
154
157
|
test "should not increment attempts when user does not exist" do
|
|
155
158
|
# SECURITY: Verify failed attempts are not tracked for nonexistent users
|
|
156
|
-
post <%=
|
|
159
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
157
160
|
user: { email_address: "nonexistent@example.com", password: "anypassword" }
|
|
158
161
|
}
|
|
159
162
|
|
|
@@ -166,7 +169,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
166
169
|
test "should handle graceful error responses for authentication failures" do
|
|
167
170
|
# ERROR HANDLING: Verify system handles authentication failures gracefully
|
|
168
171
|
|
|
169
|
-
post <%=
|
|
172
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
170
173
|
user: { email_address: "nonexistent@example.com", password: "wrongpassword" }
|
|
171
174
|
}
|
|
172
175
|
|
|
@@ -182,7 +185,7 @@ class <%= controller_namespace %>::LockableIntegrationTest < ActionDispatch::Int
|
|
|
182
185
|
# BEHAVIOR: Verify login timestamp tracking
|
|
183
186
|
start_time = Time.current
|
|
184
187
|
|
|
185
|
-
post <%=
|
|
188
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
186
189
|
user: { email_address: @user.email_address, password: "correctpassword123" }
|
|
187
190
|
}
|
|
188
191
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
|
-
class <%= controller_namespace
|
|
3
|
+
class <%= controller_namespace('passwords') %>PasswordResetIntegrationTest < ActionDispatch::IntegrationTest
|
|
4
4
|
def setup
|
|
5
5
|
@organization = Organization.create!(name: "Test Organization")
|
|
6
|
+
@agency = Agency.create!(name: "Test Agency", organization: @organization)
|
|
6
7
|
@user = User.create!(
|
|
7
8
|
email_address: "password-reset@example.com",
|
|
8
9
|
username: "passwordresetuser",
|
|
@@ -11,18 +12,15 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
11
12
|
first_name: "Password",
|
|
12
13
|
last_name: "User"
|
|
13
14
|
)
|
|
15
|
+
# Create agent association for agency access (required for real-time agency lookup)
|
|
16
|
+
Agent.create!(user: @user, agency: @agency, role: "member")
|
|
14
17
|
end
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
User.destroy_all
|
|
18
|
-
Organization.destroy_all
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# POST <%= api_versioned? ? "/#{api_namespace}" : "" %>/auth/reset - Request Password Reset Tests
|
|
19
|
+
# POST <%= auth_route_prefix %>/reset - Request Password Reset Tests
|
|
22
20
|
test "should initiate password reset with valid email_address" do
|
|
23
21
|
# BEHAVIOR: Verify password reset request works with valid email_address
|
|
24
22
|
|
|
25
|
-
post <%=
|
|
23
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: @user.email_address }
|
|
26
24
|
|
|
27
25
|
# VERIFY API RESPONSE: Should return success status
|
|
28
26
|
assert_response :ok, "Valid email_address should initiate password reset"
|
|
@@ -38,7 +36,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
38
36
|
test "should reject password reset with invalid email_address format" do
|
|
39
37
|
# VALIDATION: Verify email_address format validation
|
|
40
38
|
|
|
41
|
-
post <%=
|
|
39
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: "invalid-email-format" }
|
|
42
40
|
|
|
43
41
|
# VERIFY VALIDATION ERROR: Should return validation error
|
|
44
42
|
assert_response :unprocessable_entity, "Invalid email_address format should be rejected"
|
|
@@ -50,7 +48,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
50
48
|
test "should handle password reset for nonexistent email_address safely" do
|
|
51
49
|
# SECURITY: Verify nonexistent email_addresses don't reveal user information
|
|
52
50
|
|
|
53
|
-
post <%=
|
|
51
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: "nonexistent@example.com" }
|
|
54
52
|
|
|
55
53
|
# VERIFY SECURITY RESPONSE: Should return same response as valid email_address (prevent enumeration)
|
|
56
54
|
assert_response :ok, "Nonexistent email_address should return same response as valid email_address"
|
|
@@ -64,7 +62,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
64
62
|
test "should require email_address parameter for password reset request" do
|
|
65
63
|
# VALIDATION: Verify email_address parameter is required
|
|
66
64
|
|
|
67
|
-
post <%=
|
|
65
|
+
post '<%= auth_route_prefix %>/reset', params: {}
|
|
68
66
|
|
|
69
67
|
# VERIFY PARAMETER VALIDATION: Should return parameter error
|
|
70
68
|
assert_response :unprocessable_entity, "Missing email_address should return validation error"
|
|
@@ -78,18 +76,18 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
78
76
|
|
|
79
77
|
# EXECUTE MULTIPLE REQUESTS: Send multiple reset requests rapidly
|
|
80
78
|
5.times do
|
|
81
|
-
post <%=
|
|
79
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: @user.email_address }
|
|
82
80
|
end
|
|
83
81
|
|
|
84
82
|
# Make one more request that should be rate limited
|
|
85
|
-
post <%=
|
|
83
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: @user.email_address }
|
|
86
84
|
|
|
87
85
|
# VERIFY RATE LIMITING: Should eventually rate limit (implementation dependent)
|
|
88
86
|
# For now, verify the endpoint is accessible (rate limiting will be added later)
|
|
89
87
|
assert_response :ok, "Rate limiting test - endpoint should be accessible"
|
|
90
88
|
end
|
|
91
89
|
|
|
92
|
-
# PUT <%=
|
|
90
|
+
# PUT <%= auth_route_prefix %>/reset - Confirm Password Reset Tests
|
|
93
91
|
test "should reset password with valid token and new password" do
|
|
94
92
|
# BEHAVIOR: Verify password reset confirmation works end-to-end
|
|
95
93
|
|
|
@@ -98,7 +96,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
98
96
|
new_password = "newpassword456"
|
|
99
97
|
|
|
100
98
|
# EXECUTE RESET: Confirm password reset with token
|
|
101
|
-
|
|
99
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
102
100
|
token: reset_token,
|
|
103
101
|
password: new_password,
|
|
104
102
|
password_confirmation: new_password
|
|
@@ -125,7 +123,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
125
123
|
new_password = "attemptedpassword"
|
|
126
124
|
|
|
127
125
|
# EXECUTE WITH INVALID TOKEN: Try to reset with invalid token
|
|
128
|
-
|
|
126
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
129
127
|
token: invalid_token,
|
|
130
128
|
password: new_password,
|
|
131
129
|
password_confirmation: new_password
|
|
@@ -154,10 +152,10 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
154
152
|
exp: 1.second.ago.to_i, # Already expired
|
|
155
153
|
password_hash: @user.password_digest[0..10]
|
|
156
154
|
}
|
|
157
|
-
expired_token = JWT.encode(expired_payload,
|
|
155
|
+
expired_token = JWT.encode(expired_payload, PropelAuthentication.configuration.jwt_secret, 'HS256')
|
|
158
156
|
|
|
159
157
|
# EXECUTE WITH EXPIRED TOKEN: Try to reset with expired token
|
|
160
|
-
|
|
158
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
161
159
|
token: expired_token,
|
|
162
160
|
password: "newpassword",
|
|
163
161
|
password_confirmation: "newpassword"
|
|
@@ -176,7 +174,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
176
174
|
reset_token = @user.generate_password_reset_token
|
|
177
175
|
|
|
178
176
|
# EXECUTE WITH MISMATCHED PASSWORDS: Password and confirmation don't match
|
|
179
|
-
|
|
177
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
180
178
|
token: reset_token,
|
|
181
179
|
password: "newpassword123",
|
|
182
180
|
password_confirmation: "differentpassword456"
|
|
@@ -200,7 +198,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
200
198
|
weak_password = "123" # Too short
|
|
201
199
|
|
|
202
200
|
# EXECUTE WITH WEAK PASSWORD: Try to set weak password
|
|
203
|
-
|
|
201
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
204
202
|
token: reset_token,
|
|
205
203
|
password: weak_password,
|
|
206
204
|
password_confirmation: weak_password
|
|
@@ -223,7 +221,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
223
221
|
reset_token = @user.generate_password_reset_token
|
|
224
222
|
|
|
225
223
|
# TEST MISSING TOKEN
|
|
226
|
-
|
|
224
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
227
225
|
password: "newpassword123",
|
|
228
226
|
password_confirmation: "newpassword123"
|
|
229
227
|
}
|
|
@@ -231,7 +229,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
231
229
|
assert_response :unprocessable_entity, "Missing token should be rejected"
|
|
232
230
|
|
|
233
231
|
# TEST MISSING PASSWORD
|
|
234
|
-
|
|
232
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
235
233
|
token: reset_token,
|
|
236
234
|
password_confirmation: "newpassword123"
|
|
237
235
|
}
|
|
@@ -239,7 +237,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
239
237
|
assert_response :unprocessable_entity, "Missing password should be rejected"
|
|
240
238
|
|
|
241
239
|
# TEST MISSING CONFIRMATION
|
|
242
|
-
|
|
240
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
243
241
|
token: reset_token,
|
|
244
242
|
password: "newpassword123"
|
|
245
243
|
}
|
|
@@ -256,7 +254,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
256
254
|
|
|
257
255
|
# EXECUTE RESET: Reset password successfully
|
|
258
256
|
reset_token = @user.generate_password_reset_token
|
|
259
|
-
|
|
257
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
260
258
|
token: reset_token,
|
|
261
259
|
password: "newpassword123",
|
|
262
260
|
password_confirmation: "newpassword123"
|
|
@@ -279,7 +277,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
279
277
|
|
|
280
278
|
# EXECUTE RESET: Reset password while locked
|
|
281
279
|
reset_token = @user.generate_password_reset_token
|
|
282
|
-
|
|
280
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
283
281
|
token: reset_token,
|
|
284
282
|
password: "newpassword123",
|
|
285
283
|
password_confirmation: "newpassword123"
|
|
@@ -294,14 +292,14 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
294
292
|
assert @user.authenticate("newpassword123"), "Should authenticate with new password"
|
|
295
293
|
end
|
|
296
294
|
|
|
297
|
-
# GET <%=
|
|
295
|
+
# GET <%= auth_route_prefix %>/reset/verify - Token Verification Tests
|
|
298
296
|
test "should verify valid password reset token" do
|
|
299
297
|
# BEHAVIOR: Verify token verification endpoint works
|
|
300
298
|
|
|
301
299
|
reset_token = @user.generate_password_reset_token
|
|
302
300
|
|
|
303
301
|
# EXECUTE VERIFICATION: Verify token is valid
|
|
304
|
-
get <%=
|
|
302
|
+
get '<%= auth_route_prefix %>/reset', params: { token: reset_token }
|
|
305
303
|
|
|
306
304
|
# VERIFY API RESPONSE: Should confirm token validity
|
|
307
305
|
assert_response :ok, "Valid token should pass verification"
|
|
@@ -319,7 +317,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
319
317
|
invalid_token = "invalid.jwt.token"
|
|
320
318
|
|
|
321
319
|
# EXECUTE VERIFICATION: Verify invalid token
|
|
322
|
-
get <%=
|
|
320
|
+
get '<%= auth_route_prefix %>/reset', params: { token: invalid_token }
|
|
323
321
|
|
|
324
322
|
# VERIFY REJECTION: Should indicate token is invalid
|
|
325
323
|
assert_response :unauthorized, "Invalid token should be rejected"
|
|
@@ -340,10 +338,10 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
340
338
|
exp: 1.second.ago.to_i, # Already expired
|
|
341
339
|
password_hash: @user.password_digest[0..10]
|
|
342
340
|
}
|
|
343
|
-
expired_token = JWT.encode(expired_payload,
|
|
341
|
+
expired_token = JWT.encode(expired_payload, PropelAuthentication.configuration.jwt_secret, 'HS256')
|
|
344
342
|
|
|
345
343
|
# EXECUTE VERIFICATION: Verify expired token
|
|
346
|
-
get <%=
|
|
344
|
+
get '<%= auth_route_prefix %>/reset', params: { token: expired_token }
|
|
347
345
|
|
|
348
346
|
# VERIFY EXPIRATION: Should indicate token is expired
|
|
349
347
|
assert_response :unauthorized, "Expired token should be rejected"
|
|
@@ -355,7 +353,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
355
353
|
test "should require token parameter for verification" do
|
|
356
354
|
# VALIDATION: Verify token parameter is required for verification
|
|
357
355
|
|
|
358
|
-
get <%=
|
|
356
|
+
get '<%= auth_route_prefix %>/reset', params: {}
|
|
359
357
|
|
|
360
358
|
# VERIFY PARAMETER VALIDATION: Should return parameter error
|
|
361
359
|
assert_response :unprocessable_entity, "Missing token should return validation error"
|
|
@@ -369,12 +367,12 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
369
367
|
# INTEGRATION: Test complete password reset workflow from start to finish
|
|
370
368
|
|
|
371
369
|
# STEP 1: REQUEST RESET - Send password reset request
|
|
372
|
-
post <%=
|
|
370
|
+
post '<%= auth_route_prefix %>/reset', params: { email_address: @user.email_address }
|
|
373
371
|
assert_response :ok, "Reset request should succeed"
|
|
374
372
|
|
|
375
373
|
# STEP 2: VERIFY TOKEN - Check that we can verify tokens (simulate email link click)
|
|
376
374
|
reset_token = @user.generate_password_reset_token # Simulate token from email
|
|
377
|
-
get <%=
|
|
375
|
+
get '<%= auth_route_prefix %>/reset', params: { token: reset_token }
|
|
378
376
|
assert_response :ok, "Token verification should succeed"
|
|
379
377
|
|
|
380
378
|
verification_json = JSON.parse(response.body)
|
|
@@ -382,7 +380,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
382
380
|
|
|
383
381
|
# STEP 3: RESET PASSWORD - Complete password reset
|
|
384
382
|
new_password = "completeworkflow123"
|
|
385
|
-
|
|
383
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
386
384
|
token: reset_token,
|
|
387
385
|
password: new_password,
|
|
388
386
|
password_confirmation: new_password
|
|
@@ -390,7 +388,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
390
388
|
assert_response :ok, "Password reset should succeed"
|
|
391
389
|
|
|
392
390
|
# STEP 4: VERIFY NEW PASSWORD - Test login with new password
|
|
393
|
-
post <%=
|
|
391
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
394
392
|
user: { email_address: @user.email_address, password: new_password }
|
|
395
393
|
}
|
|
396
394
|
assert_response :ok, "Should login with new password"
|
|
@@ -399,7 +397,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
399
397
|
assert login_json['token'].present?, "Should receive JWT token"
|
|
400
398
|
|
|
401
399
|
# STEP 5: VERIFY OLD PASSWORD INVALID - Test old password doesn't work
|
|
402
|
-
post <%=
|
|
400
|
+
post '<%= auth_route_prefix %>/login', params: {
|
|
403
401
|
user: { email_address: @user.email_address, password: "originalpassword123" }
|
|
404
402
|
}
|
|
405
403
|
assert_response :unauthorized, "Should not login with old password"
|
|
@@ -411,7 +409,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
411
409
|
reset_token = @user.generate_password_reset_token
|
|
412
410
|
|
|
413
411
|
# FIRST RESET: Use token successfully
|
|
414
|
-
|
|
412
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
415
413
|
token: reset_token,
|
|
416
414
|
password: "firstnewpassword123",
|
|
417
415
|
password_confirmation: "firstnewpassword123"
|
|
@@ -419,7 +417,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
419
417
|
assert_response :ok, "First password reset should succeed"
|
|
420
418
|
|
|
421
419
|
# ATTEMPTED REUSE: Try to use same token again
|
|
422
|
-
|
|
420
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
423
421
|
token: reset_token,
|
|
424
422
|
password: "secondnewpassword456",
|
|
425
423
|
password_confirmation: "secondnewpassword456"
|
|
@@ -447,7 +445,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
447
445
|
assert @user.valid_password_reset_token?(token2), "Second token should be valid"
|
|
448
446
|
|
|
449
447
|
# USE FIRST TOKEN: Reset password with first token
|
|
450
|
-
|
|
448
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
451
449
|
token: token1,
|
|
452
450
|
password: "concurrentpassword1",
|
|
453
451
|
password_confirmation: "concurrentpassword1"
|
|
@@ -455,7 +453,7 @@ class <%= controller_namespace %>::PasswordResetIntegrationTest < ActionDispatch
|
|
|
455
453
|
assert_response :ok, "First reset should succeed"
|
|
456
454
|
|
|
457
455
|
# TRY SECOND TOKEN: Attempt reset with second token (should fail due to password change)
|
|
458
|
-
|
|
456
|
+
patch '<%= auth_route_prefix %>/reset', params: {
|
|
459
457
|
token: token2,
|
|
460
458
|
password: "concurrentpassword2",
|
|
461
459
|
password_confirmation: "concurrentpassword2"
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class <%= controller_namespace('signup') %>SignupControllerTest < ActionDispatch::IntegrationTest
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@valid_signup_params = {
|
|
7
|
+
user: {
|
|
8
|
+
email_address: "newuser@example.com",
|
|
9
|
+
username: "newuser",
|
|
10
|
+
password: "password123",
|
|
11
|
+
password_confirmation: "password123",
|
|
12
|
+
first_name: "New",
|
|
13
|
+
last_name: "User"
|
|
14
|
+
},
|
|
15
|
+
organization: {
|
|
16
|
+
name: "New Company Inc",
|
|
17
|
+
website: "https://newcompany.com",
|
|
18
|
+
time_zone: "UTC"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@valid_signup_params_with_agency = @valid_signup_params.merge(
|
|
23
|
+
agency: {
|
|
24
|
+
name: "Primary Agency",
|
|
25
|
+
description: "Main operations agency"
|
|
26
|
+
},
|
|
27
|
+
agent: {
|
|
28
|
+
role: "owner"
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test "should create user and organization successfully" do
|
|
34
|
+
assert_difference ['User.count', 'Organization.count'], 1 do
|
|
35
|
+
post '<%= auth_route_prefix %>/signup',
|
|
36
|
+
params: @valid_signup_params_with_agency,
|
|
37
|
+
as: :json
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
assert_response :created
|
|
41
|
+
response_body = JSON.parse(response.body)
|
|
42
|
+
|
|
43
|
+
# Verify response structure
|
|
44
|
+
assert_includes response_body.keys, 'token'
|
|
45
|
+
assert_includes response_body.keys, 'user'
|
|
46
|
+
assert_includes response_body.keys, 'organization'
|
|
47
|
+
assert_includes response_body.keys, 'message'
|
|
48
|
+
assert_includes response_body.keys, 'next_steps'
|
|
49
|
+
|
|
50
|
+
# Verify user data
|
|
51
|
+
user_data = response_body['user']
|
|
52
|
+
assert_equal @valid_signup_params[:user][:email_address], user_data['email_address']
|
|
53
|
+
assert_equal @valid_signup_params[:user][:username], user_data['username']
|
|
54
|
+
assert_equal @valid_signup_params[:user][:first_name], user_data['first_name']
|
|
55
|
+
|
|
56
|
+
# Verify organization data
|
|
57
|
+
org_data = response_body['organization']
|
|
58
|
+
assert_equal @valid_signup_params[:organization][:name], org_data['name']
|
|
59
|
+
assert_equal @valid_signup_params[:organization][:website], org_data['website']
|
|
60
|
+
|
|
61
|
+
# Verify JWT token is valid
|
|
62
|
+
token = response_body['token']
|
|
63
|
+
assert_not_nil token
|
|
64
|
+
|
|
65
|
+
# Verify the token can be used for authenticated requests
|
|
66
|
+
get '<%= auth_route_prefix %>/me',
|
|
67
|
+
headers: { 'Authorization' => "Bearer #{token}" }
|
|
68
|
+
assert_response :success
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
test "should create user, organization, agency, and agent when agency tenancy enabled" do
|
|
72
|
+
skip "Agency tenancy test - enable when PropelApi.configuration.agency_tenancy = true" unless agency_tenancy_enabled?
|
|
73
|
+
|
|
74
|
+
assert_difference ['User.count', 'Organization.count', 'Agency.count', 'Agent.count'], 1 do
|
|
75
|
+
post '<%= auth_route_prefix %>/signup',
|
|
76
|
+
params: @valid_signup_params_with_agency,
|
|
77
|
+
as: :json
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
assert_response :created
|
|
81
|
+
response_body = JSON.parse(response.body)
|
|
82
|
+
|
|
83
|
+
# Verify user, agency, and agent were created
|
|
84
|
+
assert_includes response_body.keys, 'user'
|
|
85
|
+
assert_includes response_body.keys, 'agency'
|
|
86
|
+
assert_includes response_body.keys, 'agent'
|
|
87
|
+
|
|
88
|
+
user_data = response_body['user']
|
|
89
|
+
agency_data = response_body['agency']
|
|
90
|
+
assert_equal @valid_signup_params_with_agency[:agency][:name], agency_data['name']
|
|
91
|
+
|
|
92
|
+
agent_data = response_body['agent']
|
|
93
|
+
assert_equal @valid_signup_params_with_agency[:agent][:role], agent_data['role']
|
|
94
|
+
|
|
95
|
+
# Verify JWT contains minimal secure claims (agency access is now real-time lookup)
|
|
96
|
+
token = response_body['token']
|
|
97
|
+
payload = JWT.decode(token, PropelAuthentication.configuration.jwt_secret, true, { algorithm: 'HS256' })[0]
|
|
98
|
+
assert_includes payload.keys, 'user_id'
|
|
99
|
+
assert_includes payload.keys, 'organization_id'
|
|
100
|
+
assert_not_includes payload.keys, 'agency_ids', "agency_ids removed for security - now real-time lookup"
|
|
101
|
+
|
|
102
|
+
# Verify user has real-time agency access via agents association
|
|
103
|
+
created_user = User.find(user_data['id'])
|
|
104
|
+
assert_includes created_user.agency_ids, agency_data['id']
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
test "should reject signup with missing user data" do
|
|
108
|
+
invalid_params = @valid_signup_params.except(:user)
|
|
109
|
+
|
|
110
|
+
post '<%= auth_route_prefix %>/signup',
|
|
111
|
+
params: invalid_params,
|
|
112
|
+
as: :json
|
|
113
|
+
|
|
114
|
+
assert_response :unprocessable_entity
|
|
115
|
+
response_body = JSON.parse(response.body)
|
|
116
|
+
assert_includes response_body.keys, 'error'
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
test "should reject signup with missing organization data" do
|
|
120
|
+
invalid_params = @valid_signup_params.except(:organization)
|
|
121
|
+
|
|
122
|
+
post '<%= auth_route_prefix %>/signup',
|
|
123
|
+
params: invalid_params,
|
|
124
|
+
as: :json
|
|
125
|
+
|
|
126
|
+
assert_response :unprocessable_entity
|
|
127
|
+
response_body = JSON.parse(response.body)
|
|
128
|
+
assert_includes response_body.keys, 'error'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
test "should reject signup with invalid email format" do
|
|
132
|
+
invalid_params = @valid_signup_params_with_agency.dup
|
|
133
|
+
invalid_params[:user][:email_address] = "invalid-email"
|
|
134
|
+
|
|
135
|
+
post '<%= auth_route_prefix %>/signup',
|
|
136
|
+
params: invalid_params,
|
|
137
|
+
as: :json
|
|
138
|
+
|
|
139
|
+
assert_response :unprocessable_entity
|
|
140
|
+
response_body = JSON.parse(response.body)
|
|
141
|
+
assert_includes response_body.keys, 'details'
|
|
142
|
+
assert_includes response_body['details'].keys, 'email_address'
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
test "should reject signup with password confirmation mismatch" do
|
|
146
|
+
invalid_params = @valid_signup_params_with_agency.dup
|
|
147
|
+
invalid_params[:user][:password_confirmation] = "different_password"
|
|
148
|
+
|
|
149
|
+
post '<%= auth_route_prefix %>/signup',
|
|
150
|
+
params: invalid_params,
|
|
151
|
+
as: :json
|
|
152
|
+
|
|
153
|
+
assert_response :unprocessable_entity
|
|
154
|
+
response_body = JSON.parse(response.body)
|
|
155
|
+
assert_includes response_body.keys, 'details'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
test "should reject duplicate email address" do
|
|
159
|
+
# Create first user
|
|
160
|
+
post '<%= auth_route_prefix %>/signup',
|
|
161
|
+
params: @valid_signup_params_with_agency,
|
|
162
|
+
as: :json
|
|
163
|
+
assert_response :created
|
|
164
|
+
|
|
165
|
+
# Try to create second user with same email
|
|
166
|
+
duplicate_params = @valid_signup_params_with_agency.dup
|
|
167
|
+
duplicate_params[:user][:username] = "different_username"
|
|
168
|
+
duplicate_params[:organization][:name] = "Different Company"
|
|
169
|
+
duplicate_params[:agency][:name] = "Different Agency"
|
|
170
|
+
|
|
171
|
+
post '<%= auth_route_prefix %>/signup',
|
|
172
|
+
params: duplicate_params,
|
|
173
|
+
as: :json
|
|
174
|
+
|
|
175
|
+
assert_response :unprocessable_entity
|
|
176
|
+
response_body = JSON.parse(response.body)
|
|
177
|
+
assert_includes response_body.keys, 'details'
|
|
178
|
+
assert_includes response_body['details'].keys, 'email_address'
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
test "should require agency data when agency tenancy is enabled" do
|
|
182
|
+
skip "Agency tenancy test - enable when PropelApi.configuration.agency_tenancy = true" unless agency_tenancy_enabled?
|
|
183
|
+
|
|
184
|
+
# Try signup without agency data when agency tenancy is enabled
|
|
185
|
+
post '<%= auth_route_prefix %>/signup',
|
|
186
|
+
params: @valid_signup_params,
|
|
187
|
+
as: :json
|
|
188
|
+
|
|
189
|
+
assert_response :unprocessable_entity
|
|
190
|
+
response_body = JSON.parse(response.body)
|
|
191
|
+
assert_equal 'MISSING_AGENCY_DATA', response_body['code']
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
private
|
|
195
|
+
|
|
196
|
+
def agency_tenancy_enabled?
|
|
197
|
+
defined?(PropelApi) && PropelApi.configuration.agency_tenancy
|
|
198
|
+
rescue
|
|
199
|
+
false
|
|
200
|
+
end
|
|
201
|
+
end
|