rvd_front.pl 49.7 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';
12
use Time::Piece;
13
14
#use Mojolicious::Plugin::I18N;

15
use Mojo::Home;
16
#####
17
18
#my $self->plugin('I18N');
#package Ravada::I18N:en;
19
20
#####

21
22
use lib 'lib';

23
use Ravada::Front;
Francesc Guasch's avatar
Francesc Guasch committed
24
use Ravada::Auth;
25
use POSIX qw(locale_h);
Francesc Guasch's avatar
Francesc Guasch committed
26
27

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

Francesc Guasch's avatar
Francesc Guasch committed
29
30
31
my $FILE_CONFIG = "/etc/rvd_front.conf";

my $error_file_duplicated = 0;
32
for my $file ( "/etc/rvd_front.conf" , ($ENV{HOME} or '')."/rvd_front.conf") {
Francesc Guasch's avatar
Francesc Guasch committed
33
    warn "WARNING: Found config file at $file and at $FILE_CONFIG\n"
34
35
        if -e $file && $FILE_CONFIG;
    $FILE_CONFIG = $file if -e $file;
Francesc Guasch's avatar
Francesc Guasch committed
36
    $error_file_duplicated++;
37
}
Francesc Guasch's avatar
Francesc Guasch committed
38
warn "WARNING: using $FILE_CONFIG\n"    if$error_file_duplicated>2;
39
40

my $FILE_CONFIG_RAVADA;
41
for my $file ( "/etc/ravada.conf" , ($ENV{HOME} or '')."/ravada.conf") {
42
43
44
    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
45
}
46

amesones's avatar
amesones committed
47
48
49
my $CONFIG_FRONT = plugin Config => { default => {
                                                hypnotoad => {
                                                pid_file => 'log/rvd_front.pid'
fv3rdugo's avatar
Indent    
fv3rdugo committed
50
51
                                                ,listen => ['http://*:8081']
                                                }
52
                                              ,login_bg_file => '/img/intro-bg.jpg'
Francesc Guasch's avatar
Francesc Guasch committed
53
                                              ,login_header => 'Welcome'
54
                                              ,login_message => ''
55
                                              ,secrets => ['changeme0']
fv3rdugo's avatar
fv3rdugo committed
56
                                              ,login_custom => ''
57
58
                                              ,admin => {
                                                    hide_clones => 15
amesones's avatar
amesones committed
59
                                              }
60
                                              ,config => $FILE_CONFIG_RAVADA
amesones's avatar
amesones committed
61
                                              }
Francesc Guasch's avatar
Francesc Guasch committed
62
                                      ,file => $FILE_CONFIG
63
};
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#####
#####
#####
# 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);
#####
#####
#####
86
plugin I18N => {namespace => 'Ravada::I18N', default => 'en'};
87
plugin 'RenderFile';
Francesc Guasch's avatar
Francesc Guasch committed
88

89
my %config;
90
%config = (config => $CONFIG_FRONT->{config}) if $CONFIG_FRONT->{config};
91
our $RAVADA = Ravada::Front->new(%config);
92

93
our $USER;
Francesc Guasch's avatar
Francesc Guasch committed
94

95
# TODO: get those from the config file
96
our $DOCUMENT_ROOT = "/var/www";
97
98

# session times out in 5 minutes
99
our $SESSION_TIMEOUT = ($CONFIG_FRONT->{session_timeout} or 5 * 60);
100
# session times out in 15 minutes for admin users
101
our $SESSION_TIMEOUT_ADMIN = ($CONFIG_FRONT->{session_timeout_admin} or 15 * 60);
102

Francesc Guasch's avatar
Francesc Guasch committed
103
104
init();
############################################################################3
105

