]>
git.proxmox.com Git - pve-http-server.git/blob - src/PVE/APIServer/Formatter/HTML.pm
743d0ad8165a16612c04cf27c3e7d95efb2590f5
1 package PVE
::APIServer
::Formatter
::HTML
;
6 use PVE
::APIServer
::Formatter
;
11 use PVE
::APIServer
::Formatter
::Bootstrap
;
12 use PVE
::APIServer
::Formatter
::Standard
;
14 my $portal_format = 'html';
15 my $portal_ct = 'text/html;charset=UTF-8';
17 my $get_portal_base_url = sub {
19 return "$config->{base_uri}/$portal_format";
22 my $get_portal_login_url = sub {
24 return "$config->{base_uri}/$portal_format/access/ticket";
28 my ($doc, $html, $config) = @_;
36 href
=> $get_portal_login_url->($config),
37 onClick
=> "PVE.delete_auth_cookie();",
41 my $base_url = $get_portal_base_url->($config);
44 class => "navbar navbar-inverse navbar-fixed-top",
45 role => "navigation", cn
=> {
46 class => "container", cn
=> [
48 class => "navbar-header", cn
=> [
52 class => "navbar-toggle",
53 'data-toggle' => "collapse",
54 'data-target' => ".navbar-collapse",
56 { tag
=> 'span', class => 'sr-only', text
=> "Toggle navigation" },
57 { tag
=> 'span', class => 'icon-bar' },
58 { tag
=> 'span', class => 'icon-bar' },
59 { tag
=> 'span', class => 'icon-bar' },
64 class => "navbar-brand",
66 text
=> $config->{title
},
71 class => "collapse navbar-collapse",
74 class => "nav navbar-nav",
82 my @pcomp = split('/', $doc->{url
});
85 shift @pcomp; # $format
88 push @$items, { tag
=> 'li', cn
=> {
93 foreach my $comp (@pcomp) {
95 push @$items, { tag
=> 'li', cn
=> {
101 my $breadcrumbs = $doc->el(tag
=> 'ol', class => 'breadcrumb container', cn
=> $items);
103 return $doc->body($nav . $breadcrumbs . $html);
106 my $login_form = sub {
107 my ($config, $doc, $param, $errmsg) = @_;
109 $param = {} if !$param;
111 my $username = $param->{username
} || '';
112 my $password = $param->{password
} || '';
117 text
=> "Please sign in",
122 class => 'form-control',
125 placeholder
=> "Enter user name",
132 class => 'form-control',
135 placeholder
=> 'Password',
142 $html .= $doc->alert(text
=> $errmsg) if ($errmsg);
145 class => 'container',
150 action
=> $get_portal_login_url->($config),
153 class => 'form-group',
159 class => 'btn btn-lg btn-primary btn-block',
168 PVE
::APIServer
::Formatter
::register_login_formatter
($portal_format, sub {
169 my ($path, $auth, $config) = @_;
171 my $headers = HTTP
::Headers-
>new(Location
=> $get_portal_login_url->($config));
172 return HTTP
::Response-
>new(301, "Moved", $headers);
175 PVE
::APIServer
::Formatter
::register_formatter
($portal_format, sub {
176 my ($res, $data, $param, $path, $auth, $config) = @_;
179 PVE
::APIServer
::Formatter
::Standard
::prepare_response_data
($portal_format, $res);
180 $data = $res->{data
};
183 my $doc = PVE
::APIServer
::Formatter
::Bootstrap-
>new($res, $path, $auth, $config);
185 if (!HTTP
::Status
::is_success
($res->{status
})) {
186 $html .= $doc->alert(text
=> "Error $res->{status}: $res->{message}");
191 if (my $info = $res->{info
}) {
192 $html .= $doc->el(tag
=> 'h3', text
=> 'Description');
193 $html .= $doc->el(tag
=> 'p', text
=> $info->{description
});
195 $lnk = PVE
::JSONSchema
::method_get_child_link
($info);
198 if ($lnk && $data && $data->{data
} && HTTP
::Status
::is_success
($res->{status
})) {
200 my $href = $lnk->{href
};
201 if ($href =~ m/^\{(\S+)\}$/) {
206 $path =~ s/\/+$//; # remove trailing slash
208 foreach my $elem (sort {$a->{$prop} cmp $b->{$prop}} @{$data->{data
}}) {
211 if (defined(my $value = $elem->{$prop})) {
212 my $tv = to_json
($elem, {pretty
=> 1, allow_nonref
=> 1, canonical
=> 1});
216 class => 'list-group-item',
217 href
=> "$path/$value",
221 class => 'list-group-item-heading',
226 class => 'list-group-item',
234 $html .= $doc->el(class => 'list-group', cn
=> $items);
238 my $json = to_json
($data, {allow_nonref
=> 1, pretty
=> 1, canonical
=> 1});
239 $html .= $doc->el(tag
=> 'pre', text
=> $json);
244 my $json = to_json
($data, {allow_nonref
=> 1, pretty
=> 1, canonical
=> 1});
245 $html .= $doc->el(tag
=> 'pre', text
=> $json);
248 $html = $doc->el(class => 'container', html
=> $html);
250 my $raw = render_page
($doc, $html, $config);
251 return ($raw, $portal_ct);
254 PVE
::APIServer
::Formatter
::register_page_formatter
(
255 'format' => $portal_format,
257 path
=> "/access/ticket",
259 my ($res, $data, $param, $path, $auth, $config) = @_;
261 my $doc = PVE
::APIServer
::Formatter
::Bootstrap-
>new($res, $path, $auth, $config);
263 my $html = $login_form->($config, $doc);
265 my $raw = render_page
($doc, $html, $config);
266 return ($raw, $portal_ct);
269 PVE
::APIServer
::Formatter
::register_page_formatter
(
270 'format' => $portal_format,
272 path
=> "/access/ticket",
274 my ($res, $data, $param, $path, $auth, $config) = @_;
276 if (HTTP
::Status
::is_success
($res->{status
})) {
277 my $cookie = PVE
::APIServer
::Formatter
::create_auth_cookie
(
278 $data->{ticket
}, $config->{cookie_name
});
280 my $headers = HTTP
::Headers-
>new(Location
=> $get_portal_base_url->($config),
281 'Set-Cookie' => $cookie);
282 return HTTP
::Response-
>new(301, "Moved", $headers);
285 # Note: HTTP server redirects to 'GET /access/ticket', so below
286 # output is not really visible.
288 my $doc = PVE
::APIServer
::Formatter
::Bootstrap-
>new($res, $path, $auth, $config);
290 my $html = $login_form->($config, $doc);
292 my $raw = render_page
($doc, $html, $config);
293 return ($raw, $portal_ct);