| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| # implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """ |
| Contains html text in variables to make and html response |
| """ |
| |
| import yaml |
| from http import HTTPStatus |
| from html import escape as html_escape |
| |
| __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>" |
| |
| html_start = """ |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <link href="/osm/static/style.css" rel="stylesheet"> |
| <title>Welcome to OSM</title> |
| <link rel="shortcut icon" href="/osm/static/favicon.ico"> |
| </head> |
| <body> |
| <div id="osm_topmenu"> |
| <div> |
| <a href="https://osm.etsi.org"> <img src="/osm/static/OSM-logo.png" height="42" width="100" |
| style="vertical-align:middle"> </a> |
| <a>( {} )</a> |
| <a href="/osm/pdu/v1/pdu_descriptors">PDUs </a> |
| <a href="/osm/vnfpkgm/v1/vnf_packages">VNFDs </a> |
| <a href="/osm/nsd/v1/ns_descriptors">NSDs </a> |
| <a href="/osm/nslcm/v1/ns_instances">NSs </a> |
| <a href="/osm/nst/v1/netslice_templates">NSTDs </a> |
| <a href="/osm/nsilcm/v1/netslice_instances">NSIs </a> |
| <a href="/osm/admin/v1/users">USERs </a> |
| <a href="/osm/admin/v1/projects">PROJECTs </a> |
| <a href="/osm/admin/v1/tokens">TOKENs </a> |
| <a href="/osm/admin/v1/vim_accounts">VIMs </a> |
| <a href="/osm/admin/v1/wim_accounts">WIMs </a> |
| <a href="/osm/admin/v1/sdns">SDNs </a> |
| <a href="/osm/admin/v1/k8sclusters">K8s_clusters </a> |
| <a href="/osm/admin/v1/k8srepos">K8s_repos </a> |
| <a href="/osm/nslcm/v1/subscriptions">NS_Subs </a> |
| <a href="/osm/admin/v1/tokens?METHOD=DELETE">logout </a> |
| </div> |
| </div> |
| """ |
| |
| html_body = """ |
| <h1>{item}</h1> |
| """ |
| |
| html_end = """ |
| </body> |
| </html> |
| """ |
| |
| html_body_error = "<h2> Error <pre>{}</pre> </h2>" |
| |
| |
| html_auth2 = """ |
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> |
| <html> |
| <head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <link href="/osm/static/style.css" rel="stylesheet"> |
| <title>OSM Login</title> |
| <link rel="shortcut icon" href="/osm/static/favicon.ico"> |
| </head> |
| <body> |
| <div id="osm_header"> |
| <div> |
| <a href="https://osm.etsi.org"> <h1><img src="/osm/static/OSM-logo.png" style="vertical-align:middle"></h1> </a> |
| </div> |
| </div> |
| <div id="osm_error_message"> |
| <h1>{error}</h1> |
| </div> |
| <div class="gerritBody" id="osm_body"> |
| <h1>Sign in to OSM</h1> |
| <form action="/osm/admin/v1/tokens" id="login_form" method="POST"> |
| <table style="border: 0;"> |
| <tr><th>Username</th><td><input id="f_user" name="username" size="25" tabindex="1" type="text"></td></tr> |
| <tr><th>Password</th><td><input id="f_pass" name="password" size="25" tabindex="2" type="password"></td></tr> |
| <tr><td><input tabindex="3" type="submit" value="Sign In"></td></tr> |
| </table> |
| </form> |
| <div style="clear: both; margin-top: 15px; padding-top: 2px; margin-bottom: 15px;"> |
| <div id="osm_footer"> |
| <div></div> |
| </div> |
| </div> |
| </div> |
| <script src="/osm/static/login.js"> </script> |
| </body> |
| </html> |
| """ |
| |
| html_upload_body = """ |
| <form action="/osm{}" method="post" enctype="multipart/form-data"> |
| <h3> <table style="border: 0;"> <tr> |
| <td> Upload {} descriptor (tar.gz) file: <input type="file" name="descriptor_file"/> </td> |
| <td> <input type="submit" value="Upload"/> </td> |
| </tr> </table> </h3> |
| </form> |
| """ |
| |
| html_nslcmop_body = """ |
| <a href="/osm/nslcm/v1/ns_lcm_op_occs?nsInstanceId={id}">nslcm operations </a> |
| <a href="/osm/nslcm/v1/vnf_instances?nsr-id-ref={id}">VNFRS </a> |
| <form action="/osm/nslcm/v1/ns_instances/{id}/terminate" method="post" enctype="multipart/form-data"> |
| <h3> <table style="border: 0;"> <tr> |
| <td> <input type="submit" value="Terminate"/> </td> |
| </tr> </table> </h3> |
| </form> |
| """ |
| |
| html_nsilcmop_body = """ |
| <a href="/osm/nsilcm/v1/nsi_lcm_op_occs?netsliceInstanceId={id}">nsilcm operations </a> |
| <form action="/osm/nsilcm/v1/netslice_instances/{id}/terminate" method="post" enctype="multipart/form-data"> |
| <h3> <table style="border: 0;"> <tr> |
| <td> <input type="submit" value="Terminate"/> </td> |
| </tr> </table> </h3> |
| </form> |
| """ |
| |
| html_vnfpackage_body = ( |
| """<a href="/osm/vnfpkgm/v1/vnf_packages/{id}/artifacts">Artifacts </a>""" |
| ) |
| html_nspackage_body = ( |
| """<a href="/osm/nsd/v1/ns_descriptors/{id}/artifacts">Artifacts </a>""" |
| ) |
| |
| |
| def format(data, request, response, toke_info): |
| """ |
| Format a nice html response, depending on the data |
| :param data: |
| :param request: cherrypy request |
| :param response: cherrypy response |
| :return: string with teh html response |
| """ |
| response.headers["Content-Type"] = "text/html" |
| if response.status == HTTPStatus.UNAUTHORIZED.value: |
| if response.headers.get("WWW-Authenticate") and request.config.get( |
| "auth.allow_basic_authentication" |
| ): |
| response.headers["WWW-Authenticate"] = ( |
| "Basic" + response.headers["WWW-Authenticate"][6:] |
| ) |
| return |
| else: |
| return html_auth2.format(error=data) |
| if request.path_info in ("/version", "/system"): |
| return ( |
| "<pre>" |
| + yaml.safe_dump( |
| data, explicit_start=False, indent=4, default_flow_style=False |
| ) |
| + "</pre>" |
| ) |
| body = html_body.format(item=html_escape(request.path_info)) |
| if response.status and response.status > 202: |
| # input request.path_info (URL) can contain XSS that are translated into output error detail |
| body += html_body_error.format( |
| html_escape( |
| yaml.safe_dump( |
| data, explicit_start=True, indent=4, default_flow_style=False |
| ) |
| ) |
| ) |
| elif isinstance(data, (list, tuple)): |
| if request.path_info == "/vnfpkgm/v1/vnf_packages": |
| body += html_upload_body.format(request.path_info + "_content", "VNFD") |
| elif request.path_info == "/nsd/v1/ns_descriptors": |
| body += html_upload_body.format(request.path_info + "_content", "NSD") |
| elif request.path_info == "/nst/v1/nst_templates": |
| body += html_upload_body.format(request.path_info + "_content", "NSTD") |
| for k in data: |
| if isinstance(k, dict): |
| data_id = k.pop("_id", None) |
| elif isinstance(k, str): |
| data_id = k |
| body += '<p> <a href="/osm/{url}/{id}">{id}</a>: {t} </p>'.format( |
| url=request.path_info, id=data_id, t=html_escape(str(k)) |
| ) |
| elif isinstance(data, dict): |
| if "Location" in response.headers: |
| body += '<a href="{}"> show </a>'.format(response.headers["Location"]) |
| else: |
| _id = request.path_info[request.path_info.rfind("/") + 1 :] |
| body += ( |
| '<a href="/osm/{}?METHOD=DELETE"> ' |
| '<img src="/osm/static/delete.png" height="25" width="25"> </a>' |
| ).format(request.path_info) |
| if request.path_info.startswith( |
| "/nslcm/v1/ns_instances_content/" |
| ) or request.path_info.startswith("/nslcm/v1/ns_instances/"): |
| body += html_nslcmop_body.format(id=_id) |
| elif request.path_info.startswith( |
| "/nsilcm/v1/netslice_instances_content/" |
| ) or request.path_info.startswith("/nsilcm/v1/netslice_instances/"): |
| body += html_nsilcmop_body.format(id=_id) |
| elif request.path_info.startswith( |
| "/vnfpkgm/v1/vnf_packages/" |
| ) or request.path_info.startswith("/vnfpkgm/v1/vnf_packages_content/"): |
| body += html_vnfpackage_body.format(id=_id) |
| elif request.path_info.startswith( |
| "/nsd/v1/ns_descriptors/" |
| ) or request.path_info.startswith("/nsd/v1/ns_descriptors_content/"): |
| body += html_nspackage_body.format(id=_id) |
| body += ( |
| "<pre>" |
| + html_escape( |
| yaml.safe_dump( |
| data, explicit_start=True, indent=4, default_flow_style=False |
| ) |
| ) |
| + "</pre>" |
| ) |
| elif data is None: |
| if request.method == "DELETE" or "METHOD=DELETE" in request.query_string: |
| body += "<pre> deleted </pre>" |
| else: |
| body = html_escape(str(data)) |
| user_text = " " |
| if toke_info: |
| if toke_info.get("username"): |
| user_text += "user: {}".format(toke_info.get("username")) |
| if toke_info.get("project_id"): |
| user_text += ", project: {}".format(toke_info.get("project_name")) |
| return html_start.format(user_text) + body + html_end |
| # yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False) |
| # tags=False, |
| # encoding='utf-8', allow_unicode=True) |