rvd_front.pl 66.4 KB
Newer Older
1
2
3
#!/usr/bin/env perl
use warnings;
use strict;
4
5
6
#####
use locale ':not_characters';
#####
7
use Carp qw(confess);
8
use Data::Dumper;
9
use Digest::SHA qw(sha256_hex);
10
use Hash::Util qw(lock_hash);
11
use Mojolicious::Lite 'Ravada::I18N';
Francesc Guasch's avatar
Francesc Guasch committed
12
use Mojo::JSON qw(decode_json encode_json);
13
use Time::Piece;
14
#use Mojolicious::Plugin::I18N;
15
use Mojo::Home;
Francesc Guasch's avatar
Francesc Guasch committed
16
17

use I18N::LangTags::Detect;
18
#####
19
20
#my $self->plugin('I18N');
#package Ravada::I18N:en;
21
#####
22
23
24
#
no warnings "experimental::signatures";
use feature qw(signatures);
25

26
27
use lib 'lib';

28
use Ravada::Front;
29
use Ravada::Front::Domain;
Francesc Guasch's avatar
Francesc Guasch committed
30
use Ravada::Auth;
31
use POSIX qw(locale_h);
Francesc Guasch's avatar
Francesc Guasch committed
32
33

my $help;
Francesc Guasch's avatar
Francesc Guasch committed
34

Francesc Guasch's avatar
Francesc Guasch committed
35
36
37
my $FILE_CONFIG = "/etc/rvd_front.conf";

my $error_file_duplicated = 0;
38
for my $file ( "/etc/rvd_front.conf" , ($ENV{HOME} or '')."/rvd_front.conf") {
Francesc Guasch's avatar
Francesc Guasch committed
39
    warn "WARNING: Found config file at $file and at $FILE_CONFIG\n"
40
        if -e $file && $FILE_CONFIG && $file ne $FILE_CONFIG;
41
    $FILE_CONFIG = $file if -e $file;
Francesc Guasch's avatar
Francesc Guasch committed
42
    $error_file_duplicated++;
43
}
Francesc Guasch's avatar
Francesc Guasch committed
44
warn "WARNING: using $FILE_CONFIG\n"    if$error_file_duplicated>2;
45
46

my $FILE_CONFIG_RAVADA;
47
for my $file ( "/etc/ravada.conf" , ($ENV{HOME} or '')."/ravada.conf") {
48
49
50
    warn "WARNING: Found config file at $file and at $FILE_CONFIG_RAVADA\n"
        if -e $file && $FILE_CONFIG_RAVADA;
    $FILE_CONFIG_RAVADA = $file if -e $file;
Francesc Guasch's avatar
Francesc Guasch committed
51
}
52

amesones's avatar
amesones committed
53
54
55
my $CONFIG_FRONT = plugin Config => { default => {
                                                hypnotoad => {
                                                pid_file => 'log/rvd_front.pid'
fv3rdugo's avatar
Indent    
fv3rdugo committed
56
57
                                                ,listen => ['http://*:8081']
                                                }
58
                                              ,login_bg_file => '/img/intro-bg.jpg'
Francesc Guasch's avatar
Francesc Guasch committed
59
                                              ,login_header => 'Welcome'
60
                                              ,login_message => ''
61
                                              ,secrets => ['changeme0']
62
                                              ,guide => 0
fv3rdugo's avatar
fv3rdugo committed
63
                                              ,login_custom => ''
64
                                              ,footer => 'bootstrap/footer'
65
                                              ,monitoring => 0
66
                                              ,fallback => 0
67
                                              ,guide_custom => ''
68
69
                                              ,admin => {
                                                    hide_clones => 15
Francesc Guasch's avatar
Francesc Guasch committed
70
                                                    ,autostart => 0
amesones's avatar
amesones committed
71
                                              }
72
                                              ,config => $FILE_CONFIG_RAVADA
73
                                              ,auto_view => 0
amesones's avatar
amesones committed
74
                                              }
Francesc Guasch's avatar
Francesc Guasch committed
75
                                      ,file => $FILE_CONFIG
76
};
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#####
#####
#####
# Import locale-handling tool set from POSIX module.
# This example uses: setlocale -- the function call
#                    LC_CTYPE -- explained below

# query and save the old locale
my $old_locale = setlocale(LC_CTYPE);

setlocale(LC_CTYPE, "en_US.ISO8859-1");
# LC_CTYPE now in locale "English, US, codeset ISO 8859-1"

setlocale(LC_CTYPE, "");
# LC_CTYPE now reset to default defined by LC_ALL/LC_CTYPE/LANG
# environment variables.  See below for documentation.

# restore the old locale
setlocale(LC_CTYPE, $old_locale);
#####
#####
#####
100
plugin I18N => {namespace => 'Ravada::I18N', default => 'en'};
Francesc Guasch's avatar
Francesc Guasch committed
101
plugin 'RenderFile';
Francesc Guasch's avatar
Francesc Guasch committed
102

103
my %config;
104
%config = (config => $CONFIG_FRONT->{config}) if $CONFIG_FRONT->{config};
105
our $RAVADA = Ravada::Front->new(%config);
106

