ZWCTAZGLJZQNTYWTC2XQUKMILJF6JGDL5IND6QNYWK4FIGMLRFXAC GPHLV42M5EGNMSMFVZ54H3LY6QD5R4FE43565A7HJMI3V23FPDCAC KSVD6RAPQW57PJEN3VY5XFMSHMLKC5JN6BVVNA4GFNXTVGG3FZKQC KNU2FBIGLJ4NJKV6M67LEOKXDUEK2NMMM4P6WI2LNTUQGWDKFGKAC 2M7J26V4WXJTOVN7TIOMOLUD2QA4LNTFLNOUTJWKL4XEGE6W2GKQC RFE6T5LGBFFNEPHZOPF4UNMFC2L4CGD5TPAMOXDLRPH3TZJ43UBAC PC6UOHH72AUR64GFBIXXLKGP2CLEUWCI3E3QMKNYCZHRMNCHUDVAC D5QIOJGPKQJIYBUCSC3MFJ3TXLPNZ2XMI37GXMFRVRFWWR2VMTFAC VHYWSRISYUZOFS3ZEI3TSQJCSPRXORA7TPT2LDHLKLDSIT3TOPFQC J5UVLXOK6EDIL5I7VKWH4V2QDS4DPD7FHRK6XBWSXFRQS4JKXFZQC JLDUSNUOOQNL63BOPXIWZOWFRQ5X35RWG33PJB3J3KMR6QR7TN7QC JM3DPYOMVNMCL5GMEYC3Y4NDRGTNIFBBFTPGPVT66GPENVPU7EVQC X27GNHDV5KPZ5GSH6DCAJMNCEMZLCP7M43JWF2X3O5QWXMOX273AC S66BOMVUACAUDSGSDWP7ZIXVMZSQHWXOZYVTB7ILUCWZ7DDFAKVAC ODNCGFQ5FPKFI624BVMLW7PJ2EFJOR3TY66OCZM42UNNTWBCF2TQC IK53RV4VGOHLCZGQCCIKPB45M3C7M7YMNBOJFBGZJ4LWIZNU4QNQC QL55ECJ6KMMBUOWQ6LKSOVN7L43CH4S6SPE2AQ3VX3KSGC32RP4AC ZI535LI6PJMKSOBJE33B3RRZ5S2JVTR3XPUDTSXJW6BZNTAHS3GQC N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC package Hydra::Controller::Admin;use strict;use warnings;use base 'Catalyst::Controller';use Hydra::Helper::Nix;use Hydra::Helper::CatalystUtils;sub admin : Path('/admin') Args(0) {my ($self, $c) = @_;requireAdmin($c);$c->stash->{template} = 'admin.tt';}sub clearfailedcache : Path('/admin/clear-failed-cache') Args(0) {my ($self, $c) = @_;requireAdmin($c);my $r = `nix-store --clear-failed-paths '*'`;$c->res->redirect("/admin");}sub clearevalcache : Path('/admin/clear-eval-cache') Args(0) {my ($self, $c) = @_;requireAdmin($c);print "Clearing evaluation cache\n";$c->model('DB::JobsetInputHashes')->delete_all;$c->res->redirect("/admin");}sub clearvcscache : Path('/admin/clear-vcs-cache') Args(0) {my ($self, $c) = @_;requireAdmin($c);print "Clearing path cache\n";$c->model('DB::CachedPathInputs')->delete_all;print "Clearing git cache\n";$c->model('DB::CachedGitInputs')->delete_all;print "Clearing subversion cache\n";$c->model('DB::CachedSubversionInputs')->delete_all;$c->res->redirect("/admin");}sub managenews : Path('/admin/news') Args(0) {my ($self, $c) = @_;requireAdmin($c);$c->stash->{newsItems} = [$c->model('DB::NewsItems')->search({}, {order_by => 'createtime DESC'})];$c->stash->{template} = 'news.tt';}sub news_submit : Path('/admin/news/submit') Args(0) {my ($self, $c) = @_;requireAdmin($c);requirePost($c);my $contents = trim $c->request->params->{"contents"};my $createtime = time;$c->model('DB::NewsItems')->create({createtime => $createtime,contents => $contents,author => $c->user->username});$c->res->redirect("/admin/news");}sub news_delete : Path('/admin/news/delete') Args(1) {my ($self, $c, $id) = @_;requireAdmin($c);txn_do($c->model('DB')->schema, sub {my $newsItem = $c->model('DB::NewsItems')->find($id)or notFound($c, "Newsitem with id $id doesn't exist.");$newsItem->delete;});$c->res->redirect("/admin/news");}1;
package Hydra::Schema::NewsItems;# Created by DBIx::Class::Schema::Loader# DO NOT MODIFY THE FIRST PART OF THIS FILEuse strict;use warnings;use base 'DBIx::Class::Core';=head1 NAMEHydra::Schema::NewsItems=cut__PACKAGE__->table("NewsItems");=head1 ACCESSORS=head2 iddata_type: integerdefault_value: undefis_auto_increment: 1is_nullable: 0size: undef=head2 contentsdata_type: textdefault_value: undefis_nullable: 0size: undef=head2 createtimedata_type: integerdefault_value: undefis_nullable: 0size: undef=head2 authordata_type: textdefault_value: undefis_foreign_key: 1is_nullable: 0size: undef=cut__PACKAGE__->add_columns("id",{data_type => "integer",default_value => undef,is_auto_increment => 1,is_nullable => 0,size => undef,},"contents",{data_type => "text",default_value => undef,is_nullable => 0,size => undef,},"createtime",{data_type => "integer",default_value => undef,is_nullable => 0,size => undef,},"author",{data_type => "text",default_value => undef,is_foreign_key => 1,is_nullable => 0,size => undef,},);__PACKAGE__->set_primary_key("id");=head1 RELATIONS=head2 authorType: belongs_toRelated object: L<Hydra::Schema::Users>=cut__PACKAGE__->belongs_to("author", "Hydra::Schema::Users", { username => "author" }, {});# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-04-27 15:13:51# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SX13YZYhf5Uz5KZGphG/+wuse Hydra::Helper::Nix;# !!! Ugly, should be generated.my $hydradbi = getHydraDBPath;if ($hydradbi =~ m/^dbi:Pg/) {__PACKAGE__->sequence('newsitems_id_seq');}1;
# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-03-05 13:07:45# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SXJ+FzgNDad87OKSBH2qrg
# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-04-20 11:21:42# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1VZpwwaEdEJzrrV31ErPzw# These lines were loaded from '/home/rbvermaa/src/hydra/src/lib/Hydra/Schema/Projects.pm' found in @INC.# They are now part of the custom portion of this file# for you to hand-edit. If you do not either delete# this section or remove that file from @INC, this section# will be repeated redundantly when you re-create this# file again via Loader! See skip_load_external to disable# this feature.
package Hydra::Schema::Users;# Created by DBIx::Class::Schema::Loader# DO NOT MODIFY THE FIRST PART OF THIS FILEuse strict;use warnings;use base 'DBIx::Class::Core';=head1 NAMEHydra::Schema::Users=cut__PACKAGE__->table("Users");=head1 ACCESSORS=head2 usernamedata_type: textdefault_value: undefis_nullable: 0size: undef=head2 fullnamedata_type: textdefault_value: undefis_nullable: 1size: undef=head2 emailaddressdata_type: textdefault_value: undefis_nullable: 0size: undef=head2 passworddata_type: textdefault_value: undefis_nullable: 0size: undef=head2 emailonerrordata_type: integerdefault_value: 0is_nullable: 0size: undef=cut__PACKAGE__->add_columns("username",{data_type => "text",default_value => undef,is_nullable => 0,size => undef,},"fullname",{data_type => "text",default_value => undef,is_nullable => 1,size => undef,},"emailaddress",{data_type => "text",default_value => undef,is_nullable => 0,size => undef,},"password",{data_type => "text",default_value => undef,is_nullable => 0,size => undef,},"emailonerror",{ data_type => "integer", default_value => 0, is_nullable => 0, size => undef },);__PACKAGE__->set_primary_key("username");=head1 RELATIONS=head2 userrolesType: has_manyRelated object: L<Hydra::Schema::UserRoles>=cut__PACKAGE__->has_many("userroles","Hydra::Schema::UserRoles",{ "foreign.username" => "self.username" },);=head2 projectsType: has_manyRelated object: L<Hydra::Schema::Projects>=cut__PACKAGE__->has_many("projects","Hydra::Schema::Projects",{ "foreign.owner" => "self.username" },);=head2 projectmembersType: has_manyRelated object: L<Hydra::Schema::ProjectMembers>=cut__PACKAGE__->has_many("projectmembers","Hydra::Schema::ProjectMembers",{ "foreign.username" => "self.username" },);=head2 newsitemsType: has_manyRelated object: L<Hydra::Schema::NewsItems>=cut__PACKAGE__->has_many("newsitems","Hydra::Schema::NewsItems",{ "foreign.author" => "self.username" },);# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-04-27 15:13:51# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:C5uoz6EYyYL442zRYmXkyw# These lines were loaded from '/home/rbvermaa/src/hydra/src/lib/Hydra/Schema/Users.pm' found in @INC.# They are now part of the custom portion of this file# for you to hand-edit. If you do not either delete# this section or remove that file from @INC, this section# will be repeated redundantly when you re-create this# file again via Loader! See skip_load_external to disable# this feature.
# End of lines loaded from '/home/rbvermaa/src/hydra/src/lib/Hydra/Schema/Users.pm'# These lines were loaded from '/home/rbvermaa/src/hydra/src/lib/Hydra/Schema/Users.pm' found in @INC.# They are now part of the custom portion of this file# for you to hand-edit. If you do not either delete# this section or remove that file from @INC, this section# will be repeated redundantly when you re-create this# file again via Loader! See skip_load_external to disable# this feature.# You can replace this text with custom content, and it will be preserved on regeneration1;
[% WRAPPER layout.tt title="Admin" %][% PROCESS common.tt %]<h1>Admin</h1><ul><li>[% INCLUDE maybeLink uri = c.uri_for(c.controller('Project').action_for('create')) content = "Create project" %]</li><li>Caching<ul><li>[% INCLUDE maybeLink uri = c.uri_for(c.controller('Admin').action_for('clearfailedcache')) content = "Clear failed builds cache" confirmmsg = "Are you sure you want to clear the failed builds cache?" %]</li><li>[% INCLUDE maybeLink uri = c.uri_for(c.controller('Admin').action_for('clearevalcache')) content = "Clear evaluation cache" confirmmsg = "Are you sure you want to clear the evaluation cache?" %]</li><li>[% INCLUDE maybeLink uri = c.uri_for(c.controller('Admin').action_for('clearvcscache')) content = "Clear VCS caches" confirmmsg = "Are you sure you want to clear the VCS caches?" %]</li></ul></li><li>[% INCLUDE maybeLink uri = c.uri_for(c.controller('Admin').action_for('managenews')) content = "News" %]</li></ul>[% END %]
[% IF uri %]<a [% HTML.attributes(href => uri) %]>[% content %]</a>[% ELSE; content; END -%]
[% IF uri %]<a [% HTML.attributes(href => uri) %][% IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END %]>[% content %]</a>[% ELSE; content; END -%]
[% WRAPPER layout.tt title="News items" %][% PROCESS common.tt %][% USE String %]<h1>News items</h1>[% IF newsItems.size == 0 %]<p>No news items</p>[% ELSE %]<table><thead><th>Date</th><th>Contents</th><th></th></thead><tbody>[% FOREACH i IN newsItems %][% contents = String.new(i.contents) %]<tr><td>[% INCLUDE renderDateTime timestamp=i.createtime %]</td><td>[% contents.replace('\n','<br />\n') %]</td><td>[ [% INCLUDE maybeLink uri = c.uri_for(c.controller('Admin').action_for('news_delete') i.id) content = "Delete" confirmmsg = "Are you sure you want to delete this news item?" %] ]</td></tr>[% END %]</tbody></table>[% END %]<form action="[% c.uri_for('/admin/news/submit') %]" method="post"><h2>Add news item</h2><p><textarea class="longString" name="contents"></textarea></p><p><button type="submit">Post</button></p></form>[% END %]
[% IF newItems.size != 0 %]<div class="newsbar">[% FOREACH i IN newsItems %][% contents = String.new(i.contents) %]<p><b>[% INCLUDE renderDateTime timestamp=i.createtime %]</b> <tt>by [% i.author.fullname %]</tt> <br/>[% contents.replace('\n','<br />\n') %][% END %]</div>[% END %]
.newsbar {background-color:#D9E3EA;border:1px solid #999999;float:right;font-size:x-small;margin:0 0 0.5em 0.5em;overflow:hidden;padding:0.5em;width:30em;}
);create table NewsItems (#ifdef POSTGRESQLid serial primary key not null,#elseid integer primary key autoincrement not null,#endifcontents text not null,createTime integer not null,author text not null,foreign key (author) references Users(userName) on delete cascade on update cascade