source: web/lib/Sophie/Controller/Admin.pm @ 468

Last change on this file since 468 was 468, checked in by nanardon, 8 years ago

Fix conflict

File size: 14.4 KB
Line 
1package Sophie::Controller::Admin;
2use Moose;
3use namespace::autoclean;
4use YAML qw/freeze thaw/;
5
6BEGIN {extends 'Catalyst::Controller'; }
7
8=head1 NAME
9
10Sophie::Controller::Admin - Catalyst Controller
11
12=head1 DESCRIPTION
13
14Catalyst Controller.
15
16=head1 METHODS
17
18=cut
19
20sub begin : Private {
21    my ($self, $c) = @_;
22
23    if (!($c->user_exists && $c->check_user_roles($c->user, 'Admin'))) {
24        $c->go('/login/index');
25    }
26
27    $c->forward('/begin');
28}
29
30sub create :XMLRPC {
31    my ( $self, $c, $distribution, $version, $arch ) = @_;
32
33    my $rs = $c->model('Base')->resultset('Distribution');
34    my $rs_d = $rs->find_or_create({ name => $distribution}) or do {
35        $c->stash->{xmlrpc} = 'Erreur adding distrib';
36        return;
37    };
38
39    my $rs_r = $rs_d->Release->find_or_create({ version => $version, }) or do {
40        $c->stash->{xmlrpc} = 'Erreur adding release';
41        return;
42    };
43
44    my $rs_a = $rs_r->Arch->find_or_create({ arch => $arch }) or do {
45        $c->stash->{xmlrpc} = 'Erreur adding arch';
46        return;
47    };
48
49    $c->stash->{xmlrpc} = 'Ok';
50
51    $c->model('Base')->storage->dbh->commit;
52
53}
54
55sub add_media :XMLRPC {
56    my ( $self, $c, $distribspec, $mediaspec) = @_;
57
58    my $d = $c->model('Base')->resultset('Distribution')
59        ->search({ name => $distribspec->{distribution} })
60        ->search_related('Release', { version => $distribspec->{release} })
61        ->search_related('Arch',    { arch => $distribspec->{arch} })->next;
62    if ($d) {
63        my $new = my $rs = $c->model('Base')->resultset('Medias')
64            ->update_or_create({
65                %{ $mediaspec },
66                Arch => $d,
67            },
68            { key => 'label' }
69        );
70        if ($new) {
71            $c->stash->{xmlrpc} = 'OK';
72            $c->model('Base')->storage->dbh->commit;
73        } else {
74            $c->stash->{xmlrpc} = 'Erreur adding media';
75        }
76    }
77}
78
79sub remove_media :XMLRPC {
80    my ( $self, $c, $distribspec, $medianame) = @_;
81
82    my $med = $c->model('Base::Medias')->find(
83        {
84            label => $medianame,
85            d_arch => $c->model('Base')->resultset('Distribution')
86                ->search({ name => $distribspec->{distribution} })
87                ->search_related('Release',
88                    { version => $distribspec->{release}} )
89                ->search_related('Arch',
90                    { arch => $distribspec->{arch} })->next->d_arch_key,
91        }
92    );
93
94    if ($med->delete) {
95            $c->stash->{xmlrpc} = 'OK';
96            $c->model('Base')->storage->dbh->commit;
97    } else {
98            $c->stash->{xmlrpc} = "Cannot delete $medianame";
99    }
100}
101
102sub list_path :XMLRPC {
103    my ($self, $c, $distribution, $version, $arch, $media) = @_;
104   
105    if (ref $distribution) {
106        ($distribution, $version, $arch, $media) = 
107        (
108            $distribution->{distribution},
109            $distribution->{release},
110            $distribution->{arch},
111            $version,
112        );
113    }
114
115    $c->stash->{xmlrpc}  = [
116    $c->model('Base')->resultset('Distribution')
117        ->search($distribution ? (name => $distribution) : ())
118        ->search_related('Release', $version ? (version => $version) : ())
119        ->search_related('Arch', $arch ? (arch => $arch) : ())
120        ->search_related('Medias', $media ? (label => $media) : ())
121        ->search_related('MediasPaths')
122        ->search_related('Paths', { meta_path => undef })->get_column('path')
123        ->all ];
124}
125
126sub list_meta_path :XMLRPC {
127    my ($self, $c, $distribution, $version, $arch, $media) = @_;
128   
129    if (ref $distribution) {
130        ($distribution, $version, $arch, $media) = 
131        (
132            $distribution->{distribution},
133            $distribution->{release},
134            $distribution->{arch},
135            $version,
136        );
137    }
138
139    $c->stash->{xmlrpc}  = [
140    $c->model('Base')->resultset('Distribution')
141        ->search($distribution ? (name => $distribution) : ())
142        ->search_related('Release', $version ? (version => $version) : ())
143        ->search_related('Arch', $arch ? (arch => $arch) : ())
144        ->search_related('MetaPaths')
145        ->get_column('path')->all ];
146}
147
148sub media_path :XMLRPC {
149    my ( $self, $c, $distribution, $version, $arch, $label, $path ) = @_;
150
151    if (ref $distribution) {
152        ($distribution, $version, $arch, $label, $path) = 
153        (
154            $distribution->{distribution},
155            $distribution->{release},
156            $distribution->{arch},
157            $version,
158            $arch,
159        );
160    }
161
162    $path =~ s/\/*$//;
163    $path =~ s/\/+/\//g;
164
165    my $med = $c->model('Base')->resultset('Distribution')
166        ->search({ name => $distribution })
167        ->search_related('Release', { version => $version })
168        ->search_related('Arch',    { arch => $arch })
169        ->search_related('Medias',  { label => $label })->next or return;
170
171    my $rspath = $c->model('Base')->resultset('Paths')
172        ->find_or_create({ path => $path }) or do {
173    };
174    my $new = $c->model('Base')->resultset('MediasPaths')->new({
175            Medias => $med,
176            Paths =>  $rspath,
177        });
178    $new->insert;
179
180    $c->model('Base')->storage->dbh->commit;
181}
182
183sub media_remove_path :XMLRPC {
184    my ( $self, $c, $distribution, $version, $arch, $label, $path ) = @_;
185
186    if (ref $distribution) {
187        ($distribution, $version, $arch, $label, $path) = 
188        (
189            $distribution->{distribution},
190            $distribution->{release},
191            $distribution->{arch},
192            $version,
193            $arch,
194        );
195    }
196
197    $path =~ s/\/*$//;
198    $path =~ s/\/+/\//g;
199
200    my $med = $c->model('Base')->resultset('Distribution')
201        ->search(name => $distribution)
202        ->search_related('Release', version => $version)
203        ->search_related('Arch', arch => $arch)
204        ->search_related('Medias', label => $label)->find or return;
205
206    my $rspath = $c->model('Base')->resultset('Paths')
207        ->find({ path => $path }) or do {
208            return;
209    };
210    my $new = $c->model('Base')->resultset('MediasPaths')->search({
211            d_media => $med->d_media_key,
212            d_path =>  $rspath->d_path_key,
213        })->next->delete;
214
215    $c->model('Base')->storage->dbh->commit;
216}
217
218sub ls_local : XMLRPC {
219    my ($self, $c, $path) = @_;
220
221    $c->stash->{xmlrpc} = [ <$path*> ];
222}
223
224sub replace_path : XMLRPC {
225    my ($self, $c, $path, $newpath) = @_;
226
227    my $dpath = $c->model('Base::Paths')->find({
228        path => $path,
229    }) or do {
230        return $c->stash->{xmlrpc} = 'Path not found';
231    };
232
233    $newpath =~ s/\/*$//;
234
235    $dpath->update(
236        {
237            updated => undef,
238            path => $newpath,
239        }
240    ) and $c->model('Base')->storage->dbh->commit;
241    return $c->stash->{xmlrpc} = 'OK';
242}
243
244sub remove_path : XMLRPC {
245    my ($self, $c, $path) = @_;
246
247    my $dpath = $c->model('Base::Paths')->find({
248        path => $path,
249    }) or do {
250        return $c->stash->{xmlrpc} = 'Path not found';
251    };
252
253
254    $dpath->delete and $c->model('Base')->storage->dbh->commit;
255    return $c->stash->{xmlrpc} = 'OK';
256}
257
258
259sub dump_distrib : XMLRPC {
260    my ($self, $c, $distribution, $version, $arch) = @_;
261   
262    if (!ref $distribution) {
263        $distribution = {
264            distribution => $distribution,
265            release => $version,
266            arch => $arch,
267        };
268    }
269
270    $c->forward('/distrib/exists', [ $distribution ]) or do {
271        $c->error('No such distribution');
272        return;
273    };
274
275    my $ref = {
276        distrib => $distribution,
277    };
278
279    $ref->{media} = $c->forward('/distrib/struct', [ $distribution ]);
280
281    foreach (@{ $ref->{media} || []}) {
282        warn $_->{label};
283        $ref->{path}{$_->{label}} = $c->forward('list_path', [ $distribution,
284                $_->{label} ]);
285    }
286
287    $ref->{metapath} = [ map { { $_->get_columns } }
288        $c->model('Base')->resultset('Distribution')
289        ->search({ name => $distribution->{distribution} })
290        ->search_related('Release', { version => $distribution->{release} })
291        ->search_related('Arch', { arch => $distribution->{arch} })
292        ->search_related('MetaPaths')
293        ->search({}, 
294            { 
295                'select' => [ qw(path type data) ], 
296                'as'     => [ qw(path type data) ] ,
297            }
298        )->all ];
299
300    $c->stash->{xmlrpc} = freeze($ref);
301}
302
303sub add_meta_path : XMLRPC {
304    my ($self, $c, $distrib, $meta, $type, $data) = @_;
305    warn "$distrib, $meta, $type";
306
307    my ($dist) = 
308        $c->model('Base')->resultset('Distribution')
309        ->search(name => $distrib->{distribution})
310        ->search_related('Release', version => $distrib->{release})
311        ->search_related('Arch', arch => $distrib->{arch})
312        ->get_column('d_arch_key')->all or do {
313            return $c->stash->{xmlrpc} = "No such distrib";
314        };
315
316    if ($c->model('Base::MetaPaths')->find_or_create(
317        {
318            d_arch => $dist,
319            type => $type,
320            path => $meta,
321            data => $data,
322        },
323        { key => 'upath' },
324    )) {
325        $c->model('Base')->storage->dbh->commit;
326        return $c->stash->{xmlrpc} = 'OK';
327    } else {
328        return;
329    }
330
331}
332
333sub clean_distrib : XMLRPC {
334    my ($self, $c, $distribution, $version, $arch) = @_;
335   
336    if (!ref $distribution) {
337        $distribution = {
338            distribution => $distribution,
339            release => $version,
340            arch => $arch,
341        };
342    }
343
344    my $rsdist = $c->model('Base')->resultset('Distribution')
345        ->search({ name => $distribution->{distribution} })
346        ->search_related('Release', { version => $distribution->{release} })
347        ->search_related('Arch',    { arch => $distribution->{arch} })
348        ->search_related('Medias');
349
350    my $new = $c->model('Base')->resultset('MediasPaths')->search({
351            d_media => { IN => $rsdist->get_column('d_media_key')->as_query },
352        })->delete;
353
354    # $c->model('Base')->storage->dbh->rollback;
355   
356}
357
358sub load_distrib : XMLRPC {
359    my ( $self, $c, $dump ) = @_;
360
361    my $ref = thaw($dump);
362
363    $c->forward('clean_distrib', [ $ref->{distrib} ]);
364
365    $c->forward('create', [ 
366            $ref->{distrib}{distribution},
367            $ref->{distrib}{release},
368            $ref->{distrib}{arch},
369        ]);
370
371    # cleaning media not existing anymore
372    foreach my $media (@{ $c->forward('/distrib/list', [ $ref->{distrib} ]) || []}) {
373        if (!grep { $media eq $_->{label} } (@{ $ref->{media} || []})) {
374            $c->forward('remove_media', [ $ref->{distrib}, $media ]);
375        }
376    }
377    foreach my $media (@{ $ref->{media} || []}) {
378        $c->forward('add_media', [ $ref->{distrib}, $media ]);
379    }
380    foreach my $media (keys %{ $ref->{path} || {} }) {
381        foreach my $path (@{ $ref->{path}{$media} || [] }) {
382            $c->forward('media_path', [ $ref->{distrib}, $media, $path ]);
383        }
384    }
385    foreach my $meta (@{ $ref->{metapath} || []}) {
386        warn $meta;
387        $c->forward('add_meta_path', 
388            [ $ref->{distrib}, $meta->{path}, $meta->{type}, $meta->{data} ]);
389    }
390
391    $c->model('Base')->storage->dbh->commit;
392}
393
394sub set_user_data : XMLRPC {
395    my ( $self, $c, $user, $dataname, $data ) = @_;
396    $c->forward('/user/set_user_data', [ $user, $dataname, $data ]);
397}
398
399sub get_user_data : XMLRPC {
400    my ( $self, $c, $user, $dataname ) = @_;
401    $c->forward('/user/fetch_user_data', [ $user, $dataname ]);
402}
403
404sub update_user_data : XMLRPC {
405    my ( $self, $c, $user, $dataname, $data ) = @_;
406    $c->forward('/user/update_user_data', [ $user, $dataname, $data ]);
407}
408
409sub set_user_password : XMLRPC {
410    my ( $self, $c, $user, $password ) = @_;
411
412    $c->forward('/user/set_user_password', $user, $password);
413}
414
415sub list_user : XMLRPC {
416    my ($self, $c, $match) = @_;
417
418    $c->stash->{xmlrpc} = [
419        $c->model('Base::Users')->search(
420            {
421                $match ? ( mail => { '~' => $match } ) : (),
422            }
423        )->get_column('mail')->all ];
424}
425
426sub delete_user : XMLRPC {
427    my ($self, $c, $mail) = @_;
428
429    if (my $user = $c->model('Base::Users')->find({ mail => $mail })) {
430        if ($user->delete) {
431            $c->model('Base')->storage->dbh->commit;
432            return $c->stash->{xmlrpc} = "User $mail deleted";
433        }
434    }
435    $c->stash->{xmlrpc} = "No user $mail";
436}
437
438sub create_user : XMLRPC {
439    my ($self, $c, $user, $password) = @_;
440
441    if ($c->model('Base::Users')->create({
442            mail => $user,
443        })) {
444        $c->forward('set_user_password', [ $user, $password ]);
445        return $c->stash->{xmlrpc} = "User $user created";
446    } else {
447        return;
448    }
449}
450
451sub help : Private {
452    my ( $self, $c, $cmd ) = @_;
453    my $ctx = $c->session->{admin_ctx} || '';
454    my $module = 'Admin::Cli' . ($ctx ? "::$ctx" : '');
455    if ($cmd) {
456        my @message = grep { /\S+/ } split(/\n/,
457            $c->model('Help::POD')->admin_help_text($ctx, $cmd) || 'No help available');
458        return $c->stash->{xmlrpc} = [ $self->prompt($c), \@message ];
459    } else {
460        return $c->stash->{xmlrpc} = [
461            $self->prompt($c),
462            [
463                'available command:',
464                join(', ', sort grep { $_ !~ /^end$/ }
465                    ('help', @{ $c->controller($module)->_commands })),
466            ]
467        ];
468    }
469}   
470
471sub prompt : XMLRPC {
472    my ($self, $c) = @_;
473    my $ctx = $c->session->{admin_ctx} || '';
474    my $path = '/admin/cli' . ($ctx ? lc("/$ctx") : '');
475    if ($c->get_action( 'prompt', $path )) {
476        return $c->stash->{xmlrpc} = $c->forward("$path/prompt");
477    } else {
478        return $c->stash->{xmlrpc} = '> ';
479    }
480}
481
482sub cli : XMLRPC {
483    my ($self, $c, $cmd, @args) = @_;
484
485    if ($cmd eq 'help') {
486        $c->go('help', [ @args ]);
487    }
488   
489    my $ctx = $c->session->{admin_ctx} || '';
490    my $path = '/admin/cli' . ($ctx ? lc("/$ctx") : '');
491    if ($c->get_action( $cmd, $path )) {
492        return $c->go($path . '/' . $cmd, [ @args ]);
493    } else {
494        $c->error( "No such command $cmd" );
495    }
496}
497
498sub complete : XMLRPC {
499    my ($self, $c, $cmd, @args) = @_;
500
501    my $ctx = $c->session->{admin_ctx} || '';
502    my $path = '/admin/cli' . ($ctx ? lc("/$ctx") : '');
503    if ($c->get_action( "_c_$cmd", $path )) {
504        my $vals = $c->go($path . '/' . "_c_$cmd", [ @args ]);
505        return $args[-1] ? [ grep { index($_, $args[-1]) == 0 } @$vals ] : $vals;
506    } else {
507        return $c->stash->{xmlrpc} = [];
508    }
509}
510
511
512=head1 AUTHOR
513
514Olivier Thauvin
515
516=head1 LICENSE
517
518This library is free software. You can redistribute it and/or modify
519it under the same terms as Perl itself.
520
521=cut
522
523__PACKAGE__->meta->make_immutable;
524
5251;
Note: See TracBrowser for help on using the repository browser.