107
our $USER;
Francesc Guasch's avatar
Francesc Guasch committed
108

109
# TODO: get those from the config file
110
our $DOCUMENT_ROOT = "/var/www";
111
112

# session times out in 5 minutes
113
our $SESSION_TIMEOUT = ($CONFIG_FRONT->{session_timeout} or 5 * 60);
114
# session times out in 15 minutes for admin users
115
our $SESSION_TIMEOUT_ADMIN = ($CONFIG_FRONT->{session_timeout_admin} or 15 * 60);
116

Francesc Guasch's avatar
Francesc Guasch committed
117
118
init();
############################################################################3
119

120
121
122
hook before_routes => sub {
  my $c = shift;

123
124
  $USER = undef;

Francesc Guasch's avatar
Francesc Guasch committed
125
  $c->stash(version => $RAVADA->version);
126
  my $url = $c->req->url->to_abs->path;
fv3rdugo's avatar
fv3rdugo committed
127
  my $host = $c->req->url->to_abs->host;
128
  $c->stash(css=>['/css/sb-admin.css']
Francesc Guasch's avatar
Francesc Guasch committed
129
130
            ,js=>[
                '/js/ravada.js'
131
132
133
                ]
            ,csssnippets => []
            ,navbar_custom => 0
Francesc Guasch's avatar
Francesc Guasch committed
134
135
136
137
            ,url => undef
            ,_logged_in => undef
            ,_anonymous => undef
            ,_user => undef
138
            ,footer=> $CONFIG_FRONT->{footer}
139
            ,monitoring => 0
fv3rdugo's avatar
fv3rdugo committed
140
            ,fallback => $CONFIG_FRONT->{fallback}
141
            ,check_netdata => 0
142
            ,guide => $CONFIG_FRONT->{guide}
fv3rdugo's avatar
fv3rdugo committed
143
            ,host => $host
144
            );
145

Francesc Guasch's avatar
Francesc Guasch committed
146
147
    return if _logged_in($c);
    return if $url =~ m{^/(anonymous|login|logout|requirements|robots.txt)}
Francesc Guasch's avatar
Francesc Guasch committed
148
149
           || $url =~ m{^/(css|font|img|js)}
	   || $url =~ m{^/fallback/.*\.(css|js|map)$};
150

Francesc Guasch's avatar
Francesc Guasch committed
151
152
153
154
155
156
157
158
159
    # anonymous URLs
    if (($url =~ m{^/machine/(clone|display|info|view)/}
        || $url =~ m{^/(list_bases_anonymous|request/)}i
        ) && !_logged_in($c)) {
        $USER = _anonymous_user($c);
        return if $USER->is_temporary;
    }
    return access_denied($c)
        if $url =~ /(screenshot|\.json)/
160
        && !_logged_in($c);
Francesc Guasch's avatar
Francesc Guasch committed
161
    return login($c) if !_logged_in($c);
162

163
164
165
166
167
168
    if ($USER && $USER->is_admin && $CONFIG_FRONT->{monitoring}) {
        if (!defined $c->session('monitoring')) {
            $c->stash(check_netdata => "https://$host:19999/index.html");
        }
        $c->stash( monitoring => 1) if $c->session('monitoring');
    }
169
        $c->stash( fallback => 1) if $c->session('fallback');
170
171
172
173
174
};


############################################################################3

Francesc Guasch's avatar
Francesc Guasch committed
175
176
177
178
179
any '/robots.txt' => sub {
    my $c = shift;
    return $c->render(text => "User-agent: *\nDisallow: /\n", format => 'text');
};

180
any '/' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
181
    my $c = shift;
182
    return quick_start($c);
Francesc Guasch's avatar
Francesc Guasch committed
183
184
};

Francesc Guasch's avatar
Francesc Guasch committed
185
186
any '/index.html' => sub {
    my $c = shift;
187
    return quick_start($c);
Francesc Guasch's avatar
Francesc Guasch committed
188
189
};

190
191
any '/login' => sub {
    my $c = shift;
192
    return login($c);
193
194
};

Francesc Guasch's avatar
Francesc Guasch committed
195
196
197
198
199
200
201
202
203
any '/test' => sub {
    my $c = shift;
    my $logged = _logged_in($c);
    my $count = $c->session('count');
    $c->session(count => ++$count);

    my $name_mojo = $c->signed_cookie('mojolicious');

    my $dump_log = ''.(Dumper($logged) or '');
Francesc Guasch's avatar
Francesc Guasch committed
204
205
206
207
208
    return $c->render(text => "$count ".($name_mojo or '')."<br> ".$dump_log
        ."<br>"
        ."<script>alert(window.screen.availWidth"
        ."+\" \"+window.screen.availHeight)</script>"
    );
Francesc Guasch's avatar
Francesc Guasch committed
209
210
};

Francesc Guasch's avatar
Francesc Guasch committed
211
212
any '/logout' => sub {
    my $c = shift;
213
    logout($c);
Francesc Guasch's avatar
Francesc Guasch committed
214
215
216
    $c->redirect_to('/');
};

217
get '/anonymous' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
218
    my $c = shift;
