File Coverage

blib/lib/Apache/Sling/Group.pm
Criterion Covered Total %
statement 104 189 55.0
branch 23 58 39.6
condition n/a
subroutine 24 26 92.3
pod 9 13 69.2
total 160 286 55.9


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2              
3             package Apache::Sling::Group;
4              
5 1     1   2855 use 5.008001;
  1         6  
  1         50  
6 1     1   7 use strict;
  1         1  
  1         41  
7 1     1   6 use warnings;
  1         1  
  1         36  
8 1     1   6 use Carp;
  1         4  
  1         93  
9 1     1   1578 use Getopt::Long qw(:config bundling);
  1         12960  
  1         6  
10 1     1   1309 use JSON;
  1         34798  
  1         7  
11 1     1   1371 use Text::CSV;
  1         35722  
  1         8  
12 1     1   126 use Apache::Sling;
  1         3  
  1         52  
13 1     1   1566 use Apache::Sling::GroupUtil;
  1         4  
  1         69  
14 1     1   6 use Apache::Sling::Print;
  1         3  
  1         38  
15 1     1   6 use Apache::Sling::Request;
  1         22  
  1         46  
16              
17             require Exporter;
18              
19 1     1   7 use base qw(Exporter);
  1         2  
  1         4015  
20              
21             our @EXPORT_OK = qw(command_line);
22              
23             our $VERSION = '0.27';
24              
25             #{{{sub new
26              
27             sub new {
28 2     2 1 1366 my ( $class, $authn, $verbose, $log ) = @_;
29 2 100       7 if ( !defined $authn ) { croak 'no authn provided!'; }
  1         36  
30 1         3 my $response;
31 1 50       7 $verbose = ( defined $verbose ? $verbose : 0 );
32 1         15 my $group = {
33 1         3 BaseURL => ${$authn}->{'BaseURL'},
34             Authn => $authn,
35             Message => q{},
36             Response => \$response,
37             Verbose => $verbose,
38             Log => $log
39             };
40 1         3 bless $group, $class;
41 1         4 return $group;
42             }
43              
44             #}}}
45              
46             #{{{sub set_results
47             sub set_results {
48 1     1 1 2772 my ( $group, $message, $response ) = @_;
49 1         5 $group->{'Message'} = $message;
50 1         3 $group->{'Response'} = $response;
51 1         6 return 1;
52             }
53              
54             #}}}
55              
56             #{{{sub add
57             sub add {
58 1     1 1 1021 my ( $group, $act_on_group, $properties ) = @_;
59 1         10 my $res = Apache::Sling::Request::request(
60             \$group,
61             Apache::Sling::GroupUtil::add_setup(
62             $group->{'BaseURL'}, $act_on_group, $properties
63             )
64             );
65 0         0 my $success = Apache::Sling::GroupUtil::add_eval($res);
66 0         0 my $message = "Group: \"$act_on_group\" ";
67 0 0       0 $message .= ( $success ? 'added!' : 'was not added!' );
68 0         0 $group->set_results( "$message", $res );
69 0         0 return $success;
70             }
71              
72             #}}}
73              
74             #{{{sub add_from_file
75             sub add_from_file {
76 3     3 1 3326 my ( $group, $file, $fork_id, $number_of_forks ) = @_;
77 3 50       12 $fork_id = defined $fork_id ? $fork_id : 0;
78 3 50       10 $number_of_forks = defined $number_of_forks ? $number_of_forks : 1;
79 3         23 my $csv = Text::CSV->new();
80 3         274 my $count = 0;
81 3         7 my $number_of_columns = 0;
82 3         3 my @column_headings;
83 3 100       9 if ( !defined $file ) {
84 1         15 croak 'File to upload from not defined';
85             }
86 1 100   1   13 if ( open my ($input), '<', $file ) {
  1         2  
  1         9  
  2         108  
87 1         1832 while (<$input>) {
88 1 50       6 if ( $count++ == 0 ) {
    0          
89              
90             # Parse file column headings first to determine field names:
91 1 50       10 if ( $csv->parse($_) ) {
92 1         389 @column_headings = $csv->fields();
93              
94             # First field must be group:
95 1 50       12 if ( $column_headings[0] !~ /^[Gg][Rr][Oo][Uu][Pp]$/msx ) {
96 1         28 croak 'First CSV column must be the group ID, '
97             . 'column heading must be "group". '
98             . 'Found: "'
99             . $column_headings[0] . "\".\n";
100             }
101 0         0 $number_of_columns = @column_headings;
102             }
103             else {
104 0         0 croak 'CSV broken, failed to parse line: '
105             . $csv->error_input;
106             }
107             }
108             elsif ( $fork_id == ( $count++ % $number_of_forks ) ) {
109 0         0 my @properties;
110 0 0       0 if ( $csv->parse($_) ) {
111 0         0 my @columns = $csv->fields();
112 0         0 my $columns_size = @columns;
113              
114             # Check row has same number of columns as there were column headings:
115 0 0       0 if ( $columns_size != $number_of_columns ) {
116 0         0 croak
117             "Found \"$columns_size\" columns. There should have been \"$number_of_columns\".\n"
118             . "Row contents was: $_";
119             }
120 0         0 my $id = $columns[0];
121 0         0 for ( my $i = 1 ; $i < $number_of_columns ; $i++ ) {
122 0         0 my $heading = $column_headings[$i];
123 0         0 my $data = $columns[$i];
124 0         0 my $value = "$heading=$data";
125 0         0 push @properties, $value;
126             }
127 0         0 $group->add( $id, \@properties );
128 0         0 Apache::Sling::Print::print_result($group);
129             }
130             else {
131 0         0 croak 'CSV broken, failed to parse line: '
132             . $csv->error_input;
133             }
134             }
135             }
136 0 0       0 close $input or croak q{Problem closing input!};
137             }
138             else {
139 1         18 croak "Problem opening file: '$file'";
140             }
141 0         0 return 1;
142             }
143              
144             #}}}
145              
146             #{{{sub check_exists
147             sub check_exists {
148 1     1 1 996 my ( $group, $act_on_group ) = @_;
149 1         8 my $res = Apache::Sling::Request::request(
150             \$group,
151             Apache::Sling::GroupUtil::exists_setup(
152             $group->{'BaseURL'}, $act_on_group
153             )
154             );
155 0         0 my $success = Apache::Sling::GroupUtil::exists_eval($res);
156 0         0 my $message = "Group \"$act_on_group\" ";
157 0 0       0 $message .= ( $success ? 'exists!' : 'does not exist!' );
158 0         0 $group->set_results( "$message", $res );
159 0         0 return $success;
160             }
161              
162             #}}}
163              
164             #{{{ sub command_line
165             sub command_line {
166 0     0 0 0 my ( $group, @ARGV ) = @_;
167 0         0 my $sling = Apache::Sling->new;
168 0         0 my $config = $group->config( $sling, @ARGV );
169 0         0 return $group->run( $sling, $config );
170             }
171              
172             #}}}
173              
174             #{{{sub config
175              
176             sub config {
177 1     1 1 2409 my ( $group, $sling, @ARGV ) = @_;
178 1         7 my $group_config = $group->config_hash( $sling, @ARGV );
179              
180 1 50       10 GetOptions(
181             $group_config, 'auth=s', 'help|?', 'log|L=s',
182             'man|M', 'pass|p=s', 'threads|t=s', 'url|U=s',
183             'user|u=s', 'verbose|v+', 'add|a=s', 'additions|A=s',
184             'delete|d=s', 'exists|e=s', 'property|P=s', 'view|V=s'
185             ) or $group->help();
186              
187 1         1314 return $group_config;
188             }
189              
190             #}}}
191              
192             #{{{sub config_hash
193              
194             sub config_hash {
195 1     1 0 4 my ( $group, $sling, @ARGV ) = @_;
196 1         3 my $additions;
197             my $add;
198 0         0 my $delete;
199 0         0 my $exists;
200 0         0 my @property;
201 0         0 my $view;
202              
203 1         28 my %group_config = (
204             'auth' => \$sling->{'Auth'},
205             'help' => \$sling->{'Help'},
206             'log' => \$sling->{'Log'},
207             'man' => \$sling->{'Man'},
208             'pass' => \$sling->{'Pass'},
209             'threads' => \$sling->{'Threads'},
210             'url' => \$sling->{'URL'},
211             'user' => \$sling->{'User'},
212             'verbose' => \$sling->{'Verbose'},
213             'add' => \$add,
214             'additions' => \$additions,
215             'delete' => \$delete,
216             'exists' => \$exists,
217             'property' => \@property,
218             'view' => \$view
219             );
220              
221 1         6 return \%group_config;
222             }
223              
224             #}}}
225              
226             #{{{sub del
227             sub del {
228 1     1 1 1119 my ( $group, $act_on_group ) = @_;
229 1         7 my $res = Apache::Sling::Request::request(
230             \$group,
231             Apache::Sling::GroupUtil::delete_setup(
232             $group->{'BaseURL'}, $act_on_group
233             )
234             );
235 0         0 my $success = Apache::Sling::GroupUtil::delete_eval($res);
236 0         0 my $message = "Group: \"$act_on_group\" ";
237 0 0       0 $message .= ( $success ? 'deleted!' : 'was not deleted!' );
238 0         0 $group->set_results( "$message", $res );
239 0         0 return $success;
240             }
241              
242             #}}}
243              
244             #{{{ sub help
245             sub help {
246              
247 1     1 0 1660 print <<"EOF";
248             Usage: perl $0 [-OPTIONS [-MORE_OPTIONS]] [--] [PROGRAM_ARG1 ...]
249             The following options are accepted:
250              
251             --additions or -A (file) - file containing list of groups to be added.
252             --add or -a (actOnGroup) - add specified group.
253             --auth (type) - Specify auth type. If ommitted, default is used.
254             --delete or -d (actOnGroup) - delete specified group.
255             --exists or -e (actOnGroup) - check whether specified group exists.
256             --help or -? - view the script synopsis and options.
257             --log or -L (log) - Log script output to specified log file.
258             --man or -M - view the full script documentation.
259             --pass or -p (password) - Password of user performing actions.
260             --property or -P (property=value) - Specify property to set on group.
261             --threads or -t (threads) - Used with -A, defines number of parallel
262             processes to have running through file.
263             --url or -U (URL) - URL for system being tested against.
264             --user or -u (username) - Name of user to perform any actions as.
265             --verbose or -v or -vv or -vvv - Increase verbosity of output.
266             --view or -V (actOnGroup) - view details for specified group in json format.
267              
268             Options may be merged together. -- stops processing of options.
269             Space is not required between options and their arguments.
270             For full details run: perl $0 --man
271             EOF
272              
273 1         4 return 1;
274             }
275              
276             #}}}
277              
278             #{{{ sub man
279             sub man {
280              
281 0     0 0 0 my ($group) = @_;
282              
283 0         0 print <<'EOF';
284             group perl script. Provides a means of managing groups in sling from the
285             command line. The script also acts as a reference implementation for the Group
286             perl library.
287              
288             EOF
289              
290 0         0 $group->help();
291              
292 0         0 print <<"EOF";
293             Example Usage
294              
295             * Authenticate and add a group with id g-test:
296              
297             perl group.pl -U http://localhost:8080 -u admin -p admin -a g-test
298              
299             * Authenticate and check whether group with id g-test exists:
300              
301             perl group.pl -U http://localhost:8080 -u admin -p admin -a g-test
302              
303             * Authenticate and view details for group with id g-test:
304              
305             perl group.pl -U http://localhost:8080 -u admin -p admin -V g-test
306              
307             * Authenticate and delete group with id g-test:
308              
309             perl group.pl -U http://localhost:8080 -u admin -p admin -d g-test
310              
311             * Authenticate and add a group with id g-test and property p1=v1:
312              
313             perl group.pl -U http://localhost:8080 -u admin -p admin -a g-test -P p1=v1
314              
315             EOF
316              
317 0         0 return 1;
318             }
319              
320             #}}}
321              
322             #{{{sub run
323             sub run {
324 2     2 1 43 my ( $group, $sling, $config ) = @_;
325 2 100       10 if ( !defined $config ) {
326 1         22 croak 'No group config supplied!';
327             }
328 1         7 $sling->check_forks;
329 1         3 my $authn =
330             defined $sling->{'Authn'}
331 1 50       5 ? ${ $sling->{'Authn'} }
332             : new Apache::Sling::Authn( \$sling );
333              
334 1         2 my $success = 1;
335              
336 1 50       9 if ( $sling->{'Help'} ) { $group->help(); }
  0 50       0  
    50          
337 0         0 elsif ( $sling->{'Man'} ) { $group->man(); }
  1         5  
338             elsif ( defined ${ $config->{'additions'} } ) {
339 0         0 my $message =
340 0         0 "Adding groups from file \"" . ${ $config->{'additions'} } . "\":\n";
341 0         0 Apache::Sling::Print::print_with_lock( "$message", $sling->{'Log'} );
342 0         0 my @childs = ();
343 0         0 for my $i ( 0 .. $sling->{'Threads'} ) {
344 0         0 my $pid = fork;
345 0 0       0 if ($pid) { push @childs, $pid; } # parent
  0 0       0  
346             elsif ( $pid == 0 ) { # child
347             # Create a new separate user agent per fork in order to
348             # ensure cookie stores are separate, then log the user in:
349 0         0 $authn->{'LWP'} = $authn->user_agent( $sling->{'Referer'} );
350 0         0 $authn->login_user();
351 0         0 my $group =
352             new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
353             $sling->{'Log'} );
354 0         0 $group->add_from_file( ${ $config->{'additions'} },
  0         0  
355             $i, $sling->{'Threads'} );
356 0         0 exit 0;
357             }
358             else {
359 0         0 croak "Could not fork $i!";
360             }
361             }
362 0         0 foreach (@childs) { waitpid $_, 0; }
  0         0  
363             }
364             else {
365 1         9 $authn->login_user();
366 1 50       2 if ( defined ${ $config->{'exists'} } ) {
  1 50       6  
  1 50       5  
    50          
367 0         0 $group =
368             new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
369             $sling->{'Log'} );
370 0         0 $success = $group->check_exists( ${ $config->{'exists'} } );
  0         0  
371             }
372 1         5 elsif ( defined ${ $config->{'add'} } ) {
373 0         0 $group =
374             new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
375             $sling->{'Log'} );
376 0         0 $success =
377 0         0 $group->add( ${ $config->{'add'} }, $config->{'property'} );
378             }
379 1         4 elsif ( defined ${ $config->{'delete'} } ) {
380 0         0 $group =
381             new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
382             $sling->{'Log'} );
383 0         0 $success = $group->del( ${ $config->{'delete'} } );
  0         0  
384             }
385             elsif ( defined ${ $config->{'view'} } ) {
386 0         0 $group =
387             new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
388             $sling->{'Log'} );
389 0         0 $success = $group->view( ${ $config->{'view'} } );
  0         0  
390             }
391             else {
392 1         5 $group->help();
393 1         8 return 1;
394             }
395 0         0 Apache::Sling::Print::print_result($group);
396             }
397 0         0 return $success;
398             }
399              
400             #}}}
401              
402             #{{{sub view
403             sub view {
404 1     1 1 1090 my ( $group, $act_on_group ) = @_;
405 1         8 my $res = Apache::Sling::Request::request(
406             \$group,
407             Apache::Sling::GroupUtil::view_setup(
408             $group->{'BaseURL'}, $act_on_group
409             )
410             );
411 0           my $success = Apache::Sling::GroupUtil::view_eval($res);
412 0           my $message = (
413             $success
414 0 0         ? ${$res}->content
415             : "Problem viewing group: \"$act_on_group\""
416             );
417 0           $group->set_results( "$message", $res );
418 0           return $success;
419             }
420              
421             #}}}
422              
423             1;
424              
425             __END__