Initial auth example, something is a bit wonky with the session?
[catagits/Web-Simple.git] / examples / auth / auth.cgi
1 #!/usr/bin/env perl
2
3 package AuthApp;
4
5 use lib 'lib';
6 use Web::Simple;
7 use Authen::Passphrase::SaltedDigest;
8 with 'Web::Simple::Application::Role::Authentication';
9
10 use AuthApp::Schema;
11
12 has 'schema' => (is => 'lazy');
13 has 'deployed' => (is => 'rw');
14
15 sub dispatch_request {
16     my ($self) = @_;
17     
18     my $user;
19     $self->check_authenticated($user);
20
21     sub (GET + /) {
22         my ($self) = @_;
23
24         return [ 200, [ 'Content-type', 'text/html' ], [ $self->main_page($user)  ]];
25     },
26
27     sub (POST + /login + %username=&password=) {
28         my ($self, $usern, $passw) = @_;
29         
30         my $user = $self->get_check_user($usern, $passw);
31         
32         if($user) {
33             return ($self->set_authenticated($user), 
34                     [ 303, [ 'Content-type', 'text/html', 
35                              'Location', '/' ], 
36                       [ 'Login succeeded, back to <a href="/"></a>' ]]);
37         } else {
38             return [ 200, [ 'Content-type', 'text/html' ], [ 'Login failed' ]];
39         }
40     },
41     sub (POST + /register + %username=&password=) {
42         my ($self, $username, $password) = @_;
43
44         ## FIXME: Check length of inputs!
45         my $newuser = $self->create_user($username, $password);
46
47         if($newuser) {
48             return 
49                 [ 303, [ 'Content-type', 'text/html', 
50                          'Location', '/' ], 
51                   [ 'Registration succeeded, back to <a href="/"></a>' ]];
52         } else {
53             return [ 200, [ 'Content-type', 'text/html' ], [ 'Registration failed' ]];
54         }
55     },
56     sub (GET + /logout) {
57         my ($self) = @_;
58
59         if($user) {
60             $user = undef;
61         }
62
63         return ($self->logout,
64                 [ 303, [ 'Content-type', 'text/html', 
65                          'Location', '/' ], 
66                       [ 'Logout succeeded, back to <a href="/"></a>' ]]);
67     },
68 }
69
70 ## Implement these two (examples based on DBIx::Class):
71
72 ## _ident_from_user, return a unique way of identifying a user, this
73 ## will be stored in the session
74 sub _ident_from_user {
75   my ($self, $user) = @_;
76   return $user->ident_condition;
77 }
78
79 ## _user_from_ident, return a user object, given the unique user identifier
80 sub _user_from_ident {
81   my ($self, $ident) = @_;
82   return $self->users_rs->find($ident);
83 }
84
85 sub _build_schema {
86     my ($self) = @_;
87
88     my $schema = AuthApp::Schema->connect("dbi:SQLite:auth.db");
89     if(!$self->deployed) {
90         $schema->deploy;
91         $self->deployed(1);
92     }
93
94     return $schema;
95 }
96
97 sub get_check_user {
98     my ($self, $username, $password) = @_;
99     
100     my $user = $self->schema->resultset('User')->find({ username => $username });
101     if($user && $user->password->match($password)) {
102         return $user;
103     }
104     
105     return;
106 }
107
108 sub create_user {
109     my ($self, $username, $password) = @_;
110     
111     my $user = $self->schema->resultset('User')->find({ username => $username });
112     if($user) {
113         warn "Cowardly refusing to re-create an existing user $username";
114         return;
115     }
116
117     $user = $self->schema->resultset('User')->create({
118         username => $username,
119         password => Authen::Passphrase::SaltedDigest->new(algorithm => "SHA-1", salt_random => 20, passphrase=>$password),
120                                              });
121     
122     return $user;
123 }
124
125 sub main_page {
126     my ($self, $user) = @_;
127
128     my $is_user = $user ? $user->username . ' is logged in. <a href="logout">Logout</a>' : <<FORM;
129 Login:<br>
130    <form action="login" method="post">
131     Username: <input type="text" name="username"><br>
132     Password: <input type="password" name="password"><br>
133     <input type="submit">
134    </form>
135 Register:<br>
136    <form action="register" method="post">
137     Username: <input type="text" name="username"><br>
138     Password: <input type="password" name="password"><br>
139     <input type="submit">
140    </form>
141 FORM
142
143     return << "HTML";
144 <html>
145   <head><title>Auth App</title></head>
146   <body>
147   $is_user
148   </body>
149 </html>
150 HTML
151
152 }
153
154 AuthApp->run_if_script;