practical 0.1.0 → 3.0.0.pre.alpha1
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/README.md +4 -4
- data/app/components/practical/views/flash_messages_component.rb +0 -1
- data/app/components/practical/views/form/fallback_errors_section_component.rb +5 -3
- data/app/components/practical/views/form/option_label_component.rb +0 -1
- data/app/components/practical/views/navigation/breadcrumb_item_component.rb +0 -1
- data/app/components/practical/views/navigation/breadcrumbs_component.rb +2 -1
- data/app/{controllers/concerns/practical/auth/passkeys → concerns/practical/auth/passkeys/controllers}/emergency_registrations.rb +2 -2
- data/app/{controllers/concerns/practical/auth/passkeys → concerns/practical/auth/passkeys/controllers}/web_authn_debug_context.rb +1 -1
- data/app/concerns/practical/memberships/controllers/membership_invitations/register_with_passkey.rb +92 -0
- data/app/lib/practical/forms/datatables/base.rb +80 -0
- data/app/lib/practical/loaders/base.rb +44 -0
- data/app/lib/practical/relation_builders/base.rb +35 -0
- data/app/lib/practical/test/shared/attachment/models/attachment/base.rb +123 -0
- data/app/lib/practical/test/shared/attachment/models/attachment/for_organization.rb +39 -0
- data/app/lib/practical/test/shared/attachment/models/organization/has_attachments.rb +12 -0
- data/app/lib/practical/test/shared/auth/passkeys/controllers/emergency_registration/base.rb +9 -6
- data/app/lib/practical/test/shared/auth/passkeys/controllers/emergency_registration/cross_pollination.rb +49 -0
- data/app/lib/practical/test/shared/auth/passkeys/controllers/passkey_management/base.rb +508 -0
- data/app/lib/practical/test/shared/auth/passkeys/controllers/reauthentication/base.rb +27 -9
- data/app/lib/practical/test/shared/auth/passkeys/controllers/reauthentication/cross_pollination.rb +19 -0
- data/app/lib/practical/test/shared/auth/passkeys/controllers/registrations/self_destroy.rb +26 -8
- data/app/lib/practical/test/shared/auth/passkeys/controllers/registrations/self_signup.rb +3 -2
- data/app/lib/practical/test/shared/auth/passkeys/controllers/registrations/update.rb +55 -19
- data/app/lib/practical/test/shared/auth/passkeys/controllers/sessions/cross_pollination.rb +29 -0
- data/app/lib/practical/test/shared/auth/passkeys/forms/emergency_registration.rb +0 -1
- data/app/lib/practical/test/shared/auth/passkeys/models/{passkey.rb → passkey/base.rb} +1 -1
- data/app/lib/practical/test/shared/auth/passkeys/models/passkey/emergency_registration.rb +23 -0
- data/app/lib/practical/test/shared/auth/passkeys/models/{resource_with_passkeys.rb → resource_with_passkeys/base.rb} +1 -1
- data/app/lib/practical/test/shared/auth/passkeys/models/resource_with_passkeys/emergency_registration.rb +41 -0
- data/app/lib/practical/test/shared/memberships/controllers/membership_invitations/base.rb +165 -0
- data/app/lib/practical/test/shared/memberships/controllers/membership_invitations/register_with_passkey.rb +417 -0
- data/app/lib/practical/test/shared/memberships/controllers/organization/membership.rb +400 -0
- data/app/lib/practical/test/shared/memberships/controllers/organization/membership_invitation.rb +148 -0
- data/app/lib/practical/test/shared/memberships/controllers/user/membership.rb +119 -0
- data/app/lib/practical/test/shared/memberships/controllers/user/membership_invitation.rb +57 -0
- data/app/lib/practical/test/shared/memberships/forms/create_new_user_with_membership_invitation.rb +197 -0
- data/app/lib/practical/test/shared/memberships/forms/organization/membership.rb +162 -0
- data/app/lib/practical/test/shared/memberships/forms/organization/new_membership_invitation.rb +195 -0
- data/app/lib/practical/test/shared/memberships/forms/user/membership.rb +87 -0
- data/app/lib/practical/test/shared/memberships/models/membership/base.rb +45 -0
- data/app/lib/practical/test/shared/memberships/models/membership_invitation/base.rb +85 -0
- data/app/lib/practical/test/shared/memberships/models/membership_invitation/sending.rb +76 -0
- data/app/lib/practical/test/shared/memberships/models/membership_invitation/use_for_and_notify.rb +55 -0
- data/app/lib/practical/test/shared/memberships/models/organization/base.rb +25 -0
- data/app/lib/practical/test/shared/memberships/models/user/base.rb +23 -0
- data/app/lib/practical/test/shared/memberships/policies/organization/base_resource.rb +29 -0
- data/app/lib/practical/test/shared/memberships/policies/organization/membership.rb +103 -0
- data/app/lib/practical/test/shared/memberships/policies/organization/membership_invitation.rb +94 -0
- data/app/lib/practical/test/shared/memberships/policies/organization/resource/inherits.rb +10 -0
- data/app/lib/practical/test/shared/memberships/policies/organization.rb +70 -0
- data/app/lib/practical/test/shared/memberships/policies/user/membership.rb +78 -0
- data/app/lib/practical/test/shared/memberships/policies/user/membership_invitation.rb +31 -0
- data/app/lib/practical/test/shared/models/normalized_email.rb +0 -1
- data/app/lib/practical/test/shared/policies/user/base.rb +14 -0
- data/app/lib/practical/views/error_handling.rb +2 -0
- data/app/lib/practical/views/error_response.rb +27 -0
- data/app/lib/practical/views/form_builders/base.rb +5 -4
- data/app/lib/practical/views/form_builders/collection_option.rb +5 -0
- data/app/lib/practical/views/icon_set.rb +12 -6
- data/config/locales/auth.en.yml +18 -0
- data/config/locales/memberships.en.yml +129 -0
- data/db/seeds/memberships/default.rb +68 -0
- data/db/seeds/moderators/default.rb +36 -0
- data/db/seeds/setup.rb +16 -0
- data/db/seeds/test/cases/membership_invitations.rb +31 -0
- data/db/seeds/users/default.rb +17 -15
- data/lib/generators/practical/test/shared_test/shared_test_generator.rb +2 -0
- data/lib/practical/framework/engine.rb +8 -0
- data/lib/practical/helpers/honeybadger_helper.rb +11 -0
- data/lib/practical/helpers/selector_helper.rb +8 -0
- data/lib/practical/version.rb +1 -1
- data/lib/practical/views/element_helper.rb +2 -0
- data/lib/practical/views/theme_helper.rb +13 -0
- data/lib/practical.rb +4 -1
- data/lib/tasks/practical/utility.rake +20 -0
- metadata +54 -11
- data/lib/tasks/practical/framework_tasks.rake +0 -6
@@ -10,14 +10,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
10
10
|
client = webauthn_client
|
11
11
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
12
12
|
|
13
|
-
|
13
|
+
assert_reauthentication_challenge_authorized do
|
14
|
+
new_reauthentication_challenge_action
|
15
|
+
end
|
14
16
|
assert_response :ok
|
15
17
|
assert_reauthentication_token_challenge
|
16
18
|
|
17
19
|
challenge = response.parsed_body["challenge"]
|
18
20
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
19
21
|
|
20
|
-
|
22
|
+
assert_reauthentication_authorized do
|
23
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
24
|
+
end
|
21
25
|
assert_response :ok
|
22
26
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
23
27
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -28,9 +32,11 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
28
32
|
resource_id = resource_instance.id
|
29
33
|
|
30
34
|
assert_difference "#{resource_class}.count", -1 do
|
35
|
+
assert_destroy_authorized do
|
31
36
|
destroy_registration_action(params: params)
|
32
37
|
assert_redirected_to destroy_success_url
|
33
38
|
end
|
39
|
+
end
|
34
40
|
|
35
41
|
assert_nil resource_class.find_by(id: resource_id)
|
36
42
|
end
|
@@ -41,14 +47,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
41
47
|
client = webauthn_client
|
42
48
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
43
49
|
|
44
|
-
|
50
|
+
assert_reauthentication_challenge_authorized do
|
51
|
+
new_reauthentication_challenge_action
|
52
|
+
end
|
45
53
|
assert_response :ok
|
46
54
|
assert_reauthentication_token_challenge
|
47
55
|
|
48
56
|
challenge = response.parsed_body["challenge"]
|
49
57
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
50
58
|
|
51
|
-
|
59
|
+
assert_reauthentication_authorized do
|
60
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
61
|
+
end
|
52
62
|
assert_response :ok
|
53
63
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
54
64
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -73,14 +83,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
73
83
|
client = webauthn_client
|
74
84
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
75
85
|
|
76
|
-
|
86
|
+
assert_reauthentication_challenge_authorized do
|
87
|
+
new_reauthentication_challenge_action
|
88
|
+
end
|
77
89
|
assert_response :ok
|
78
90
|
assert_reauthentication_token_challenge
|
79
91
|
|
80
92
|
challenge = response.parsed_body["challenge"]
|
81
93
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
82
94
|
|
83
|
-
|
95
|
+
assert_reauthentication_authorized do
|
96
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
97
|
+
end
|
84
98
|
assert_response :ok
|
85
99
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
86
100
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -105,14 +119,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
105
119
|
client = webauthn_client
|
106
120
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
107
121
|
|
108
|
-
|
122
|
+
assert_reauthentication_challenge_authorized do
|
123
|
+
new_reauthentication_challenge_action
|
124
|
+
end
|
109
125
|
assert_response :ok
|
110
126
|
assert_reauthentication_token_challenge
|
111
127
|
|
112
128
|
challenge = response.parsed_body["challenge"]
|
113
129
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
114
130
|
|
115
|
-
|
131
|
+
assert_reauthentication_authorized do
|
132
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
133
|
+
end
|
116
134
|
assert_response :ok
|
117
135
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
118
136
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -80,7 +80,8 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
80
80
|
end
|
81
81
|
|
82
82
|
new_resource = resource_class.last
|
83
|
-
credential = hydrate_response_from_raw_credential(client: client, relying_party: webauthn_relying_party,
|
83
|
+
credential = hydrate_response_from_raw_credential(client: client, relying_party: webauthn_relying_party,
|
84
|
+
raw_credential: raw_credential).credential
|
84
85
|
|
85
86
|
new_passkey = new_resource.passkeys.last
|
86
87
|
assert_equal passkey_label, new_passkey.label
|
@@ -205,7 +206,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
|
|
205
206
|
|
206
207
|
client = webauthn_client
|
207
208
|
challenge = expected_stored_challenge
|
208
|
-
|
209
|
+
create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
|
209
210
|
|
210
211
|
params = params_for_registration(email: email, passkey_label: passkey_label, raw_credential: " ")
|
211
212
|
|
@@ -3,16 +3,20 @@
|
|
3
3
|
module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Update
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
6
|
+
included do
|
7
7
|
test "edit renders successfully for the resource" do
|
8
8
|
sign_in_as_resource
|
9
|
-
|
9
|
+
assert_edit_authorized do
|
10
|
+
edit_registration_action
|
11
|
+
end
|
10
12
|
assert_response :ok
|
11
13
|
end
|
12
14
|
|
13
15
|
test "edit does not render a different resource" do
|
14
16
|
sign_in_as_resource
|
15
|
-
|
17
|
+
assert_edit_authorized do
|
18
|
+
attempt_to_edit_other_resource_action
|
19
|
+
end
|
16
20
|
assert_response :ok
|
17
21
|
assert_not_includes response.body, other_resource.email
|
18
22
|
end
|
@@ -23,14 +27,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
23
27
|
client = webauthn_client
|
24
28
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
25
29
|
|
26
|
-
|
30
|
+
assert_reauthentication_challenge_authorized do
|
31
|
+
new_reauthentication_challenge_action
|
32
|
+
end
|
27
33
|
assert_response :ok
|
28
34
|
assert_reauthentication_token_challenge
|
29
35
|
|
30
36
|
challenge = response.parsed_body["challenge"]
|
31
37
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
32
38
|
|
33
|
-
|
39
|
+
assert_reauthentication_authorized do
|
40
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
41
|
+
end
|
34
42
|
assert_response :ok
|
35
43
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
36
44
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -41,8 +49,10 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
41
49
|
params = params_for_updating_resource(email: new_email, reauthentication_token: reauthentication_token)
|
42
50
|
|
43
51
|
assert_no_difference "#{resource_class}.count" do
|
52
|
+
assert_update_authorized do
|
44
53
|
update_registration_action(params: params)
|
45
|
-
|
54
|
+
assert_update_redirect
|
55
|
+
end
|
46
56
|
end
|
47
57
|
|
48
58
|
resource_instance.reload
|
@@ -55,14 +65,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
55
65
|
client = webauthn_client
|
56
66
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
57
67
|
|
58
|
-
|
68
|
+
assert_reauthentication_challenge_authorized do
|
69
|
+
new_reauthentication_challenge_action
|
70
|
+
end
|
59
71
|
assert_response :ok
|
60
72
|
assert_reauthentication_token_challenge
|
61
73
|
|
62
74
|
challenge = response.parsed_body["challenge"]
|
63
75
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
64
76
|
|
65
|
-
|
77
|
+
assert_reauthentication_authorized do
|
78
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
79
|
+
end
|
66
80
|
assert_response :ok
|
67
81
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
68
82
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -89,14 +103,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
89
103
|
client = webauthn_client
|
90
104
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
91
105
|
|
92
|
-
|
106
|
+
assert_reauthentication_challenge_authorized do
|
107
|
+
new_reauthentication_challenge_action
|
108
|
+
end
|
93
109
|
assert_response :ok
|
94
110
|
assert_reauthentication_token_challenge
|
95
111
|
|
96
112
|
challenge = response.parsed_body["challenge"]
|
97
113
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
98
114
|
|
99
|
-
|
115
|
+
assert_reauthentication_authorized do
|
116
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
117
|
+
end
|
100
118
|
assert_response :ok
|
101
119
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
102
120
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -123,14 +141,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
123
141
|
client = webauthn_client
|
124
142
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
125
143
|
|
126
|
-
|
144
|
+
assert_reauthentication_challenge_authorized do
|
145
|
+
new_reauthentication_challenge_action
|
146
|
+
end
|
127
147
|
assert_response :ok
|
128
148
|
assert_reauthentication_token_challenge
|
129
149
|
|
130
150
|
challenge = response.parsed_body["challenge"]
|
131
151
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
132
152
|
|
133
|
-
|
153
|
+
assert_reauthentication_authorized do
|
154
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
155
|
+
end
|
134
156
|
assert_response :ok
|
135
157
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
136
158
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -142,9 +164,11 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
142
164
|
params = params_for_updating_resource(email: new_email, reauthentication_token: reauthentication_token)
|
143
165
|
|
144
166
|
assert_no_difference "#{resource_class}.count" do
|
167
|
+
assert_update_authorized do
|
145
168
|
update_registration_action(params: params)
|
146
169
|
assert_response :unprocessable_entity
|
147
|
-
|
170
|
+
assert_form_error_for_blank_email
|
171
|
+
end
|
148
172
|
end
|
149
173
|
|
150
174
|
resource_instance.reload
|
@@ -157,14 +181,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
157
181
|
client = webauthn_client
|
158
182
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
159
183
|
|
160
|
-
|
184
|
+
assert_reauthentication_challenge_authorized do
|
185
|
+
new_reauthentication_challenge_action
|
186
|
+
end
|
161
187
|
assert_response :ok
|
162
188
|
assert_reauthentication_token_challenge
|
163
189
|
|
164
190
|
challenge = response.parsed_body["challenge"]
|
165
191
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
166
192
|
|
167
|
-
|
193
|
+
assert_reauthentication_authorized do
|
194
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
195
|
+
end
|
168
196
|
assert_response :ok
|
169
197
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
170
198
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -176,9 +204,11 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
176
204
|
params = params_for_updating_resource(email: new_email, reauthentication_token: reauthentication_token)
|
177
205
|
|
178
206
|
assert_no_difference "#{resource_class}.count" do
|
207
|
+
assert_update_authorized do
|
179
208
|
update_registration_action(params: params)
|
180
209
|
assert_response :unprocessable_entity
|
181
|
-
|
210
|
+
assert_form_error_for_taken_email
|
211
|
+
end
|
182
212
|
end
|
183
213
|
|
184
214
|
resource_instance.reload
|
@@ -191,14 +221,18 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
191
221
|
client = webauthn_client
|
192
222
|
create_passkey_for_user_and_return_webauthn_credential(user: resource_instance)
|
193
223
|
|
194
|
-
|
224
|
+
assert_reauthentication_challenge_authorized do
|
225
|
+
new_reauthentication_challenge_action
|
226
|
+
end
|
195
227
|
assert_response :ok
|
196
228
|
assert_reauthentication_token_challenge
|
197
229
|
|
198
230
|
challenge = response.parsed_body["challenge"]
|
199
231
|
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
200
232
|
|
201
|
-
|
233
|
+
assert_reauthentication_authorized do
|
234
|
+
reauthenticate_action(params: {passkey_credential: credential.to_json})
|
235
|
+
end
|
202
236
|
assert_response :ok
|
203
237
|
assert_equal expected_stored_reauthentication_token, response.parsed_body["reauthentication_token"]
|
204
238
|
assert_nil expected_stored_reauthentication_challenge
|
@@ -209,8 +243,10 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
|
|
209
243
|
params = params_trying_to_update_other_resource(email: new_email, reauthentication_token: reauthentication_token)
|
210
244
|
|
211
245
|
assert_no_difference "#{resource_class}.count" do
|
246
|
+
assert_update_authorized do
|
212
247
|
update_registration_action(params: params)
|
213
|
-
|
248
|
+
assert_update_redirect
|
249
|
+
end
|
214
250
|
end
|
215
251
|
|
216
252
|
resource_instance.reload
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Practical::Test::Shared::Auth::Passkeys::Controllers::Sessions::CrossPollination
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
test "create: does not allow another resource to log in" do
|
8
|
+
sign_in_as_other_resource
|
9
|
+
|
10
|
+
issue_new_challenge_action
|
11
|
+
assert_response :ok
|
12
|
+
|
13
|
+
assert_passkey_authentication_challenge(
|
14
|
+
data: response.parsed_body,
|
15
|
+
stored_challenge: expected_stored_challenge,
|
16
|
+
credentials_to_allow: []
|
17
|
+
)
|
18
|
+
|
19
|
+
challenge = response.parsed_body["challenge"]
|
20
|
+
credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
|
21
|
+
|
22
|
+
authenticate_action(params: {resource_key => {passkey_credential: credential.to_json}})
|
23
|
+
assert_response :unprocessable_entity
|
24
|
+
|
25
|
+
assert_nil get_session_challenge
|
26
|
+
assert_resource_not_signed_in
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -75,7 +75,6 @@ module Practical::Test::Shared::Auth::Passkeys::Forms::EmergencyRegistration
|
|
75
75
|
assert_equal new_passkey, emergency_registration.passkey
|
76
76
|
assert_equal time.to_formatted_s(:db), emergency_registration.used_at.to_formatted_s(:db)
|
77
77
|
|
78
|
-
|
79
78
|
assert_new_passkey_email(new_passkey: new_passkey)
|
80
79
|
end
|
81
80
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Practical::Test::Shared::Auth::Passkeys::Models::Passkey::EmergencyRegistration
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
test "has_one: emergency_passkey_registration, dependent: :destroy" do
|
8
|
+
reflection = model_class.reflect_on_association(emergency_passkey_registration_reflection_name)
|
9
|
+
assert_equal :has_one, reflection.macro
|
10
|
+
assert_equal :destroy, reflection.options[:dependent]
|
11
|
+
end
|
12
|
+
|
13
|
+
test "can destroy a passkey if it has an emergency_passkey_registration" do
|
14
|
+
instance = model_instance_with_emergency_registration
|
15
|
+
|
16
|
+
assert_not_nil instance.emergency_passkey_registration
|
17
|
+
|
18
|
+
assert_difference "#{model_class}.count", -1 do
|
19
|
+
instance.destroy!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Practical::Test::Shared::Auth::Passkeys::Models::ResourceWithPasskeys::EmergencyRegistration
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
test "email: is required and cannot be blank" do
|
8
|
+
instance = model_instance
|
9
|
+
instance.email = ""
|
10
|
+
assert_equal false, instance.valid?
|
11
|
+
assert_equal true, instance.errors.of_kind?(:email, :blank)
|
12
|
+
|
13
|
+
instance.email = Faker::Internet.email
|
14
|
+
assert_equal true, instance.valid?
|
15
|
+
end
|
16
|
+
|
17
|
+
test "email: is unique" do
|
18
|
+
instance = model_class.new(email: model_instance.email)
|
19
|
+
assert_equal false, instance.valid?
|
20
|
+
assert_equal true, instance.errors.of_kind?(:email, :taken)
|
21
|
+
|
22
|
+
instance.email = Faker::Internet.email
|
23
|
+
instance.valid?
|
24
|
+
|
25
|
+
assert_equal false, instance.errors.of_kind?(:email, :taken)
|
26
|
+
end
|
27
|
+
|
28
|
+
test "has many emergency_passkey_registrations" do
|
29
|
+
reflection = model_class.reflect_on_association(:emergency_passkey_registrations)
|
30
|
+
assert_equal :has_many, reflection.macro
|
31
|
+
|
32
|
+
assert_difference "#{emergency_passkey_registration_class}.count", +1 do
|
33
|
+
new_emergency_registration = model_instance.emergency_passkey_registrations.create!
|
34
|
+
|
35
|
+
assert_instance_of emergency_passkey_registration_class, new_emergency_registration
|
36
|
+
|
37
|
+
assert_includes model_instance.emergency_passkey_registrations, new_emergency_registration
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Practical::Test::Shared::Memberships::Controllers::MembershipInvitations::Base
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
test "show: renders successfully when given a visible, unused membership_invitation token" do
|
8
|
+
show_membership_invitation_action(token: visible_unused_token)
|
9
|
+
assert_response :ok
|
10
|
+
end
|
11
|
+
|
12
|
+
test "show: returns 404 if a used membership_invitation token is given" do
|
13
|
+
show_membership_invitation_action(token: used_token)
|
14
|
+
assert_response :not_found
|
15
|
+
end
|
16
|
+
|
17
|
+
test "show: returns 404 if a hidden membership_invitation token is given" do
|
18
|
+
show_membership_invitation_action(token: hidden_token)
|
19
|
+
assert_response :not_found
|
20
|
+
end
|
21
|
+
|
22
|
+
test "show: raises ActiveSupport::MessageVerifier::InvalidSignature if a bad token is given" do
|
23
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
24
|
+
show_membership_invitation_action(token: bad_token)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
test "show: raises ActiveSupport::MessageVerifier::InvalidSignature if a raw token is given" do
|
29
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
30
|
+
show_membership_invitation_action(token: raw_token)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
test "sign_out_then_show: signs out the resource, but stores the path and redirects them" do
|
35
|
+
sign_in_as_resource
|
36
|
+
|
37
|
+
sign_out_then_show_action(token: visible_unused_token)
|
38
|
+
assert_redirected_to_invitation(token: visible_unused_token)
|
39
|
+
end
|
40
|
+
|
41
|
+
test "sign_out_then_show: returns 404 if a used membership_invitation token is given" do
|
42
|
+
sign_in_as_resource
|
43
|
+
|
44
|
+
sign_out_then_show_action(token: used_token)
|
45
|
+
assert_response :not_found
|
46
|
+
end
|
47
|
+
|
48
|
+
test "sign_out_then_show: returns 404 if a hidden membership_invitation token is given" do
|
49
|
+
sign_in_as_resource
|
50
|
+
|
51
|
+
sign_out_then_show_action(token: hidden_token)
|
52
|
+
assert_response :not_found
|
53
|
+
end
|
54
|
+
|
55
|
+
test "sign_out_then_show: raises ActiveSupport::MessageVerifier::InvalidSignature if a bad token is given" do
|
56
|
+
sign_in_as_resource
|
57
|
+
|
58
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
59
|
+
sign_out_then_show_action(token: bad_token)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
test "sign_out_then_show: raises ActiveSupport::MessageVerifier::InvalidSignature if a raw token is given" do
|
64
|
+
sign_in_as_resource
|
65
|
+
|
66
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
67
|
+
sign_out_then_show_action(token: raw_token)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
test "accept_as_current_user: links the invitation to a given resource, creating the final membership" do
|
72
|
+
sign_in_as_resource
|
73
|
+
|
74
|
+
assert_difference "#{membership_class}.count", +1 do
|
75
|
+
accept_as_current_user_action(token: visible_unused_token)
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_redirected_to_organization
|
79
|
+
assert_accepted_invitation_flash_message
|
80
|
+
|
81
|
+
assert_membership_accepted_for_resource(resource: resource_instance)
|
82
|
+
end
|
83
|
+
|
84
|
+
test "accept_as_current_user: links the invitation to a given resource, even if the email does not match" do
|
85
|
+
sign_in_as_resource_with_different_email
|
86
|
+
|
87
|
+
assert_difference "#{membership_class}.count", +1 do
|
88
|
+
accept_as_current_user_action(token: visible_unused_token)
|
89
|
+
end
|
90
|
+
|
91
|
+
assert_redirected_to_organization
|
92
|
+
assert_accepted_invitation_flash_message
|
93
|
+
|
94
|
+
assert_membership_accepted_for_resource(resource: resource_instance_with_different_email)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "accept_as_current_user: raises an error and does not change the invitation if the resource is already a member of this organization" do
|
98
|
+
sign_in_as_resource_already_in_organization
|
99
|
+
|
100
|
+
assert_no_difference "#{membership_class}.count" do
|
101
|
+
accept_as_current_user_action(token: visible_unused_token)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_response :unprocessable_entity
|
105
|
+
assert_taken_flash_message
|
106
|
+
|
107
|
+
assert_membership_invitation_unclaimed
|
108
|
+
end
|
109
|
+
|
110
|
+
test "accept_as_current_user: returns 404 if the resource is not signed in" do
|
111
|
+
assert_no_difference "#{membership_class}.count" do
|
112
|
+
accept_as_current_user_action(token: visible_unused_token)
|
113
|
+
end
|
114
|
+
|
115
|
+
assert_response :not_found
|
116
|
+
assert_membership_invitation_unclaimed
|
117
|
+
end
|
118
|
+
|
119
|
+
test "accept_as_current_user: returns 404 if a used membership_invitation token is given" do
|
120
|
+
sign_in_as_resource
|
121
|
+
|
122
|
+
assert_no_difference "#{membership_class}.count" do
|
123
|
+
accept_as_current_user_action(token: used_token)
|
124
|
+
end
|
125
|
+
|
126
|
+
assert_response :not_found
|
127
|
+
assert_membership_invitation_unclaimed
|
128
|
+
end
|
129
|
+
|
130
|
+
test "accept_as_current_user: returns 404 if a hidden membership_invitation token is given" do
|
131
|
+
sign_in_as_resource
|
132
|
+
|
133
|
+
assert_no_difference "#{membership_class}.count" do
|
134
|
+
accept_as_current_user_action(token: hidden_token)
|
135
|
+
end
|
136
|
+
|
137
|
+
assert_response :not_found
|
138
|
+
assert_membership_invitation_unclaimed
|
139
|
+
end
|
140
|
+
|
141
|
+
test "accept_as_current_user: raises ActiveSupport::MessageVerifier::InvalidSignature if a bad token is given" do
|
142
|
+
sign_in_as_resource
|
143
|
+
|
144
|
+
assert_no_difference "#{membership_class}.count" do
|
145
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
146
|
+
accept_as_current_user_action(token: bad_token)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
assert_membership_invitation_unclaimed
|
151
|
+
end
|
152
|
+
|
153
|
+
test "accept_as_current_user: raises ActiveSupport::MessageVerifier::InvalidSignature if a raw token is given" do
|
154
|
+
sign_in_as_resource
|
155
|
+
|
156
|
+
assert_no_difference "#{membership_class}.count" do
|
157
|
+
assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
|
158
|
+
accept_as_current_user_action(token: raw_token)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
assert_membership_invitation_unclaimed
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|