106
107
108
hook before_routes => sub {
  my $c = shift;

Francesc Guasch's avatar
Francesc Guasch committed
109
  $c->stash(version => $RAVADA->version);
110
  my $url = $c->req->url->to_abs->path;
111
  $c->stash(css=>['/css/sb-admin.css']
Francesc Guasch's avatar
Francesc Guasch committed
112
113
            ,js=>[
                '/js/ravada.js'
114
115
116
                ]
            ,csssnippets => []
            ,navbar_custom => 0
Francesc Guasch's avatar
Francesc Guasch committed
117
118
119
120
            ,url => undef
            ,_logged_in => undef
            ,_anonymous => undef
            ,_user => undef
121
            );
122
123

  return access_denied($c)
124
    if $url =~ /(screenshot|\.json)/
125
126
127
    && !_logged_in($c);

  return login($c)
Francesc Guasch's avatar
Francesc Guasch committed
128
    if
Francesc Guasch's avatar
Francesc Guasch committed
129
        $url !~ m{^/(anonymous|login|logout|requirements|robots.txt)}
Francesc Guasch's avatar
Francesc Guasch committed
130
        && $url !~ m{^/(css|font|img|js)}
131
132
        && !_logged_in($c);

133
    _logged_in($c)  if $url =~ m{^/requirements};
134
135
136
137
138
};


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

Francesc Guasch's avatar
Francesc Guasch committed
139
140
141
142
143
144
any '/robots.txt' => sub {
    my $c = shift;
    warn "robots";
    return $c->render(text => "User-agent: *\nDisallow: /\n", format => 'text');
};

145
any '/' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
146
    my $c = shift;
147
    return quick_start($c);
Francesc Guasch's avatar
Francesc Guasch committed
148
149
};

Francesc Guasch's avatar
Francesc Guasch committed
150
151
any '/index.html' => sub {
    my $c = shift;
152
    return quick_start($c);
Francesc Guasch's avatar
Francesc Guasch committed
153
154
};

155
156
any '/login' => sub {
    my $c = shift;
157
    return login($c);
158
159
};

Francesc Guasch's avatar
Francesc Guasch committed
160
161
162
163
164
165
166
167
168
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
169
170
171
172
173
    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
174
175
};

Francesc Guasch's avatar
Francesc Guasch committed
176
177
any '/logout' => sub {
    my $c = shift;
178
    logout($c);
Francesc Guasch's avatar
Francesc Guasch committed
179
180
181
    $c->redirect_to('/');
};

182
get '/anonymous' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
183
    my $c = shift;
184
#    $c->render(template => 'bases', base => list_bases());
185
    $USER = _anonymous_user($c);
186
    return list_bases_anonymous($c);
Francesc Guasch's avatar
Francesc Guasch committed
187
188
};

189
get '/anonymous_logout.html' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
190
    my $c = shift;
191
192
    $c->session('anonymous_user' => '');
    return $c->redirect_to('/');
Francesc Guasch's avatar
Francesc Guasch committed
193
194
};

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

198
    $c->stash(_anonymous => 1 , _logged_in => 0);
199
    _init_error($c);
200
    my $base_id = $c->stash('base_id');
201
202
    my $base = $RAVADA->search_domain_by_id($base_id);

203
    $USER = _anonymous_user($c);
204
    return quick_start_domain($c,$base->id, $USER->name);
Francesc Guasch's avatar
Francesc Guasch committed
205
206
};

amesones's avatar
amesones committed
207
208
any '/admin' => sub {
  my $c = shift;
209
210
211
212
  $c->redirect_to("/admin/machines")
};
any '/admin/(#type)' => sub {
  my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
213

214
215
216
  return admin($c)  if $c->stash('type') eq 'machines'
                        && $USER->is_operator;

217
218
  return access_denied($c)    if !$USER->is_operator;

amesones's avatar
amesones committed
219
  return admin($c);
Francesc Guasch's avatar
Francesc Guasch committed
220
221
};

222
any '/new_machine' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
223
    my $c = shift;
224
    return access_denied($c)    if !$USER->can_create_domain;
225
    return new_machine($c);
Francesc Guasch's avatar
Francesc Guasch committed
226
227
};

228
get '/domain/new.html' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
229
230
    my $c = shift;

231
232
    return access_denied($c) if !_logged_in($c) || !$USER->is_admin();
    $c->stash(error => []);
