Showing 6 changed files with 226 additions and 31 deletions
+24 -3
lib/Gitprep.pm
... ...
@@ -146,13 +146,34 @@ EOS
146 146
       );
147 147
     };
148 148
   }
149
-    
149
+  
150
+  # Routes
151
+  my $r = $self->routes;
152
+  
150 153
   # Auto route
151
-  $self->plugin('AutoRoute');
154
+  {
155
+    my $r = $r->under(sub {
156
+      my $self = shift;
157
+      
158
+      my $api = $self->gitprep_api;
159
+      
160
+      # Admin page authentication
161
+      {
162
+        my $path = $self->req->url->path->parts->[0] || '';
163
+
164
+        if ($path eq '_admin' && !$api->logined_admin) {
165
+          $self->redirect_to('/');
166
+          return;
167
+        }
168
+      }
169
+      
170
+      return 1; 
171
+    });
172
+    $self->plugin('AutoRoute', route => $r);
173
+  }
152 174
   
153 175
   # User defined Routes
154 176
   {
155
-    my $r = $self->routes;
156 177
 
157 178
     # Reset admin password
158 179
     $r->any('/reset-password')->name('reset-password')
+44 -14
lib/Gitprep/API.pm
... ...
@@ -57,6 +57,36 @@ sub root_ns {
57 57
   return $root;
58 58
 }
59 59
 
60
+sub is_admin {
61
+  my ($self, $user) = @_;
62
+  
63
+  # Controler
64
+  my $c = $self->cntl;
65
+  
66
+  # DBI
67
+  my $dbi = $c->app->dbi;
68
+  
69
+  # Check admin
70
+  my $row = $dbi->model('user')->select('config', id => $user)->one;
71
+  return unless $row;
72
+  my $config = $self->json($row->{config});
73
+  
74
+  return $config->{admin};
75
+}
76
+
77
+sub logined_admin {
78
+  my $self = shift;
79
+
80
+  # Controler
81
+  my $c = $self->cntl;
82
+  
83
+  # Check logined as admin
84
+  my $user = $c->session('user_id');
85
+  
86
+  return $self->is_admin($user) && $self->logined;
87
+}
88
+
89
+
60 90
 sub json {
61 91
   my ($self, $value) = @_;
62 92
   
... ...
@@ -68,21 +98,8 @@ sub json {
68 98
   }
69 99
 }
70 100
 
71
-sub users {
72
-  my $self = shift;
73
- 
74
-  my $users = $self->cntl->app->dbi->model('user')->select(
75
-    ['id', 'config'],
76
-    append => 'order by id'
77
-  )->filter(config => 'json')->all;
78
-
79
-  @$users = grep { ! $_->{config}{admin} } @$users;
80
-  
81
-  return $users;
82
-}
83
-
84 101
 sub logined {
85
-  my $self = shift;
102
+  my ($self, $user) = @_;
86 103
   
87 104
   my $c = $self->cntl;
88 105
   
... ...
@@ -99,6 +116,19 @@ sub logined {
99 116
   return $password eq $config->{password};
100 117
 }
101 118
 
119
+sub users {
120
+  my $self = shift;
121
+ 
122
+  my $users = $self->cntl->app->dbi->model('user')->select(
123
+    ['id', 'config'],
124
+    append => 'order by id'
125
+  )->filter(config => 'json')->all;
126
+
127
+  @$users = grep { ! $_->{config}{admin} } @$users;
128
+  
129
+  return $users;
130
+}
131
+
102 132
 sub params {
103 133
   my $self = shift;
104 134
   
+40 -6
lib/Gitprep/RepManager.pm
... ...
@@ -27,6 +27,24 @@ sub create_project {
27 27
   croak $error if $@;
28 28
 }
29 29
 
30
+sub create_user {
31
+  my ($self, $user, $data) = @_;
32
+
33
+  my $dbi = $self->app->dbi;
34
+  
35
+  # Create user
36
+  my $error;
37
+  eval {
38
+    $dbi->connector->txn(sub {
39
+      eval { $self->_create_db_user($user, $data) };
40
+      croak $error = $@ if $@;
41
+      eval {$self->_create_user_dir($user) };
42
+      croak $error = $@ if $@;
43
+    });
44
+  };
45
+  croak $error if $@;
46
+}
47
+
30 48
 sub delete_project {
31 49
   my ($self, $user, $project) = @_;
32 50
   
... ...
@@ -47,22 +65,38 @@ sub delete_project {
47 65
   return 1;
48 66
 }
49 67
 
50
-sub create_user {
51
-  my ($self, $user, $data) = @_;
52
-
68
+sub delete_user {
69
+  my ($self, $user) = @_;
70
+  
53 71
   my $dbi = $self->app->dbi;
54 72
   
55
-  # Create user
73
+  # Delete user
56 74
   my $error;
57 75
   eval {
58 76
     $dbi->connector->txn(sub {
59
-      eval { $self->_create_db_user($user, $data) };
77
+      eval { $self->_delete_db_user($user) };
60 78
       croak $error = $@ if $@;
61
-      eval {$self->_create_user_dir($user) };
79
+      eval {$self->_delete_user_dir($user) };
62 80
       croak $error = $@ if $@;
63 81
     });
64 82
   };
65 83
   croak $error if $@;
84
+  
85
+  return 1;
86
+}
87
+
88
+sub _delete_db_user {
89
+  my ($self, $user) = @_;
90
+  
91
+  $self->app->dbi->model('user')->delete(id => $user);
92
+}
93
+
94
+sub _delete_user_dir {
95
+  my ($self, $user) = @_;
96
+
97
+  my $home = $self->app->git->rep_home;
98
+  my $user_dir = "$home/$user";
99
+  rmtree $user_dir;
66 100
 }
67 101
 
68 102
 sub _create_db_user {
+4 -3
templates/auto/_admin/user/create.html.ep
... ...
@@ -6,13 +6,14 @@
6 6
   my $errors;
7 7
   if ($op eq 'create') {
8 8
     
9
+    # Validation
9 10
     my $params = $api->params;
10 11
     my $validator = $self->app->validator;
11 12
     my $rule = [
12 13
       id => [
13
-        ['not_blank' => 'Input admin user.'],
14
-        [{'regex' => qr/^[a-zA-Z0-9_]+$/} => 'Admin User contain invalid character.'],
15
-        [{'length' => {max => 20}} => 'Admin User is too long.']
14
+        ['not_blank' => 'User name is empty.'],
15
+        [{'regex' => qr/^[a-zA-Z0-9_]+$/} => 'User name contain invalid character.'],
16
+        [{'length' => {max => 20}} => 'User name is too long.']
16 17
       ],
17 18
       password => [
18 19
         ['not_blank' => 'Input password.'],
+95
templates/auto/_admin/user/delete.html.ep
... ...
@@ -0,0 +1,95 @@
1
+<%
2
+  my $api = gitprep_api;
3
+  
4
+  my $user = param('user');
5
+  my $op = param('op') || '';
6
+  
7
+  my $errors;
8
+  if ($op eq 'delete') {
9
+
10
+    # Validation
11
+    my $params = $api->params;
12
+    my $validator = $self->app->validator;
13
+    my $rule = [
14
+      user => [
15
+        ['not_blank' => 'User name is empty.'],
16
+        [{'regex' => qr/^[a-zA-Z0-9_]+$/} => 'User name contain invalid character.'],
17
+        [{'length' => {max => 20}} => 'User name is too long.']
18
+      ]
19
+    ];
20
+    my $vresult = $validator->validate($params, $rule);
21
+    
22
+    if ($vresult->is_ok) {
23
+      
24
+      # Valid parameters
25
+      my $params = $vresult->data;
26
+      my $user = $params->{user};
27
+      
28
+      # Delete user
29
+      eval { app->manager->delete_user($user) };
30
+      if ($@) {
31
+        app->log->error($@);
32
+        $errors = ['Internal Error'];
33
+      }
34
+      else {
35
+        $self->flash(user_deleted => 1);
36
+        $self->flash(user => $user);
37
+        $self->redirect_to('/_admin/users');
38
+      }
39
+    }
40
+    else { $errors = $vresult->messages }
41
+  }
42
+%>
43
+
44
+% layout 'common';
45
+
46
+  %= include '/include/header';
47
+
48
+  <div class="container">
49
+    <div class="alert">
50
+      <button type="button" class="close" data-dismiss="alert">&times;</button>
51
+      <p>
52
+        <big>
53
+          <big>
54
+            If you click delete button, user and all of user's repositories is deleted.
55
+            Be careful!
56
+          </big>
57
+        </big>
58
+      </p>
59
+    </div>
60
+
61
+    % my $id = '';
62
+    % if (flash('success')) {
63
+      <div class="alert alert-success">
64
+        <button type="button" class="close" data-dismiss="alert">&times;</button>
65
+        Success: User <b><%= flash('user') %></b> is deleted.
66
+      </div>
67
+    % }
68
+    
69
+    % if ($errors) {
70
+      <div class="alert">
71
+        <button type="button" class="close" data-dismiss="alert">&times;</button>
72
+        % for my $error (@$errors) {
73
+          <p><%= $error %></p>
74
+        % }
75
+      </div>
76
+    % }
77
+    
78
+    <div class="text-center"><h3>Delete User</h3></div>
79
+    <div class="well" style="background-color:white;padding-top:15px;padding-left:60px;width:300px;margin-left:auto;margin-right:auto">
80
+      <form action="<%= url_for->query(op => 'delete') %>" method="post">
81
+        <div class="control-group">
82
+          <label class="control-label" for="user-name">User name</label>
83
+          <b><big><big><%= $user %></big></big></b>
84
+        </div>
85
+        %= hidden_field user => $user;
86
+        <div class="control-group">
87
+          <div class="controls">
88
+            <button type="submit" class="btn">Delete user and repositories</button>
89
+          </div>
90
+        </div>
91
+      </form>
92
+    </div>
93
+    <div class="text-center" style="margin-bottom:20px"><big><a href="/_admin/users">See Users</a></big></div>
94
+  </div>
95
+  %= include '/include/footer';
+19 -5
templates/auto/_admin/users.html.ep
... ...
@@ -8,14 +8,28 @@
8 8
   %= include '/include/header';
9 9
 
10 10
   <div class="container">
11
+    % if (flash('user_deleted')) {
12
+      <div class="alert alert-success">
13
+        <button type="button" class="close" data-dismiss="alert">&times;</button>
14
+        Success: User <b><%= flash('user') %></b> is deleted.
15
+      </div>
16
+    % }
17
+    
11 18
     <div><h3>Admin Users</h3></div>
12 19
     <div style="margin-bottom:10px"><a class="btn" href="/_admin/user/create">Create User</a></div>
13 20
     <div class="container">
14
-      <ul class="nav nav-tabs nav-stacked">
15
-        % for my $user (@$users) {
16
-          <li><a href="#"><%= $user->{id} %></a></li>
17
-        % }
18
-      </ul>
21
+        <table class="table">
22
+            % for my $user (@$users) {
23
+              <tr>
24
+                <td>
25
+                  <a href="#"><%= $user->{id} %></a>
26
+                </td>
27
+                <td style="text-align:right">
28
+                  <a class="btn btn-mini" href="<%= url_for("/_admin/user/delete?user=$user->{id}") %>">Delete</a>
29
+                </td>
30
+              </tr>
31
+            % }
32
+        </table>
19 33
     </div>
20 34
   </div>
21 35
   <div class="text-center" style="margin-bottom:20px"><big><a href="/_admin">Admin page</a></big></div>