Skip to content

Commit

Permalink
Merge pull request #163 from canonical/create-endpoint-for-pages
Browse files Browse the repository at this point in the history
Created endpoint with smaller notices
  • Loading branch information
samhotep authored Jul 10, 2024
2 parents 3c31dfa + 6373fc3 commit 936051d
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 17 deletions.
57 changes: 57 additions & 0 deletions tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,63 @@ def test_usn(self):
assert response.status_code == 200
assert response.json["cves_ids"] == self.models["notice"].cves_ids

def test_multiple_usn(self):
response = self.client.get("/security/notices.json")

assert response.status_code == 200
# Should include cve
assert (
self.models["notice"].id
in response.json["notices"][0]["cves"][0]["notices_ids"]
)

def test_page_notice(self):
response = self.client.get("/security/page/notices.json")

assert response.status_code == 200
assert (
response.json["notices"][0]["cves_ids"]
== self.models["notice"].cves_ids
)
# Should not include cves
assert response.json["notices"][0].get("cves") is None

# Test details field
response = self.client.get(
(
"/security/page/notices.json?"
f"details={self.models['notice'].id[:3]}"
)
)

assert response.status_code == 200
assert response.json["notices"][0]["id"] == self.models["notice"].id

# Test cve_id field
response = self.client.get(
(
"/security/page/notices.json"
f"?cve_id={self.models['notice'].cves[0].id}"
)
)

assert response.status_code == 200
assert response.json["notices"][0]["id"] == self.models["notice"].id

# Test release field
response = self.client.get(
(
"/security/page/notices.json?"
f"release={self.models['notice'].releases[0].codename}"
)
)

assert response.status_code == 200
assert (
response.json["notices"][0]["releases"][0]["codename"]
== self.models["notice"].releases[0].codename
)

def test_usns_returns_200_for_non_existing_release(self):
response = self.client.get("/security/notices.json?release=no-exist")

Expand Down
24 changes: 16 additions & 8 deletions webapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@
from webapp.api_spec import WebappFlaskApiSpec
from webapp.database import db
from webapp.views import (
get_cve,
get_notice,
get_cves,
get_notices,
create_notice,
update_notice,
delete_notice,
create_release,
delete_cve,
bulk_upsert_cve,
create_release,
delete_notice,
delete_release,
update_release,
get_cve,
get_cves,
get_notice,
get_notices,
get_page_notices,
get_release,
get_releases,
update_notice,
update_release,
)


Expand Down Expand Up @@ -73,12 +74,19 @@
provide_automatic_options=False,
)

app.add_url_rule(
"/security/page/notices.json",
view_func=get_page_notices,
provide_automatic_options=False,
)

app.add_url_rule(
"/security/releases/<release_codename>.json",
view_func=get_release,
methods=["GET"],
provide_automatic_options=False,
)

app.add_url_rule(
"/security/releases.json",
view_func=get_releases,
Expand Down
13 changes: 13 additions & 0 deletions webapp/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,19 @@ class NoticeAPIDetailedSchema(NoticeAPISchema):
releases = List(Nested(NoticeReleasesSchema))


class PageNoticeAPISchema(NoticeSchema):
cves_ids = List(String(validate=Regexp(r"(cve-|CVE-)\d{4}-\d{4,7}")))
notice_type = String(data_key="type")
releases = List(Nested(NoticeReleasesSchema))


class PageNoticesAPISchema(Schema):
notices = List(Nested(PageNoticeAPISchema))
offset = Int(allow_none=True)
limit = Int(allow_none=True)
total_results = Int()


class CVEAPIDetailedSchema(CVEAPISchema):
notices = List(Nested(NoticeAPISchema))

Expand Down
70 changes: 61 additions & 9 deletions webapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@
STATUS_STATUSES,
)
from webapp.schemas import (
CreateNoticeImportSchema,
CVEAPIDetailedSchema,
CVEImportSchema,
CVEParameter,
CVEsAPISchema,
CVEsParameters,
NoticesParameters,
NoticesAPISchema,
NoticeImportSchema,
MessageSchema,
MessageWithErrorsSchema,
CreateNoticeImportSchema,
CVEImportSchema,
ReleaseSchema,
NoticeParameters,
CVEParameter,
CVEAPIDetailedSchema,
NoticeAPIDetailedSchema,
NoticeImportSchema,
NoticeParameters,
NoticesAPISchema,
NoticesParameters,
PageNoticesAPISchema,
ReleaseAPISchema,
ReleaseSchema,
ReleasesAPISchema,
UpdateReleaseSchema,
)
Expand Down Expand Up @@ -476,6 +477,57 @@ def get_notices(**kwargs):
}


@marshal_with(PageNoticesAPISchema, code=200)
@marshal_with(MessageWithErrorsSchema, code=422)
@use_kwargs(NoticesParameters, location="query")
def get_page_notices(**kwargs):
details = kwargs.get("details")
cve_id = kwargs.get("cve_id")
release = kwargs.get("release")
limit = kwargs.get("limit", 20)
offset = kwargs.get("offset", 0)
order_by = kwargs.get("order")

notices_query: Query = db.session.query(Notice)

if not kwargs.get("show_hidden", False):
notices_query = notices_query.filter(Notice.is_hidden == "False")

if cve_id:
notices_query = notices_query.filter(Notice.cves.any(CVE.id == cve_id))

if release:
notices_query = notices_query.join(Release, Notice.releases).filter(
Release.codename == release
)

if details:
notices_query = notices_query.filter(
or_(
Notice.id.ilike(f"%{details}%"),
Notice.details.ilike(f"%{details}%"),
Notice.title.ilike(f"%{details}%"),
)
)

sort = asc if order_by == "oldest" else desc

notices = (
notices_query.options(selectinload(Notice.releases))
.order_by(sort(Notice.published), sort(Notice.id))
.offset(offset)
.limit(limit)
.all()
)

return {
"notices": notices,
"offset": offset,
"limit": limit,
"total_results": notices_query.count(),
}


@authorization_required
@marshal_with(MessageSchema, code=200)
@marshal_with(MessageWithErrorsSchema, code=422)
Expand Down

0 comments on commit 936051d

Please sign in to comment.