devise_token_auth 0.1.30.beta3 → 0.1.30.beta4
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 +16 -2
- data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +9 -9
- data/app/controllers/devise_token_auth/confirmations_controller.rb +5 -5
- data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +10 -10
- data/app/controllers/devise_token_auth/passwords_controller.rb +34 -23
- data/app/controllers/devise_token_auth/registrations_controller.rb +10 -11
- data/app/controllers/devise_token_auth/sessions_controller.rb +23 -8
- data/app/controllers/devise_token_auth/token_validations_controller.rb +3 -3
- data/app/models/devise_token_auth/concerns/user.rb +1 -0
- data/app/views/devise_token_auth/omniauth_success.html.erb +1 -1
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +6 -6
- data/test/controllers/demo_group_controller_test.rb +14 -14
- data/test/controllers/demo_mang_controller_test.rb +25 -25
- data/test/controllers/demo_user_controller_test.rb +25 -25
- data/test/controllers/devise_token_auth/confirmations_controller_test.rb +6 -6
- data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +11 -11
- data/test/controllers/devise_token_auth/passwords_controller_test.rb +110 -84
- data/test/controllers/devise_token_auth/registrations_controller_test.rb +23 -23
- data/test/controllers/devise_token_auth/sessions_controller_test.rb +68 -5
- data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +3 -3
- data/test/controllers/overrides/passwords_controller_test.rb +4 -4
- data/test/controllers/overrides/sessions_controller_test.rb +1 -1
- data/test/controllers/overrides/token_validations_controller_test.rb +5 -5
- data/test/dummy/app/controllers/demo_mang_controller.rb +2 -2
- data/test/dummy/app/controllers/demo_user_controller.rb +2 -2
- data/test/dummy/app/controllers/overrides/confirmations_controller.rb +5 -5
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +6 -6
- data/test/dummy/app/controllers/overrides/registrations_controller.rb +4 -4
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +7 -7
- data/test/dummy/app/controllers/overrides/token_validations_controller.rb +3 -3
- data/test/dummy/config/application.yml +8 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +2 -2
- data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +2 -2
- data/test/dummy/db/migrate/20140928231203_devise_token_auth_create_evil_users.rb +2 -2
- data/test/dummy/db/schema.rb +12 -9
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +1979 -0
- data/test/dummy/log/test.log +183708 -0
- data/test/dummy/tmp/generators/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/test/dummy/tmp/generators/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/test/models/user_test.rb +37 -27
- metadata +10 -10
- data/test/dummy/tmp/generators/app/models/user.rb +0 -7
- data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +0 -22
- data/test/dummy/tmp/generators/db/migrate/20141028214843_devise_token_auth_create_users.rb +0 -54
@@ -11,6 +11,7 @@ module DeviseTokenAuth::Concerns::User
|
|
11
11
|
serialize :tokens, JSON
|
12
12
|
|
13
13
|
validates_presence_of :email, if: Proc.new { |u| u.provider == 'email' }
|
14
|
+
validates_presence_of :uid
|
14
15
|
|
15
16
|
# only validate unique emails among email registration users
|
16
17
|
validate :unique_email_user, on: :create
|
@@ -1,8 +1,11 @@
|
|
1
1
|
class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table(:<%= user_class.pluralize.underscore %>) do |t|
|
4
|
+
## Required
|
5
|
+
t.string :provider, :null => false
|
6
|
+
t.string :uid, :null => false, :default => ""
|
7
|
+
|
4
8
|
## Database authenticatable
|
5
|
-
t.string :email
|
6
9
|
t.string :encrypted_password, :null => false, :default => ""
|
7
10
|
|
8
11
|
## Recoverable
|
@@ -34,10 +37,7 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
|
|
34
37
|
t.string :name
|
35
38
|
t.string :nickname
|
36
39
|
t.string :image
|
37
|
-
|
38
|
-
## unique oauth id
|
39
|
-
t.string :provider
|
40
|
-
t.string :uid, :null => false, :default => ""
|
40
|
+
t.string :email
|
41
41
|
|
42
42
|
## Tokens
|
43
43
|
t.text :tokens
|
@@ -46,7 +46,7 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
|
|
46
46
|
end
|
47
47
|
|
48
48
|
add_index :<%= user_class.pluralize.underscore %>, :email
|
49
|
-
add_index :<%= user_class.pluralize.underscore %>, :uid,
|
49
|
+
add_index :<%= user_class.pluralize.underscore %>, [:uid, :provider], :unique => true
|
50
50
|
add_index :<%= user_class.pluralize.underscore %>, :reset_password_token, :unique => true
|
51
51
|
# add_index :<%= user_class.pluralize.underscore %>, :confirmation_token, :unique => true
|
52
52
|
# add_index :<%= user_class.pluralize.underscore %>, :unlock_token, :unique => true
|
@@ -11,15 +11,15 @@ class DemoGroupControllerTest < ActionDispatch::IntegrationTest
|
|
11
11
|
describe "Token access" do
|
12
12
|
before do
|
13
13
|
# user
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
14
|
+
@resource = users(:confirmed_email_user)
|
15
|
+
@resource.skip_confirmation!
|
16
|
+
@resource.save!
|
17
17
|
|
18
|
-
@
|
18
|
+
@resource_auth_headers = @resource.create_new_auth_token
|
19
19
|
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
20
|
+
@resource_token = @resource_auth_headers['access-token']
|
21
|
+
@resource_client_id = @resource_auth_headers['client']
|
22
|
+
@resource_expiry = @resource_auth_headers['expiry']
|
23
23
|
|
24
24
|
# mang
|
25
25
|
@mang = mangs(:confirmed_email_user)
|
@@ -36,9 +36,9 @@ class DemoGroupControllerTest < ActionDispatch::IntegrationTest
|
|
36
36
|
describe 'user access' do
|
37
37
|
before do
|
38
38
|
# ensure that request is not treated as batch request
|
39
|
-
age_token(@
|
39
|
+
age_token(@resource, @resource_client_id)
|
40
40
|
|
41
|
-
get '/demo/members_only_group', {}, @
|
41
|
+
get '/demo/members_only_group', {}, @resource_auth_headers
|
42
42
|
|
43
43
|
@resp_token = response.headers['access-token']
|
44
44
|
@resp_client_id = response.headers['client']
|
@@ -52,7 +52,7 @@ class DemoGroupControllerTest < ActionDispatch::IntegrationTest
|
|
52
52
|
|
53
53
|
describe 'devise mappings' do
|
54
54
|
it 'should define current_user' do
|
55
|
-
assert_equal @
|
55
|
+
assert_equal @resource, @controller.current_user
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'should define user_signed_in?' do
|
@@ -60,19 +60,19 @@ class DemoGroupControllerTest < ActionDispatch::IntegrationTest
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'should not define current_mang' do
|
63
|
-
refute_equal @
|
63
|
+
refute_equal @resource, @controller.current_mang
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'should define current_member' do
|
67
|
-
assert_equal @
|
67
|
+
assert_equal @resource, @controller.current_member
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'should define current_members' do
|
71
|
-
assert @controller.current_members.include? @
|
71
|
+
assert @controller.current_members.include? @resource
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'should define member_signed_in?' do
|
75
|
-
assert @controller.current_members.include? @
|
75
|
+
assert @controller.current_members.include? @resource
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -10,11 +10,11 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
10
10
|
describe DemoMangController do
|
11
11
|
describe "Token access" do
|
12
12
|
before do
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
13
|
+
@resource = mangs(:confirmed_email_user)
|
14
|
+
@resource.skip_confirmation!
|
15
|
+
@resource.save!
|
16
16
|
|
17
|
-
@auth_headers = @
|
17
|
+
@auth_headers = @resource.create_new_auth_token
|
18
18
|
|
19
19
|
@token = @auth_headers['access-token']
|
20
20
|
@client_id = @auth_headers['client']
|
@@ -24,7 +24,7 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
24
24
|
describe 'successful request' do
|
25
25
|
before do
|
26
26
|
# ensure that request is not treated as batch request
|
27
|
-
age_token(@
|
27
|
+
age_token(@resource, @client_id)
|
28
28
|
|
29
29
|
get '/demo/members_only_mang', {}, @auth_headers
|
30
30
|
|
@@ -36,7 +36,7 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
36
36
|
|
37
37
|
describe 'devise mappings' do
|
38
38
|
it 'should define current_mang' do
|
39
|
-
assert_equal @
|
39
|
+
assert_equal @resource, @controller.current_mang
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should define mang_signed_in?' do
|
@@ -44,7 +44,7 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'should not define current_user' do
|
47
|
-
refute_equal @
|
47
|
+
refute_equal @resource, @controller.current_user
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -61,7 +61,7 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should return the user's uid in the auth header" do
|
64
|
-
assert_equal @
|
64
|
+
assert_equal @resource.uid, @resp_uid
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'should not treat this request as a batch request' do
|
@@ -70,9 +70,9 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
70
70
|
|
71
71
|
describe 'subsequent requests' do
|
72
72
|
before do
|
73
|
-
@
|
73
|
+
@resource.reload
|
74
74
|
# ensure that request is not treated as batch request
|
75
|
-
age_token(@
|
75
|
+
age_token(@resource, @client_id)
|
76
76
|
|
77
77
|
get '/demo/members_only_mang', {}, @auth_headers.merge({'access-token' => @resp_token})
|
78
78
|
end
|
@@ -104,24 +104,24 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
104
104
|
describe 'disable change_headers_on_each_request' do
|
105
105
|
before do
|
106
106
|
DeviseTokenAuth.change_headers_on_each_request = false
|
107
|
-
@
|
108
|
-
age_token(@
|
107
|
+
@resource.reload
|
108
|
+
age_token(@resource, @client_id)
|
109
109
|
|
110
110
|
get '/demo/members_only_mang', {}, @auth_headers
|
111
111
|
|
112
112
|
@first_is_batch_request = assigns(:is_batch_request)
|
113
|
-
@first_user = assigns(:
|
113
|
+
@first_user = assigns(:resource).dup
|
114
114
|
@first_access_token = response.headers['access-token']
|
115
115
|
@first_response_status = response.status
|
116
116
|
|
117
|
-
@
|
118
|
-
age_token(@
|
117
|
+
@resource.reload
|
118
|
+
age_token(@resource, @client_id)
|
119
119
|
|
120
120
|
# use expired auth header
|
121
121
|
get '/demo/members_only_mang', {}, @auth_headers
|
122
122
|
|
123
123
|
@second_is_batch_request = assigns(:is_batch_request)
|
124
|
-
@second_user = assigns(:
|
124
|
+
@second_user = assigns(:resource).dup
|
125
125
|
@second_access_token = response.headers['access-token']
|
126
126
|
@second_response_status = response.status
|
127
127
|
end
|
@@ -163,19 +163,19 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
163
163
|
describe 'batch requests' do
|
164
164
|
describe 'success' do
|
165
165
|
before do
|
166
|
-
age_token(@
|
166
|
+
age_token(@resource, @client_id)
|
167
167
|
#request.headers.merge!(@auth_headers)
|
168
168
|
|
169
169
|
get '/demo/members_only_mang', {}, @auth_headers
|
170
170
|
|
171
171
|
@first_is_batch_request = assigns(:is_batch_request)
|
172
|
-
@first_user = assigns(:
|
172
|
+
@first_user = assigns(:resource)
|
173
173
|
@first_access_token = response.headers['access-token']
|
174
174
|
|
175
175
|
get '/demo/members_only_mang', {}, @auth_headers
|
176
176
|
|
177
177
|
@second_is_batch_request = assigns(:is_batch_request)
|
178
|
-
@second_user = assigns(:
|
178
|
+
@second_user = assigns(:resource)
|
179
179
|
@second_access_token = response.headers['access-token']
|
180
180
|
end
|
181
181
|
|
@@ -202,24 +202,24 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
202
202
|
|
203
203
|
describe 'time out' do
|
204
204
|
before do
|
205
|
-
@
|
206
|
-
age_token(@
|
205
|
+
@resource.reload
|
206
|
+
age_token(@resource, @client_id)
|
207
207
|
|
208
208
|
get '/demo/members_only_mang', {}, @auth_headers
|
209
209
|
|
210
210
|
@first_is_batch_request = assigns(:is_batch_request)
|
211
|
-
@first_user = assigns(:
|
211
|
+
@first_user = assigns(:resource).dup
|
212
212
|
@first_access_token = response.headers['access-token']
|
213
213
|
@first_response_status = response.status
|
214
214
|
|
215
|
-
@
|
216
|
-
age_token(@
|
215
|
+
@resource.reload
|
216
|
+
age_token(@resource, @client_id)
|
217
217
|
|
218
218
|
# use expired auth header
|
219
219
|
get '/demo/members_only_mang', {}, @auth_headers
|
220
220
|
|
221
221
|
@second_is_batch_request = assigns(:is_batch_request)
|
222
|
-
@second_user = assigns(:
|
222
|
+
@second_user = assigns(:resource)
|
223
223
|
@second_access_token = response.headers['access-token']
|
224
224
|
@second_response_status = response.status
|
225
225
|
end
|
@@ -10,11 +10,11 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
10
10
|
describe DemoUserController do
|
11
11
|
describe "Token access" do
|
12
12
|
before do
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
13
|
+
@resource = users(:confirmed_email_user)
|
14
|
+
@resource.skip_confirmation!
|
15
|
+
@resource.save!
|
16
16
|
|
17
|
-
@auth_headers = @
|
17
|
+
@auth_headers = @resource.create_new_auth_token
|
18
18
|
|
19
19
|
@token = @auth_headers['access-token']
|
20
20
|
@client_id = @auth_headers['client']
|
@@ -24,7 +24,7 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
24
24
|
describe 'successful request' do
|
25
25
|
before do
|
26
26
|
# ensure that request is not treated as batch request
|
27
|
-
age_token(@
|
27
|
+
age_token(@resource, @client_id)
|
28
28
|
|
29
29
|
get '/demo/members_only', {}, @auth_headers
|
30
30
|
|
@@ -36,7 +36,7 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
36
36
|
|
37
37
|
describe 'devise mappings' do
|
38
38
|
it 'should define current_user' do
|
39
|
-
assert_equal @
|
39
|
+
assert_equal @resource, @controller.current_user
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should define user_signed_in?' do
|
@@ -44,7 +44,7 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'should not define current_mang' do
|
47
|
-
refute_equal @
|
47
|
+
refute_equal @resource, @controller.current_mang
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -61,7 +61,7 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should return the user's uid in the auth header" do
|
64
|
-
assert_equal @
|
64
|
+
assert_equal @resource.uid, @resp_uid
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'should not treat this request as a batch request' do
|
@@ -70,9 +70,9 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
70
70
|
|
71
71
|
describe 'subsequent requests' do
|
72
72
|
before do
|
73
|
-
@
|
73
|
+
@resource.reload
|
74
74
|
# ensure that request is not treated as batch request
|
75
|
-
age_token(@
|
75
|
+
age_token(@resource, @client_id)
|
76
76
|
|
77
77
|
get '/demo/members_only', {}, @auth_headers.merge({'access-token' => @resp_token})
|
78
78
|
end
|
@@ -104,24 +104,24 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
104
104
|
describe 'disable change_headers_on_each_request' do
|
105
105
|
before do
|
106
106
|
DeviseTokenAuth.change_headers_on_each_request = false
|
107
|
-
@
|
108
|
-
age_token(@
|
107
|
+
@resource.reload
|
108
|
+
age_token(@resource, @client_id)
|
109
109
|
|
110
110
|
get '/demo/members_only', {}, @auth_headers
|
111
111
|
|
112
112
|
@first_is_batch_request = assigns(:is_batch_request)
|
113
|
-
@first_user = assigns(:
|
113
|
+
@first_user = assigns(:resource).dup
|
114
114
|
@first_access_token = response.headers['access-token']
|
115
115
|
@first_response_status = response.status
|
116
116
|
|
117
|
-
@
|
118
|
-
age_token(@
|
117
|
+
@resource.reload
|
118
|
+
age_token(@resource, @client_id)
|
119
119
|
|
120
120
|
# use expired auth header
|
121
121
|
get '/demo/members_only', {}, @auth_headers
|
122
122
|
|
123
123
|
@second_is_batch_request = assigns(:is_batch_request)
|
124
|
-
@second_user = assigns(:
|
124
|
+
@second_user = assigns(:resource).dup
|
125
125
|
@second_access_token = response.headers['access-token']
|
126
126
|
@second_response_status = response.status
|
127
127
|
end
|
@@ -163,19 +163,19 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
163
163
|
describe 'batch requests' do
|
164
164
|
describe 'success' do
|
165
165
|
before do
|
166
|
-
age_token(@
|
166
|
+
age_token(@resource, @client_id)
|
167
167
|
#request.headers.merge!(@auth_headers)
|
168
168
|
|
169
169
|
get '/demo/members_only', {}, @auth_headers
|
170
170
|
|
171
171
|
@first_is_batch_request = assigns(:is_batch_request)
|
172
|
-
@first_user = assigns(:
|
172
|
+
@first_user = assigns(:resource)
|
173
173
|
@first_access_token = response.headers['access-token']
|
174
174
|
|
175
175
|
get '/demo/members_only', {}, @auth_headers
|
176
176
|
|
177
177
|
@second_is_batch_request = assigns(:is_batch_request)
|
178
|
-
@second_user = assigns(:
|
178
|
+
@second_user = assigns(:resource)
|
179
179
|
@second_access_token = response.headers['access-token']
|
180
180
|
end
|
181
181
|
|
@@ -202,24 +202,24 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
202
202
|
|
203
203
|
describe 'time out' do
|
204
204
|
before do
|
205
|
-
@
|
206
|
-
age_token(@
|
205
|
+
@resource.reload
|
206
|
+
age_token(@resource, @client_id)
|
207
207
|
|
208
208
|
get '/demo/members_only', {}, @auth_headers
|
209
209
|
|
210
210
|
@first_is_batch_request = assigns(:is_batch_request)
|
211
|
-
@first_user = assigns(:
|
211
|
+
@first_user = assigns(:resource).dup
|
212
212
|
@first_access_token = response.headers['access-token']
|
213
213
|
@first_response_status = response.status
|
214
214
|
|
215
|
-
@
|
216
|
-
age_token(@
|
215
|
+
@resource.reload
|
216
|
+
age_token(@resource, @client_id)
|
217
217
|
|
218
218
|
# use expired auth header
|
219
219
|
get '/demo/members_only', {}, @auth_headers
|
220
220
|
|
221
221
|
@second_is_batch_request = assigns(:is_batch_request)
|
222
|
-
@second_user = assigns(:
|
222
|
+
@second_user = assigns(:resource)
|
223
223
|
@second_access_token = response.headers['access-token']
|
224
224
|
@second_response_status = response.status
|
225
225
|
end
|
@@ -35,11 +35,11 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
|
|
35
35
|
describe "success" do
|
36
36
|
before do
|
37
37
|
xhr :get, :show, {confirmation_token: @token, redirect_url: @redirect_url}
|
38
|
-
@
|
38
|
+
@resource = assigns(:resource)
|
39
39
|
end
|
40
40
|
|
41
41
|
test "user should now be confirmed" do
|
42
|
-
assert @
|
42
|
+
assert @resource.confirmed?
|
43
43
|
end
|
44
44
|
|
45
45
|
test "should redirect to success url" do
|
@@ -52,8 +52,8 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
|
|
52
52
|
assert_raises(ActionController::RoutingError) {
|
53
53
|
xhr :get, :show, {confirmation_token: "bogus"}
|
54
54
|
}
|
55
|
-
@
|
56
|
-
refute @
|
55
|
+
@resource = assigns(:resource)
|
56
|
+
refute @resource.confirmed?
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -95,11 +95,11 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
|
|
95
95
|
before do
|
96
96
|
@redirect_url = Faker::Internet.url
|
97
97
|
xhr :get, :show, {confirmation_token: @token, redirect_url: @redirect_url}
|
98
|
-
@
|
98
|
+
@resource = assigns(:resource)
|
99
99
|
end
|
100
100
|
|
101
101
|
test "user should now be confirmed" do
|
102
|
-
assert @
|
102
|
+
assert @resource.confirmed?
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|