| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
1
|
|
|
1
|
|
301448
|
use strict; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
38
|
|
|
2
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
30
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
25
|
use 5.0100; |
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
82
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package WebPrototypes::Registration; |
|
7
|
|
|
|
|
|
|
BEGIN { |
|
8
|
1
|
|
|
1
|
|
27
|
$WebPrototypes::Registration::VERSION = '0.002'; |
|
9
|
|
|
|
|
|
|
} |
|
10
|
1
|
|
|
1
|
|
6
|
use parent qw(Plack::Component); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
6
|
|
|
11
|
1
|
|
|
1
|
|
1090
|
use Plack::Request; |
|
|
1
|
|
|
|
|
41738
|
|
|
|
1
|
|
|
|
|
38
|
|
|
12
|
1
|
|
|
1
|
|
885
|
use URL::Encode 'url_encode_utf8'; |
|
|
1
|
|
|
|
|
11111
|
|
|
|
1
|
|
|
|
|
70
|
|
|
13
|
1
|
|
|
1
|
|
968
|
use String::Random 'random_regex'; |
|
|
1
|
|
|
|
|
3511
|
|
|
|
1
|
|
|
|
|
73
|
|
|
14
|
1
|
|
|
1
|
|
904
|
use Email::Sender::Simple qw(sendmail); |
|
|
1
|
|
|
|
|
297792
|
|
|
|
1
|
|
|
|
|
9
|
|
|
15
|
1
|
|
|
1
|
|
325
|
use Email::Simple; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
23
|
|
|
16
|
1
|
|
|
1
|
|
6
|
use Email::Simple::Creator; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
17
|
1
|
|
|
1
|
|
1139
|
use Email::Valid; |
|
|
1
|
|
|
|
|
237662
|
|
|
|
1
|
|
|
|
|
47
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
1
|
|
|
1
|
|
10
|
use Plack::Util::Accessor qw( email_validator ); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
13
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub prepare_app { |
|
22
|
1
|
|
|
1
|
1
|
119
|
my $self = shift; |
|
23
|
1
|
50
|
|
|
|
10
|
$self->email_validator( Email::Valid->new() ) if !defined $self->email_validator; |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
|
|
26
|
0
|
|
|
0
|
1
|
0
|
sub find_user { die 'find_user needs to be implemented in subclass' } |
|
27
|
|
|
|
|
|
|
|
|
28
|
0
|
|
|
0
|
1
|
0
|
sub create_user { die 'find_user needs to be implemented in subclass' } |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub wrap_text{ |
|
31
|
3
|
|
|
3
|
1
|
6
|
my( $self, $text ) = @_; |
|
32
|
3
|
|
|
|
|
64
|
return "$text"; |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub build_reply{ |
|
36
|
3
|
|
|
3
|
1
|
6
|
my( $self, $text ) = @_; |
|
37
|
3
|
|
|
|
|
22
|
return [ 200, [ 'Content-Type' => 'text/html' ], [ $self->wrap_text( $text ) ] ]; |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub call { |
|
41
|
3
|
|
|
3
|
1
|
67410
|
my($self, $env) = @_; |
|
42
|
3
|
|
|
|
|
35
|
my $req = Plack::Request->new( $env ); |
|
43
|
3
|
|
|
|
|
35
|
my $uerror = ''; |
|
44
|
3
|
|
|
|
|
6
|
my $eerror = ''; |
|
45
|
3
|
|
|
|
|
5
|
my $username = ''; |
|
46
|
3
|
|
|
|
|
6
|
my $email = ''; |
|
47
|
3
|
100
|
|
|
|
17
|
if( $req->method eq 'POST' ){ |
|
48
|
2
|
|
|
|
|
33
|
$username = $req->param( 'username' ); |
|
49
|
2
|
|
|
|
|
1313
|
$email = $req->param( 'email' ); |
|
50
|
2
|
100
|
|
|
|
33
|
if( $self->find_user( $username ) ){ |
|
51
|
1
|
|
|
|
|
8
|
$uerror = 'This username is already registered'; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
2
|
100
|
|
|
|
20
|
if( !$self->email_validator->address( $email ) ){ |
|
54
|
1
|
|
|
|
|
1829
|
$eerror = 'Wrong format of email'; |
|
55
|
|
|
|
|
|
|
} |
|
56
|
2
|
50
|
66
|
|
|
421
|
if( !$uerror && !$eerror ){ |
|
57
|
1
|
|
|
|
|
7
|
my $pass_token = random_regex( '\w{40}' ); |
|
58
|
1
|
|
|
|
|
204
|
my $user = $self->create_user( username => $username, email => $email, pass_token => $pass_token ); |
|
59
|
1
|
|
|
|
|
16
|
$self->_send_pass_token( $env, $user, $username, $email, $pass_token ); |
|
60
|
1
|
|
|
|
|
1831
|
return $self->build_reply( "Email sent" ); |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
} |
|
63
|
2
|
|
|
|
|
27
|
my $encoded_username = url_encode_utf8( $username ); |
|
64
|
2
|
|
|
|
|
53
|
my $encoded_email = url_encode_utf8( $email ); |
|
65
|
2
|
|
|
|
|
63
|
return $self->build_reply( <
|
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Username: $uerror |
|
68
|
|
|
|
|
|
|
Email: $eerror |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
END |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub build_email { |
|
76
|
1
|
|
|
1
|
1
|
3
|
my( $self, $to, $reset_url ) = @_; |
|
77
|
1
|
|
|
|
|
46
|
return Email::Simple->create( |
|
78
|
|
|
|
|
|
|
header => [ |
|
79
|
|
|
|
|
|
|
To => $to, |
|
80
|
|
|
|
|
|
|
From => 'root@localhost', |
|
81
|
|
|
|
|
|
|
Subject => "Password reset", |
|
82
|
|
|
|
|
|
|
], |
|
83
|
|
|
|
|
|
|
body => $reset_url, |
|
84
|
|
|
|
|
|
|
); |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub send_mail { |
|
88
|
0
|
|
|
0
|
1
|
0
|
my( $self, $mail ) = @_; |
|
89
|
0
|
|
|
|
|
0
|
sendmail( $mail ); |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub _send_pass_token { |
|
93
|
1
|
|
|
1
|
|
3
|
my( $self, $env, $user, $username, $email, $pass_token ) = @_; |
|
94
|
1
|
0
|
50
|
|
|
16
|
my $my_server = $env->{HTTP_ORIGIN} // |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
95
|
|
|
|
|
|
|
( $env->{'psgi.url_scheme'} // 'http' ) . '://' . |
|
96
|
|
|
|
|
|
|
( $env->{HTTP_HOST} // |
|
97
|
|
|
|
|
|
|
$env->{SERVER_NAME} . |
|
98
|
|
|
|
|
|
|
( $env->{SERVER_PORT} && $env->{SERVER_PORT} != 80 ? ':' . $env->{SERVER_PORT} : '' ) |
|
99
|
|
|
|
|
|
|
); |
|
100
|
1
|
|
|
|
|
9
|
my $reset_url = URI->new( $my_server ); |
|
101
|
1
|
|
|
|
|
72
|
$reset_url->path( "/ResetPass/reset/$username/$pass_token" ); |
|
102
|
1
|
|
|
|
|
58
|
$self->send_mail( $self->build_email( $email, $reset_url ) ); |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
1; |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=pod |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=head1 NAME |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
WebPrototypes::Registration - (Experimental) Plack application for registering a new user |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 VERSION |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
version 0.002 |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# connecting with DBIx::Class |
|
123
|
|
|
|
|
|
|
{ |
|
124
|
|
|
|
|
|
|
package My::Register; |
|
125
|
|
|
|
|
|
|
use parent 'WebPrototypes::Registration'; |
|
126
|
|
|
|
|
|
|
use Plack::Util::Accessor qw( schema ); |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub find_user { |
|
129
|
|
|
|
|
|
|
my( $self, $name ) = @_; |
|
130
|
|
|
|
|
|
|
return $self->schema->resultset( 'User' )->search({ username => $name })->next; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub create_user { |
|
134
|
|
|
|
|
|
|
my( $self, %fields ) = @_; |
|
135
|
|
|
|
|
|
|
return $self->schema->resultset( 'User' )->create({ %fields }); |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
use Plack::Builder; |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
my $app = My::Register->new( schema => $schema ); |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
builder { |
|
144
|
|
|
|
|
|
|
mount "/register" => builder { |
|
145
|
|
|
|
|
|
|
$app->to_app; |
|
146
|
|
|
|
|
|
|
}; |
|
147
|
|
|
|
|
|
|
}; |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
This application implements a user registration mechanism. After the registration |
|
152
|
|
|
|
|
|
|
and email address verification letter is sent. |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
The examples here are with DBIx::Class |
|
155
|
|
|
|
|
|
|
but they can be easily ported to other storage layers. |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
This application uses the Template Method design pattern. |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head2 PURE VIRTUAL METHODS |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
These methods need to be overriden in subclass. |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=over 4 |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=item find_user ( name ) |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Should return a true value if the name is already registered |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item create_user ( attributes ) |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Should create the user object. |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=back |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head2 VIRTUAL METHODS |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
These methods have defaults - but should probably be overriden anyway. |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=over 4 |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item wrap_text ( text ) |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Should return the html page containing the passed text fragment. By default it just adds |
|
184
|
|
|
|
|
|
|
the html and body tags. |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=item build_reply ( page_body ) |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Should return the PSGI response data structure. |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=item build_email ( to_address, link_to_the_reset_page ) |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Should create the email containing the link. |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item send_mail ( mail ) |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
Should send the mail (created by build_mail). |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=back |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 OTHER METHODS |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=over 4 |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=item call ( env ) |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=back |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
L |
|
211
|
|
|
|
|
|
|
L |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 AUTHOR |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
Zbigniew Lukasiak |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
This software is Copyright (c) 2011 by Zbigniew Lukasiak . |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
This is free software, licensed under: |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
The Artistic License 2.0 (GPL Compatible) |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=cut |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
__END__ |