File Coverage

blib/lib/AproJo.pm
Criterion Covered Total %
statement 53 83 63.8
branch 2 18 11.1
condition 0 9 0.0
subroutine 9 15 60.0
pod 1 1 100.0
total 65 126 51.5


line stmt bran cond sub pod time code
1             package AproJo;
2 2     2   10851 use Mojo::Base 'Mojolicious';
  2         12254  
  2         8  
3              
4 2     2   502422 use Data::Dumper;
  2         4  
  2         113  
5              
6             our $VERSION = '0.011';
7              
8 2     2   10 use File::Basename 'dirname';
  2         12  
  2         68  
9 2     2   7 use File::Spec::Functions qw'rel2abs catdir';
  2         2  
  2         69  
10 2     2   789 use File::ShareDir 'dist_dir';
  2         7559  
  2         120  
11 2     2   10 use Cwd;
  2         3  
  2         1665  
12              
13             has db => sub {
14             my $self = shift;
15             my $schema_class = $self->config->{db_schema}
16             or die "Unknown DB Schema Class";
17             eval "require $schema_class"
18             or die "Could not load Schema Class ($schema_class), $@";
19              
20             my $db_connect = $self->config->{db_connect}
21             or die "No DBI connection string provided";
22             my @db_connect = ref $db_connect ? @$db_connect : ($db_connect);
23              
24             my $schema = $schema_class->connect(@db_connect)
25             or die "Could not connect to $schema_class using $db_connect[0]";
26              
27             return $schema;
28             };
29              
30             has app_debug => 0;
31              
32             has home_path => sub {
33             my $path = $ENV{MOJO_HOME} || getcwd;
34             return File::Spec->rel2abs($path);
35             };
36              
37             has config_file => sub {
38             my $self = shift;
39             return $ENV{APROJO_CONFIG} if $ENV{APROJO_CONFIG};
40              
41             return rel2abs('aprojo.conf', $self->home_path);
42             };
43              
44             sub startup {
45 1     1 1 37844 my $app = shift;
46              
47 1         5 $app->plugin(
48             Config => {
49             file => $app->config_file,
50             default => {
51             'db_connect' => [
52             'dbi:SQLite:dbname=' . $app->home->rel_file('aprojo.db'),
53             undef,
54             undef,
55             {'sqlite_unicode' => 1}
56             ],
57             'db_schema' => 'AproJo::DB::Schema',
58             'secret' => '47110815'
59             },
60             }
61             );
62              
63 1         1356 $app->plugin('I18N');
64 1         6068 $app->plugin('Mojolicious::Plugin::ServerInfo');
65 1         1296 $app->plugin('Mojolicious::Plugin::DBInfo');
66              
67 1         1061 $app->plugin('Mojolicious::Plugin::Form');
68            
69             {
70             # use content from directories under share/files or using File::ShareDir
71 1         1015 my $lib_base = catdir(dirname(rel2abs(__FILE__)), '..', 'share','files');
  1         5  
72              
73 1         67 my $public = catdir($lib_base, 'public');
74 1 50       19 $app->static->paths->[0] = -d $public ? $public : catdir(dist_dir('AproJo'), 'files','public');
75 1         94 my $static_path = $app->static->paths->[0];
76             #print STDERR '$static_path: ',$static_path,"\n";
77              
78 1         12 my $templates = catdir($lib_base, 'templates');
79 1 50       19 $app->renderer->paths->[0] = -d $templates ? $templates : catdir(dist_dir('AproJo'), 'files', 'templates');
80             }
81              
82 1         103 push @{$app->commands->namespaces}, 'AproJo::Command';
  1         11  
83              
84             #DEPRECATED: $app->secret( $app->config->{secret} );
85 1         57 $app->secrets([$app->config->{secret}]);
86              
87 1     3   21 $app->helper(schema => sub { shift->app->db });
  3         94  
88              
89 1     1   19 $app->helper('home_page' => sub {'/'});
  1         37  
90              
91             $app->helper(
92             'auth_fail' => sub {
93 0     0   0 my $self = shift;
94 0   0     0 my $message = shift || "Not Authorized";
95 0         0 $self->flash(onload_message => $message);
96 0         0 $self->redirect_to($self->home_page);
97 0         0 return 0;
98             }
99 1         16 );
100              
101             $app->helper(
102             'source_id' => sub {
103 0     0   0 my ($self, $source) = @_;
104 0 0       0 return undef unless $source;
105 0         0 my @columns = $self->schema->source($source)->columns;
106 0         0 my $table_name = $self->schema->class($source)->table;
107 0         0 my $source_id = $table_name . '_id';
108 0 0       0 return $source_id if (grep {/$source_id/} @columns);
  0         0  
109 0 0       0 return $columns[0] if (scalar @columns);
110             }
111 1         17 );
112              
113             $app->helper(
114             'get_user' => sub {
115 0     0   0 my ($self, $name) = @_;
116 0 0       0 unless ($name) {
117 0         0 $name = $self->session->{username};
118             }
119 0 0       0 return undef unless $name;
120             #say STDERR 'get_user: ', $name if $self->app->app_debug;
121 0         0 return $self->schema->resultset('User')->single({name => $name});
122             }
123 1         16 );
124            
125             $app->helper(
126             'has_role' => sub {
127 0     0   0 my $self = shift;
128 0   0     0 my $user_string = shift || '';
129 0   0     0 my $role_string = shift || '';
130 0         0 my $user = $self->get_user($user_string);
131 0 0       0 return undef unless $user;
132 0         0 my $role = $user->roles()->single({name => $role_string});
133             #say STDERR 'has_role: ', $role->name if $self->app->app_debug;
134 0   0     0 return ($role && $role->name eq $role_string);
135             }
136 1         16 );
137             $app->helper(
138             'is_admin' => sub {
139 0     0   0 my ($self,$user) = @_;
140 0         0 return $self->has_role($user,'admin');
141             }
142 1         16 );
143              
144 1         14 my $routes = $app->routes;
145              
146 1         9 $routes->get('/')->to('front#index');
147 1         121 $routes->get('/front/*name')->to('front#page');
148 1         180 $routes->post('/save')->to('front#save');
149 1         147 $routes->post('/login')->to('user#login');
150 1         148 $routes->any('/logout')->to('user#logout');
151              
152             my $if_admin = $routes->under(
153             sub {
154 0     0   0 my $self = shift;
155 0 0       0 return $self->auth_fail unless $self->is_admin;
156 0         0 return 1;
157             }
158 1         156 );
159              
160 1         82 $if_admin->post('/admin/save/:table')->to('admin#save');
161              
162 1         254 $if_admin->get('/admin/change/:table/:id')->to('admin#change');
163 1         213 $if_admin->get('/admin/show/:table')->to('admin#show');
164              
165             }
166              
167             1;
168              
169             __END__
170              
171             =head1 NAME
172              
173             AproJo - A time recording application based on Mojolicious
174              
175             =for html
176              
177             <a href="https://travis-ci.org/wollmers/AproJo"><img src="https://travis-ci.org/wollmers/AproJo.png" alt="AproJo"></a>
178             <a href='https://coveralls.io/r/wollmers/AproJo?branch=master'><img src='https://coveralls.io/repos/wollmers/AproJo/badge.png?branch=master' alt='Coverage Status' /></a>
179             <a href='http://cpants.cpanauthors.org/dist/AproJo'><img src='http://cpants.cpanauthors.org/dist/AproJo.png' alt='Kwalitee Score' /></a>
180             <a href="http://badge.fury.io/pl/AproJo"><img src="https://badge.fury.io/pl/AproJo.svg" alt="CPAN version" height="18"></a>
181              
182              
183             =head1 SYNOPSIS
184              
185             $ aprojo setup
186             $ aprojo daemon
187              
188             =head1 DESCRIPTION
189              
190             L<AproJo> is a Perl web apllication.
191              
192             =head1 INSTALLATION
193              
194             L<AproJo> uses well-tested and widely-used CPAN modules, so installation should be as simple as
195              
196             $ cpanm AproJo
197              
198             when using L<App::cpanminus>. Of course you can use your favorite CPAN client or install manually by cloning the L</"SOURCE REPOSITORY">.
199              
200             =head1 SETUP
201              
202             =head2 Environment
203              
204             Although most of L<AproJo> is controlled by a configuration file, a few properties must be set before that file can be read. These properties are controlled by the following environment variables.
205              
206             =over
207              
208             =item C<APROJO_HOME>
209              
210             This is the directory where L<AproJo> expects additional files. These include the configuration file and log files. The default value is the current working directory (C<cwd>).
211              
212             =item C<APROJO_CONFIG>
213              
214             This is the full path to a configuration file. The default is a file named F<aprojo.conf> in the C<APROJO_HOME> path, however this file need not actually exist, defaults may be used instead. This file need not be written by hand, it may be generated by the C<aprojo config> command.
215              
216             =back
217              
218             =head2 The F<aprojo> command line application
219              
220             L<AproJo> installs a command line application, C<aprojo>. It inherits from the L<mojo> command, but it provides extra functions specifically for use with AproJo.
221              
222             =head3 config
223              
224             $ aprojo config [options]
225              
226             This command writes a configuration file in your C<APROJO_HOME> path. It uses the preset defaults for all values, except that it prompts for a secret. This can be any string, however stronger is better. You do not need to memorize it or remember it. This secret protects the cookies employed by AproJo from being tampered with on the client side.
227              
228             L<AproJo> does not need to be configured, however it is recommended to do so to set your application's secret.
229              
230             The C<--force> option may be passed to overwrite any configuration file in the current working directory. The default is to die if such a configuration file is found.
231              
232             =head3 setup
233              
234             $ aprojo setup
235              
236             This step is required. Run C<aprojo setup> to setup a database. It will use the default DBI settings (SQLite) or whatever is setup in the C<APROJO_CONFIG> configuration file.
237              
238             =head1 RUNNING THE APPLICATION
239              
240             $ aprojo daemon
241              
242             After the database is has been setup, you can run C<aprojo daemon> to start the server.
243              
244             You may also use L<morbo> (Mojolicious' development server) or L<hypnotoad> (Mojolicious' production server). You may even use any other server that Mojolicious supports, however for full functionality it must support websockets. When doing so you will need to know the full path to the C<aprojo> application. A useful recipe might be
245              
246             $ hypnotoad `which aprojo`
247              
248             where you may replace C<hypnotoad> with your server of choice.
249              
250             =head2 Logging
251              
252             Logging in L<AproJo> is the same as in L<Mojolicious|Mojolicious::Lite/Logging>. Messages will be printed to C<STDERR> unless a directory named F<log> exists in the C<APROJO_HOME> path, in which case messages will be logged to a file in that directory.
253              
254             =head1 TECHNOLOGIES USED
255              
256             =over
257              
258             =item *
259              
260             L<Mojolicious|http://mojolicio.us> - a next generation web framework for the Perl programming language
261              
262             =item *
263              
264             L<DBIx::Class|http://www.dbix-class.org/> - an extensible and flexible Object/Relational Mapper written in Perl
265              
266             =item *
267              
268             L<Bootstrap|http://twitter.github.com/bootstrap> - the CSS/JS library from Twitter
269              
270             =item *
271              
272             L<jQuery|http://jquery.com/> - jQuery
273              
274              
275             =back
276              
277             =head1 SEE ALSO
278              
279             =over
280              
281             =item *
282              
283             L<Contenticious> - File-based Markdown website application
284              
285             =back
286              
287             =head1 SOURCE REPOSITORY
288              
289             L<http://github.com/wollmers/aprojo>
290              
291             =head1 AUTHOR
292              
293             Helmut Wollmersdorfer, E<lt>helmut.wollmersdorfer@gmail.comE<gt>
294              
295             =for html
296             <a href='http://cpants.cpanauthors.org/author/wollmers'><img src='http://cpants.cpanauthors.org/author/wollmers.png' alt='Kwalitee Score' /></a>
297              
298             =head1 COPYRIGHT AND LICENSE
299              
300             Copyright (C) 2013-2015 by Helmut Wollmersdorfer
301              
302             This library is free software; you can redistribute it and/or modify
303             it under the same terms as Perl itself.
304              
305             =cut
306              
307              
308              
309             ������