From a639e87e644fd62da805a0de7dd7817b71d9838d Mon Sep 17 00:00:00 2001 From: Davide Arcuri Date: Thu, 11 Apr 2024 16:33:24 +0200 Subject: [PATCH] #1073 wip --- compose/local/django/Dockerfile | 2 +- orochi/api/models.py | 3 + orochi/api/routers/utils.py | 98 ++++++++++++++++++- orochi/static/js/handlebars/maxmind.js | 37 +++++++ orochi/static/js/handlebars/vt.js | 37 +++++++ orochi/templates/base.html | 6 +- .../templates/handlebars/maxmind.handlebars | 29 ++++++ orochi/templates/handlebars/vt.handlebars | 29 ++++++ orochi/templates/users/user_bookmarks.html | 3 +- orochi/templates/users/user_rules.html | 4 +- orochi/templates/website/file_download.html | 2 +- orochi/templates/website/index.html | 33 ++++++- orochi/templates/website/list_symbols.html | 3 + orochi/website/urls.py | 3 - orochi/website/views.py | 50 +--------- 15 files changed, 275 insertions(+), 64 deletions(-) create mode 100644 orochi/static/js/handlebars/maxmind.js create mode 100644 orochi/static/js/handlebars/vt.js create mode 100644 orochi/templates/handlebars/maxmind.handlebars create mode 100644 orochi/templates/handlebars/vt.handlebars diff --git a/compose/local/django/Dockerfile b/compose/local/django/Dockerfile index 7437a999..60314eb9 100644 --- a/compose/local/django/Dockerfile +++ b/compose/local/django/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12-slim-bookworm as common-base +FROM python:3.12.2-slim-bookworm as common-base ENV DJANGO_SETTINGS_MODULE config.settings.local ENV PYTHONUNBUFFERED 1 diff --git a/orochi/api/models.py b/orochi/api/models.py index 02becbcc..433206a8 100644 --- a/orochi/api/models.py +++ b/orochi/api/models.py @@ -51,6 +51,9 @@ class SuccessResponse(Schema): message: str +################################################### +# Utils +################################################### class DaskStatusOut(Schema): running: int = 0 diff --git a/orochi/api/routers/utils.py b/orochi/api/routers/utils.py index 2a002075..ac4a892b 100644 --- a/orochi/api/routers/utils.py +++ b/orochi/api/routers/utils.py @@ -1,17 +1,62 @@ +import json +from pathlib import Path +from typing import Any + +import geoip2.database from dask.distributed import Client from django.conf import settings +from geoip2.errors import GeoIP2Error from ninja import Router from ninja.security import django_auth -from orochi.api.models import DaskStatusOut +from orochi.api.models import DaskStatusOut, ErrorsOut router = Router() +@router.get("changelog", auth=django_auth, response={200: Any, 400: ErrorsOut}) +def changelog(request): + """ + Summary: + Endpoint to retrieve the changelog content. + + Explanation: + Retrieves the content of the CHANGELOG.md file and returns it as a response. If an exception occurs during the process, it returns an error response. + + Args: + - request: The request object. + + Returns: + - Tuple[int, Dict[str, str]]: A tuple containing the status code and a dictionary with the changelog content. + + Raises: + - ErrorsOut: If an exception occurs during the file reading process. + """ + try: + changelog_path = Path("/app/CHANGELOG.md") + with open(changelog_path, "r") as f: + changelog_content = "".join(f.readlines()) + return 200, {"note": changelog_content} + except Exception as excp: + return 400, ErrorsOut(errors=str(excp)) + + @router.get( - "/dask_status", auth=django_auth, response=DaskStatusOut, url_name="dask_status" + "/dask_status", + auth=django_auth, + response=DaskStatusOut, + url_name="dask_status", ) def dask_status(request): + """ + Get the total number of running tasks on the Dask scheduler. + + Args: + request: The request object. + + Returns: + int: The total number of running tasks on the Dask scheduler. + """ dask_client = Client(settings.DASK_SCHEDULER_URL) res = dask_client.run_on_scheduler( lambda dask_scheduler: { @@ -21,3 +66,52 @@ def dask_status(request): ) dask_client.close() return sum(len(running_tasks) for running_tasks in res.values()) + + +@router.get( + "/maxmind", + auth=django_auth, + url_name="maxmind", + response={200: Any, 400: ErrorsOut}, +) +def maxmind(request, ip: str): + """ + Retrieve geolocation data for the given IP address using MaxMind databases. + + Args: + request: The request object. + ip (str): The IP address for which geolocation data is to be retrieved. + + Returns: + tuple: A tuple containing the HTTP status code and the geolocation data as a dictionary. + The status code 200 indicates success, while 400 indicates an error. + """ + if ( + not Path("/maxmind/GeoLite2-ASN.mmdb").exists() + and not Path("/maxmind/GeoLite2-City.mmdb").exists() + and not Path("/maxmind/GeoLite2-Country.mmdb").exists() + ): + return 400, ErrorsOut(errors="Maxmind databases not found.") + + try: + data = {} + if Path("/maxmind/GeoLite2-ASN.mmdb").exists(): + with geoip2.database.Reader("/maxmind/GeoLite2-ASN.mmdb") as reader: + data |= reader.asn(ip).raw + if Path("/maxmind/GeoLite2-City.mmdb").exists(): + with geoip2.database.Reader("/maxmind/GeoLite2-City.mmdb") as reader: + data |= reader.city(ip).raw + if Path("/maxmind/GeoLite2-Country.mmdb").exists(): + with geoip2.database.Reader("/maxmind/GeoLite2-Country.mmdb") as reader: + data |= reader.country(ip).raw + return 200, data + except (GeoIP2Error, Exception) as excp: + return 400, ErrorsOut(errors=str(excp)) + + +@router.get("/vt", url_name="vt", response={200: Any, 400: ErrorsOut}, auth=django_auth) +def get_extracted_dump_vt_report(request, path: str): + path = Path(path) + if path.exists(): + return 200, json.loads(open(path, "r").read()) + return 400, ErrorsOut(errors="File not found.") diff --git a/orochi/static/js/handlebars/maxmind.js b/orochi/static/js/handlebars/maxmind.js new file mode 100644 index 00000000..d238cf4b --- /dev/null +++ b/orochi/static/js/handlebars/maxmind.js @@ -0,0 +1,37 @@ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['maxmind'] = template({"1":function(container,depth0,helpers,partials,data) { + var helper, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n " + + container.escapeExpression(((helper = (helper = lookupProperty(helpers,"errors") || (depth0 != null ? lookupProperty(depth0,"errors") : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"errors","hash":{},"data":data,"loc":{"start":{"line":8,"column":4},"end":{"line":8,"column":14}}}) : helper))) + + "\n
\n"; +},"3":function(container,depth0,helpers,partials,data) { + var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n \n"; +},"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n
Maxmind Report
\n \n
\n
\n" + + ((stack1 = lookupProperty(helpers,"if").call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"errors") : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data,"loc":{"start":{"line":6,"column":4},"end":{"line":24,"column":11}}})) != null ? stack1 : "") + + "
\n
\n \n
\n\n"; +},"useData":true}); +})(); diff --git a/orochi/static/js/handlebars/vt.js b/orochi/static/js/handlebars/vt.js new file mode 100644 index 00000000..f5cea5a1 --- /dev/null +++ b/orochi/static/js/handlebars/vt.js @@ -0,0 +1,37 @@ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['vt'] = template({"1":function(container,depth0,helpers,partials,data) { + var helper, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n " + + container.escapeExpression(((helper = (helper = lookupProperty(helpers,"errors") || (depth0 != null ? lookupProperty(depth0,"errors") : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"errors","hash":{},"data":data,"loc":{"start":{"line":8,"column":4},"end":{"line":8,"column":14}}}) : helper))) + + "\n
\n"; +},"3":function(container,depth0,helpers,partials,data) { + var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n \n"; +},"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) { + if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { + return parent[propertyName]; + } + return undefined + }; + + return "
\n
VirusTotal Report
\n \n
\n
\n" + + ((stack1 = lookupProperty(helpers,"if").call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"errors") : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data,"loc":{"start":{"line":6,"column":4},"end":{"line":24,"column":11}}})) != null ? stack1 : "") + + "
\n
\n \n
\n\n"; +},"useData":true}); +})(); diff --git a/orochi/templates/base.html b/orochi/templates/base.html index 1185639c..b670c7c6 100644 --- a/orochi/templates/base.html +++ b/orochi/templates/base.html @@ -20,6 +20,7 @@ + {% endblock %} @@ -160,6 +161,8 @@ + + + + {{/if}} + + + diff --git a/orochi/templates/handlebars/vt.handlebars b/orochi/templates/handlebars/vt.handlebars new file mode 100644 index 00000000..94f99011 --- /dev/null +++ b/orochi/templates/handlebars/vt.handlebars @@ -0,0 +1,29 @@ + + + + diff --git a/orochi/templates/users/user_bookmarks.html b/orochi/templates/users/user_bookmarks.html index b27ce47d..2d156827 100644 --- a/orochi/templates/users/user_bookmarks.html +++ b/orochi/templates/users/user_bookmarks.html @@ -91,6 +91,7 @@ type: 'get', dataType: 'json', beforeSend: function () { + $("#modal-update .modal-content").html(''); $("#modal-update").modal("show"); row = table.row($(btn).closest('tr')).index(); }, @@ -210,4 +211,4 @@ }); -{% endblock javascript %} \ No newline at end of file +{% endblock javascript %} diff --git a/orochi/templates/users/user_rules.html b/orochi/templates/users/user_rules.html index 4fa41b51..a0cdb6d7 100644 --- a/orochi/templates/users/user_rules.html +++ b/orochi/templates/users/user_rules.html @@ -260,6 +260,7 @@ dataType: 'json', beforeSend: function () { $("#modal-update .modal-dialog").removeClass('modal-xl'); + $("#modal-update .modal-content").html(''); $("#modal-update").modal("show"); }, success: function (data) { @@ -310,6 +311,7 @@ dataType: 'json', success: function (data) { $("#modal-update .modal-dialog").addClass('modal-xl'); + $("#modal-update .modal-content").html(''); $("#modal-update").modal("show"); $("#modal-update .modal-content").html(data.html_form); }, @@ -386,4 +388,4 @@ }); -{% endblock javascript %} \ No newline at end of file +{% endblock javascript %} diff --git a/orochi/templates/website/file_download.html b/orochi/templates/website/file_download.html index 9d7292eb..4b3b8750 100644 --- a/orochi/templates/website/file_download.html +++ b/orochi/templates/website/file_download.html @@ -15,7 +15,7 @@ {% endif %} {% if vt %} - + {% endif %} diff --git a/orochi/templates/website/index.html b/orochi/templates/website/index.html index 2757a036..ba3ed74c 100644 --- a/orochi/templates/website/index.html +++ b/orochi/templates/website/index.html @@ -72,6 +72,12 @@
History Log