219
#    $c->render(template => 'bases', base => list_bases());
220
    $USER = _anonymous_user($c);
221
    return list_bases_anonymous($c);
Francesc Guasch's avatar
Francesc Guasch committed
222
223
};

224
get '/anonymous_logout.html' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
225
    my $c = shift;
226
227
    $c->session('anonymous_user' => '');
    return $c->redirect_to('/');
Francesc Guasch's avatar
Francesc Guasch committed
228
229
};

230
get '/anonymous/(#base_id).html' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
231
232
    my $c = shift;

233
    $c->stash(_anonymous => 1 , _logged_in => 0);
234
    _init_error($c);
235
    my $base_id = $c->stash('base_id');
236
237
    my $base = $RAVADA->search_domain_by_id($base_id);

238
    $USER = _anonymous_user($c);
239
    return quick_start_domain($c,$base->id, $USER->name);
Francesc Guasch's avatar
Francesc Guasch committed
240
241
};

242
any '/admin/#type' => sub {
243
  my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
244

245
246
247
  return admin($c)  if $c->stash('type') eq 'machines'
                        && $USER->is_operator;

248
249
  return access_denied($c)    if !$USER->is_operator;

amesones's avatar
amesones committed
250
  return admin($c);
Francesc Guasch's avatar
Francesc Guasch committed
251
252
};

253
any '/new_machine' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
254
    my $c = shift;
255
    return access_denied($c)    if !$USER->can_create_machine;
256
    return new_machine($c);
Francesc Guasch's avatar
Francesc Guasch committed
257
258
};

259
260
261
262
263
any '/copy_machine' => sub {
    my $c = shift;
    return new_machine_copy($c);
};

264
get '/domain/new.html' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
265
266
    my $c = shift;

267
268
    return access_denied($c) if !_logged_in($c) || !$USER->is_admin();
    $c->stash(error => []);
amesones's avatar
amesones committed
269
    return $c->render(template => "main/new_machine");
Francesc Guasch's avatar
Francesc Guasch committed
270
271
272

};

273
274
get '/list_vm_types.json' => sub {
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
275
    $c->render(json => $RAVADA->list_vm_types);
276
277
};

278
279
280
281
282
283
284
285
286
287
288
289
290
291
get '/list_nodes.json' => sub {
    my $c = shift;
    $c->render(json => [$RAVADA->list_vms]);
};

get '/node/enable/(:id).json' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->is_admin;
    return $c->render(json => {enabled => $RAVADA->enable_node($c->stash('id'),1)});
};

get '/node/disable/(:id).json' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->is_admin;
292
293
294
295
296

    my $machines = $RAVADA->_list_machines_vm($c->stash('id'));
    for ( @$machines ) {
        my $req = Ravada::Request->shutdown_domain( uid => $USER->id , id_domain => $_->{id} );
    }
297
298
    return $c->render(json => {enabled => $RAVADA->enable_node($c->stash('id'),0)});
};
299
300
301
302
303
get '/node/remove/(:id).json' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->is_admin;
    return $c->render(json => {remove => $RAVADA->remove_node($c->stash('id'),1)});
};
304

Francesc Guasch's avatar
Francesc Guasch committed
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
get '/node/shutdown/(:id).json' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->is_admin;

    my $machines = $RAVADA->_list_machines_vm($c->stash('id'));
    for ( @$machines ) {
        my $req = Ravada::Request->shutdown_domain(
                    uid => $USER->id
            , id_domain => $_->{id}
        );
    }
    my $at = 0;
    if (@$machines) {
        $at = time + 60 + scalar @$machines;
    }
    my $req = Ravada::Request->shutdown_node(
                id_node => $c->stash('id')
                ,at => $at
    );
    Ravada::Request->connect_node(
                id_node => $c->stash('id')
                ,at => $at + 10
    );
    return $c->render(json => {id_req => $req->id });
};

get '/node/start/(:id).json' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->is_admin;
    my $req = Ravada::Request->start_node(
                id_node => $c->stash('id')
    );
    for my $seconds ( 30,60,90,120 ) {
        Ravada::Request->connect_node(
            id_node => $c->stash('id')
            ,at => time + $seconds
        );
    }

    return $c->render(json => {id_req => $req->id });

};

