Skip to content

Commit

Permalink
add key delete feature and update authorized_key file system
Browse files Browse the repository at this point in the history
  • Loading branch information
gitprep committed May 19, 2014
1 parent 0085a92 commit 1758ae1
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 12 deletions.
4 changes: 4 additions & 0 deletions gitprep.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
;;; encoding name follow Perl encoding API.
;encoding_suspects=cp932,UTF-8

;;; authorized_keys file for public key authentication via ssh.
;;; default is "$ENV{HOME}/.ssh/authorized_keys"
; authorized_keys_file=/home/gitprep/.ssh/authorized_keys

[admin]
;;; If you forget admin password,
;;; set this value to 1 and access /reset-password page.
Expand Down
14 changes: 14 additions & 0 deletions lib/Gitprep.pm
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ sub startup {
weaken $manager->{app};
$self->manager($manager);

# authorized_keys file
my $authorized_keys_file = $self->config('authorized_keys_file');
unless (defined $authorized_keys_file) {
if (defined $ENV{HOME}) {
$authorized_keys_file = "$ENV{HOME}/.ssh/authorized_keys_file";
}
}
if (defined $authorized_keys_file) {
$self->manager->authorized_keys_file($authorized_keys_file);
}
else {
$self->app->log->warn(qq/Config "authorized_keys_file" can't be detected/);
}

# Repository home
my $rep_home = $ENV{GITPREP_REP_HOME} || $self->home->rel_file('data/rep');
$git->rep_home($rep_home);
Expand Down
119 changes: 119 additions & 0 deletions lib/Gitprep/Manager.pm
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ use Encode 'encode';
use File::Copy qw/move copy/;
use File::Path qw/mkpath rmtree/;
use File::Temp ();
use Fcntl ':flock';
use Carp 'croak';
use File::Copy qw/copy move/;

has 'app';
has 'authorized_keys_file';

sub admin_user {
my $self = shift;
Expand Down Expand Up @@ -448,6 +452,121 @@ EOS
}
}


sub update_authorized_keys_file {
my $self = shift;

my $authorized_keys_file = $self->authorized_keys_file;
if (defined $authorized_keys_file) {

# Lock file
my $lock_file = $self->app->rel_file('lock/authorized_keys');
open my $lock_fh, $lock_file
or croak "Can't open lock file $lock_file";
flock $lock_fh, LOCK_EX
or croak "Can't lock $lock_file";

# Create authorized_keys_file
unless (-f $authorized_keys_file) {
open my $fh, '>', $authorized_keys_file
or croak "Can't create $authorized_keys_file";
}

# Parse file
my ($before_part, $gitprep_part, $after_part)
= $self->_parse_authorized_keys_file($authorized_keys_file);

# Backup at first time
if ($gitprep_part eq '') {
# Backup original file
my $to = "$authorized_keys_file.gitprep.original";
unless (-f $to) {
copy $authorized_keys_file, $to
or croak "Can't copy $authorized_keys_file to $to";
}
}

# Create public keys
my $ssh_public_keys = $self->app->dbi->mode('ssh_public_key')->select->all;
my $ssh_public_keys_str = '';
for my $key (@$ssh_public_keys) {
my $ssh_public_key_str = $self->app->home->rel_file('script/gitprep-shell')
. " $key->{user_id},no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty $key->{key}";
$ssh_public_keys_str .= "$ssh_public_key_str\n\n";
}

# Output tmp file
my $output = "$before_part\n\n$ssh_public_keys_str\n\n$after_part";
my $output_file = "$authorized_keys_file.gitprep.tmp";
open my $out_fh, '>', $output_file
or croak "Can't create authorized_keys tmp file $output_file";
print $out_fh $output;
close $out_fh
or croak "Can't close authorized_keys tmp file $output_file";

# Replace
move $output_file, $authorized_keys_file
or croak "Can't replace $authorized_keys_file by $output_file";

# Unlock file
flock $lock_fh, LOCK_EX
or croak "Can't unlock $lock_file"
}
else {
croak qq/authorized_keys file "$authorized_keys_file" is not found./;
}
}

sub _parse_authorized_keys_file {
my ($self, $file) = shift;

my $start_symbol = "# gitprep start";
my $end_symbol = "# gitprep end";

# Parse
open my $fh, '<', $file
or croak "Can't open $file";
my $start_symbol_count = 0;
my $end_symbol_count = 0;
my $before_part = '';
my $gitprep_part = '';
my $after_part = '';
my $error_prefix = "authorized_keys file $file format error:";
while (my $line = <$fh>) {
if ($line =~ /^$start_symbol/) {
if ($start_symbol_count > 0) {
croak qq/$error_prefix "$start_symbol" is found more than one/;
}
else {
if ($end_symbol_count > 0) {
croak qq/$error_prefix "$end_symbol" is found before "$start_symbol"/;
}
else {
$start_symbol_count++;
}
}
}
elsif ($line =~ /^$end_symbol/) {
if ($end_symbol > 0) {
croak qq/$error_prefix "$end_symbol" is found more than one/;
}
else {
$end_symbol++;
}
}
elsif ($start_symbol_count == 0 && $end_symbol_count == 0) {
$before_part .= $line;
}
elsif ($start_symbol_count == 1 && $end_symbol_count == 0) {
$gitprep_part .= $line;
}
elsif ($start_symbol_count == 1 && $end_symbol_count == 1) {
$after_part .= $line;
}
}
return ($before_part, $gitprep_part, $after_part);
}

sub _create_project {
my ($self, $user, $project, $params) = @_;
$params ||= {};
Expand Down
Empty file added lock/authorized_keys
Empty file.
46 changes: 34 additions & 12 deletions templates/user-settings/ssh.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@
key => $key
};
eval {
app->dbi->model('ssh_public_key')->insert($p);
app->dbi->connector->txn(sub {
app->dbi->model('ssh_public_key')->insert($p);
# $self->manager->update_authorized_keys_file;
});
};

if (my $e = $@) {
Expand All @@ -102,6 +105,22 @@
$errors = $vresult->messages;
}
}
# Delete ssh public key
elsif ($op eq 'delete') {
my $row_id = param('row-id');
eval {
app->dbi->model('ssh_public_key')->delete(where => {row_id => $row_id});
};

if (my $e = $@) {
app->log->error(url_with . ": $e");
$errors = ['Internal Error'];
}
else {
flash(message => 'Success: a key is deleted');
$self->redirect_to('current');
}
}
}

