mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Report number of checked endpoints in the result and warn if the number of specified endpoints in FTL and the OpenAPI specs do not match
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
openapi: 3.0.2
|
||||
components:
|
||||
paths:
|
||||
docs:
|
||||
summary: Pi-hole's API documentation
|
||||
get:
|
||||
summary: Get the embedded API documentation rendered as HTML
|
||||
tags:
|
||||
- "Documentation"
|
||||
operationId: "get_docs"
|
||||
security: []
|
||||
description: |
|
||||
This API hook returns the embedded API documentation rendered as HTML.
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
description: HTML document
|
||||
type: string
|
||||
format: binary
|
||||
@@ -1193,9 +1193,9 @@ components:
|
||||
required: false
|
||||
example: 219
|
||||
message_id:
|
||||
in: query
|
||||
in: path
|
||||
description: ID of the message to be deleted
|
||||
name: id
|
||||
name: message_id
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
|
||||
@@ -285,7 +285,7 @@ components:
|
||||
device_id:
|
||||
in: path
|
||||
description: Device ID
|
||||
name: id
|
||||
name: device_id
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
|
||||
+21
-20
@@ -71,29 +71,30 @@ if __name__ == "__main__":
|
||||
|
||||
# Verify that all the endpoint defined by GET /api/endpoints are documented
|
||||
# and that there are no undocumented endpoints
|
||||
print("Verifying the /api/endpoints endpoint...")
|
||||
verifyer = ResponseVerifyer(ftl, openapi)
|
||||
errors = verifyer.verify_endpoints()
|
||||
if len(errors) == 0:
|
||||
print(" GET /api/endpoints: OK")
|
||||
else:
|
||||
print(" Errors:")
|
||||
for error in errors:
|
||||
print(" - " + error)
|
||||
errs[2] += len(errors)
|
||||
print("Comparing all endpoints defined in FTL against the OpenAPI specs...")
|
||||
with ResponseVerifyer(ftl, openapi) as verifyer:
|
||||
errors, checked = verifyer.verify_endpoints()
|
||||
if len(errors) == 0:
|
||||
print(" OK (" + str(checked) + " endpoints checked)")
|
||||
else:
|
||||
print(" Errors (" + str(checked) + " endpoints checked):")
|
||||
for error in errors:
|
||||
print(" - " + error)
|
||||
errs[2] += len(errors)
|
||||
print("")
|
||||
|
||||
# Verify FTL Teleporter import
|
||||
print("Verifying FTL Teleporter import...")
|
||||
verifyer = ResponseVerifyer(ftl, openapi)
|
||||
errors = verifyer.verify_teleporter_zip(teleporter)
|
||||
if len(errors) == 0:
|
||||
print(" POST /api/teleporter: OK")
|
||||
else:
|
||||
print(" Errors:")
|
||||
for error in errors:
|
||||
print(" - " + error)
|
||||
errs[2] += len(errors)
|
||||
|
||||
with ResponseVerifyer(ftl, openapi) as verifyer:
|
||||
errors = verifyer.verify_teleporter_zip(teleporter)
|
||||
if len(errors) == 0:
|
||||
print(" POST /api/teleporter: OK")
|
||||
else:
|
||||
print(" Errors:")
|
||||
for error in errors:
|
||||
print(" - " + error)
|
||||
errs[2] += len(errors)
|
||||
print("")
|
||||
|
||||
# Print the number error (if any)
|
||||
if errs[0] > 0:
|
||||
|
||||
@@ -355,6 +355,8 @@ class ResponseVerifyer():
|
||||
|
||||
|
||||
def verify_endpoints(self):
|
||||
checked_ftl = 0
|
||||
checked_openapi = 0
|
||||
# Get FTL response
|
||||
authentication_method = random.choice([a for a in AuthenticationMethods])
|
||||
FTLresponse = self.ftl.GET("/api/endpoints", authenticate = authentication_method)
|
||||
@@ -379,17 +381,13 @@ class ResponseVerifyer():
|
||||
if method not in self.openapi.METHODS:
|
||||
# Skip keys like "parameters" and "summary"
|
||||
continue
|
||||
#if "parameters" in self.openapi.paths[endpoint][method]:
|
||||
# # Construct full URI to check (this is what we specify in OpenAPI specs)
|
||||
# for param in self.openapi.paths[endpoint][method]["parameters"]:
|
||||
# if param["in"] == "query":
|
||||
# endpoint += "?" + param["name"] + "=" + urllib.parse.quote_plus(str(param["example"]))
|
||||
openapi[endpoint][method] = endpoint
|
||||
|
||||
# Check if FTL reports endpoints not defined in the API specs
|
||||
for method in FTLresponse['endpoints']:
|
||||
for endpoint in FTLresponse['endpoints'][method]:
|
||||
m = method.upper() # type: str
|
||||
checked_ftl += 1
|
||||
if endpoint["full_uri"] not in self.openapi.paths or method not in self.openapi.paths[endpoint["full_uri"]]:
|
||||
self.errors.append("Endpoint " + m + " " + endpoint["full_uri"] + " not found in the OpenAPI specs")
|
||||
|
||||
@@ -397,8 +395,14 @@ class ResponseVerifyer():
|
||||
for endpoint in openapi:
|
||||
for method in openapi[endpoint]:
|
||||
full_uris = [ep["full_uri"] for ep in FTLresponse['endpoints'][method]] # type: list[str]
|
||||
checked_openapi += 1
|
||||
if endpoint not in full_uris:
|
||||
m = method.upper() # type: str
|
||||
self.errors.append("Endpoint " + m + " " + endpoint + " not found in FTL endpoints")
|
||||
|
||||
return self.errors
|
||||
# Check if the number of endpoints checked is the same
|
||||
if checked_ftl != checked_openapi:
|
||||
self.errors.append("Number of endpoints checked does not match (FTL " + str(checked_ftl) + " vs. OpenAPI " + str(checked_openapi) + ")")
|
||||
|
||||
checked = max(checked_ftl, checked_openapi)
|
||||
return self.errors, checked
|
||||
|
||||
Reference in New Issue
Block a user