348
349
350
351
352
353
any '/new_node' => sub {
    my $c = shift;
    return access_denied($c)    if !$USER->is_admin;
    return new_node($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
get '/node/connect/(#backend)/(#hostname)' => sub {
    my $c = shift;
    return access_denied($c)    if !$USER->is_admin;
    my $req = Ravada::Request->connect_node(
                backend => $c->stash('backend')
                    ,hostname => $c->stash('hostname')
    );
    return $c->render(json => {id_req => $req->id });
};

get '/node/connect/(#id)' => sub {
    my $c = shift;
    return access_denied($c)    if !$USER->is_admin;
    my $req = Ravada::Request->connect_node(
        id_node => $c->stash('id')
    );
    return $c->render(json => {id_req => $req->id });
};


374
375
get '/list_bases.json' => sub {
    my $c = shift;
376
377
378
379
380
381
382
383
384
385
386

    my $domains = $RAVADA->list_bases();
    my @domains_show = @$domains;
    if (!$USER->is_admin) {
        @domains_show = ();
        for (@$domains) {
            push @domains_show,($_) if $_->{is_public};
        }
    }
    $c->render(json => [@domains_show]);

387
388
389
390
};

get '/list_images.json' => sub {
    my $c = shift;
391

elodin1's avatar
elodin1 committed
392
393
394
    return access_denied($c) unless _logged_in($c)
        && $USER->can_create_machine();

395
396
397
    my $vm_name = $c->param('backend');

    $c->render(json => $RAVADA->list_iso_images($vm_name or undef));
398
399
};

400
get '/iso_file.json' => sub {
joelalju's avatar
joelalju committed
401
    my $c = shift;
elodin1's avatar
elodin1 committed
402
403
    return access_denied($c) unless _logged_in($c)
        && $USER->can_create_machine();
404
    my @isos =('<NONE>');
Fernando Verdugo's avatar
Fernando Verdugo committed
405
    push @isos,(@{$RAVADA->iso_file('KVM')});
406
    $c->render(json => \@isos);
joelalju's avatar
joelalju committed
407
408
};

409
get '/list_machines.json' => sub {
410
    my $c = shift;
411

412
    return access_denied($c) unless _logged_in($c)
413
414
415
416
417
        && (
            $USER->can_list_machines
            || $USER->can_list_own_machines()
            || $USER->can_list_clones()
            || $USER->can_list_clones_from_own_base()
418
419
420
            || $USER->is_admin()
        );

421
    return $c->render( json => $RAVADA->list_machines($USER) );
422

423
};
Francesc Guasch's avatar
Francesc Guasch committed
424

425
426
427
get '/list_machines_user.json' => sub {
    my $c = shift;
    return $c->render( json => $RAVADA->list_machines_user($USER));
428
};
Francesc Guasch's avatar
Francesc Guasch committed
429

430
431
432
433
434
435
436
get '/list_bases_anonymous.json' => sub {
    my $c = shift;

    # shouldn't this be "list_bases" ?
    $c->render(json => $RAVADA->list_bases_anonymous(_remote_ip($c)));
};

Francesc Guasch's avatar
Francesc Guasch committed
437
get '/list_lxc_templates.json' => sub {
fv3rdugo's avatar
fv3rdugo committed
438
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
439
    $c->render(json => $RAVADA->list_lxc_templates);
fv3rdugo's avatar
fv3rdugo committed
440
441
};

joansp's avatar
udpate    
joansp committed
442
443
444
445
446
get '/pingbackend.json' => sub {

    my $c = shift;
    $c->render(json => $RAVADA->ping_backend);
};
fv3rdugo's avatar
fv3rdugo committed
447

448
449
# machine commands

450
get '/machine/info/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
451
    my $c = shift;
452
    my $id = $c->stash('id');
Francesc Guasch's avatar
Francesc Guasch committed
453
    die "No id " if !$id;
454

joelalju's avatar
joelalju committed
455
456
457
    my ($domain) = _search_requested_machine($c);
    return access_denied($c)    if !$domain;

458
    return access_denied($c,"Access denied to user ".$USER->name) unless $USER->can_manage_machine($domain->id);
Francesc Guasch's avatar
Francesc Guasch committed
459

460
461
    my $info = $domain->info($USER);
    if ($domain->is_active && !$info->{ip}) {
Francesc Guasch's avatar
Francesc Guasch committed
462
        Ravada::Request->refresh_machine(id_domain => $domain->id, uid => $USER->id);
463
464
    }
    return $c->render(json => $info);
Francesc Guasch's avatar
Francesc Guasch committed
465
466
};

Francesc Guasch's avatar
Francesc Guasch committed
467
get '/machine/requests/(:id).json' => sub {
468
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
469
    my $id_domain = $c->stash('id');
470
    return access_denied($c) unless $USER->can_manage_machine($id_domain);
joelalju's avatar
joelalju committed
471

Francesc Guasch's avatar
Francesc Guasch committed
472
473
    $c->render(json => $RAVADA->list_requests($id_domain,10));
};
joelalju's avatar
joelalju committed
474

475
any '/machine/manage/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
476
   	 my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
477
     Ravada::Request->refresh_machine(id_domain => $c->stash('id'), uid => $USER->id);
Francesc Guasch's avatar
Francesc Guasch committed
478
     return manage_machine($c);
479
};
joelalju's avatar
joelalju committed
480

Francesc Guasch's avatar
Francesc Guasch committed
481
482
483
any '/hardware/(:id).(:type)' => sub {
   	 my $c = shift;
     return $c->render(template => 'main/hardware');
484
485
};

