Add user registration

[?]
Feb 27, 2013, 5:33 PM
XJRJ4J7M6BC433TBLWHHKX7UYYCFX6M7ZQLUEYYTREPCSM6M3RDQC

Dependencies

  • [2] 3U3QRKAW Log time required by a request
  • [3] U2ZK6LZ7 Fix some warnings
  • [4] LC64D4PU Correctly redirect to the referring page when logging in
  • [5] UICHT2PS Add a search feature
  • [6] PCKLFRT5 Support push notification of repository changes
  • [7] JLDUSNUO * Unify rendering of finished and scheduled builds.
  • [8] S66BOMVU * Added authentication.
  • [9] RU7AQO7U * Role-based access control. Only admins can create projects. Only
  • [10] 6KJXJB7N qualify ordery_by clauses when necessary, remove unnecessary order_by's, reported by Ludo, resulted in errors in sqlite
  • [11] KNU2FBIG * hydra: order project list on name
  • [12] IZEXRZWT Replace old logo with Nix/NixOS logo.
  • [13] 3PNG7NIB Remove trailing whitespace
  • [14] PZL3SZM3 Give every page a consistent title
  • [15] K5BEBWKM
  • [16] ODNCGFQ5 * Improved the navigation bar: don't include all projects (since that
  • [17] YJYBKPZ5 Hydra/33: 'Sign in' should return to the referring page
  • [18] HQGXL4MX Add validation for project and jobset names
  • [19] W3HI52QV use NIX_*_DIR env vars when defined
  • [20] BN2MO2MP fix redirect after login
  • [21] QMPX3JDF * hydra: show queue optimization
  • [22] 3Y7AFJSS * Support linking to the latest job in a view for a specific platform, e.g.
  • [23] H7CNGK4O * Log evaluation errors etc. in the DB.
  • [24] G4X5IUYJ Remove default logo, replaced by text for now. Hide template in jobset edit.
  • [25] ZWCTAZGL added newsitems, added some admin options to clear various caches.
  • [26] QTFVCDIF added hide feature for project/jobset
  • [27] MGOGOKQP add tracker html code via HYDRA_TRACKER
  • [28] N45RZUQ6 Reduce I/O in build listings by only fetching required columns
  • [29] L2E6EVE2 * Merged the Build and Job tables.
  • [30] HRAFVVOE make logo configurable via HYDRA_LOGO env var
  • [31] CHCVBZ3W * Slight cleanup.
  • [32] LE6BJMGZ
  • [33] K42RSSSI
  • [34] NOSDBMWD Remove comments, re-add logo.
  • [35] JFZNAYJX * Showing releases.
  • [36] WRIU3S5E * UI for cloning builds (not functional yet).
  • [37] 2AUODJBT
  • [38] EFWN7JBV * Added a status page that shows all the currently executing build steps.
  • [39] SZYDW2DG hydra: added some user admin
  • [40] J5UVLXOK * Start of a basic Catalyst web interface.
  • [41] YTSIRIMK * Separate job status and all builds pages.
  • [42] DXBTGOA4 Print out an Apache-style access log
  • [43] MOX7XJ2E Merge the BuildSchedulingInfo table into the Builds table
  • [44] JARRBLZD Bootstrapify the Hydra forms (except the project and jobset edit pages)
  • [45] FPK5LF53 * Put the project-related actions in a separate controller. Put the
  • [46] LMETCA7G Cleanup
  • [*] SAFVRDTK * Put Hydra's dependencies so that they can easily be installed in a
  • [*] AMFMXR52 Provide a command ‘hydra-init’ to initialise/upgrade the database
  • [*] IK2KI6KZ Add create-user action that was mostly present already.
  • [*] D5QIOJGP * Move everything up one directory.
  • [*] LBNVQXUB * Build the /build stuff in a separate controller.
  • [*] AFTXA575 * $HYDRA_DATA environment variable.
  • [*] 7ZQAHJQM Fix indentation
  • [*] QL55ECJ6 - adapted ui for hydra, more in line with nixos.org website

