Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new: [website] Added first version of the API endpoint in order to st… #81

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions website/web/api/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def custom_ui() -> str:
from website.web.api.v1 import bundle
from website.web.api.v1 import epss
from website.web.api.v1 import sighting
from website.web.api.v1 import fediverse

api.add_namespace(base.default_ns, path="/")
api.add_namespace(base.api_ns, path="/api")
Expand All @@ -68,6 +69,7 @@ def custom_ui() -> str:
api.add_namespace(bundle.bundle_ns, path="/api")
api.add_namespace(sighting.sighting_ns, path="/api")
api.add_namespace(epss.epss_ns, path="/api")
api.add_namespace(fediverse.status_ns, path="/api")

return api

Expand Down
103 changes: 103 additions & 0 deletions website/web/api/v1/fediverse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from typing import Tuple
from datetime import datetime

import logging
import orjson
from flask_restx import Namespace # type: ignore[import-untyped]
from flask_restx import reqparse
from flask_restx import Resource
from redis import Redis

from vulnerabilitylookup.default import get_config
from website.web.api.v1.common import auth_func
from website.web.api.v1.types import ResultType

logger = logging.getLogger(__name__)

status_ns = Namespace("status", description="status related operations")

storage = Redis(
host=get_config("generic", "storage_db_hostname"),
port=get_config("generic", "storage_db_port"),
)


# Argument Parsing
parser = reqparse.RequestParser()
parser.add_argument(
"data",
type=dict,
location="json",
help="The JSON data of the status.",
)


@status_ns.route("/status/")
class StatusList(Resource): # type: ignore[misc]
@status_ns.doc("list_status") # type: ignore[misc]
# @status_ns.marshal_list_with(status_list_fields) # type: ignore[misc]
def get(self) -> Tuple[ResultType, int]:
"""List all statuses."""
args = parser.parse_args()
offset = args.pop("page", 1) - 1
limit = args.pop("per_page", 1000)
vuln_id = args.pop("vuln_id", None)

result: ResultType = {
"data": [],
"metadata": {
"count": 0,
"offset": offset,
"limit": limit,
},
}

# all_entries = storage.zrange(f"status:{vuln_id}", 0, -1, withscores=True)
# latest_entries = r.zrevrange(f"status:{vuln_id}", 0, 4, withscores=True)
for vuln_id in storage.zrevrange(f"status:{vuln_id}", offset, limit, withscores=True):
if vuln := storage.get(vuln_id):
result["data"].append(vuln)

return result, 200


@status_ns.expect(parser) # type: ignore[misc]
@auth_func
def post(self) -> Tuple[ResultType, int]:
"""Create a new status."""
result: ResultType = {
"data": [],
"metadata": {
"count": 0,
"offset": 0,
"limit": 10,
},
}

date = datetime.now()

ids: dict[str, float] = {}

status = status_ns.payload["status"]
vuln_id = status_ns.payload["vuln_id"]

uri = status["url"]
ids[uri] = status["created_at"]

# Store the status in kvrocks
p = storage.pipeline()
p.set(uri, orjson.dumps(status))
p.hincrby("top_sighting_vulns", vuln_id, 1)
p.zadd(f"status:{vuln_id}", ids) # type: ignore


# p.hincrby("top:{vuln_id}", date.strftime("%Y%m%d"), 1)

# p.zadd(f"index:{source}", ids) # type: ignore
# p.zadd("index", ids) # type: ignore

# p.zadd(f"top_status:{vuln_id}", {uri: float(nb_items)}) # type: ignore

p.execute()