amesones's avatar
amesones committed
233
    return $c->render(template => "main/new_machine");
Francesc Guasch's avatar
Francesc Guasch committed
234
235
236

};

237
238
get '/list_vm_types.json' => sub {
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
239
    $c->render(json => $RAVADA->list_vm_types);
240
241
};

242
243
get '/list_bases.json' => sub {
    my $c = shift;
244
245
246
247
248
249
250
251
252
253
254

    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]);

255
256
257
258
};

get '/list_images.json' => sub {
    my $c = shift;
259
260
261
262

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

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

265
get '/iso_file.json' => sub {
joelalju's avatar
joelalju committed
266
    my $c = shift;
267
268
269
    my @isos =('<NONE>');
    push @isos,(@{$RAVADA->iso_file});
    $c->render(json => \@isos);
joelalju's avatar
joelalju committed
270
271
};

272
get '/list_machines.json' => sub {
273
    my $c = shift;
274

275
    return access_denied($c) if !_logged_in($c) || !$USER->is_admin();
Francesc Guasch's avatar
Francesc Guasch committed
276
    $c->render(json => $RAVADA->list_domains);
277
};
Francesc Guasch's avatar
Francesc Guasch committed
278

279
280
281
282
283
284
285
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
286
get '/list_lxc_templates.json' => sub {
fv3rdugo's avatar
fv3rdugo committed
287
    my $c = shift;
Francesc Guasch's avatar
Francesc Guasch committed
288
    $c->render(json => $RAVADA->list_lxc_templates);
fv3rdugo's avatar
fv3rdugo committed
289
290
};

joansp's avatar
udpate    
joansp committed
291
292
293
294
295
get '/pingbackend.json' => sub {

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

297
298
# machine commands

299
get '/machine/info/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
300
    my $c = shift;
301
    my $id = $c->stash('id');
Francesc Guasch's avatar
Francesc Guasch committed
302
    die "No id " if !$id;
303

joelalju's avatar
joelalju committed
304
305
306
307
308
309
    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;

Francesc Guasch's avatar
Francesc Guasch committed
310
    $c->render(json => $RAVADA->domain_info(id => $id));
Francesc Guasch's avatar
Francesc Guasch committed
311
312
};

313
any '/machine/settings/(:id).(:type)' => sub {
314
315
316
   	 my $c = shift;
	 return access_denied($c)     if !$USER->can_change_settings();
	 return settings_machine($c);
Francesc Guasch's avatar
Francesc Guasch committed
317
318
};

319
any '/machine/manage/(:id).(:type)' => sub {
320
    my $c = shift;
joelalju's avatar
joelalju committed
321
322
323
324
325
326
327

    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;

328
329
330
    return manage_machine($c);
};

331
get '/machine/view/(:id).(:type)' => sub {
332
    my $c = shift;
333
334
    my $id = $c->stash('id');
    my $type = $c->stash('type');
Francesc Guasch's avatar
Francesc Guasch committed
335

joelalju's avatar
joelalju committed
336
337
338
339
340
341
    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;

342
343
344
    return view_machine($c);
};

345
get '/machine/clone/(:id).(:type)' => sub {
346
347
    my $c = shift;      
    return access_denied($c)	     if !$USER->can_clone();
348
349
350
    return clone_machine($c);
};

351
get '/machine/shutdown/(:id).(:type)' => sub {
352
        my $c = shift;
353
	return access_denied($c)        if !$USER ->can_shutdown_all();
354
355
        return shutdown_machine($c);
};
Francesc Guasch's avatar
Francesc Guasch committed
356

357
get '/machine/shutdown/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
358
        my $c = shift;
359
	return access_denied($c)        if !$USER ->can_shutdown_all();
Francesc Guasch's avatar
Francesc Guasch committed
360
361
362
363
        return shutdown_machine($c);
};


364
any '/machine/remove/(:id).(:type)' => sub {
joansp's avatar
joansp committed
365
        my $c = shift;
366
	return access_denied($c)       if !$USER -> can_remove();
joansp's avatar
joansp committed
367
368
        return remove_machine($c);
};
369
370
371

