diff --git a/.envs/.local/.postgres b/.envs/.local/.postgres index ddf23c54..bfb10230 100755 --- a/.envs/.local/.postgres +++ b/.envs/.local/.postgres @@ -5,3 +5,4 @@ POSTGRES_PORT=5432 POSTGRES_DB=orochi POSTGRES_USER=debug POSTGRES_PASSWORD=debug +DATABASE_URL=postgresql://debug:debug@posgtgres:5432/orochi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c3ac67a3..9abf900b 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: - id: check-yaml - repo: https://github.com/psf/black - rev: 24.3.0 + rev: 24.4.2 hooks: - id: black diff --git a/compose/local/dask/Dockerfile b/compose/local/dask/Dockerfile index 6d345e62..102b2e51 100644 --- a/compose/local/dask/Dockerfile +++ b/compose/local/dask/Dockerfile @@ -1,4 +1,4 @@ -FROM daskdev/dask:2024.4.1-py3.12 +FROM daskdev/dask:2024.5.1-py3.12 ENV DEBIAN_FRONTEND noninteractive ARG local_folder=/uploads @@ -47,7 +47,7 @@ RUN python setup.py build \ # Workers should have similar reqs as django WORKDIR / COPY ./requirements /requirements -RUN pip install uv==0.1.29 -e git+https://github.com/volatilityfoundation/volatility3.git@a19dfb57a68cc7efc8926d9f6e7c24e5a2dbab9d#egg=volatility3 \ +RUN pip install uv==0.1.44 -e git+https://github.com/volatilityfoundation/volatility3.git@dc7a3878fa39156d89d567c3e823f1956675f192#egg=volatility3 \ && uv pip install --no-cache --system -r /requirements/base.txt COPY ./compose/local/dask/prepare.sh /usr/bin/prepare.sh diff --git a/compose/local/django/Dockerfile b/compose/local/django/Dockerfile index 60314eb9..7aa05de3 100644 --- a/compose/local/django/Dockerfile +++ b/compose/local/django/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12.2-slim-bookworm as common-base +FROM python:3.12.3-slim-bookworm as common-base ENV DJANGO_SETTINGS_MODULE config.settings.local ENV PYTHONUNBUFFERED 1 @@ -65,7 +65,7 @@ RUN /usr/local/go/bin/go build FROM common-base WORKDIR / COPY ./requirements /requirements -RUN pip install uv==0.1.29 -e git+https://github.com/volatilityfoundation/volatility3.git@a19dfb57a68cc7efc8926d9f6e7c24e5a2dbab9d#egg=volatility3 \ +RUN pip install uv==0.1.44 -e git+https://github.com/volatilityfoundation/volatility3.git@dc7a3878fa39156d89d567c3e823f1956675f192#egg=volatility3 \ && uv pip install --no-cache --system -r /requirements/base.txt COPY ./compose/local/__init__.py /src/volatility3/volatility3/framework/constants/__init__.py diff --git a/config/settings/base.py b/config/settings/base.py index d285b5ef..65eec6da 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -91,18 +91,12 @@ ] -if use_ldap := env.bool("USE_LDAP", False): - AUTHENTICATION_BACKENDS = [ - "django_auth_ldap.backend.LDAPBackend" - "django.contrib.auth.backends.ModelBackend", - "guardian.backends.ObjectPermissionBackend", - ] -else: - AUTHENTICATION_BACKENDS = [ - "django.contrib.auth.backends.ModelBackend", - "allauth.account.auth_backends.AuthenticationBackend", - "guardian.backends.ObjectPermissionBackend", - ] +AUTHENTICATION_BACKENDS = [ + "django_auth_ldap.backend.LDAPBackend", + "django.contrib.auth.backends.ModelBackend", + "guardian.backends.ObjectPermissionBackend", + "allauth.account.auth_backends.AuthenticationBackend", +] AUTH_USER_MODEL = "users.User" LOGIN_REDIRECT_URL = "users:redirect" @@ -244,6 +238,7 @@ "root": {"level": DEBUG_LEVEL, "handlers": ["console"]}, "loggers": { "distributed": {"level": DEBUG_LEVEL, "handlers": ["console"]}, + "django_auth_ldap": {"level": DEBUG_LEVEL, "handlers": ["console"]}, }, } @@ -251,8 +246,8 @@ # ------------------------------------------------------------------------------ ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True) ACCOUNT_AUTHENTICATION_METHOD = "username" -ACCOUNT_EMAIL_REQUIRED = True -ACCOUNT_EMAIL_VERIFICATION = "mandatory" +ACCOUNT_EMAIL_REQUIRED = False +ACCOUNT_EMAIL_VERIFICATION = "optional" ACCOUNT_ADAPTER = "orochi.users.adapters.AccountAdapter" SOCIALACCOUNT_ADAPTER = "orochi.users.adapters.SocialAccountAdapter" @@ -281,16 +276,15 @@ # LDAP # ------------------------------------------------------------------------------ -if use_ldap: - AUTH_LDAP_SERVER_URI = env("AUTH_LDAP_SERVER_URI") - AUTH_LDAP_BIND_DN = env("AUTH_LDAP_BIND_DN") - AUTH_LDAP_BIND_PASSWORD = env("AUTH_LDAP_BIND_PASSWORD") - AUTH_LDAP_USER_SEARCH = LDAPSearch( - env("AUTH_LDAP_USER_SEARCH_DN"), - ldap.SCOPE_SUBTREE, - env("AUTH_LDAP_USER_SEARCH_ALIAS"), - ) - AUTH_LDAP_USER_ATTR_MAP = env.dict("AUTH_LDAP_USER_ATTR_MAP") +AUTH_LDAP_SERVER_URI = env("AUTH_LDAP_SERVER_URI") +AUTH_LDAP_BIND_DN = env("AUTH_LDAP_BIND_DN") +AUTH_LDAP_BIND_PASSWORD = env("AUTH_LDAP_BIND_PASSWORD") +AUTH_LDAP_USER_SEARCH = LDAPSearch( + env("AUTH_LDAP_USER_SEARCH_DN"), + ldap.SCOPE_SUBTREE, + env("AUTH_LDAP_USER_SEARCH_ALIAS"), +) +AUTH_LDAP_USER_ATTR_MAP = env.dict("AUTH_LDAP_USER_ATTR_MAP") # django-cors-headers - https://github.com/adamchainz/django-cors-headers#setup CORS_URLS_REGEX = r"^/api/.*$" diff --git a/docker-compose.yml b/docker-compose.yml index d6daad8d..73be38e5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -121,7 +121,7 @@ services: - "6379:6379" es01: - image: elasticsearch:8.9.0 + image: elasticsearch:8.13.0 container_name: orochi_es01 environment: - discovery.type=single-node @@ -144,7 +144,7 @@ services: - 9200:9200 kib01: - image: kibana:8.9.0 + image: kibana:8.13.0 container_name: orochi_kib01 ports: - 5601:5601 diff --git a/orochi/api/api.py b/orochi/api/api.py index 8dea779d..f008272a 100644 --- a/orochi/api/api.py +++ b/orochi/api/api.py @@ -15,4 +15,4 @@ api.add_router("/dumps/", dumps_router, tags=["Dumps"]) api.add_router("/plugins/", plugins_router, tags=["Plugins"]) api.add_router("/utils/", utils_router, tags=["Utils"]) -api.add_router("/bookmars/", bookmarks_router, tags=["Bookmars"]) +api.add_router("/bookmarks/", bookmarks_router, tags=["Bookmarks"]) diff --git a/orochi/api/models.py b/orochi/api/models.py index ad766799..a87d2fed 100644 --- a/orochi/api/models.py +++ b/orochi/api/models.py @@ -6,7 +6,7 @@ from ninja.orm import create_schema from orochi.website.defaults import OSEnum -from orochi.website.models import Bookmark, Dump, Folder, Plugin, Result +from orochi.website.models import Bookmark, Dump, Folder, Plugin ################################################### # Auth @@ -210,6 +210,13 @@ class ResultSmallOutSchema(Schema): ################################################### # Bookmarks ################################################### +class BookmarksEditInSchema(ModelSchema): + + class Meta: + model = Bookmark + fields = ["name", "icon", "query"] + + class BookmarksSchema(ModelSchema): user: UserOutSchema = None indexes: List[DumpSchema] = [] @@ -217,3 +224,12 @@ class BookmarksSchema(ModelSchema): class Meta: model = Bookmark fields = ["id", "name", "icon", "star", "query"] + + +class BookmarksInSchema(Schema): + selected_indexes: str = None + name: str = None + star: bool = False + icon: str = None + selected_plugin: str = None + query: Optional[str] = None diff --git a/orochi/api/routers/bookmarks.py b/orochi/api/routers/bookmarks.py index dbf0f0c3..03f86910 100644 --- a/orochi/api/routers/bookmarks.py +++ b/orochi/api/routers/bookmarks.py @@ -1,15 +1,78 @@ from typing import List +import django +import psycopg2 from django.shortcuts import get_object_or_404 +from guardian.shortcuts import get_objects_for_user from ninja import Router from ninja.security import django_auth -from orochi.api.models import BookmarksSchema, ErrorsOut, SuccessResponse -from orochi.website.models import Bookmark +from orochi.api.models import ( + BookmarksEditInSchema, + BookmarksInSchema, + BookmarksSchema, + ErrorsOut, + SuccessResponse, +) +from orochi.website.models import Bookmark, Dump, Plugin router = Router() +@router.post( + "/", + auth=django_auth, + response={201: BookmarksSchema, 400: ErrorsOut}, + url_name="create_bookmark", +) +def create_bookmarks(request, bookmarks_in: BookmarksInSchema): + """ + Create bookmarks for the user. + + Args: + request: The request object. + bookmarks_in: Input data for creating bookmarks. + + Returns: + Tuple[int, Bookmark]: A tuple containing the status code and the created bookmark. + + Raises: + 400: If an exception occurs during the bookmark creation process. + """ + try: + indexes = [] + ok_indexes = list( + get_objects_for_user(request.user, "website.can_see").values_list( + "index", flat=True + ) + ) + for index_id in bookmarks_in.selected_indexes.split(","): + index_id = str(index_id) + if index_id not in ok_indexes: + continue + index = get_object_or_404(Dump, index=index_id) + indexes.append(index) + if indexes: + plugin = get_object_or_404(Plugin, name=bookmarks_in.selected_plugin) + bookmark = Bookmark.objects.create( + user=request.user, + plugin=plugin, + star=bookmarks_in.star, + icon=bookmarks_in.icon, + name=bookmarks_in.name, + query=bookmarks_in.query, + ) + bookmark.save() + for index in indexes: + bookmark.indexes.add(index) + return 201, bookmark + return 400, {"errors": "No valid indexes selected"} + except (psycopg2.errors.UniqueViolation, django.db.utils.IntegrityError): + return 400, {"errors": "Bookmark name already used"} + except Exception as excp: + return 400, {"errors": str(excp)} + + @router.get("/", auth=django_auth, response=List[BookmarksSchema]) def list_bookmarks(request): """ @@ -21,6 +84,64 @@ def list_bookmarks(request): return Bookmark.objects.filter(user=request.user) +@router.get( + "/{int:id}", + auth=django_auth, + response={200: BookmarksSchema, 400: ErrorsOut}, + url_name="get_bookmark", +) +def get_bookmark(request, id: int): + """ + Retrieves a bookmark by its ID. + + Args: + request: The request object. + id: The ID of the bookmark to retrieve. + + Returns: + dict: A dictionary containing the bookmark data. + + Raises: + 400: If an exception occurs during the process. + """ + try: + bookmark = get_object_or_404(Bookmark, pk=id, user=request.user) + return 200, bookmark + except Exception as excp: + return 400, {"errors": str(excp)} + + +@router.patch( + "/{int:id}", + response={201: BookmarksSchema, 400: ErrorsOut}, + auth=django_auth, + url_name="edit_bookmark", +) +def edit_bookmark(request, id: int, data: BookmarksEditInSchema): + """ + Edit bookmark. + + Args: + request: The request object. + id: The ID of the bookmark to edit. + data: Input data for editing bookmarks. + + Returns: + Bookmark: The edited bookmark object. + + Raises: + 400: If an exception occurs during the process. + """ + try: + bookmark = get_object_or_404(Bookmark, pk=id, user=request.user) + for attr, value in data.dict(exclude_unset=True).items(): + setattr(bookmark, attr, value) + bookmark.save() + return 201, bookmark + except Exception as excp: + return 400, {"errors": str(excp)} + + @router.delete( "/{int:id}", auth=django_auth, diff --git a/orochi/static/README.txt b/orochi/static/README.txt index ae4b3062..51fe47c7 100644 --- a/orochi/static/README.txt +++ b/orochi/static/README.txt @@ -41,7 +41,7 @@ # Keyrune [MTG icons] --> https://github.com/andrewgioia/keyrune ---> version 3.12.2 +--> version 3.14.0 # Marked [Changelog with MD] --> https://github.com/markedjs/marked diff --git a/orochi/static/fonts/keyrune.ttf b/orochi/static/fonts/keyrune.ttf index d6d04864..530bbc2e 100644 Binary files a/orochi/static/fonts/keyrune.ttf and b/orochi/static/fonts/keyrune.ttf differ diff --git a/orochi/static/fonts/keyrune.woff b/orochi/static/fonts/keyrune.woff index f48ba64d..da9c8d78 100644 Binary files a/orochi/static/fonts/keyrune.woff and b/orochi/static/fonts/keyrune.woff differ diff --git a/orochi/static/fonts/keyrune.woff2 b/orochi/static/fonts/keyrune.woff2 index d7d781e1..aed768be 100644 Binary files a/orochi/static/fonts/keyrune.woff2 and b/orochi/static/fonts/keyrune.woff2 differ diff --git a/orochi/templates/users/user_bookmarks.html b/orochi/templates/users/user_bookmarks.html index 70e54d6d..eda778fa 100644 --- a/orochi/templates/users/user_bookmarks.html +++ b/orochi/templates/users/user_bookmarks.html @@ -105,34 +105,45 @@ $(document).on("submit", "#edit-bookmark", function (e) { e.preventDefault(); var form = $(this); + + let formData = form.serializeArray(); + let obj = {}; + formData.forEach(item => { + if (item.name != 'csrfmiddlewaretoken') { + obj[item.name] = item.value; + } + }); + $.ajaxSetup({ + headers: { 'X-CSRFToken': $('input[name="csrfmiddlewaretoken"]').val() } + }); + $.ajax({ url: form.attr("action"), - data: form.serialize(), - type: form.attr("method"), + data: JSON.stringify(obj), + type: 'PATCH', dataType: 'json', success: function (data) { - if (data.form_is_valid) { - $("#modal-update").modal('hide'); - var d = table.row(row).data(); - d[0] = ``; - d[1] = data.data.name; - d[4] = data.data.query; - table.row(row).data(d).draw(); - $.toast({ - title: 'Bookmark status!', - content: 'Bookmark updated.', - type: 'success', - delay: 5000 - }); - } else { - $("#modal-update .modal-content").html(data.html_form); - $.toast({ - title: 'Bookmark status!', - content: 'Error during submission.', - type: 'error', - delay: 5000 - }); - } + var d = table.row(row).data(); + d[0] = ``; + d[1] = data.name; + d[4] = data.query; + table.row(row).data(d).draw(); + $.toast({ + title: 'Bookmark status!', + content: 'Bookmark updated.', + type: 'success', + delay: 5000 + }); + $("#modal-update").modal('hide'); + }, + error: function () { + $.toast({ + title: 'Bookmark status!', + content: 'Error during submission.', + type: 'error', + delay: 5000 + }); + $("#modal-update").modal('hide'); } }); }); diff --git a/orochi/templates/website/index.html b/orochi/templates/website/index.html index c2d5cd1e..6e7e0e0a 100644 --- a/orochi/templates/website/index.html +++ b/orochi/templates/website/index.html @@ -116,7 +116,7 @@
History Log
}); // ADD BOOKMARK FORM SUBMIT - $(document).on("submit", "#add-bookmark", function (e) { + $(document).on("submit", "#create-bookmark", function (e) { e.preventDefault(); var form = $(this); @@ -124,29 +124,41 @@
History Log
$("#id_selected_plugin").val(selected_plugin); $("#id_query").val($("#example_filter input").val()); + let formData = form.serializeArray(); + let obj = {}; + formData.forEach(item=>{ + if(item.name != 'csrfmiddlewaretoken'){ + obj[item.name] = item.value; + } + }); + $.ajaxSetup({ + headers: { 'X-CSRFToken': $('input[name="csrfmiddlewaretoken"]').val() } + }); + $.ajax({ url: form.attr("action"), - data: form.serialize(), + data: JSON.stringify(obj), + contentType: "application/json", type: form.attr("method"), dataType: 'json', success: function (data) { - if (data.form_is_valid) { - $("#modal-update").modal('hide'); - $.toast({ - title: 'Bookmark saved!', - content: 'Bookmark saved.', - type: 'success', - delay: 5000 - }); - } else { - $("#modal-update").modal('hide'); - $.toast({ - title: 'Bookmark status!', - content: 'Error during submission.', - type: 'error', - delay: 5000 - }); - } + + $.toast({ + title: 'Bookmark saved!', + content: 'Bookmark saved.', + type: 'success', + delay: 5000 + }); + $("#modal-update").modal('hide'); + }, + error: function () { + $.toast({ + title: 'Bookmark status!', + content: 'Error during submission.', + type: 'error', + delay: 5000 + }); + $("#modal-update").modal('hide'); } }); }); diff --git a/orochi/templates/website/partial_bookmark_create.html b/orochi/templates/website/partial_bookmark_create.html index 32ccd3cb..a8d7a9b5 100644 --- a/orochi/templates/website/partial_bookmark_create.html +++ b/orochi/templates/website/partial_bookmark_create.html @@ -1,7 +1,7 @@ {% load widget_tweaks %} {% load custom_tags %} -
+ {{ form.media }} {% csrf_token %} -
\ No newline at end of file + diff --git a/orochi/templates/website/partial_bookmark_edit.html b/orochi/templates/website/partial_bookmark_edit.html index c97d2a44..3cb6ccaa 100644 --- a/orochi/templates/website/partial_bookmark_edit.html +++ b/orochi/templates/website/partial_bookmark_edit.html @@ -1,6 +1,6 @@ {% load widget_tweaks %} -
+ {{ form.media }} {% csrf_token %} -
\ No newline at end of file + diff --git a/orochi/website/defaults.py b/orochi/website/defaults.py index d6b6b6ea..54f9fc8b 100644 --- a/orochi/website/defaults.py +++ b/orochi/website/defaults.py @@ -66,105 +66,114 @@ class OSEnum(models.TextChoices): (RESULT_STATUS_ERROR, "Error"), (RESULT_STATUS_DISABLED, "Disabled"), ) -ICONS = ( - ("ss-arn", "Arabian Nights"), - ("ss-atq", "Antiquities"), - ("ss-leg", "Legends"), - ("ss-drk", "The Dark"), - ("ss-fem", "Fallen Empires"), - ("ss-hml", "Homelands"), - ("ss-ice", "Ice Age"), - ("ss-ice2", "Ice Age (Original)"), - ("ss-all", "Alliances"), - ("ss-csp", "Coldsnap"), - ("ss-mir", "Mirage"), - ("ss-vis", "Visions"), - ("ss-wth", "Weatherlight"), - ("ss-tmp", "Tempest"), - ("ss-sth", "Stronghold"), - ("ss-exo", "Exodus"), - ("ss-usg", "Urza's Saga"), - ("ss-ulg", "Urza's Legacy"), - ("ss-uds", "Urza's Destiny"), - ("ss-mmq", "Mercadian Masques"), - ("ss-nem", "Nemesis"), - ("ss-pcy", "Prophecy"), - ("ss-inv", "Invasion"), - ("ss-pls", "Planeshift"), - ("ss-apc", "Apocalypse"), - ("ss-ody", "Odyssey"), - ("ss-tor", "Torment"), - ("ss-jud", "Judgement"), - ("ss-ons", "Onslaught"), - ("ss-lgn", "Legions"), - ("ss-scg", "Scourge"), - ("ss-mrd", "Mirrodin"), - ("ss-dst", "Darksteel"), - ("ss-5dn", "Fifth Dawn"), - ("ss-chk", "Champions of Kamigawa"), - ("ss-bok", "Betrayers of Kamigawa"), - ("ss-sok", "Saviors of Kamigawa"), - ("ss-rav", "Ravnica"), - ("ss-gpt", "Guildpact"), - ("ss-dis", "Dissension"), - ("ss-tsp", "Time Spiral"), - ("ss-plc", "Planar Chaos"), - ("ss-fut", "Future Sight"), - ("ss-lrw", "Lorwyn"), - ("ss-mor", "Morningtide"), - ("ss-shm", "Shadowmoor"), - ("ss-eve", "Eventide"), - ("ss-ala", "Shards of Alara"), - ("ss-con", "Conflux"), - ("ss-arb", "Alara Reborn"), - ("ss-zen", "Zendikar"), - ("ss-wwk", "Worldwake"), - ("ss-roe", "Rise of the Eldrazi"), - ("ss-som", "Scars of Mirrodin"), - ("ss-mbs", "Mirrodin Besieged"), - ("ss-nph", "New Phyrexia"), - ("ss-isd", "Innistrad"), - ("ss-dka", "Dark Ascension"), - ("ss-avr", "Avacyn Restored"), - ("ss-rtr", "Return to Ravnica"), - ("ss-gtc", "Gatecrash"), - ("ss-dgm", "Dragon's Maze"), - ("ss-ths", "Theros"), - ("ss-bng", "Born of the Gods"), - ("ss-jou", "Journey into Nyx"), - ("ss-ktk", "Khans of Tarkir"), - ("ss-frf", "Fate Reforged"), - ("ss-dtk", "Dragons of Tarkir"), - ("ss-bfz", "Battle for Zendikar"), - ("ss-ogw", "Oath of the Gatewatch"), - ("ss-soi", "Shadows Over Innistrad"), - ("ss-emn", "Eldritch Moon"), - ("ss-kld", "Kaladesh"), - ("ss-aer", "Aether Revolt"), - ("ss-akh", "Amonkhet"), - ("ss-hou", "Hour of Devastation"), - ("ss-xln", "Ixalan"), - ("ss-rix", "Rivals of Ixalan"), - ("ss-dom", "Dominaria"), - ("ss-grn", "Guilds of Ravnica"), - ("ss-rna", "Ravnica Allegiance"), - ("ss-war", "War of the Spark"), - ("ss-eld", "Throne of Eldraine"), - ("ss-thb", "Theros: Beyond Death"), - ("ss-iko", "koria: Lair of Behemoths"), - ("ss-znr", "Zendikar Rising"), - ("ss-khm", "Kaldheim"), - ("ss-stx", "Strixhaven: School of Mages"), - ("ss-mid", "Innistrad: Midnight Hunt"), - ("ss-vow", "Innistrad: Crimson Vow"), - ("ss-neo", "Kamigawa: Neon Dynasty"), - ("ss-snc", "Streets of New Capenna"), - ("ss-dmu", "Dominaria United"), - ("ss-bro", "The Brothers' War"), - ("ss-one", "Phyrexia: All Will Be One"), - ("ss-mom", "March of the Machine"), - ("ss-mat", "March of the Machine: The Aftermath"), - ("ss-woe", "Wilds of Eldraine"), -) + + +class IconEnum(models.TextChoices): + SS_ORI = "ss-ori", "Magic Origins" + SS_AFR = "ss-afr", "Adventures in the Forgotten Realms" + SS_ARN = "ss-arn", "Arabian Nights" + SS_ATQ = "ss-atq", "Antiquities" + SS_LEG = "ss-leg", "Legends" + SS_DRK = "ss-drk", "The Dark" + SS_FEM = "ss-fem", "Fallen Empires" + SS_HML = "ss-hml", "Homelands" + SS_ICE = "ss-ice", "Ice Age" + SS_ICE2 = "ss-ice2", "Ice Age (Original)" + SS_ALL = "ss-all", "Alliances" + SS_CSP = "ss-csp", "Coldsnap" + SS_MIR = "ss-mir", "Mirage" + SS_VIS = "ss-vis", "Visions" + SS_WTH = "ss-wth", "Weatherlight" + SS_TMP = "ss-tmp", "Tempest" + SS_STH = "ss-sth", "Stronghold" + SS_EXO = "ss-exo", "Exodus" + SS_USG = "ss-usg", "Urza's Saga" + SS_ULG = "ss-ulg", "Urza's Legacy" + SS_UDS = "ss-uds", "Urza's Destiny" + SS_MMQ = "ss-mmq", "Mercadian Masques" + SS_NEM = "ss-nem", "Nemesis" + SS_PCY = "ss-pcy", "Prophecy" + SS_INV = "ss-inv", "Invasion" + SS_PLS = "ss-pls", "Planeshift" + SS_APC = "ss-apc", "Apocalypse" + SS_ODY = "ss-ody", "Odyssey" + SS_TOR = "ss-tor", "Torment" + SS_JUD = "ss-jud", "Judgement" + SS_ONS = "ss-ons", "Onslaught" + SS_LGN = "ss-lgn", "Legions" + SS_SCG = "ss-scg", "Scourge" + SS_MRD = "ss-mrd", "Mirrodin" + SS_DST = "ss-dst", "Darksteel" + SS_5DN = "ss-5dn", "Fifth Dawn" + SS_CHK = "ss-chk", "Champions of Kamigawa" + SS_BOK = "ss-bok", "Betrayers of Kamigawa" + SS_SOK = "ss-sok", "Saviors of Kamigawa" + SS_RAV = "ss-rav", "Ravnica" + SS_GPT = "ss-gpt", "Guildpact" + SS_DIS = "ss-dis", "Dissension" + SS_TSP = "ss-tsp", "Time Spiral" + SS_PLC = "ss-plc", "Planar Chaos" + SS_FUT = "ss-fut", "Future Sight" + SS_LRW = "ss-lrw", "Lorwyn" + SS_MOR = "ss-mor", "Morningtide" + SS_SHM = "ss-shm", "Shadowmoor" + SS_EVE = "ss-eve", "Eventide" + SS_ALA = "ss-ala", "Shards of Alara" + SS_CON = "ss-con", "Conflux" + SS_ARB = "ss-arb", "Alara Reborn" + SS_ZEN = "ss-zen", "Zendikar" + SS_WWK = "ss-wwk", "Worldwake" + SS_ROE = "ss-roe", "Rise of the Eldrazi" + SS_SOM = "ss-som", "Scars of Mirrodin" + SS_MBS = "ss-mbs", "Mirrodin Besieged" + SS_NPH = "ss-nph", "New Phyrexia" + SS_ISD = "ss-isd", "Innistrad" + SS_DKA = "ss-dka", "Dark Ascension" + SS_AVR = "ss-avr", "Avacyn Restored" + SS_RTR = "ss-rtr", "Return to Ravnica" + SS_GTC = "ss-gtc", "Gatecrash" + SS_DGM = "ss-dgm", "Dragon's Maze" + SS_THS = "ss-ths", "Theros" + SS_BNG = "ss-bng", "Born of the Gods" + SS_JOU = "ss-jou", "Journey into Nyx" + SS_KTK = "ss-ktk", "Khans of Tarkir" + SS_FRF = "ss-frf", "Fate Reforged" + SS_DTK = "ss-dtk", "Dragons of Tarkir" + SS_BFZ = "ss-bfz", "Battle for Zendikar" + SS_OGW = "ss-ogw", "Oath of the Gatewatch" + SS_SOI = "ss-soi", "Shadows Over Innistrad" + SS_EMN = "ss-emn", "Eldritch Moon" + SS_KLD = "ss-kld", "Kaladesh" + SS_AER = "ss-aer", "Aether Revolt" + SS_AKH = "ss-akh", "Amonkhet" + SS_HOU = "ss-hou", "Hour of Devastation" + SS_XLN = "ss-xln", "Ixalan" + SS_RIX = "ss-rix", "Rivals of Ixalan" + SS_DOM = "ss-dom", "Dominaria" + SS_GRN = "ss-grn", "Guilds of Ravnica" + SS_RNA = "ss-rna", "Ravnica Allegiance" + SS_WAR = "ss-war", "War of the Spark" + SS_ELD = "ss-eld", "Throne of Eldraine" + SS_THB = "ss-thb", "Theros: Beyond Death" + SS_IKO = "ss-iko", "koria: Lair of Behemoths" + SS_ZNR = "ss-znr", "Zendikar Rising" + SS_KHM = "ss-khm", "Kaldheim" + SS_STX = "ss-stx", "Strixhaven: School of Mages" + SS_MID = "ss-mid", "Innistrad: Midnight Hunt" + SS_VOW = "ss-vow", "Innistrad: Crimson Vow" + SS_NEO = "ss-neo", "Kamigawa: Neon Dynasty" + SS_SNC = "ss-snc", "Streets of New Capenna" + SS_DMU = "ss-dmu", "Dominaria United" + SS_BRO = "ss-bro", "The Brothers' War" + SS_ONE = "ss-one", "Phyrexia: All Will Be One" + SS_MOM = "ss-mom", "March of the Machine" + SS_MAT = "ss-mat", "March of the Machine: The Aftermath" + SS_WOE = "ss-woe", "Wilds of Eldraine" + SS_LCI = "ss-lci", "Lost Caverns of Ixalan" + SS_MKM = "ss-mkm", "Murders at Karlov Manor" + SS_OTJ = "ss-otj", "Outlaws of Thunder Junction" + SS_BIG = "ss-big", "The Big Score" + SS_BLB = "ss-blb", "Bloomburrow" + DEFAULT_YARA_PATH = "/yara/default.yara" diff --git a/orochi/website/forms.py b/orochi/website/forms.py index a248575f..3d257156 100644 --- a/orochi/website/forms.py +++ b/orochi/website/forms.py @@ -53,7 +53,6 @@ class Meta: class EditBookmarkForm(forms.ModelForm): - selected_bookmark = forms.CharField(widget=forms.HiddenInput()) class Meta: model = Bookmark diff --git a/orochi/website/migrations/0056_alter_bookmark_icon.py b/orochi/website/migrations/0056_alter_bookmark_icon.py new file mode 100644 index 00000000..740e22d8 --- /dev/null +++ b/orochi/website/migrations/0056_alter_bookmark_icon.py @@ -0,0 +1,128 @@ +# Generated by Django 5.0.4 on 2024-04-16 16:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("website", "0055_alter_dump_status"), + ] + + operations = [ + migrations.AlterField( + model_name="bookmark", + name="icon", + field=models.CharField( + choices=[ + ("ss-ori", "Magic Origins"), + ("ss-afr", "Adventures in the Forgotten Realms"), + ("ss-arn", "Arabian Nights"), + ("ss-atq", "Antiquities"), + ("ss-leg", "Legends"), + ("ss-drk", "The Dark"), + ("ss-fem", "Fallen Empires"), + ("ss-hml", "Homelands"), + ("ss-ice", "Ice Age"), + ("ss-ice2", "Ice Age (Original)"), + ("ss-all", "Alliances"), + ("ss-csp", "Coldsnap"), + ("ss-mir", "Mirage"), + ("ss-vis", "Visions"), + ("ss-wth", "Weatherlight"), + ("ss-tmp", "Tempest"), + ("ss-sth", "Stronghold"), + ("ss-exo", "Exodus"), + ("ss-usg", "Urza's Saga"), + ("ss-ulg", "Urza's Legacy"), + ("ss-uds", "Urza's Destiny"), + ("ss-mmq", "Mercadian Masques"), + ("ss-nem", "Nemesis"), + ("ss-pcy", "Prophecy"), + ("ss-inv", "Invasion"), + ("ss-pls", "Planeshift"), + ("ss-apc", "Apocalypse"), + ("ss-ody", "Odyssey"), + ("ss-tor", "Torment"), + ("ss-jud", "Judgement"), + ("ss-ons", "Onslaught"), + ("ss-lgn", "Legions"), + ("ss-scg", "Scourge"), + ("ss-mrd", "Mirrodin"), + ("ss-dst", "Darksteel"), + ("ss-5dn", "Fifth Dawn"), + ("ss-chk", "Champions of Kamigawa"), + ("ss-bok", "Betrayers of Kamigawa"), + ("ss-sok", "Saviors of Kamigawa"), + ("ss-rav", "Ravnica"), + ("ss-gpt", "Guildpact"), + ("ss-dis", "Dissension"), + ("ss-tsp", "Time Spiral"), + ("ss-plc", "Planar Chaos"), + ("ss-fut", "Future Sight"), + ("ss-lrw", "Lorwyn"), + ("ss-mor", "Morningtide"), + ("ss-shm", "Shadowmoor"), + ("ss-eve", "Eventide"), + ("ss-ala", "Shards of Alara"), + ("ss-con", "Conflux"), + ("ss-arb", "Alara Reborn"), + ("ss-zen", "Zendikar"), + ("ss-wwk", "Worldwake"), + ("ss-roe", "Rise of the Eldrazi"), + ("ss-som", "Scars of Mirrodin"), + ("ss-mbs", "Mirrodin Besieged"), + ("ss-nph", "New Phyrexia"), + ("ss-isd", "Innistrad"), + ("ss-dka", "Dark Ascension"), + ("ss-avr", "Avacyn Restored"), + ("ss-rtr", "Return to Ravnica"), + ("ss-gtc", "Gatecrash"), + ("ss-dgm", "Dragon's Maze"), + ("ss-ths", "Theros"), + ("ss-bng", "Born of the Gods"), + ("ss-jou", "Journey into Nyx"), + ("ss-ktk", "Khans of Tarkir"), + ("ss-frf", "Fate Reforged"), + ("ss-dtk", "Dragons of Tarkir"), + ("ss-bfz", "Battle for Zendikar"), + ("ss-ogw", "Oath of the Gatewatch"), + ("ss-soi", "Shadows Over Innistrad"), + ("ss-emn", "Eldritch Moon"), + ("ss-kld", "Kaladesh"), + ("ss-aer", "Aether Revolt"), + ("ss-akh", "Amonkhet"), + ("ss-hou", "Hour of Devastation"), + ("ss-xln", "Ixalan"), + ("ss-rix", "Rivals of Ixalan"), + ("ss-dom", "Dominaria"), + ("ss-grn", "Guilds of Ravnica"), + ("ss-rna", "Ravnica Allegiance"), + ("ss-war", "War of the Spark"), + ("ss-eld", "Throne of Eldraine"), + ("ss-thb", "Theros: Beyond Death"), + ("ss-iko", "koria: Lair of Behemoths"), + ("ss-znr", "Zendikar Rising"), + ("ss-khm", "Kaldheim"), + ("ss-stx", "Strixhaven: School of Mages"), + ("ss-mid", "Innistrad: Midnight Hunt"), + ("ss-vow", "Innistrad: Crimson Vow"), + ("ss-neo", "Kamigawa: Neon Dynasty"), + ("ss-snc", "Streets of New Capenna"), + ("ss-dmu", "Dominaria United"), + ("ss-bro", "The Brothers' War"), + ("ss-one", "Phyrexia: All Will Be One"), + ("ss-mom", "March of the Machine"), + ("ss-mat", "March of the Machine: The Aftermath"), + ("ss-woe", "Wilds of Eldraine"), + ("ss-lci", "Lost Caverns of Ixalan"), + ("ss-mkm", "Murders at Karlov Manor"), + ("ss-otj", "Outlaws of Thunder Junction"), + ("ss-big", "The Big Score"), + ("ss-blb", "Bloomburrow"), + ], + default="ss-ori", + max_length=50, + ), + ), + ] diff --git a/orochi/website/models.py b/orochi/website/models.py index 27119692..ff2bb90a 100644 --- a/orochi/website/models.py +++ b/orochi/website/models.py @@ -14,7 +14,6 @@ from orochi.website.defaults import ( DEFAULT_YARA_PATH, - ICONS, RESULT, RESULT_STATUS_DISABLED, RESULT_STATUS_NOT_STARTED, @@ -22,6 +21,7 @@ STATUS, TOAST_DUMP_COLORS, TOAST_RESULT_COLORS, + IconEnum, OSEnum, ) from orochi.ya.models import Ruleset @@ -144,7 +144,9 @@ class Bookmark(models.Model): indexes = models.ManyToManyField(Dump) plugin = models.ForeignKey(Plugin, on_delete=models.CASCADE) name = models.CharField(max_length=250) - icon = models.CharField(choices=ICONS, default="ss-ori", max_length=50) + icon = models.CharField( + choices=IconEnum.choices, default=IconEnum.SS_ORI, max_length=50 + ) star = models.BooleanField(default=False) query = models.CharField(max_length=500, blank=True, null=True) diff --git a/orochi/website/views.py b/orochi/website/views.py index 71aa82b1..c64561c7 100644 --- a/orochi/website/views.py +++ b/orochi/website/views.py @@ -822,92 +822,30 @@ def export(request): # BOOKMARKS ############################## @login_required +@require_http_methods(["GET"]) def add_bookmark(request): """Add bookmark in user settings""" - data = {} - - if request.method == "POST": - updated_request = { - "name": request.POST.get("name"), - "query": request.POST.get("query"), - "star": request.POST.get("star"), - "icon": request.POST.get("icon"), - } - - id_indexes = request.POST.get("selected_indexes") - indexes = [] - for id_index in id_indexes.split(","): - index = get_object_or_404(Dump, index=id_index) - indexes.append(index) - - id_plugin = request.POST.get("selected_plugin") - plugin = get_object_or_404(Plugin, name=id_plugin) - - form = BookmarkForm(data=updated_request) - if form.is_valid(): - bookmark = form.save(commit=False) - bookmark.user = request.user - bookmark.plugin = plugin - bookmark.save() - for index in indexes: - bookmark.indexes.add(index) - data["form_is_valid"] = True - else: - data["form_is_valid"] = False - else: - form = BookmarkForm() - - context = {"form": form} - data["html_form"] = render_to_string( - "website/partial_bookmark_create.html", - context, - request=request, - ) + data = { + "html_form": render_to_string( + "website/partial_bookmark_create.html", + {"form": BookmarkForm()}, + request=request, + ) + } return JsonResponse(data) @login_required +@require_http_methods(["GET"]) def edit_bookmark(request): """Edit bookmark information""" - data = {} - bookmark = None - - if request.method == "POST": - bookmark = get_object_or_404( - Bookmark, name=request.POST.get("selected_bookmark"), user=request.user - ) - elif request.method == "GET": - bookmark = get_object_or_404( - Bookmark, pk=request.GET.get("pk"), user=request.user - ) - - if request.method == "POST": - form = EditBookmarkForm( - data=request.POST, - instance=bookmark, - ) - if form.is_valid(): - bookmark = form.save() - data["form_is_valid"] = True - data["data"] = { - "name": bookmark.name, - "icon": bookmark.icon, - "query": bookmark.query, - } - else: - data["form_is_valid"] = False - else: - form = EditBookmarkForm( - instance=bookmark, - initial={"selected_bookmark": bookmark.name}, + bookmark = get_object_or_404(Bookmark, pk=request.GET.get("pk"), user=request.user) + context = {"form": EditBookmarkForm(instance=bookmark), "id": bookmark.pk} + data = { + "html_form": render_to_string( + "website/partial_bookmark_edit.html", context, request=request ) - - context = {"form": form} - data["html_form"] = render_to_string( - "website/partial_bookmark_edit.html", - context, - request=request, - ) + } return JsonResponse(data) diff --git a/requirements/base.txt b/requirements/base.txt index cc56bad1..1cd7be5a 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -7,7 +7,7 @@ argon2-cffi==23.1.0 # https://github.com/evansd/whitenoise whitenoise==6.6.0 # https://github.com/andymccurdy/redis-py -redis==5.0.3 +redis==5.0.4 # https://github.com/redis/hiredis-py hiredis==2.3.2 # https://github.com/psycopg/psycopg2 @@ -20,21 +20,21 @@ python-magic==0.4.27 # Django # ------------------------------------------------------------------------------ # https://www.djangoproject.com/ -django==5.0.4 +django==5.0.6 # https://github.com/django/channels -channels[daphne]==4.0.0 +channels[daphne]==4.1.0 # https://github.com/django/channels_redis channels_redis==4.2.0 # https://github.com/joke2k/django-environ django-environ==0.11.2 # https://github.com/pennersr/django-allauth -django-allauth==0.61.1 +django-allauth==0.63.1 # https://github.com/django-crispy-forms/django-crispy-forms django-crispy-forms==2.1 # https://github.com/jazzband/django-redis django-redis==5.4.0 # https://gunicorn.org/ -gunicorn==21.2.0 +gunicorn==22.0.0 # Django Ninja @@ -64,18 +64,18 @@ django-admin-multiple-choice-list-filter==0.1.1 # Elasticsearch # ------------------------------------------------------------------------------ # https://github.com/elastic/elasticsearch-py -elasticsearch==8.13.0 +elasticsearch==8.13.1 # https://github.com/elastic/elasticsearch-dsl-py -elasticsearch-dsl==8.13.0 +elasticsearch-dsl==8.13.1 # https://github.com/jurismarches/luqum luqum==0.13.0 # Dask & co # ------------------------------------------------------------------------------ # https://github.com/dask/dask -dask==2024.4.1 +dask==2024.5.1 # https://github.com/dask/distributed -distributed==2024.4.1 +distributed==2024.5.1 # https://msgpack.org/ TO BE ALIGNED WITH SCHEDULER msgpack==1.0.8 # https://github.com/python-lz4/python-lz4 @@ -89,7 +89,7 @@ toolz==0.12.1 # https://pypi.org/project/tornado/ tornado==6.4 # https://pandas.pydata.org/ -pandas==2.2.1 +pandas==2.2.2 # Volatility # ------------------------------------------------------------------------------ @@ -100,13 +100,13 @@ pandas==2.2.1 # https://github.com/Viicos/clamdpy clamdpy==0.1.0.post1 # https://github.com/VirusTotal/vt-py -vt-py==0.18.0 +vt-py==0.18.2 # https://github.com/mkorman90/regipy/ -regipy[full]==4.1.1 +regipy[full]==4.2.1 # http://www.capstone-engine.org/ capstone==5.0.1 # https://github.com/Julian/jsonschema -jsonschema==4.21.1 +jsonschema==4.22.0 # https://github.com/Legrandin/pycryptodome pycryptodome==3.20.0 # https://github.com/maxmind/GeoIP2-python @@ -133,7 +133,7 @@ pefile==2023.2.7 # misp export # ------------------------------------------------------------------------------ # https://github.com/MISP/PyMISP -pymisp==2.4.188 +pymisp==2.4.190 # ldap # ------------------------------------------------------------------------------ diff --git a/requirements/local.txt b/requirements/local.txt index 6c84a993..e3a5c767 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -5,7 +5,7 @@ # https://github.com/python/mypy mypy==1.9.0 # https://github.com/typeddjango/django-stubs -django-stubs==4.2.7 +django-stubs==5.0.0 # https://github.com/pytest-dev/pytest pytest==8.1.1 # https://github.com/Frozenball/pytest-sugar @@ -18,13 +18,13 @@ flake8==7.0.0 # https://github.com/gforcada/flake8-isort flake8-isort==6.1.1 # https://github.com/nedbat/coveragepy -coverage==7.4.4 +coverage==7.5.1 # https://github.com/ambv/black -black==24.3.0 +black==24.4.2 # https://github.com/PyCQA/pylint-django pylint-django==2.5.5 # https://github.com/pre-commit/pre-commit -pre-commit==3.6.2 +pre-commit==3.7.1 # Django # ------------------------------------------------------------------------------