486
get '/machine/view/(:id).(:type)' => sub {
487
    my $c = shift;
488
489
    my $id = $c->stash('id');
    my $type = $c->stash('type');
Francesc Guasch's avatar
Francesc Guasch committed
490

joelalju's avatar
joelalju committed
491
492
493
494
495
496
    my ($domain) = _search_requested_machine($c);
    return access_denied($c)    if !$domain;

    return access_denied($c) unless $USER->is_admin
                              || $domain->id_owner == $USER->id;

497
498
499
    return view_machine($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
500
any '/machine/clone/(:id).(:type)' => sub {
Joel Alarcón's avatar
Joel Alarcón committed
501
    my $c = shift;
502

Francesc Guasch's avatar
Francesc Guasch committed
503
504
505
506
507
508
509
510
511
512
513
    return clone_machine($c)    if $USER && $USER->can_clone() && !$USER->is_temporary();

    my $bases_anonymous = $RAVADA->list_bases_anonymous(_remote_ip($c));
    for (@$bases_anonymous) {
        if ($_->{id} == $c->stash('id') ) {
            return clone_machine($c,1);
        }
    }

    return login($c)    if !$USER || $USER->is_temporary;
    return access_denied($c);
514
};
Francesc Guasch's avatar
Francesc Guasch committed
515

516
get '/machine/shutdown/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
517
        my $c = shift;
518
    return access_denied($c)        if !$USER ->can_shutdown($c->stash('id'));
Francesc Guasch's avatar
Francesc Guasch committed
519
520
521
522

        return shutdown_machine($c);
};

523
any '/machine/remove/(:id).(:type)' => sub {
joansp's avatar
joansp committed
524
        my $c = shift;
525
    return access_denied($c)       if !$USER->can_remove_machine($c->stash('id'));
joansp's avatar
joansp committed
526
527
        return remove_machine($c);
};
528
529

any '/machine/remove_clones/(:id).(:type)' => sub {
530
531
532
533
534
535
    my $c = shift;

    # TODO : call to $domain->_allow_remove();
	return access_denied($c)
        unless
            $USER -> can_remove_clone_all()
Francesc Guasch's avatar
Francesc Guasch committed
536
537
	        || $USER->can_remove_clone()
            || $USER->can_remove_all();
538
    return remove_clones($c);
539
540
};

541
get '/machine/prepare/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
542
543
544
545
        my $c = shift;
        return prepare_machine($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
546
get '/machine/set_base_vm/(:id_vm)/(:id_domain).(:type)' => sub {
547
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
548
549
550
551
552
553
    return set_base_vm($c, 1);
};

get '/machine/remove_base_vm/(:id_vm)/(:id_domain).(:type)' => sub {
    my $c = shift;
    return set_base_vm($c, 0);
554
555
};

556
get '/machine/remove_b/(:id).(:type)' => sub {
joansp's avatar
joansp committed
557
558
559
560
        my $c = shift;
        return remove_base($c);
};

561
get '/machine/remove_base/(:id).(:type)' => sub {
562
563
564
565
    my $c = shift;
    return remove_base($c);
};

566
get '/machine/screenshot/(:id).(:type)' => sub {
567
        my $c = shift;
568
569
        my $domain = _search_requested_machine($c);
        return access_denied($c)   if (!$USER->can_screenshot() || $domain->is_base());
570
571
572
        return screenshot_machine($c);
};

573
get '/machine/copy_screenshot/(:id).(:type)' => sub {
574
575
576
        my $c = shift; 
        my $domain = _search_requested_machine($c);
        return access_denied($c) if (!$USER->is_admin() || $domain->id_base() == NULL );
577
578
579
        return copy_screenshot($c);
};

580
get '/machine/pause/(:id).(:type)' => sub {
joansp's avatar
joansp committed
581
582
583
584
        my $c = shift;
        return pause_machine($c);
};

585
get '/machine/hibernate/(:id).(:type)' => sub {
586
        my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
587
          return access_denied($c)
Francesc Guasch's avatar
Francesc Guasch committed
588
             unless $USER->is_admin() || $USER->can_shutdown($c->stash('id'));
Francesc Guasch's avatar
Francesc Guasch committed
589

590
591
592
        return hybernate_machine($c);
};

593
get '/machine/resume/(:id).(:type)' => sub {
joansp's avatar
joansp committed
594
595
596
597
        my $c = shift;
        return resume_machine($c);
};

598
get '/machine/start/(:id).(:type)' => sub {
joansp's avatar
joansp committed
599
600
601
        my $c = shift;
        return start_machine($c);
};
joansp's avatar
joansp committed
602

603
get '/machine/exists/#name' => sub {
604
    my $c = shift;
605
    my $name = $c->stash('name');
606
607
608
609
610
611
    #TODO
    # return failure if it can't find the name in the URL

    return $c->render(json => $RAVADA->domain_exists($name));

};
joansp's avatar
joansp committed
612

Francesc Guasch's avatar
Francesc Guasch committed
613
post '/machine/hardware/change' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
614
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
615
616
617
618
619
620
621
622
623
624
625
626
    my $arg = decode_json($c->req->body);

    my $domain = Ravada::Front::Domain->open(delete $arg->{id_domain});

    return access_denied($c)
        unless $USER->id == $domain->id_owner || $USER->is_admin;

    my $hardware = delete $arg->{hardware} or die "Missing hardware name";
    my $index = delete $arg->{index};
    my $data = delete $arg->{data};

    die "Unknown fields in request ".Dumper($arg) if keys %{$arg};
Francesc Guasch's avatar
Francesc Guasch committed
627
    return $c->render(json => { req => Ravada::Request->change_hardware(
Francesc Guasch's avatar
Francesc Guasch committed
628
629
630
631
                id_domain => $domain->id
                ,hardware => $hardware
                ,index => $index
                ,data => $data
Francesc Guasch's avatar
Francesc Guasch committed
632
633
634
635
636
                ,uid => $USER->id
            )
    });
};

637
638
639
640
641
642
643
get '/node/exists/#name' => sub {
    my $c = shift;
    my $name = $c->stash('name');

    return $c->render(json => $RAVADA->node_exists($name));

};
644
get '/machine/rename/#id/#value' => sub {
645
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
646
    return access_denied($c)       if !$USER->can_manage_machine($c->stash('id'));
647
648
649
    return rename_machine($c);
};

650
651
any '/machine/copy' => sub {
    my $c = shift;
652
    return access_denied($c)    if !$USER -> can_clone_all();
653
654
655
    return copy_machine($c);
};

656
657
658
659
660
661
get '/machine/public/#id' => sub {
    my $c = shift;
    return machine_is_public($c);
};

get '/machine/public/#id/#value' => sub {
662
663
664
665
    my $c = shift;
    return machine_is_public($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
666
667
668
669
670
671
672
673
674
675
676
677
get '/machine/set/#id/#field/#value' => sub {
    my $c = shift;
    my $id = $c->stash('id');
    my $field = $c->stash('field');
    my $value = $c->stash('value');

    return access_denied($c)       if !$USER->can_manage_machine($c->stash('id'));

    my $domain = Ravada::Front::Domain->open($id) or die "Unkown domain $id";
    return $c->render(json => { $field => $domain->_data($field, $value)});
};

678
679
680
681
682
683
684
685
686
687
get '/machine/autostart/#id/#value' => sub {
    my $c = shift;
    my $req = Ravada::Request->domain_autostart(
        id_domain => $c->stash('id')
           ,value => $c->stash('value')
             ,uid => $USER->id
    );
    return $c->render(json => { request => $req->id});
};

688
get '/machine/display/(:id).vv' => sub {
689
690
691
692
693
694
695
696
697
698
699
700
    my $c = shift;

    my $id = $c->stash('id');

    my $domain = $RAVADA->search_domain_by_id($id);
    return $c->render(text => "unknown machine id=$id") if !$id;

    return access_denied($c)
        if $USER->id ne $domain->id_owner
        && !$USER->is_admin;

    $c->res->headers->content_type('application/x-virt-viewer');
701
702
        $c->res->headers->content_disposition(
        "inline;filename=".$domain->id.".vv");
703

704
    return $c->render(data => $domain->display_file($USER), format => 'vv');
705
706
};

Francesc Guasch's avatar
Francesc Guasch committed
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
get '/machine/display-tls/(:id)-tls.vv' => sub {
    my $c = shift;

    my $id = $c->stash('id');

    my $domain = $RAVADA->search_domain_by_id($id);
    return $c->render(text => "unknown machine id=$id") if !$id;

    return access_denied($c)
        if $USER->id ne $domain->id_owner
        && !$USER->is_admin;

    $c->res->headers->content_type('application/x-virt-viewer');
        $c->res->headers->content_disposition(
        "inline;filename=".$domain->id."-tls.vv");

    return $c->render(data => $domain->display_file_tls($USER), format => 'vv');
};

Francesc Guasch's avatar
Francesc Guasch committed
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
# Network ##########################################################3

get '/network/interfaces/(:vm_type)/(:type)' => sub {
    my $c = shift;

    my $vm_type = $c->stash('vm_type');
    my $type = $c->stash('type');

    return $c->render( json => $RAVADA->list_network_interfaces(
               user => $USER
              ,type => $type
           ,vm_type => $vm_type
       )
    );
};
Francesc Guasch's avatar
Francesc Guasch committed
741

742
743
# Users ##########################################################3

Laura Figuerola's avatar
Laura Figuerola committed
744
745
##add user

746
any '/users/register' => sub {
747

Laura Figuerola's avatar
Laura Figuerola committed
748
       my $c = shift;
749
       return access_denied($c) if !$USER->is_admin();
Laura Figuerola's avatar
Laura Figuerola committed
750
751
752
       return register($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
753
754
any '/admin/user/(:id).(:type)' => sub {
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
755
    return access_denied($c) if !$USER->can_manage_users() && !$USER->can_grant();
Francesc Guasch's avatar
Francesc Guasch committed
756
757
758
759
760
761

    my $user = Ravada::Auth::SQL->search_by_id($c->stash('id'));

    return $c->render(text => "Unknown user id: ".$c->stash('id'))
        if !$user;

Francesc Guasch's avatar
Francesc Guasch committed
762
763
764
765
766
    if ($c->param('make_admin')) {
        $USER->make_admin($c->stash('id'))  if $c->param('is_admin');
        $USER->remove_admin($c->stash('id'))if !$c->param('is_admin');
        $user = Ravada::Auth::SQL->search_by_id($c->stash('id'));
    }
767
768
769
770
771
772
773
774
775
776
777
    if ($c->param('grant')) {
        return access_denied($c)    if !$USER->can_grant();
        my %grant;
        for my $param_name (@{$c->req->params->names}) {
            if ( $param_name =~ /^perm_(.*)/ ) {
                $grant{$1} = 1;
            } elsif ($param_name =~ /^off_perm_(.*)/) {
                $grant{$1} = 0 if !exists $grant{$1};
            }
        }
        for my $perm (keys %grant) {
778
            if ( $grant{$perm} ) {
779
780
781
782
783
784
                $USER->grant($user, $perm);
            } else {
                $USER->revoke($user, $perm);
            }
        }
    }
Francesc Guasch's avatar
Francesc Guasch committed
785
786
787
    $c->stash(user => $user);
    return $c->render(template => 'main/manage_user');
};
Laura Figuerola's avatar
Laura Figuerola committed
788

789
790
791
792
793
794
795
796
797
798
799
800
801
802
get '/list_ldap_attributes/(#cn)' => sub {
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $cn = $c->stash('cn');
    my $user;
    eval {
        ($user) = Ravada::Auth::LDAP::search_user($cn);
    };
    return $c->render(json => { error => $@ }) if $@;
    return $c->render(json => []) if !$user;

    $c->session(ldap_attributes_cn => $cn) if $user;
803
    return $c->render(json => {attributes => [sort $user->attributes]});
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
};

get '/count_ldap_entries/(#attribute)/(#value)' => sub {
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my @entries;
    eval {
        @entries = Ravada::Auth::LDAP::search_user(
            field => $c->stash('attribute')
            ,name => $c->stash('value')
            ,typesonly => 1
        );
    };
    @entries = [ 'too many' ] if $@ =~ /Sizelimit exceeded/;
    return $c->render(json => { entries => scalar @entries });
};

823
get '/add_ldap_access/(#id_domain)/(#attribute)/(#value)/(#allowed)/(#last)' => sub {
824
825
826
827
828
829
830
831
832
833
834
835
836
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $domain_id = $c->stash('id_domain');
    my $domain = Ravada::Front::Domain->open($domain_id);

    my $attribute = $c->stash('attribute');
    my $value = $c->stash('value');
    my $allowed = 1;
    if ($c->stash('allowed') eq 'false') {
        $allowed = 0;
    }
837
838
839
840
841
    my $last = 1;
    if ($c->stash('last') eq 'false') {
        $last = 0;
    }
    $last = 1 if !$allowed;
842

843
    eval { $domain->allow_ldap_access($attribute => $value, $allowed, $last ) };
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
    _fix_default_ldap_access($c, $domain, $allowed) if !$@;
    return $c->render(json => { error => $@ }) if $@;
    return $c->render(json => { ok => 1 });

};

sub _fix_default_ldap_access($c, $domain, $allowed) {
    my @list = $domain->list_ldap_access();
    my $default_found;
    for ( @list ) {
        if ( $_->{value} eq '*' ) {
            $default_found = $_->{id};
        }
    }
    if ( $default_found ) {
        $domain->move_ldap_access($default_found, +1);
        return;
    }
    my $allowed_default = 0;
    $allowed_default = 1 if !$allowed;
    eval { $domain->allow_ldap_access('DEFAULT' => '*', $allowed_default ) };
    warn $@ if $@;
}

get '/delete_ldap_access/(#id_domain)/(#id_access)' => sub {
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $domain_id = $c->stash('id_domain');
    my $domain = Ravada::Front::Domain->open($domain_id);

    $domain->delete_ldap_access($c->stash('id_access'));

878
879
880
881
882
883
    # delete default if it is the only one left
    my @ldap_access = $domain->list_ldap_access();
    if (scalar @ldap_access == 1 && $ldap_access[0]->{value} eq '*') {
        $domain->delete_ldap_access($ldap_access[0]->{id});
    }

884
885
886
887
888
889
890
891
892
893
894
895
896
    return $c->render(json => { ok => 1 });
};

get '/list_ldap_access/(#id_domain)' => sub {
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $domain_id = $c->stash('id_domain');
    my $domain = Ravada::Front::Domain->open($domain_id);

    my @ldap_access = $domain->list_ldap_access();
    my $default = {};
897
    if (scalar @ldap_access && $ldap_access[-1]->{value} eq '*') {
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
        $default = pop @ldap_access;
    }
    return $c->render(json => {list => \@ldap_access, default => $default} );
};

get '/move_ldap_access/(#id_domain)/(#id_access)/(#count)' => sub {
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $domain_id = $c->stash('id_domain');
    my $domain = Ravada::Front::Domain->open($domain_id);

    $domain->move_ldap_access($c->stash('id_access'), $c->stash('count'));

    return $c->render(json => { ok => 1});
};

916
get '/set_ldap_access/(#id_domain)/(#id_access)/(#allowed)/(#last)' => sub {
917
918
919
920
921
922
923
924
925
926
927
928
929
    my $c = shift;

    return _access_denied($c) if !$USER->is_admin;

    my $domain_id = $c->stash('id_domain');
    my $domain = Ravada::Front::Domain->open($domain_id);

    my $allowed = $c->stash('allowed');
    if ($allowed =~ /false/ || !$allowed) {
        $allowed = 0;
    } else {
        $allowed = 1;
    }
930
931
932
933
934
935
936
    my $last= $c->stash('last');
    if ($last=~ /false/ || !$last) {
        $last= 0;
    } else {
        $last= 1;
    }
    warn "last = $last";
937

938
    $domain->set_ldap_access($c->stash('id_access'), $allowed, $last);
939
940
    return $c->render(json => { ok => 1});
};
941
##############################################
Laura Figuerola's avatar
Laura Figuerola committed
942

Francesc Guasch's avatar
Francesc Guasch committed
943
944
945
946
947
948
949
950
951
952
953
954
955
post '/request/(:name)/' => sub {
    my $c = shift;

    my $args = decode_json($c->req->body);
    warn Dumper($args);

    my $req = Ravada::Request->new_request(
        $c->stash('name')
        ,uid => $USER->id
        ,%$args
    );
    return $c->render(json => { ok => 1 });
};
956

957
get '/request/(:id).(:type)' => sub {
958
    my $c = shift;
959
    my $id = $c->stash('id');
960

Francesc Guasch's avatar
Francesc Guasch committed
961
962
963
    if (!$USER) {
        $USER = _get_anonymous_user($c) or access_denied($c);
    }
964
965
966
967
    if ($c->stash('type') eq 'json') {
        my $request = Ravada::Request->open($id);
        return $c->render(json => $request->info($USER));
    }
968
969
970
    return _show_request($c,$id);
};

971
972
973
974
975
976
977
978
979
get '/anonymous/request/(:id).(:type)' => sub {
    my $c = shift;
    my $id = $c->stash('id');

    $USER = _anonymous_user($c);

    return _show_request($c,$id);
};

Francesc Guasch's avatar
Francesc Guasch committed
980
981
get '/requests.json' => sub {
    my $c = shift;
elodin1's avatar
elodin1 committed
982
983
    return access_denied($c) unless _logged_in($c)
        && $USER->is_admin;
Francesc Guasch's avatar
Francesc Guasch committed
984
985
986
    return list_requests($c);
};

joansp's avatar
joansp committed
987
get '/messages.json' => sub {
joansp's avatar
joansp committed
988
989
990
991
992
993
    my $c = shift;


    return $c->render( json => [$USER->messages()] );
};

994
get '/unshown_messages.json' => sub {
995
996
997
998
    my $c = shift;

    return $c->redirect_to('/login') if !_logged_in($c);

999
    return $c->render( json => [$USER->unshown_messages()] );
Antonio's avatar
Antonio committed
1000
1001
1002
};


joansp's avatar
joansp committed
1003
1004
1005
get '/messages/read/all.html' => sub {
    my $c = shift;
    $USER->mark_all_messages_read;
1006
    return $c->render(inline => "1");
1007
1008
};

1009
get '/messages/read/(#id).json' => sub {
1010
    my $c = shift;
1011
    my $id = $c->stash('id');
joansp's avatar
joansp committed
1012
    $USER->mark_message_read($id);
1013
    return $c->render(inline => "1");
joansp's avatar
joansp committed
1014
};
1015

amesones's avatar
amesones committed
1016
get '/messages/unread/(#id).json' => sub {
joansp's avatar
joansp committed
1017
    my $c = shift;
1018
    my $id = $c->stash('id');
joansp's avatar
joansp committed
1019
    $USER->mark_message_unread($id);
1020
    return $c->render(inline => "1");
joansp's avatar
joansp committed
1021
1022
};

1023
get '/messages/view/(#id).html' => sub {
1024
    my $c = shift;
1025
1026
    my $id = $c->stash('id');
    return $c->render( json => $USER->show_message($id) );
1027
1028
};

1029
1030
1031
1032
1033
1034
any '/ng-templates/(#template).html' => sub {
  my $c = shift;
  my $id = $c->stash('template');
  return $c->render(template => 'ng-templates/'.$id);
};

1035
any '/about' => sub {
fv3rdugo's avatar
fv3rdugo committed
1036
1037
    my $c = shift;

amesones's avatar
amesones committed
1038
    $c->render(template => 'main/about');
fv3rdugo's avatar
fv3rdugo committed
1039
1040
};

1041

1042
1043
1044
any '/requirements' => sub {
    my $c = shift;

amesones's avatar
amesones committed
1045
    $c->render(template => 'main/requirements');
1046
1047
};

fv3rdugo's avatar
fv3rdugo committed
1048
1049
1050
1051
1052
1053
any '/admin/monitoring' => sub {
    my $c = shift;

    $c->render(template => 'main/monitoring');
};

1054
any '/auto_view/(#value)/' => sub {
1055
1056
1057
    my $c = shift;
    my $value = $c->stash('value');
    if ($value =~ /toggle/i) {
1058
        $value = $c->session('auto_view');
1059
1060
1061
1062
1063
1064
        if ($value) {
            $value = 0;
        } else {
            $value