mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-10-20 11:47:57 +00:00
this project is actively using optional imports, which leads to duplicate handling here and there. This commit implements logic in special method to reduce complexity and simplify tests paths
100 lines
3.3 KiB
Python
100 lines
3.3 KiB
Python
#
|
|
# Copyright (c) 2021-2026 ahriman team.
|
|
#
|
|
# This file is part of ahriman
|
|
# (see https://github.com/arcan1s/ahriman).
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
from aiohttp.web import Response, json_response
|
|
from collections.abc import Callable
|
|
from typing import ClassVar
|
|
|
|
from ahriman.core.configuration import Configuration
|
|
from ahriman.core.utils import partition
|
|
from ahriman.models.user_access import UserAccess
|
|
from ahriman.web.apispec import aiohttp_apispec
|
|
from ahriman.web.views.base import BaseView
|
|
|
|
|
|
class SwaggerView(BaseView):
|
|
"""
|
|
api docs specification view
|
|
|
|
Attributes:
|
|
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
|
"""
|
|
|
|
GET_PERMISSION: ClassVar[UserAccess] = UserAccess.Unauthorized
|
|
ROUTES = ["/api-docs/swagger.json"]
|
|
|
|
@classmethod
|
|
def routes(cls, configuration: Configuration) -> list[str]:
|
|
"""
|
|
extract routes list for the view
|
|
|
|
Args:
|
|
configuration(Configuration): configuration instance
|
|
|
|
Returns:
|
|
list[str]: list of routes defined for the view. By default, it tries to read :attr:`ROUTES` option if set
|
|
and returns empty list otherwise
|
|
"""
|
|
if not aiohttp_apispec:
|
|
return []
|
|
return cls.ROUTES
|
|
|
|
async def get(self) -> Response:
|
|
"""
|
|
get api specification
|
|
|
|
Returns:
|
|
Response: 200 with JSON api specification
|
|
"""
|
|
spec = self.request.app["swagger_dict"]
|
|
is_body_parameter: Callable[[dict[str, str]], bool] = lambda p: p["in"] == "body" or p["in"] == "formData"
|
|
|
|
# special workaround because it writes request body to parameters section
|
|
paths = spec["paths"]
|
|
for methods in paths.values():
|
|
for method in methods.values():
|
|
if "parameters" not in method:
|
|
continue
|
|
|
|
body, other = partition(method["parameters"], is_body_parameter)
|
|
if not body:
|
|
continue # there were no ``body`` parameters found
|
|
|
|
schema = next(iter(body))
|
|
content_type = "multipart/form-data" if schema["in"] == "formData" else "application/json"
|
|
|
|
# there should be only one body parameters
|
|
method["requestBody"] = {
|
|
"content": {
|
|
content_type: {
|
|
"schema": schema["schema"]
|
|
}
|
|
}
|
|
}
|
|
method["parameters"] = other
|
|
|
|
# inject security schema
|
|
spec["components"]["securitySchemes"] = {
|
|
key: value
|
|
for schema in spec["security"]
|
|
for key, value in schema.items()
|
|
}
|
|
|
|
return json_response(spec)
|