devise_invitable 1.0.3 → 1.1.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.
Potentially problematic release.
This version of devise_invitable might be problematic. Click here for more details.
- data/app/controllers/devise/invitations_controller.rb +2 -2
- data/lib/devise_invitable/controllers/registrations.rb~ +14 -21
- data/lib/devise_invitable/model.rb +8 -2
- data/lib/devise_invitable/model.rb~ +5 -30
- data/lib/devise_invitable/version.rb +1 -1
- metadata +29 -33
- data/app/controllers/devise/invitations_controller.rb~ +0 -48
- data/app/views/devise/invitations/new.html.erb~ +0 -14
- data/lib/devise_invitable.rb~ +0 -68
- data/lib/generators/devise_invitable/install_generator.rb~ +0 -54
@@ -13,7 +13,7 @@ class Devise::InvitationsController < DeviseController
|
|
13
13
|
|
14
14
|
# POST /resource/invitation
|
15
15
|
def create
|
16
|
-
self.resource = resource_class.invite!(
|
16
|
+
self.resource = resource_class.invite!(resource_params, current_inviter)
|
17
17
|
|
18
18
|
if resource.errors.empty?
|
19
19
|
set_flash_message :notice, :send_instructions, :email => self.resource.email
|
@@ -35,7 +35,7 @@ class Devise::InvitationsController < DeviseController
|
|
35
35
|
|
36
36
|
# PUT /resource/invitation
|
37
37
|
def update
|
38
|
-
self.resource = resource_class.accept_invitation!(
|
38
|
+
self.resource = resource_class.accept_invitation!(resource_params)
|
39
39
|
|
40
40
|
if resource.errors.empty?
|
41
41
|
set_flash_message :notice, :updated
|
@@ -1,42 +1,35 @@
|
|
1
1
|
module DeviseInvitable::Controllers::Registrations
|
2
2
|
def self.included(controller)
|
3
|
-
controller.send :around_filter, :
|
3
|
+
controller.send :around_filter, :destroy_if_previously_invited, :only => :create
|
4
4
|
end
|
5
5
|
|
6
6
|
protected
|
7
7
|
|
8
8
|
def destroy_if_previously_invited
|
9
|
-
|
9
|
+
invitation_info = {}
|
10
10
|
|
11
11
|
hash = params[resource_name]
|
12
|
-
if hash && hash[:email]
|
12
|
+
if resource_class.modules.include?(:invitable) && hash && hash[:email]
|
13
13
|
resource = resource_class.where(:email => hash[:email], :encrypted_password => '').first
|
14
14
|
if resource
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
invitation_info[:invitation_sent_at] = resource[:invitation_sent_at]
|
16
|
+
invitation_info[:invited_by_id] = resource[:invited_by_id]
|
17
|
+
invitation_info[:invited_by_type] = resource[:invited_by_type]
|
18
18
|
resource.destroy
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
|
23
|
-
def keep_invitation_info
|
24
|
-
resource_invitable = resource_class.devise_modules.include?(:invitable)
|
25
|
-
destroy_if_previously_invited if resource_invitable
|
21
|
+
|
22
|
+
# execute the action (create)
|
26
23
|
yield
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def reset_invitation_info
|
31
|
-
puts @invitation_info.inspect
|
24
|
+
# Note that the after_filter is executed at THIS position !
|
25
|
+
|
32
26
|
# Restore info about the last invitation (for later reference)
|
33
27
|
# Reset the invitation_info only, if invited_by_id is still nil at this stage:
|
34
|
-
resource = resource_class.where(:email =>
|
35
|
-
puts resource.inspect
|
28
|
+
resource = resource_class.where(:email => hash[:email], :invited_by_id => nil).first
|
36
29
|
if resource
|
37
|
-
resource[:invitation_sent_at] =
|
38
|
-
resource[:invited_by_id] =
|
39
|
-
resource[:invited_by_type] =
|
30
|
+
resource[:invitation_sent_at] = invitation_info[:invitation_sent_at]
|
31
|
+
resource[:invited_by_id] = invitation_info[:invited_by_id]
|
32
|
+
resource[:invited_by_type] = invitation_info[:invited_by_type]
|
40
33
|
resource.save!
|
41
34
|
end
|
42
35
|
end
|
@@ -44,6 +44,12 @@ module Devise
|
|
44
44
|
scope :invitation_accepted, where(:invitation_accepted_at.ne => nil)
|
45
45
|
else
|
46
46
|
scope :invitation_accepted, where(arel_table[:invitation_accepted_at].not_eq(nil))
|
47
|
+
|
48
|
+
[:before_invitation_accepted, :after_invitation_accepted].each do |callback_method|
|
49
|
+
send callback_method do
|
50
|
+
notify_observers callback_method
|
51
|
+
end
|
52
|
+
end
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
@@ -109,7 +115,7 @@ module Devise
|
|
109
115
|
generate_invitation_token if self.invitation_token.nil?
|
110
116
|
self.invitation_sent_at = Time.now.utc
|
111
117
|
self.invited_by = invited_by if invited_by
|
112
|
-
|
118
|
+
|
113
119
|
# Call these before_validate methods since we aren't validating on save
|
114
120
|
self.downcase_keys if self.new_record? && self.respond_to?(:downcase_keys)
|
115
121
|
self.strip_whitespace if self.new_record? && self.respond_to?(:strip_whitespace)
|
@@ -152,7 +158,7 @@ module Devise
|
|
152
158
|
|
153
159
|
# Deliver the invitation email
|
154
160
|
def deliver_invitation
|
155
|
-
|
161
|
+
send_devise_notification(:invitation_instructions)
|
156
162
|
end
|
157
163
|
|
158
164
|
# Checks if the invitation for the user is within the limit time.
|
@@ -52,7 +52,7 @@ module Devise
|
|
52
52
|
|
53
53
|
# Verifies whether a user has accepted an invite, was never invited, or is in the process of accepting an invitation, or not
|
54
54
|
def accepting_or_not_invited?
|
55
|
-
!!completing_invite ||
|
55
|
+
!!completing_invite || invited_to_sign_up?
|
56
56
|
end
|
57
57
|
|
58
58
|
# Verifies whether a user has been invited or not
|
@@ -98,13 +98,6 @@ module Devise
|
|
98
98
|
super
|
99
99
|
accept_invitation!
|
100
100
|
end
|
101
|
-
|
102
|
-
def invite_key_valid?
|
103
|
-
return true unless self.class.invite_key.is_a? Hash # FIXME: remove this line when deprecation is removed
|
104
|
-
self.class.invite_key.all? do |key, regexp|
|
105
|
-
regexp.nil? || self.send(key).try(:match, regexp)
|
106
|
-
end
|
107
|
-
end
|
108
101
|
|
109
102
|
protected
|
110
103
|
# Overriding the method in Devise's :validatable module so password is not required on inviting
|
@@ -147,16 +140,6 @@ module Devise
|
|
147
140
|
end
|
148
141
|
|
149
142
|
module ClassMethods
|
150
|
-
# Return fields to invite
|
151
|
-
def invite_key_fields
|
152
|
-
if invite_key.is_a? Hash
|
153
|
-
invite_key.keys
|
154
|
-
else
|
155
|
-
ActiveSupport::Deprecation.warn("invite_key should be a hash like {#{invite_key.inspect} => /.../}")
|
156
|
-
Array(invite_key)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
143
|
# Attempt to find a user by it's email. If a record is not found, create a new
|
161
144
|
# user and send invitation to it. If user is found, returns the user with an
|
162
145
|
# email already exists error.
|
@@ -164,24 +147,16 @@ module Devise
|
|
164
147
|
# resend_invitation is set to false
|
165
148
|
# Attributes must contain the user email, other attributes will be set in the record
|
166
149
|
def _invite(attributes={}, invited_by=nil, &block)
|
167
|
-
|
168
|
-
attributes_hash = {}
|
169
|
-
invite_key_array.each do |k,v|
|
170
|
-
attributes_hash[k] = attributes.delete(k)
|
171
|
-
end
|
172
|
-
|
173
|
-
invitable = find_or_initialize_with_errors(invite_key_array, attributes_hash)
|
150
|
+
invitable = find_or_initialize_with_error_by(invite_key, attributes.delete(invite_key))
|
174
151
|
invitable.assign_attributes(attributes, :as => inviter_role(invited_by))
|
175
152
|
invitable.invited_by = invited_by
|
176
153
|
|
177
154
|
invitable.skip_password = true
|
178
155
|
invitable.valid? if self.validate_on_invite
|
179
156
|
if invitable.new_record?
|
180
|
-
invitable.errors.clear if !self.validate_on_invite and invitable.
|
181
|
-
|
182
|
-
|
183
|
-
invitable.errors.add(key, :taken)
|
184
|
-
end
|
157
|
+
invitable.errors.clear if !self.validate_on_invite and invitable.email.try(:match, Devise.email_regexp)
|
158
|
+
else
|
159
|
+
invitable.errors.add(invite_key, :taken) unless invitable.invited_to_sign_up? && self.resend_invitation
|
185
160
|
end
|
186
161
|
|
187
162
|
if invitable.errors.empty?
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_invitable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.3
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sergio Cambra
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-08-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: bundler
|
@@ -49,34 +49,34 @@ dependencies:
|
|
49
49
|
type: :runtime
|
50
50
|
version_requirements: *id002
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
|
-
name:
|
52
|
+
name: actionmailer
|
53
53
|
prerelease: false
|
54
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
55
|
none: false
|
56
56
|
requirements:
|
57
|
-
- -
|
57
|
+
- - ~>
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
hash:
|
59
|
+
hash: 7
|
60
60
|
segments:
|
61
|
-
-
|
62
|
-
- 0
|
61
|
+
- 3
|
63
62
|
- 0
|
64
|
-
version:
|
63
|
+
version: "3.0"
|
65
64
|
type: :runtime
|
66
65
|
version_requirements: *id003
|
67
66
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
67
|
+
name: devise
|
69
68
|
prerelease: false
|
70
69
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
70
|
none: false
|
72
71
|
requirements:
|
73
|
-
- -
|
72
|
+
- - ">="
|
74
73
|
- !ruby/object:Gem::Version
|
75
|
-
hash:
|
74
|
+
hash: 11
|
76
75
|
segments:
|
77
|
-
-
|
76
|
+
- 2
|
77
|
+
- 1
|
78
78
|
- 0
|
79
|
-
version:
|
79
|
+
version: 2.1.0
|
80
80
|
type: :runtime
|
81
81
|
version_requirements: *id004
|
82
82
|
description: It adds support for send invitations by email (it requires to be authenticated) and accept the invitation by setting a password.
|
@@ -89,35 +89,31 @@ extensions: []
|
|
89
89
|
extra_rdoc_files: []
|
90
90
|
|
91
91
|
files:
|
92
|
-
- app/
|
93
|
-
- app/views/devise/invitations/new.html.erb~
|
92
|
+
- app/controllers/devise/invitations_controller.rb
|
94
93
|
- app/views/devise/invitations/edit.html.erb
|
95
94
|
- app/views/devise/invitations/new.html.erb
|
96
|
-
- app/
|
97
|
-
- app/controllers/devise/invitations_controller.rb~
|
95
|
+
- app/views/devise/mailer/invitation_instructions.html.erb
|
98
96
|
- config/locales/en.yml
|
99
97
|
- lib/devise_invitable.rb
|
100
|
-
- lib/devise_invitable.rb
|
101
|
-
- lib/devise_invitable/routes.rb
|
98
|
+
- lib/devise_invitable/mailer.rb
|
102
99
|
- lib/devise_invitable/model.rb
|
103
100
|
- lib/devise_invitable/rails.rb
|
104
|
-
- lib/devise_invitable/
|
101
|
+
- lib/devise_invitable/routes.rb
|
105
102
|
- lib/devise_invitable/version.rb
|
106
|
-
- lib/devise_invitable/model.rb~
|
107
|
-
- lib/devise_invitable/inviter.rb
|
108
|
-
- lib/devise_invitable/controllers/url_helpers.rb
|
109
103
|
- lib/devise_invitable/controllers/helpers.rb
|
110
|
-
- lib/devise_invitable/controllers/
|
104
|
+
- lib/devise_invitable/controllers/url_helpers.rb
|
111
105
|
- lib/devise_invitable/controllers/registrations.rb
|
112
|
-
- lib/
|
106
|
+
- lib/devise_invitable/controllers/registrations.rb~
|
107
|
+
- lib/devise_invitable/inviter.rb
|
108
|
+
- lib/devise_invitable/model.rb~
|
113
109
|
- lib/generators/active_record/devise_invitable_generator.rb
|
114
|
-
- lib/generators/
|
115
|
-
- lib/generators/devise_invitable/templates/simple_form_for/invitations/edit.html.erb
|
116
|
-
- lib/generators/devise_invitable/templates/simple_form_for/invitations/new.html.erb
|
117
|
-
- lib/generators/devise_invitable/install_generator.rb
|
110
|
+
- lib/generators/active_record/templates/migration.rb
|
118
111
|
- lib/generators/devise_invitable/views_generator.rb
|
119
112
|
- lib/generators/devise_invitable/devise_invitable_generator.rb
|
120
|
-
- lib/generators/devise_invitable/install_generator.rb
|
113
|
+
- lib/generators/devise_invitable/install_generator.rb
|
114
|
+
- lib/generators/devise_invitable/templates/simple_form_for/invitations/edit.html.erb
|
115
|
+
- lib/generators/devise_invitable/templates/simple_form_for/invitations/new.html.erb
|
116
|
+
- lib/generators/mongoid/devise_invitable_generator.rb
|
121
117
|
- LICENSE
|
122
118
|
- README.rdoc
|
123
119
|
homepage: https://github.com/scambra/devise_invitable
|
@@ -155,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
151
|
requirements: []
|
156
152
|
|
157
153
|
rubyforge_project:
|
158
|
-
rubygems_version: 1.8.
|
154
|
+
rubygems_version: 1.8.23
|
159
155
|
signing_key:
|
160
156
|
specification_version: 3
|
161
157
|
summary: An invitation strategy for Devise
|
@@ -1,48 +0,0 @@
|
|
1
|
-
class Devise::InvitationsController < ApplicationController
|
2
|
-
include Devise::Controllers::InternalHelpers
|
3
|
-
|
4
|
-
before_filter :authenticate_inviter!, :only => [:new, :create]
|
5
|
-
before_filter :require_no_authentication, :only => [:edit, :update]
|
6
|
-
helper_method :after_sign_in_path_for
|
7
|
-
|
8
|
-
# GET /resource/invitation/new
|
9
|
-
def new
|
10
|
-
build_resource
|
11
|
-
render_with_scope :new
|
12
|
-
end
|
13
|
-
|
14
|
-
# POST /resource/invitation
|
15
|
-
def create
|
16
|
-
self.resource = resource_class.invite!(params[resource_name])
|
17
|
-
|
18
|
-
if resource.errors.empty?
|
19
|
-
puts params.inspect
|
20
|
-
set_flash_message :notice, :send_instructions, :email => self.resource.email
|
21
|
-
redirect_to after_sign_in_path_for(resource_name)
|
22
|
-
else
|
23
|
-
render_with_scope :new
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# GET /resource/invitation/accept?invitation_token=abcdef
|
28
|
-
def edit
|
29
|
-
if params[:invitation_token] && self.resource = resource_class.first(:conditions => { :invitation_token => params[:invitation_token] })
|
30
|
-
render_with_scope :edit
|
31
|
-
else
|
32
|
-
set_flash_message(:alert, :invitation_token_invalid)
|
33
|
-
redirect_to after_sign_out_path_for(resource_name)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# PUT /resource/invitation
|
38
|
-
def update
|
39
|
-
self.resource = resource_class.accept_invitation!(params[resource_name])
|
40
|
-
|
41
|
-
if resource.errors.empty?
|
42
|
-
set_flash_message :notice, :updated
|
43
|
-
sign_in_and_redirect(resource_name, resource)
|
44
|
-
else
|
45
|
-
render_with_scope :edit
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
<h2>Send invitation</h2>
|
2
|
-
|
3
|
-
<%= form_for resource, :as => resource_name, :url => invitation_path(resource_name), :html => {:method => :post} do |f| %>
|
4
|
-
<%= devise_error_messages! %>
|
5
|
-
|
6
|
-
<% Array(resource.class.invite_key).each do |field| -%>
|
7
|
-
<p><%= f.label field %><br />
|
8
|
-
<%= f.text_field field %></p>
|
9
|
-
<% end -%>
|
10
|
-
|
11
|
-
<p><%= f.submit "Send an invitation" %></p>
|
12
|
-
<% end %>
|
13
|
-
|
14
|
-
<%= link_to "Home", after_sign_in_path_for(resource_name) %><br />
|
data/lib/devise_invitable.rb~
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'devise'
|
2
|
-
|
3
|
-
module DeviseInvitable
|
4
|
-
autoload :Inviter, 'devise_invitable/inviter'
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'devise_invitable/mailer'
|
8
|
-
require 'devise_invitable/routes'
|
9
|
-
require 'devise_invitable/controllers/url_helpers'
|
10
|
-
require 'devise_invitable/controllers/registrations'
|
11
|
-
require 'devise_invitable/controllers/helpers'
|
12
|
-
require 'devise_invitable/rails'
|
13
|
-
|
14
|
-
module Devise
|
15
|
-
# Public: Validity period of the invitation token (default: 0). If
|
16
|
-
# invite_for is 0 or nil, the invitation will never expire.
|
17
|
-
# Set invite_for in the Devise configuration file (in config/initializers/devise.rb).
|
18
|
-
#
|
19
|
-
# config.invite_for = 2.weeks # => The invitation token will be valid 2 weeks
|
20
|
-
mattr_accessor :invite_for
|
21
|
-
@@invite_for = 0
|
22
|
-
|
23
|
-
# Public: Flag that force a record to be valid before being actually invited
|
24
|
-
# (default: false).
|
25
|
-
#
|
26
|
-
# Examples (in config/initializers/devise.rb)
|
27
|
-
#
|
28
|
-
# config.validate_on_invite = true
|
29
|
-
mattr_accessor :validate_on_invite
|
30
|
-
@@validate_on_invite = false
|
31
|
-
|
32
|
-
# Public: number of invitations the user is allowed to send
|
33
|
-
#
|
34
|
-
# Examples (in config/initializers/devise.rb)
|
35
|
-
#
|
36
|
-
# config.invitation_limit = nil
|
37
|
-
mattr_accessor :invitation_limit
|
38
|
-
@@invitation_limit = nil
|
39
|
-
|
40
|
-
# Public: The key to be used to check existing users when sending an invitation.
|
41
|
-
# It can be an array.
|
42
|
-
#
|
43
|
-
# Examples (in config/initializers/devise.rb)
|
44
|
-
#
|
45
|
-
# config.invite_key = :email
|
46
|
-
mattr_accessor :invite_key
|
47
|
-
@@invite_key = :email
|
48
|
-
|
49
|
-
# Public: The regexp to be used to test invite key when sending an invitation.
|
50
|
-
# It must be a hash indexed by invite_key
|
51
|
-
#
|
52
|
-
# Examples (in config/initializers/devise.rb)
|
53
|
-
#
|
54
|
-
# config.invite_key = :email
|
55
|
-
mattr_accessor :invite_key_validation_regexp
|
56
|
-
@@invite_key_validation_regexp = {:email => Devise.email_regexp}
|
57
|
-
|
58
|
-
# Public: Resend invitation if user with invited status is invited again
|
59
|
-
# (default: true)
|
60
|
-
#
|
61
|
-
# Example (in config/initializers/devise.rb)
|
62
|
-
#
|
63
|
-
# config.resend_invitation = false
|
64
|
-
mattr_accessor :resend_invitation
|
65
|
-
@@resend_invitation = true
|
66
|
-
end
|
67
|
-
|
68
|
-
Devise.add_module :invitable, :controller => :invitations, :model => 'devise_invitable/model', :route => :invitation
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module DeviseInvitable
|
2
|
-
module Generators
|
3
|
-
class InstallGenerator < Rails::Generators::Base
|
4
|
-
source_root File.expand_path("../../templates", __FILE__)
|
5
|
-
desc "Add DeviseInvitable config variables to the Devise initializer and copy DeviseInvitable locale files to your application."
|
6
|
-
|
7
|
-
# def devise_install
|
8
|
-
# invoke "devise:install"
|
9
|
-
# end
|
10
|
-
|
11
|
-
def add_config_options_to_initializer
|
12
|
-
devise_initializer_path = "config/initializers/devise.rb"
|
13
|
-
if File.exist?(devise_initializer_path)
|
14
|
-
old_content = File.read(devise_initializer_path)
|
15
|
-
|
16
|
-
if old_content.match(Regexp.new(/^\s# ==> Configuration for :invitable\n/))
|
17
|
-
false
|
18
|
-
else
|
19
|
-
inject_into_file(devise_initializer_path, :before => " # ==> Configuration for :confirmable\n") do
|
20
|
-
<<-CONTENT
|
21
|
-
# ==> Configuration for :invitable
|
22
|
-
# The period the generated invitation token is valid, after
|
23
|
-
# this period, the invited resource won't be able to accept the invitation.
|
24
|
-
# When invite_for is 0 (the default), the invitation won't expire.
|
25
|
-
# config.invite_for = 2.weeks
|
26
|
-
|
27
|
-
# Number of invitations users can send.
|
28
|
-
# If invitation_limit is nil, users can send unlimited invitations.
|
29
|
-
# If invitation_limit is 0, users can't send invitations.
|
30
|
-
# If invitation_limit n > 0, users can send n invitations.
|
31
|
-
# Default: nil
|
32
|
-
# config.invitation_limit = 5
|
33
|
-
|
34
|
-
# The key to be used to check existing users when sending an invitation.
|
35
|
-
# config.invite_key = {:email => /\A[^@]+@[^@]+\z/}
|
36
|
-
# config.invite_key = {:email => /\A[^@]+@[^@]+\z/, :username => nil}
|
37
|
-
|
38
|
-
# Flag that force a record to be valid before being actually invited
|
39
|
-
# Default: false
|
40
|
-
# config.validate_on_invite = true
|
41
|
-
|
42
|
-
CONTENT
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def copy_locale
|
49
|
-
copy_file "../../../config/locales/en.yml", "config/locales/devise_invitable.en.yml"
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|