return status
42 changes: 36 additions & 6 deletions website/web/templates/vuln.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,17 @@ <h5 class="modal-title">Action not permitted</h5>
<br />
<ul class="nav nav-tabs" id="pageTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="related-tab" data-bs-toggle="tab" data-bs-target="#related" type="button" role="tab" aria-controls="related" aria-selected="true">Related vulnerabilities <span class="badge bg-primary rounded-pill">{{ nb_linked_vulns }}</span></button>
<a class="nav-link active" id="related-tab" data-bs-toggle="tab" data-bs-target="#related" type="button" role="tab" aria-controls="related" aria-selected="true">Related vulnerabilities <span class="badge bg-primary rounded-pill">{{ nb_linked_vulns }}</span></a>
</li>
{% if config.user_accounts %}
<li class="nav-item" role="presentation">
<button class="nav-link" id="comments-tab" data-bs-toggle="tab" data-bs-target="#comments" type="button" role="tab" aria-controls="comments" aria-selected="false" onclick="loadComments()">Comments <span class="badge bg-primary rounded-pill" id="nb-comments">{{ nb_comments }}</span></button>
<a class="nav-link" id="comments-tab" data-bs-toggle="tab" data-bs-target="#comments" type="button" role="tab" aria-controls="comments" aria-selected="false" onclick="loadComments()" href="#comments">Comments <span class="badge bg-primary rounded-pill" id="nb-comments">{{ nb_comments }}</span></a>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="bundles-tab" data-bs-toggle="tab" data-bs-target="#bundles" type="button" role="tab" aria-controls="bundles" aria-selected="false" onclick="loadBundles()">Bundles <span class="badge bg-primary rounded-pill" id="nb-bundles">{{ nb_bundles }}</span></button>
<a class="nav-link" id="bundles-tab" data-bs-toggle="tab" data-bs-target="#bundles" type="button" role="tab" aria-controls="bundles" aria-selected="false" onclick="loadBundles()" href="#bundles">Bundles <span class="badge bg-primary rounded-pill" id="nb-bundles">{{ nb_bundles }}</span></a>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="sightings-tab" data-bs-toggle="tab" data-bs-target="#sightings" type="button" role="tab" aria-controls="sightings" aria-selected="false" onclick="loadSightings()">Sightings <span class="badge bg-primary rounded-pill" id="nb-sightings">{{ nb_sightings }}</span></button>
<a class="nav-link" id="sightings-tab" data-bs-toggle="tab" data-bs-target="#sightings" type="button" role="tab" aria-controls="sightings" aria-selected="false" onclick="loadSightings()" href="#sightings">Sightings <span class="badge bg-primary rounded-pill" id="nb-sightings">{{ nb_sightings }}</span></a>
</li>
{% endif %}
</ul>
Expand Down Expand Up @@ -358,7 +358,6 @@ <h5>Tags</h5>
return new bootstrap.Tooltip(tooltipTriggerEl)
})


var jsonContainers = document.querySelectorAll(".json-container");
Array.prototype.forEach.call(jsonContainers, function(jsonContainer) {
jsonContainer.innerHTML = prettyPrintJson.toHtml(JSON.parse(jsonContainer.innerText));
Expand Down Expand Up @@ -393,9 +392,40 @@ <h5>Tags</h5>
document.getElementById("epss-score").parentNode.parentNode.remove();
});
}

})


// Open the tab specified with an anchor in the URL.
window.onload = function() {
const hash = window.location.hash;
const tabLink = document.querySelector(`a[href="${hash}"]`);
if (tabLink) {
const tab = new bootstrap.Tab(tabLink);
tab.show();
selected_tab = tabLink.getAttribute("id");
switch (selected_tab) {
case "comments-tab":
loadComments();
break;
case "bundles-tab":
loadBundles();
break;
case "sightings-tab":
loadSightings();
break;
default:
console.log("Not a valid day.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid day?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha, it comes from previous tests of the switch statement. I just removed this console.log. Now it opens the tag of related vulnerabilities, in case the anchor in not correct.

}
}
// Update the URL when a tab is clicked, for consistent behavior
document.querySelectorAll('.nav-link[data-bs-toggle="tab"]').forEach(tabLink => {
tabLink.addEventListener("shown.bs.tab", function(event) {
history.replaceState(null, null, event.target.getAttribute("href"));
});
});
};


if (document.getElementById("deleteVulnerability")) {
document.getElementById("deleteVulnerability").onclick = function(event) {
if (!confirm('You are going to delete the vulnerability. Are you sure?')) {
Expand Down