any '/machine/remove_clones/(:id).(:type)' => sub {
        my $c = shift;
Kimia Mirehbar's avatar
Kimia Mirehbar committed
372
	return access_denied($c)	if !$USER ->can_remove_clone();
373
374
375
        return remove_clones($c);
};

376
get '/machine/prepare/(:id).(:type)' => sub {
Francesc Guasch's avatar
Francesc Guasch committed
377
378
379
380
        my $c = shift;
        return prepare_machine($c);
};

381
get '/machine/remove_b/(:id).(:type)' => sub {
joansp's avatar
joansp committed
382
383
384
385
        my $c = shift;
        return remove_base($c);
};

386
get '/machine/remove_base/(:id).(:type)' => sub {
387
388
389
390
    my $c = shift;
    return remove_base($c);
};

391
get '/machine/screenshot/(:id).(:type)' => sub {
392
        my $c = shift;
393
        return access_denied($c)   if !$USER->can_screenshot();
394
395
396
        return screenshot_machine($c);
};

397
398
399
400
401
402
get '/machine/copy_screenshot/(:id).(:type)' => sub {
        my $c = shift;
        return access_denied($c) if !$USER->is_admin();
        return copy_screenshot($c);
};

403
get '/machine/pause/(:id).(:type)' => sub {
joansp's avatar
joansp committed
404
405
406
407
        my $c = shift;
        return pause_machine($c);
};

408
409
get '/machine/hybernate/(:id).(:type)' => sub {
        my $c = shift;
410
	return access_denied($c)   if !$USER ->can_hibernate_all();
411
412
413
        return hybernate_machine($c);
};

414
get '/machine/resume/(:id).(:type)' => sub {
joansp's avatar
joansp committed
415
416
417
418
        my $c = shift;
        return resume_machine($c);
};

419
get '/machine/start/(:id).(:type)' => sub {
joansp's avatar
joansp committed
420
421
422
        my $c = shift;
        return start_machine($c);
};
joansp's avatar
joansp committed
423

424
get '/machine/exists/#name' => sub {
425
    my $c = shift;
426
    my $name = $c->stash('name');
427
428
429
430
431
432
    #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
433

434
435
get '/machine/rename/#id' => sub {
    my $c = shift;
436
    return access_denied($c)       if !$USER -> can_rename();
437
438
439
440
    return rename_machine($c);
};

get '/machine/rename/#id/#value' => sub {
441
442
443
444
    my $c = shift;
    return rename_machine($c);
};

445
446
any '/machine/copy' => sub {
    my $c = shift;
447
    return access_denied($c)    if !$USER -> can_clone_all();
448
449
450
    return copy_machine($c);
};

451
452
453
454
455
456
get '/machine/public/#id' => sub {
    my $c = shift;
    return machine_is_public($c);
};

get '/machine/public/#id/#value' => sub {
457
458
459
460
    my $c = shift;
    return machine_is_public($c);
};

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
get '/machine/display/#id' => 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(
        "attachment;filename=".$domain->id.".vv");

    return $c->render(data => $domain->display_file($USER));
};

480
481
# Users ##########################################################3

Laura Figuerola's avatar
Laura Figuerola committed
482
483
##add user

484
any '/users/register' => sub {
485

Laura Figuerola's avatar
Laura Figuerola committed
486
487
488
489
       my $c = shift;
       return register($c);
};

Francesc Guasch's avatar
Francesc Guasch committed
490
491
492
493
494
495
496
497
498
any '/admin/user/(:id).(:type)' => sub {
    my $c = shift;
    return access_denied($c) if !$USER->can_manage_users();

    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
499
500
501
502
503
    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'));
    }
504
505
506
507
508
509
510
511
512
513
514
    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) {
515
            if ( $grant{$perm} ) {
516
517
518
519
520
521
                $USER->grant($user, $perm);
            } else {
                $USER->revoke($user, $perm);
            }
        }
    }
