END LOOP;
 END
 $$ LANGUAGE plpgsql;
+
+-- Dummy implementation for testing purposes.
+CREATE OR REPLACE FUNCTION community_login(INOUT userid text, password text,
+       OUT success integer) RETURNS record AS $$
+BEGIN
+       SELECT userid, CASE WHEN LOWER(userid) = 'rhaas' AND password = 'bob'
+               THEN 1 ELSE 0 END
+       INTO userid, success;
+END
+$$ LANGUAGE plpgsql;
 
-CREATE TABLE person (
-       username                                varchar not null,
-       sha512password                  varchar not null,
-       PRIMARY KEY (username)
-);
-
 CREATE TABLE session (
        id                                              varchar not null,
-       username                                varchar not null references person (username),
+       userid                                  varchar not null,
        login_time                              timestamp not null default now(),
        PRIMARY KEY (id)
 );
                references patch_comment_type (id),
        message_id                              varchar,
        content                                 varchar,
-       creator                                 varchar not null references person (username),
+       creator                                 varchar not null,
        creation_time                   timestamp with time zone not null default now(),
        PRIMARY KEY (id)
 );
 
 package PgCommitFest::Handler;
-require Digest::SHA;
 require PgCommitFest::CommitFest;
 require PgCommitFest::CommitFestTopic;
 require PgCommitFest::Patch;
 sub login {
        my ($r) = @_;
 
-       # Prompt for username and password.
+       # Prompt for user ID and password.
        $r->set_title('Log in');
-       $r->add_control('username', 'text', 'Username', 'required' => 1);
+       $r->add_control('userid', 'text', 'User ID', 'required' => 1);
        $r->add_control('password', 'password', 'Password', 'required' => 1);
        $r->add_control('uri', 'hidden', 'URI');
        my %value = $r->initialize_controls();
        # Attempt to validate login.
        if ($r->cgi('go') && ! $r->is_error) {
                my $u = $r->db->select_one(<<EOM,
-SELECT username FROM person WHERE username = ? AND sha512password = ?
+SELECT userid FROM community_login(?, ?) WHERE success != 0
 EOM
-                       $value{'username'},
-                       Digest::SHA::sha512_base64($value{'password'}));
+                       $value{'userid'}, $value{'password'});
                if (defined $u) {
                        my $random_bits;
                        open(RANDOM_BITS, '</dev/urandom') || die "/dev/urandom: $!";
                        close(RANDOM_BITS);
                        my $session_cookie = unpack("H*", $random_bits);
                        $r->db->insert('session', { 'id' => $session_cookie,
-                               'username' => $u->{'username'} });
+                               'userid' => $u->{'userid'} });
                        $r->db->commit;
                        $r->header('Set-Cookie', "session=$session_cookie; path=/");
                        $r->redirect($value{'uri'} ne '' ? $value{'uri'} : '/');
                }
                else {
-                       $r->error('Invalid username or password.');
+                       $r->error('Invalid user ID or password.');
                }
        }
 
 
                                'patch_comment_type_id' => 2,
                                'message_id' => $message_id,
                                'content' => 'Initial version.',
-                               'creator' => $aa->{'username'},
+                               'creator' => $aa->{'userid'},
                        });
                }
                $r->db->commit;
 
                }
                else {
                        $value{'patch_id'} = $d->{'patch_id'};
-                       $value{'creator'} = $aa->{'username'};
+                       $value{'creator'} = $aa->{'userid'};
                        $id = $r->db->insert_returning_id('patch_comment', \%value);
                }
                $r->db->commit;
 
        if (!defined $self->{'authenticate'} && defined $self->cookie('session')) {
                $self->{'authenticate'} =
                        $self->db->select_one(<<EOM, $self->cookie('session'));
-SELECT p.* FROM person p, session s WHERE p.username = s.username AND s.id = ?
+SELECT s.* FROM session s WHERE s.id = ?
 EOM
        }
        if (!defined $self->{'authenticate'} && $option{'require_login'}) {
 
       </div>
     </td>
     <td id="commitfestNav">
-       [% IF authenticate.username.defined %]Welcome, [% authenticate.username | htmlsafe %] - <a href='/action/logout'>Log Out</a>
+       [% IF authenticate.userid.defined %]Welcome, [% authenticate.userid | htmlsafe %] - <a href='/action/logout'>Log Out</a>
        [% ELSE %]<a href='/action/login'>Log In</a>
        [% END %]
     </td>
 
-<p>Please log in using your username and password.</p>
+<p>Please log in using your community login user ID and password.</p>
 
 <div class='tblBasic'>
 <table cellspacing='0' class='tblBasicGrey'>
 <tr class='firstrow'>
-  <td class='colFirst'>[% control.username.display_name | htmlsafe %]</td>
-  <td class='colLast'>[% control.username.render %]</td>
+  <td class='colFirst'>[% control.userid.display_name | htmlsafe %]</td>
+  <td class='colLast'>[% control.userid.render %]</td>
 </tr>
 <tr class='lastrow'>
   <td class='colFirst'>[% control.password.display_name | htmlsafe %]</td>