my $keys = app->dbi->model('ssh_public_key')->select(where => {user_id => $user})->all;
Expand Down Expand Up @@ -144,22 +163,25 @@
This is a list of SSH keys associated with your account. Remove any keys that you do not recognize.
</div>
% for my $key (@$keys) {
<div class="border-gray" style="border-top:none;">
<div class="row">
<div class="span7" style="width:600px">
<div style="font-size:15px;padding:10px">
<div>
<b><%= $key->{title} %></b>
<form action="<%= url_for->query(op => 'delete') %>" method="post" style="margin:0;padding:0">
<div class="border-gray" style="border-top:none;">
<div class="row">
<div class="span7" style="width:600px">
<div style="font-size:15px;padding:10px">
<div>
<b><%= $key->{title} %></b>
</div>
</div>
</div>
</div>
<div class="span2">
<div style="padding:5px;text-align:right">
<a class="btn btn-danger" href="javascript:void(0)">Delete</a>
<div class="span2">
<div style="padding:5px;text-align:right">
<a class="btn btn-danger" href="javascript:void(0)" onclick="$(this).closest('form').submit()">Delete</a>
<%= hidden_field 'row-id' => $key->{row_id} %>
</div>
</div>
</div>
</div>
</div>
</form>
% }
% } else {
<div class="border-gray" style="margin-bottom:30px;border-top:none;padding:10px">
Expand Down

0 comments on commit 1758ae1

Please sign in to comment.