89e2f675ca1612790cb79437a8548d199cb9b978
[osm/NBI.git] / osm_nbi / html_out.py
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 # implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """
15 Contains html text in variables to make and html response
16 """
17
18 import yaml
19 from http import HTTPStatus
20 from html import escape as html_escape
21
22 __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
23
24 html_start = """
25 <!DOCTYPE html>
26 <html>
27 <head>
28 <link href="/osm/static/style.css" rel="stylesheet">
29 <title>Welcome to OSM</title>
30 <link rel="shortcut icon" href="/osm/static/favicon.ico">
31 </head>
32 <body>
33 <div id="osm_topmenu">
34 <div>
35 <a href="https://osm.etsi.org"> <img src="/osm/static/OSM-logo.png" height="42" width="100"
36 style="vertical-align:middle"> </a>
37 <a>( {} )</a>
38 <a href="/osm/pdu/v1/pdu_descriptors">PDUs </a>
39 <a href="/osm/vnfpkgm/v1/vnf_packages">VNFDs </a>
40 <a href="/osm/nsd/v1/ns_descriptors">NSDs </a>
41 <a href="/osm/nslcm/v1/ns_instances">NSs </a>
42 <a href="/osm/nst/v1/netslice_templates">NSTDs </a>
43 <a href="/osm/nsilcm/v1/netslice_instances">NSIs </a>
44 <a href="/osm/admin/v1/users">USERs </a>
45 <a href="/osm/admin/v1/projects">PROJECTs </a>
46 <a href="/osm/admin/v1/tokens">TOKENs </a>
47 <a href="/osm/admin/v1/vim_accounts">VIMs </a>
48 <a href="/osm/admin/v1/wim_accounts">WIMs </a>
49 <a href="/osm/admin/v1/sdns">SDNs </a>
50 <a href="/osm/admin/v1/k8sclusters">K8s_clusters </a>
51 <a href="/osm/admin/v1/k8srepos">K8s_repos </a>
52 <a href="/osm/nslcm/v1/subscriptions">NS_Subs </a>
53 <a href="/osm/admin/v1/tokens?METHOD=DELETE">logout </a>
54 </div>
55 </div>
56 """
57
58 html_body = """
59 <h1>{item}</h1>
60 """
61
62 html_end = """
63 </body>
64 </html>
65 """
66
67 html_body_error = "<h2> Error <pre>{}</pre> </h2>"
68
69
70 html_auth2 = """
71 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
72 <html>
73 <head><META http-equiv="Content-Type" content="text/html; charset=UTF-8">
74 <link href="/osm/static/style.css" rel="stylesheet">
75 <title>OSM Login</title>
76 <link rel="shortcut icon" href="/osm/static/favicon.ico">
77 </head>
78 <body>
79 <div id="osm_header">
80 <div>
81 <a href="https://osm.etsi.org"> <h1><img src="/osm/static/OSM-logo.png" style="vertical-align:middle"></h1> </a>
82 </div>
83 </div>
84 <div id="osm_error_message">
85 <h1>{error}</h1>
86 </div>
87 <div class="gerritBody" id="osm_body">
88 <h1>Sign in to OSM</h1>
89 <form action="/osm/admin/v1/tokens" id="login_form" method="POST">
90 <table style="border: 0;">
91 <tr><th>Username</th><td><input id="f_user" name="username" size="25" tabindex="1" type="text"></td></tr>
92 <tr><th>Password</th><td><input id="f_pass" name="password" size="25" tabindex="2" type="password"></td></tr>
93 <tr><td><input tabindex="3" type="submit" value="Sign In"></td></tr>
94 </table>
95 </form>
96 <div style="clear: both; margin-top: 15px; padding-top: 2px; margin-bottom: 15px;">
97 <div id="osm_footer">
98 <div></div>
99 </div>
100 </div>
101 </div>
102 <script src="/osm/static/login.js"> </script>
103 </body>
104 </html>
105 """
106
107 html_upload_body = """
108 <form action="/osm{}" method="post" enctype="multipart/form-data">
109 <h3> <table style="border: 0;"> <tr>
110 <td> Upload {} descriptor (tar.gz) file: <input type="file" name="descriptor_file"/> </td>
111 <td> <input type="submit" value="Upload"/> </td>
112 </tr> </table> </h3>
113 </form>
114 """
115
116 html_nslcmop_body = """
117 <a href="/osm/nslcm/v1/ns_lcm_op_occs?nsInstanceId={id}">nslcm operations </a>
118 <a href="/osm/nslcm/v1/vnf_instances?nsr-id-ref={id}">VNFRS </a>
119 <form action="/osm/nslcm/v1/ns_instances/{id}/terminate" method="post" enctype="multipart/form-data">
120 <h3> <table style="border: 0;"> <tr>
121 <td> <input type="submit" value="Terminate"/> </td>
122 </tr> </table> </h3>
123 </form>
124 """
125
126 html_nsilcmop_body = """
127 <a href="/osm/nsilcm/v1/nsi_lcm_op_occs?netsliceInstanceId={id}">nsilcm operations </a>
128 <form action="/osm/nsilcm/v1/netslice_instances/{id}/terminate" method="post" enctype="multipart/form-data">
129 <h3> <table style="border: 0;"> <tr>
130 <td> <input type="submit" value="Terminate"/> </td>
131 </tr> </table> </h3>
132 </form>
133 """
134
135 html_vnfpackage_body = (
136 """<a href="/osm/vnfpkgm/v1/vnf_packages/{id}/artifacts">Artifacts </a>"""
137 )
138 html_nspackage_body = (
139 """<a href="/osm/nsd/v1/ns_descriptors/{id}/artifacts">Artifacts </a>"""
140 )
141
142
143 def format(data, request, response, toke_info):
144 """
145 Format a nice html response, depending on the data
146 :param data:
147 :param request: cherrypy request
148 :param response: cherrypy response
149 :return: string with teh html response
150 """
151 response.headers["Content-Type"] = "text/html"
152 if response.status == HTTPStatus.UNAUTHORIZED.value:
153 if response.headers.get("WWW-Authenticate") and request.config.get(
154 "auth.allow_basic_authentication"
155 ):
156 response.headers["WWW-Authenticate"] = (
157 "Basic" + response.headers["WWW-Authenticate"][6:]
158 )
159 return
160 else:
161 return html_auth2.format(error=data)
162 if request.path_info in ("/version", "/system"):
163 return (
164 "<pre>"
165 + yaml.safe_dump(
166 data, explicit_start=False, indent=4, default_flow_style=False
167 )
168 + "</pre>"
169 )
170 body = html_body.format(item=html_escape(request.path_info))
171 if response.status and response.status > 202:
172 # input request.path_info (URL) can contain XSS that are translated into output error detail
173 body += html_body_error.format(
174 html_escape(
175 yaml.safe_dump(
176 data, explicit_start=True, indent=4, default_flow_style=False
177 )
178 )
179 )
180 elif isinstance(data, (list, tuple)):
181 if request.path_info == "/vnfpkgm/v1/vnf_packages":
182 body += html_upload_body.format(request.path_info + "_content", "VNFD")
183 elif request.path_info == "/nsd/v1/ns_descriptors":
184 body += html_upload_body.format(request.path_info + "_content", "NSD")
185 elif request.path_info == "/nst/v1/nst_templates":
186 body += html_upload_body.format(request.path_info + "_content", "NSTD")
187 for k in data:
188 if isinstance(k, dict):
189 data_id = k.pop("_id", None)
190 elif isinstance(k, str):
191 data_id = k
192 body += '<p> <a href="/osm/{url}/{id}">{id}</a>: {t} </p>'.format(
193 url=request.path_info, id=data_id, t=html_escape(str(k))
194 )
195 elif isinstance(data, dict):
196 if "Location" in response.headers:
197 body += '<a href="{}"> show </a>'.format(response.headers["Location"])
198 else:
199 _id = request.path_info[request.path_info.rfind("/") + 1:]
200 body += (
201 '<a href="/osm/{}?METHOD=DELETE"> '
202 '<img src="/osm/static/delete.png" height="25" width="25"> </a>'
203 ).format(
204 request.path_info
205 )
206 if request.path_info.startswith(
207 "/nslcm/v1/ns_instances_content/"
208 ) or request.path_info.startswith("/nslcm/v1/ns_instances/"):
209 body += html_nslcmop_body.format(id=_id)
210 elif request.path_info.startswith(
211 "/nsilcm/v1/netslice_instances_content/"
212 ) or request.path_info.startswith("/nsilcm/v1/netslice_instances/"):
213 body += html_nsilcmop_body.format(id=_id)
214 elif request.path_info.startswith(
215 "/vnfpkgm/v1/vnf_packages/"
216 ) or request.path_info.startswith("/vnfpkgm/v1/vnf_packages_content/"):
217 body += html_vnfpackage_body.format(id=_id)
218 elif request.path_info.startswith(
219 "/nsd/v1/ns_descriptors/"
220 ) or request.path_info.startswith("/nsd/v1/ns_descriptors_content/"):
221 body += html_nspackage_body.format(id=_id)
222 body += (
223 "<pre>"
224 + html_escape(
225 yaml.safe_dump(
226 data, explicit_start=True, indent=4, default_flow_style=False
227 )
228 )
229 + "</pre>"
230 )
231 elif data is None:
232 if request.method == "DELETE" or "METHOD=DELETE" in request.query_string:
233 body += "<pre> deleted </pre>"
234 else:
235 body = html_escape(str(data))
236 user_text = " "
237 if toke_info:
238 if toke_info.get("username"):
239 user_text += "user: {}".format(toke_info.get("username"))
240 if toke_info.get("project_id"):
241 user_text += ", project: {}".format(toke_info.get("project_name"))
242 return html_start.format(user_text) + body + html_end
243 # yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False)
244 # tags=False,
245 # encoding='utf-8', allow_unicode=True)