Francesc Guasch's avatar
Francesc Guasch committed
522
523
524
    $c->stash(user => $user);
    return $c->render(template => 'main/manage_user');
};
Laura Figuerola's avatar
Laura Figuerola committed
525

526
##############################################
Laura Figuerola's avatar
Laura Figuerola committed
527

528

529
get '/request/(:id).(:type)' => sub {
530
    my $c = shift;
531
    my $id = $c->stash('id');
532
533
534
535

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

Francesc Guasch's avatar
Francesc Guasch committed
536
537
538
539
540
get '/requests.json' => sub {
    my $c = shift;
    return list_requests($c);
};

joansp's avatar
joansp committed
541
get '/messages.json' => sub {
joansp's avatar
joansp committed
542
543
544
545
546
547
    my $c = shift;


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

548
get '/unshown_messages.json' => sub {
549
550
551
552
    my $c = shift;

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

553
    return $c->render( json => [$USER->unshown_messages()] );
Antonio's avatar
Antonio committed
554
555
556
};


joansp's avatar
joansp committed
557
558
559
get '/messages/read/all.html' => sub {
    my $c = shift;
    $USER->mark_all_messages_read;
560
    return $c->render(inline => "1");
561
562
};

563
get '/messages/read/(#id).json' => sub {
564
    my $c = shift;
565
    my $id = $c->stash('id');
joansp's avatar
joansp committed
566
    $USER->mark_message_read($id);
567
    return $c->render(inline => "1");
joansp's avatar
joansp committed
568
};
569

amesones's avatar
amesones committed
570
get '/messages/unread/(#id).json' => sub {
joansp's avatar
joansp committed
571
    my $c = shift;
572
    my $id = $c->stash('id');
joansp's avatar
joansp committed
573
    $USER->mark_message_unread($id);
574
    return $c->render(inline => "1");
joansp's avatar
joansp committed
575
576
};

577
get '/messages/view/(#id).html' => sub {
578
    my $c = shift;
579
580
    my $id = $c->stash('id');
    return $c->render( json => $USER->show_message($id) );
581
582
};

583
584
585
586
587
588
any '/ng-templates/(#template).html' => sub {
  my $c = shift;
  my $id = $c->stash('template');
  return $c->render(template => 'ng-templates/'.$id);
};

589
any '/about' => sub {
fv3rdugo's avatar
fv3rdugo committed
590
591
    my $c = shift;

amesones's avatar
amesones committed
592
    $c->render(template => 'main/about');
fv3rdugo's avatar
fv3rdugo committed
593
594
};

595

596
597
598
any '/requirements' => sub {
    my $c = shift;

amesones's avatar
amesones committed
599
    $c->render(template => 'main/requirements');
600
601
};

602
603
604
605
606
607

any '/settings' => sub {
    my $c = shift;

    $c->stash(version => $RAVADA->version );

amesones's avatar
amesones committed
608
    $c->render(template => 'main/settings');
609
610
};

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
any '/auto_start/(#value)/' => sub {
    my $c = shift;
    my $value = $c->stash('value');
    if ($value =~ /toggle/i) {
        $value = $c->session('auto_start');
        if ($value) {
            $value = 0;
        } else {
            $value = 1;
        }
    }
    $c->session('auto_start' => $value);
    return $c->render(json => {auto_start => $c->session('auto_start') });
};

get '/auto_start' => sub {
    my $c = shift;
    return $c->render(json => {auto_start => $c->session('auto_start') });
};

631
632
633
###################################################

## user_settings
634

635
636
637
638
any '/user_settings' => sub {
    my $c = shift;
    user_settings($c);
};
639

640
641
sub user_settings {
    my $c = shift;
joelalju's avatar
joelalju committed
642
643
    my $changed_lang;
    my $changed_pass;
644
    if ($c->req->method('POST')) {
645
646
647
        $USER->language($c->param('tongue'));
        $changed_lang = $c->param('tongue');
        _logged_in($c);
648
    }
649
    $c->param('tongue' => $USER->language);
joelalju's avatar
joelalju committed
650
    my @errors;
651
    if ($c->param('button_click')) {
652
        if (($c->param('password') eq "") || ($c->param('conf_password') eq "") || ($c->param('current_password') eq "")) {
653
654
655
            push @errors,("Some of the password's fields are empty");
        } 
        else {
656
657
658
659
660
661
662
663
            my $comp_password = $USER->compare_password($c->param('current_password'));
            if ($comp_password) {
                if ($c->param('password') eq $c->param('conf_password')) {
                    eval {
                        $USER->change_password($c->param('password'));
                        _logged_in($c);
                    };
                    if ($@ =~ /Password too small/) {
Joel Alarcón's avatar
Joel Alarcón committed
664
                        push @errors,("New Password is too small");
665
666
667
668
                    }
                    else {
                        $changed_pass = 1;
                    };
669
670
                }
                else {
671
672
673
674
                    push @errors,("Password fields aren't equal");
                }
            }
            else {
Joel Alarcón's avatar
Joel Alarcón committed
675
                push @errors, ("Invalid Current Password");
676
            }
677
        }
678
    }
joelalju's avatar
joelalju committed
679
680
    $c->render(template => 'bootstrap/user_settings', changed_lang=> $changed_lang, changed_pass => $changed_pass
      ,errors =>\@errors);
681
682
};

683
684
685
686
687
get '/img/screenshots/:file' => sub {
    my $c = shift;

    my $file = $c->param('file');
    my $path = $DOCUMENT_ROOT."/".$c->req->url->to_abs->path;
688

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
    my ($id_domain ) =$path =~ m{/(\d+)\..+$};
    if (!$id_domain) {
        warn"ERROR : no id domain in $path";
        return $c->reply->not_found;
    }
    if (!$USER->is_admin) {
        my $domain = $RAVADA->search_domain_by_id($id_domain);
        return $c->reply->not_found if !$domain;
        unless ($domain->is_base && $domain->is_public) {
            return access_denied($c) if $USER->id != $domain->id_owner;
        }
    }
    return $c->reply->not_found  if ! -e $path;
    return $c->render_file(
                      filepath => $path
        ,'content_disposition' => 'inline'
    );
};

708
709
get '/iso/download/(#id).json' => sub {
    my $c = shift;
710
711

    return access_denied($c)    if !$USER->is_admin;
712
713
714
715
    my $id = $c->stash('id');

    my $req = Ravada::Request->download(
        id_iso => $id
716
        ,uid => $USER->id
717
718
719
720
    );

    return $c->render(json => {request => $req->id});
};
721
722
###################################################

723
724
725
726
727
728
729
730
731
sub _init_error {
    my $c = shift;
    $c->stash(error_title => '');
    $c->stash(error => []);
    $c->stash(link => '');
    $c->stash(link_msg => '');

}

Francesc Guasch's avatar
Francesc Guasch committed
732
733
sub _logged_in {
    my $c = shift;
734

735
    confess "missing \$c" if !defined $c;
736
737
    $USER = undef;

738
    _init_error($c);
739
    $c->stash(_logged_in => undef , _user => undef, _anonymous => 1);
740
    my $login = $c->session('login');
741
742
743
744
    if ($login) {
        $USER = Ravada::Auth::SQL->new(name => $login);
        #Mojolicious::Plugin::I18N::
        $c->languages($USER->language);
745

746
747
748
        $c->stash(_logged_in => $login );
        $c->stash(_user => $USER);
        $c->stash(_anonymous => !$USER);
749

750
    }
751
    $c->stash(url => undef);
752
753

    return $USER;
Francesc Guasch's avatar
Francesc Guasch committed
754
755
}

756

757
758
759
sub login {
    my $c = shift;

760
    $c->session(login => undef);
761
762
763

    my $login = $c->param('login');
    my $password = $c->param('password');
764
    my $form_hash = $c->param('login_hash');
765
    my $url = ($c->param('url') or $c->req->url->to_abs->path);
766
767
    $url = '/' if $url =~ m{^/login};

768
    my @error =();
769
770
771

    # TODO: improve this hash
    my ($time) = time =~ m{(.*)...$};
772
    my $login_hash1 = $time.($CONFIG_FRONT->{secrets}->[0] or '');
773
774
775

    # let login varm be valid for 60 seconds
    ($time) = (time-60) =~ m{(.*)...$};
776
    my $login_hash2 = $time.($CONFIG_FRONT->{secrets}->[0] or '');
777

778
    if (defined $login || defined $password || $c->param('submit')) {
779
780
        push @error,("Empty login name")  if !length $login;
        push @error,("Empty password")  if !length $password;
781
782
783
        push @error,("Session timeout")
            if $form_hash ne sha256_hex($login_hash1)
                && $form_hash ne sha256_hex($login_hash2);
784
785
    }

786
    if ( !@error && defined $login && defined $password) {
787
788
        my $auth_ok;
        eval { $auth_ok = Ravada::Auth::login($login, $password)};
789
        if ( $auth_ok && !$@) {
790
            $c->session('login' => $login);
791
792
793
794
            my $expiration = $SESSION_TIMEOUT;
            $expiration = $SESSION_TIMEOUT_ADMIN    if $auth_ok->is_admin;

            $c->session(expiration => $expiration);
795
            return $c->redirect_to($url);
796
797
798
799
        } else {
            push @error,("Access denied");
        }
    }
800

801
802
803
804
    my @css_snippets = ["\t.intro {\n\t\tbackground:"
                    ." url($CONFIG_FRONT->{login_bg_file})"
                    ." no-repeat bottom center scroll;\n\t}"];

805
    sleep 5 if scalar(@error);
806
    $c->render(
fv3rdugo's avatar
fv3rdugo committed
807
                    template => ($CONFIG_FRONT->{login_custom} or 'main/start')
amesones's avatar
amesones committed
808
                        ,css => ['/css/main.css']
809
                        ,csssnippets => @css_snippets
810
                        ,js => ['/js/main.js']
amesones's avatar
amesones committed
811
                        ,navbar_custom => 1
joansp's avatar
joansp committed
812
                      ,login => $login
813
                      ,login_hash => sha256_hex($login_hash1)
814
                      ,error => \@error
815
816
                      ,login_header => $CONFIG_FRONT->{login_header}
                      ,login_message => $CONFIG_FRONT->{login_message}
817
818
819
820
    );

}

821
822
823
824
825
826
827
828
829
sub logout {
    my $c = shift;

    $USER = undef;
    $c->session(expires => 1);
    $c->session(login => undef);

}

Francesc Guasch's avatar
Francesc Guasch committed
830
831
832
833
834
sub quick_start {
    my $c = shift;

    _logged_in($c);

835
836
837
838
839
    my $login = $c->param('login');
    my $password = $c->param('password');
    my $id_base = $c->param('id_base');

    my @error =();
Francesc Guasch's avatar
Francesc Guasch committed
840
    if ($c->param('submit')) {
841
842
843
844
845
        push @error,("Empty login name")  if !length $login;
        push @error,("Empty password")  if !length $password;
    }

    if ( $login && $password ) {
846
847
848
        my $log_ok;
        eval { $log_ok = Ravada::Auth::login($login, $password) };
        if ($log_ok) {
Francesc Guasch's avatar
Francesc Guasch committed
849
850
851
            $c->session('login' => $login);
        } else {
            push @error,("Access denied");
852
853
        }
    }
Francesc Guasch's avatar
Francesc Guasch committed
854
855
856
857
858
    if ( $c->param('submit') && _logged_in($c) && defined $id_base ) {

        return quick_start_domain($c, $id_base, ($login or $c->session('login')));

    }
Francesc Guasch's avatar
Francesc Guasch committed
859

860
861
862
863
864
865
    return render_machines_user($c);

}

sub render_machines_user {
    my $c = shift;
Antonio's avatar
Antonio committed
866
    return $c->render(
amesones's avatar
amesones committed
867
        template => 'main/list_bases2'
868
869
        ,machines => $RAVADA->list_machines_user($USER)
        ,user => $USER
Francesc Guasch's avatar
Francesc Guasch committed
870
871
    );
}
872

Francesc Guasch's avatar
Francesc Guasch committed
873
sub create_domain {
874
    my ($c, $id_base, $domain_name, $ram, $disk) = @_;
Francesc Guasch's avatar
Francesc Guasch committed
875
876
    return $c->redirect_to('/login') if !$USER;
    my $base = $RAVADA->search_domain_by_id($id_base) or die "I can't find base $id_base";
877
    my $domain = provision($c,  $id_base,  $domain_name, $ram, $disk);
Francesc Guasch's avatar
Francesc Guasch committed
878
879
880
881
882
    return show_failure($c, $domain_name) if !$domain;
    return show_link($c,$domain);

}

Francesc Guasch's avatar
Francesc Guasch committed
883
884
sub quick_start_domain {
    my ($c, $id_base, $name) = @_;
885

886
887
    return $c->redirect_to('/login') if !$USER;

888
    confess "Missing id_base" if !defined $id_base;
889
    $name = $c->session('login')    if !$name;
890

Francesc Guasch's avatar
Francesc Guasch committed
891
892
    my $base = $RAVADA->search_domain_by_id($id_base) or die "I can't find base $id_base";

893
    my $domain_name = $base->name."-".$name;
Francesc Guasch's avatar
Francesc Guasch committed
894
895

    $domain_name =~ tr/[\.]/[\-]/;
896
    my $domain = $RAVADA->search_clone(id_base => $base->id, id_owner => $USER->id);
Francesc Guasch's avatar
Francesc Guasch committed
897

898
    $domain = provision($c,  $id_base,  $domain_name)
899
        if !$domain || $domain->is_base;
Francesc Guasch's avatar
Francesc Guasch committed
900

901
    return show_failure($c, $domain_name) if !$domain;
902

Francesc Guasch's avatar
Francesc Guasch committed
903
904
905
906
    return show_link($c,$domain);

}

Francesc Guasch's avatar
Francesc Guasch committed
907
908
909
sub show_failure {
    my $c = shift;
    my $name = shift;
amesones's avatar
amesones committed
910
    $c->render(template => 'main/fail', name => $name);
Francesc Guasch's avatar
Francesc Guasch committed
911
912
}

Francesc Guasch's avatar
Francesc Guasch committed
913
914
915

#######################################################

amesones's avatar
amesones committed
916
sub admin {
Francesc Guasch's avatar
Francesc Guasch committed
917
    my $c = shift;
918
    my $page = $c->stash('type');
joansp's avatar
joansp committed
919
    my @error = ();
joansp's avatar
joansp committed
920

921
922
    push @{$c->stash->{css}}, '/css/admin.css';
    push @{$c->stash->{js}}, '/js/admin.js';
923
924
925
926
927
928
929
930

    if ($page eq 'users') {
        $c->stash(list_users => []);
        $c->stash(name => $c->param('name' or ''));
        if ( $c->param('name') ) {
            $c->stash(list_users => $RAVADA->list_users($c->param('name') ))
        }
    }
931
932
933
934
935
936
937
938
939
    if ($page eq 'machines') {
        $c->stash(hide_clones => 0 );

        my $list_domains = $RAVADA->list_domains();

        $c->stash(hide_clones => 1 )
            if scalar @$list_domains
                        > $CONFIG_FRONT->{admin}->{hide_clones};

940
941
942
943
944
        # count clones from list_domains grepping those that have id_base
        $c->stash(n_clones => scalar(grep { $_->{id_base} } @$list_domains) );

        # if we find no clones do not hide them. They may be created later
        $c->stash(hide_clones => 0 ) if !$c->stash('n_clones');
945
    }
946
    $c->render(template => 'main/admin_'.$page);
947

948
};
949

950
sub new_machine {
951
    my $c = shift;
952
    my @error