Change contents

  • edit in deps.nix at line 8
    [49.150]
    [49.150]
    perlPackages.CatalystPluginCaptcha
  • edit in src/lib/Hydra/Controller/Admin.pm at line 90
    [7.132]
    [50.102]
  • replacement in src/lib/Hydra/Controller/Root.pm at line 23
    [7.80][7.0:51](),[7.100][7.0:51](),[7.84][7.0:51]()
    $c->stash->{tracker} = $ENV{"HYDRA_TRACKER"} ;
    [7.80]
    [7.51]
    $c->stash->{tracker} = $ENV{"HYDRA_TRACKER"};
    $c->stash->{flashMsg} = $c->flash->{flashMsg};
    $c->stash->{successMsg} = $c->flash->{successMsg};
  • edit in src/lib/Hydra/Controller/Root.pm at line 39
    [7.91][7.52:54](),[7.399][7.52:54](),[7.2335][7.52:54](),[7.604][7.52:54](),[7.54][7.430:431](),[7.431][7.54:55](),[7.54][7.54:55](),[7.55][7.432:476](),[7.476][7.491:492](),[7.492][7.481:597](),[7.481][7.481:597](),[7.597][7.55:56](),[7.55][7.55:56](),[7.56][4.0:79](),[4.79][7.80:232](),[7.80][7.80:232](),[7.232][7.209:216](),[7.209][7.209:216](),[7.216][7.598:712](),[7.56][7.598:712](),[7.712][7.233:353](),[7.262][7.920:940](),[7.353][7.920:940](),[7.920][7.920:940](),[7.940][7.73:83](),[7.83][7.955:1022](),[7.955][7.955:1022](),[7.1022][4.80:112](),[4.112][7.493:494](),[7.1022][7.493:494](),[7.494][7.1027:1132](),[7.1027][7.1027:1132](),[7.1132][7.354:424]()
    }
    sub login :Local {
    my ($self, $c) = @_;
    my $username = $c->request->params->{username} || "";
    my $password = $c->request->params->{password} || "";
    if ($username eq "" && $password eq "" && !defined $c->flash->{referer}) {
    my $baseurl = $c->uri_for('/');
    my $refurl = $c->request->referer;
    $c->flash->{referer} = $refurl if $refurl =~ m/^($baseurl)/;
    }
    if ($username && $password) {
    if ($c->authenticate({username => $username, password => $password})) {
    $c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
    $c->flash->{referer} = undef;
    return;
    }
    $c->stash->{errorMsg} = "Bad username or password.";
    }
    $c->keep_flash("referer");
    $c->stash->{template} = 'login.tt';
    }
    sub logout :Local {
    my ($self, $c) = @_;
    $c->logout;
    $c->response->redirect($c->request->referer || $c->uri_for('/'));
  • replacement in src/lib/Hydra/Controller/Root.pm at line 47
    [7.280][7.558:609](),[7.546][7.558:609](),[7.2822][7.558:609](),[7.299][7.558:609]()
    $c->stash->{flashMsg} = $c->flash->{buildMsg};
    [7.546]
    [7.2120]
    $c->stash->{flashMsg} //= $c->flash->{buildMsg};
  • file addition: User.pm (----------)
    [51.188]
    package Hydra::Controller::User;
    use strict;
    use warnings;
    use base 'Catalyst::Controller';
    use Digest::SHA1 qw(sha1_hex);
    use Hydra::Helper::Nix;
    use Hydra::Helper::CatalystUtils;
    __PACKAGE__->config->{namespace} = '';
    sub login :Local {
    my ($self, $c) = @_;
    my $username = $c->request->params->{username} || "";
    my $password = $c->request->params->{password} || "";
    if ($username eq "" && $password eq "" && !defined $c->flash->{referer}) {
    my $baseurl = $c->uri_for('/');
    my $refurl = $c->request->referer;
    $c->flash->{referer} = $refurl if $refurl =~ m/^($baseurl)/;
    }
    if ($username && $password) {
    if ($c->authenticate({username => $username, password => $password})) {
    $c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
    $c->flash->{referer} = undef;
    return;
    }
    $c->stash->{errorMsg} = "Bad username or password.";
    }
    $c->keep_flash("referer");
    $c->stash->{template} = 'login.tt';
    }
    sub logout :Local {
    my ($self, $c) = @_;
    $c->logout;
    $c->response->redirect($c->request->referer || $c->uri_for('/'));
    }
    sub captcha :Local Args(0) {
    my ($self, $c) = @_;
    $c->create_captcha();
    }
    sub register :Local Args(0) {
    my ($self, $c) = @_;
    $c->stash->{template} = 'user.tt';
    $c->stash->{create} = 1;
    return if $c->request->method ne "POST";
    my $userName = trim $c->req->params->{username};
    my $fullName = trim $c->req->params->{fullname};
    my $password = trim $c->req->params->{password};
    $c->stash->{username} = $userName;
    $c->stash->{fullname} = $fullName;
    sub fail {
    my ($c, $msg) = @_;
    $c->stash->{errorMsg} = $msg;
    }
    return fail($c, "You did not enter the correct digits from the security image.")
    unless $c->validate_captcha($c->req->param('captcha'));
    return fail($c, "Your user name is invalid. It must start with a lower-case letter followed by lower-case letters, digits, dots or underscores.")
    if $userName !~ /^$userNameRE$/;
    return fail($c, "Your user name is already taken.")
    if $c->find_user({ username => $userName });
    return fail($c, "Your must specify your full name.") if $fullName eq "";
    return fail($c, "You must specify a password of at least 6 characters.")
    if length($password) < 6;
    return fail($c, "The passwords you specified did not match.")
    if $password ne trim $c->req->params->{password2};
    txn_do($c->model('DB')->schema, sub {
    my $user = $c->model('DB::Users')->create(
    { username => $userName
    , fullname => $fullName
    , password => sha1_hex($password)
    , emailaddress => "",
    });
    });
    $c->authenticate({username => $userName, password => $password})
    or error($c, "Unable to authenticate the new user!");
    $c->flash->{successMsg} = "User <tt>$userName</tt> has been created.";
    $c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
    }
    sub preferences :Local Args(0) {
    my ($self, $c) = @_;
    error($c, "Not implemented.");
    }
    1;
  • replacement in src/lib/Hydra/Helper/CatalystUtils.pm at line 18
    [6.1657][7.1467:1555](),[7.187][7.1467:1555]()
    $pathCompRE $relPathRE $relNameRE $projectNameRE $jobsetNameRE $jobNameRE $systemRE
    [6.1657]
    [7.547]
    $pathCompRE $relPathRE $relNameRE $projectNameRE $jobsetNameRE $jobNameRE $systemRE $userNameRE
  • edit in src/lib/Hydra/Helper/CatalystUtils.pm at line 174
    [7.2077]
    [6.1658]
    Readonly our $userNameRE => "(?:[a-z][a-z0-9_\.]*)";
  • replacement in src/lib/Hydra.pm at line 16
    [7.4331][3.1445:1473]()
    AccessLog/,
    [7.4331]
    [3.1473]
    AccessLog
    Captcha/,
  • edit in src/lib/Hydra.pm at line 60
    [2.150]
    [53.1042]
    'Plugin::Captcha' => {
    session_name => 'hydra-captcha',
    new => {
    width => 270,
    height => 80,
    ptsize => 20,
    lines => 30,
    thickness => 1,
    rndmax => 5,
    scramble => 1,
    #send_ctobg => 1,
    bgcolor => '#ffffff',
    font => '/home/eelco/Dev/hydra/ttf/StayPuft.ttf',
    },
    create => [ qw/ttf circle/ ],
    particle => [ 3500 ],
    out => { force => 'jpeg' }
    },
  • edit in src/root/layout.tt at line 122
    [7.3143]
    [54.114]
    [% IF successMsg %]
    <br />
    <p class="btn-success btn-large">[% successMsg %]</p>
    [% END %]
  • edit in src/root/login.tt at line 11
    [7.9805]
    [7.9805]
    <p>Don't have an account yet? Please <a href="[%
    c.uri_for('/register') %]">register</a> first.</p>
    <br/>
  • edit in src/root/topbar.tt at line 205
    [5.3012]
    [5.3012]
    [% INCLUDE makeLink uri = c.uri_for(c.controller('Root').action_for('preferences')) title = "Preferences" %]
  • replacement in src/root/user.tt at line 1
    [7.4561][7.5554:5630]()
    [% WRAPPER layout.tt title=(create ? "New user" : "User $user.username") %]
    [7.4561]
    [7.4648]
    [% WRAPPER layout.tt title=(create ? "Register new user" : "User $user.username") %]
  • replacement in src/root/user.tt at line 5
    [7.4696][7.4696:4901](),[7.4901][7.37531:37553](),[7.37553][7.4924:5033](),[7.4924][7.4924:5033]()
    <option value="[% role %]"
    [% checked = false %]
    [% FOREACH r IN user.userroles %]
    [% checked = r.role == role %]
    [% BREAK IF checked %]
    [% END %]
    [% IF checked %]
    SELECTED
    [% END %]
    >[% role %]</option>
    [7.4696]
    [7.5033]
    <option value="[% role %]"
    [% checked = false %]
    [% FOREACH r IN user.userroles %]
    [% checked = r.role == role %]
    [% BREAK IF checked %]
    [% END %]
    [% IF checked %]
    SELECTED
    [% END %]
    >[% role %]</option>
  • replacement in src/root/user.tt at line 17
    [7.5207][7.17325:17511]()
    <form class="form-horizontal" action="[% IF create %][% c.uri_for('/admin/create-user/submit') %][% ELSE %][% c.uri_for('/admin/user' user.username 'submit') %][% END %]" method="post">
    [7.5207]
    [7.37554]
    <form class="form-horizontal" method="post">
    <fieldset>
  • replacement in src/root/user.tt at line 21
    [7.37555][7.17514:17525](),[7.17514][7.17514:17525](),[7.17525][7.5298:5316](),[7.5298][7.5298:5316](),[7.5316][7.17526:17707]()
    <fieldset>
    [% IF create %]
    <div class="control-group">
    <label class="control-label">User name</label>
    <div class="controls">
    <input type="text" class="span3" name="username" value=""></input>
    [7.37555]
    [7.17707]
    [% IF create %]
    <div class="control-group">
    <label class="control-label">User name</label>
    <div class="controls">
    <input type="text" class="span3" name="username" [% HTML.attributes(value => username) %]></input>
    </div>
  • replacement in src/root/user.tt at line 28
    [7.17718][7.17718:17727](),[7.17727][7.5434:5446](),[7.5434][7.5434:5446](),[7.5446][7.17728:17946]()
    </div>
    [% END %]
    <div class="control-group">
    <label class="control-label">Full name</label>
    <div class="controls">
    <input type="text" class="span3" name="fullname" [% HTML.attributes(value => user.fullname) %]></input>
    [7.17718]
    [7.17946]
    [% END %]
    <div class="control-group">
    <label class="control-label">Full name</label>
    <div class="controls">
    <input type="text" class="span3" name="fullname" [% HTML.attributes(value => fullname) %]></input>
    </div>
    </div>
    <div class="control-group">
    <label class="control-label">Password</label>
    <div class="controls">
    <input type="password" class="span3" name="password" value=""></input>
    </div>
  • replacement in src/root/user.tt at line 43
    [7.17957][7.17957:18188]()
    </div>
    <div class="control-group">
    <label class="control-label">Email</label>
    <div class="controls">
    <input type="text" class="span3" name="emailaddress" [% HTML.attributes(value => user.emailaddress) %]></input>
    [7.17957]
    [7.18188]
    <div class="control-group">
    <label class="control-label">Confirm password</label>
    <div class="controls">
    <input type="password" class="span3" name="password2" value=""></input>
    </div>
  • replacement in src/root/user.tt at line 50
    [7.18199][7.18199:18722]()
    </div>
    <div class="control-group">
    <label class="control-label">Evaluation error notifications</label>
    [% INCLUDE renderSelection param="emailonerror" curValue=user.emailonerror radiobuttons=1 options={"1" = "Yes", "0" = "No"} %]
    </div>
    <div class="control-group">
    <label class="control-label">Roles</label>
    <div class="controls">
    <select multiple name="roles" class="span3">
    [% INCLUDE roleoption role="admin" %]
    [% INCLUDE roleoption role="create-project" %]
    </select>
    [7.18199]
    [7.18722]
    <!--
    <div class="control-group">
    <label class="control-label">Email</label>
    <div class="controls">
    <input type="text" class="span3" name="emailaddress" [% HTML.attributes(value => user.emailaddress) %]></input>
    </div>
  • replacement in src/root/user.tt at line 58
    [7.18733][7.18733:18742]()
    </div>
    [7.18733]
    [7.6137]
    -->
  • edit in src/root/user.tt at line 60
    [7.6138][7.18743:18937]()
    <div class="form-actions">
    <button type="submit" class="btn btn-primary">
    <i class="icon-ok icon-white"></i>
    [%IF create %]Create[% ELSE %]Apply changes[% END %]
    </button>
  • replacement in src/root/user.tt at line 61
    [7.18958][7.18958:19326]()
    <button id="delete-user" type="submit" class="btn btn-danger" name="submit" value="delete">
    <i class="icon-trash icon-white"></i>
    Delete this user
    </button>
    <script type="text/javascript">
    $("#delete-user").click(function() {
    return confirm("Are you sure you want to delete this user?");
    });
    </script>
    [7.18958]
    [7.19326]
    <div class="control-group">
    <div class="controls">
    <label class="checkbox">
    <input type="checkbox" name="enabled" [% IF 1; 'checked="checked"'; END %]></input>Receive evaluation error notifications
    </label>
    </div>
    </div>
    [% END %]
    [% IF !create && c.check_user_roles('admin') %]
    <div class="control-group">
    <label class="control-label">Roles</label>
    <div class="controls">
    <select multiple name="roles" class="span3">
    [% INCLUDE roleoption role="admin" %]
    [% INCLUDE roleoption role="create-project" %]
    </select>
    </div>
    </div>
    [% END %]
    [% IF create %]
    <div class="control-group">
    <div class="controls">
    <img src="[% c.uri_for('/captcha') %]" alt="CAPTCHA"/>
    </div>
    </div>
    <div class="control-group">
    <label class="control-label">Type the digits shown in the image above</label>
    <div class="controls">
    <input type="text" class="span3" name="captcha" value=""></input>
    </div>
    </div>
  • edit in src/root/user.tt at line 96
    [7.19340]
    [7.19340]
    <div class="form-actions">
    <button type="submit" class="btn btn-primary">
    <i class="icon-ok icon-white"></i>
    [%IF create %]Create[% ELSE %]Apply changes[% END %]
    </button>
    [% IF !create %]
    <button id="delete-user" type="submit" class="btn btn-danger" name="submit" value="delete">
    <i class="icon-trash icon-white"></i>
    Delete this user
    </button>
    <script type="text/javascript">
    $("#delete-user").click(function() {
    return confirm("Are you sure you want to delete this user?");
    });
    </script>
    [% END %]