mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-03 23:33:41 +00:00 
			
		
		
		
	provide service api endpoints
This commit is contained in:
		@ -19,13 +19,17 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
from aiohttp.web import Application
 | 
					from aiohttp.web import Application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.web.views.ahriman import AhrimanView
 | 
					 | 
				
			||||||
from ahriman.web.views.index import IndexView
 | 
					from ahriman.web.views.index import IndexView
 | 
				
			||||||
from ahriman.web.views.login import LoginView
 | 
					from ahriman.web.views.service.add import AddView
 | 
				
			||||||
from ahriman.web.views.logout import LogoutView
 | 
					from ahriman.web.views.service.remove import RemoveView
 | 
				
			||||||
from ahriman.web.views.package import PackageView
 | 
					from ahriman.web.views.service.search import SearchView
 | 
				
			||||||
from ahriman.web.views.packages import PackagesView
 | 
					from ahriman.web.views.service.update import UpdateView
 | 
				
			||||||
from ahriman.web.views.status import StatusView
 | 
					from ahriman.web.views.status.ahriman import AhrimanView
 | 
				
			||||||
 | 
					from ahriman.web.views.status.package import PackageView
 | 
				
			||||||
 | 
					from ahriman.web.views.status.packages import PackagesView
 | 
				
			||||||
 | 
					from ahriman.web.views.status.status import StatusView
 | 
				
			||||||
 | 
					from ahriman.web.views.user.login import LoginView
 | 
				
			||||||
 | 
					from ahriman.web.views.user.logout import LogoutView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_routes(application: Application) -> None:
 | 
					def setup_routes(application: Application) -> None:
 | 
				
			||||||
@ -37,8 +41,13 @@ def setup_routes(application: Application) -> None:
 | 
				
			|||||||
        GET /                                  get build status page
 | 
					        GET /                                  get build status page
 | 
				
			||||||
        GET /index.html                        same as above
 | 
					        GET /index.html                        same as above
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        POST /user-api/v1/login                login to service
 | 
					        POST /service-api/v1/add               add new packages to repository
 | 
				
			||||||
        POST /user-api/v1/logout               logout from service
 | 
					
 | 
				
			||||||
 | 
					        POST /service-api/v1/remove            remove existing package from repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GET /service-api/v1/search             search for substring in AUR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        POST /service-api/v1/update            update existing package in repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        GET /status-api/v1/ahriman             get current service status
 | 
					        GET /status-api/v1/ahriman             get current service status
 | 
				
			||||||
        POST /status-api/v1/ahriman            update service status
 | 
					        POST /status-api/v1/ahriman            update service status
 | 
				
			||||||
@ -52,13 +61,21 @@ def setup_routes(application: Application) -> None:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        GET /status-api/v1/status              get web service status itself
 | 
					        GET /status-api/v1/status              get web service status itself
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        POST /user-api/v1/login                login to service
 | 
				
			||||||
 | 
					        POST /user-api/v1/logout               logout from service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param application: web application instance
 | 
					    :param application: web application instance
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    application.router.add_get("/", IndexView, allow_head=True)
 | 
					    application.router.add_get("/", IndexView, allow_head=True)
 | 
				
			||||||
    application.router.add_get("/index.html", IndexView, allow_head=True)
 | 
					    application.router.add_get("/index.html", IndexView, allow_head=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    application.router.add_post("/user-api/v1/login", LoginView)
 | 
					    application.router.add_post("/service-api/v1/add", AddView)
 | 
				
			||||||
    application.router.add_post("/user-api/v1/logout", LogoutView)
 | 
					
 | 
				
			||||||
 | 
					    application.router.add_post("/service-api/v1/remove", RemoveView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.router.add_get("/service-api/v1/search", SearchView, allow_head=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.router.add_post("/service-api/v1/update", UpdateView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    application.router.add_get("/status-api/v1/ahriman", AhrimanView, allow_head=True)
 | 
					    application.router.add_get("/status-api/v1/ahriman", AhrimanView, allow_head=True)
 | 
				
			||||||
    application.router.add_post("/status-api/v1/ahriman", AhrimanView)
 | 
					    application.router.add_post("/status-api/v1/ahriman", AhrimanView)
 | 
				
			||||||
@ -71,3 +88,6 @@ def setup_routes(application: Application) -> None:
 | 
				
			|||||||
    application.router.add_post("/status-api/v1/packages/{package}", PackageView)
 | 
					    application.router.add_post("/status-api/v1/packages/{package}", PackageView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    application.router.add_get("/status-api/v1/status", StatusView, allow_head=True)
 | 
					    application.router.add_get("/status-api/v1/status", StatusView, allow_head=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.router.add_post("/user-api/v1/login", LoginView)
 | 
				
			||||||
 | 
					    application.router.add_post("/user-api/v1/logout", LogoutView)
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@
 | 
				
			|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
from aiohttp.web import View
 | 
					from aiohttp.web import View
 | 
				
			||||||
from typing import Any, Dict
 | 
					from typing import Any, Dict, List, Optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.auth.auth import Auth
 | 
					from ahriman.core.auth.auth import Auth
 | 
				
			||||||
from ahriman.core.spawn import Spawn
 | 
					from ahriman.core.spawn import Spawn
 | 
				
			||||||
@ -54,20 +54,22 @@ class BaseView(View):
 | 
				
			|||||||
        validator: Auth = self.request.app["validator"]
 | 
					        validator: Auth = self.request.app["validator"]
 | 
				
			||||||
        return validator
 | 
					        return validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def extract_data(self) -> Dict[str, Any]:
 | 
					    async def extract_data(self, list_keys: Optional[List[str]] = None) -> Dict[str, Any]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        extract json data from either json or form data
 | 
					        extract json data from either json or form data
 | 
				
			||||||
 | 
					        :param list_keys: optional list of keys which must be forced to list from form data
 | 
				
			||||||
        :return: raw json object or form data converted to json
 | 
					        :return: raw json object or form data converted to json
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            json: Dict[str, Any] = await self.request.json()
 | 
					            json: Dict[str, Any] = await self.request.json()
 | 
				
			||||||
            return json
 | 
					            return json
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            return await self.data_as_json()
 | 
					            return await self.data_as_json(list_keys or [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def data_as_json(self) -> Dict[str, Any]:
 | 
					    async def data_as_json(self, list_keys: List[str]) -> Dict[str, Any]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        extract form data and convert it to json object
 | 
					        extract form data and convert it to json object
 | 
				
			||||||
 | 
					        :param list_keys: list of keys which must be forced to list from form data
 | 
				
			||||||
        :return: form data converted to json. In case if a key is found multiple times it will be returned as list
 | 
					        :return: form data converted to json. In case if a key is found multiple times it will be returned as list
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        raw = await self.request.post()
 | 
					        raw = await self.request.post()
 | 
				
			||||||
@ -77,6 +79,8 @@ class BaseView(View):
 | 
				
			|||||||
                json[key].append(value)
 | 
					                json[key].append(value)
 | 
				
			||||||
            elif key in json:
 | 
					            elif key in json:
 | 
				
			||||||
                json[key] = [json[key], value]
 | 
					                json[key] = [json[key], value]
 | 
				
			||||||
 | 
					            elif key in list_keys:
 | 
				
			||||||
 | 
					                json[key] = [value]
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                json[key] = value
 | 
					                json[key] = value
 | 
				
			||||||
        return json
 | 
					        return json
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								src/ahriman/web/views/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/ahriman/web/views/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
							
								
								
									
										52
									
								
								src/ahriman/web/views/service/add.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/ahriman/web/views/service/add.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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 HTTPFound, Response, json_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.web.views.base import BaseView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddView(BaseView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add package web view
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def post(self) -> Response:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        add new package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JSON body must be supplied, the following model is used:
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "packages": "ahriman",   # either list of packages or package name as in AUR
 | 
				
			||||||
 | 
					            "build_now": true       # optional flag which runs build
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: redirect to main page on success
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        data = await self.extract_data(["packages"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            now = data.get("build_now") or False
 | 
				
			||||||
 | 
					            packages = data["packages"]
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return json_response(text=str(e), status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.spawner.packages_add(packages, now)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return HTTPFound("/")
 | 
				
			||||||
							
								
								
									
										50
									
								
								src/ahriman/web/views/service/remove.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/ahriman/web/views/service/remove.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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 HTTPFound, Response, json_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.web.views.base import BaseView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RemoveView(BaseView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    remove package web view
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def post(self) -> Response:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        remove existing packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JSON body must be supplied, the following model is used:
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "packages": "ahriman",   # either list of packages or package name
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: redirect to main page on success
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        data = await self.extract_data(["packages"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            packages = data["packages"]
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return json_response(text=str(e), status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.spawner.packages_remove(packages)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return HTTPFound("/")
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/ahriman/web/views/service/search.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/ahriman/web/views/service/search.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					import aur  # type: ignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp.web import Response, json_response
 | 
				
			||||||
 | 
					from typing import Iterator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.web.views.base import BaseView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SearchView(BaseView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    AUR search web view
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get(self) -> Response:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        search packages in AUR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        search string (non empty) must be supplied as `for` parameter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: 200 with found package bases sorted by name
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        search: Iterator[str] = filter(lambda s: len(s) > 3, self.request.query.getall("for", default=[]))
 | 
				
			||||||
 | 
					        search_string = " ".join(search)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not search_string:
 | 
				
			||||||
 | 
					            return json_response(text="Search string must not be empty", status=400)
 | 
				
			||||||
 | 
					        packages = aur.search(search_string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return json_response(sorted(package.package_base for package in packages))
 | 
				
			||||||
							
								
								
									
										50
									
								
								src/ahriman/web/views/service/update.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/ahriman/web/views/service/update.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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 HTTPFound, Response, json_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.web.views.base import BaseView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateView(BaseView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    update package web view
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def post(self) -> Response:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        update existing packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JSON body must be supplied, the following model is used:
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "packages": "ahriman",   # either list of packages or package name
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: redirect to main page on success
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        data = await self.extract_data(["packages"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            packages = data["packages"]
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return json_response(text=str(e), status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.spawner.packages_update(packages)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return HTTPFound("/")
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/ahriman/web/views/status/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/ahriman/web/views/status/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
# You should have received a copy of the GNU General Public License
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
 | 
					from aiohttp.web import HTTPNoContent, Response, json_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.models.build_status import BuildStatusEnum
 | 
					from ahriman.models.build_status import BuildStatusEnum
 | 
				
			||||||
from ahriman.web.views.base import BaseView
 | 
					from ahriman.web.views.base import BaseView
 | 
				
			||||||
@ -51,7 +51,7 @@ class AhrimanView(BaseView):
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            status = BuildStatusEnum(data["status"])
 | 
					            status = BuildStatusEnum(data["status"])
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            raise HTTPBadRequest(text=str(e))
 | 
					            return json_response(text=str(e), status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.service.update_self(status)
 | 
					        self.service.update_self(status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
# You should have received a copy of the GNU General Public License
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
from aiohttp.web import HTTPBadRequest, HTTPNoContent, HTTPNotFound, Response, json_response
 | 
					from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.exceptions import UnknownPackage
 | 
					from ahriman.core.exceptions import UnknownPackage
 | 
				
			||||||
from ahriman.models.build_status import BuildStatusEnum
 | 
					from ahriman.models.build_status import BuildStatusEnum
 | 
				
			||||||
@ -80,11 +80,11 @@ class PackageView(BaseView):
 | 
				
			|||||||
            package = Package.from_json(data["package"]) if "package" in data else None
 | 
					            package = Package.from_json(data["package"]) if "package" in data else None
 | 
				
			||||||
            status = BuildStatusEnum(data["status"])
 | 
					            status = BuildStatusEnum(data["status"])
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            raise HTTPBadRequest(text=str(e))
 | 
					            return json_response(text=str(e), status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.service.update(base, status, package)
 | 
					            self.service.update(base, status, package)
 | 
				
			||||||
        except UnknownPackage:
 | 
					        except UnknownPackage:
 | 
				
			||||||
            raise HTTPBadRequest(text=f"Package {base} is unknown, but no package body set")
 | 
					            return json_response(text=f"Package {base} is unknown, but no package body set", status=400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return HTTPNoContent()
 | 
					        return HTTPNoContent()
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/ahriman/web/views/user/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/ahriman/web/views/user/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021 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/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
import argparse
 | 
					import argparse
 | 
				
			||||||
import aur
 | 
					 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from pytest_mock import MockerFixture
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
@ -8,7 +7,6 @@ from ahriman.application.ahriman import _parser
 | 
				
			|||||||
from ahriman.application.application import Application
 | 
					from ahriman.application.application import Application
 | 
				
			||||||
from ahriman.application.lock import Lock
 | 
					from ahriman.application.lock import Lock
 | 
				
			||||||
from ahriman.core.configuration import Configuration
 | 
					from ahriman.core.configuration import Configuration
 | 
				
			||||||
from ahriman.models.package import Package
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
@ -32,31 +30,6 @@ def args() -> argparse.Namespace:
 | 
				
			|||||||
    return argparse.Namespace(lock=None, force=False, unsafe=False, no_report=True)
 | 
					    return argparse.Namespace(lock=None, force=False, unsafe=False, no_report=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					 | 
				
			||||||
def aur_package_ahriman(package_ahriman: Package) -> aur.Package:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    fixture for AUR package
 | 
					 | 
				
			||||||
    :param package_ahriman: package fixture
 | 
					 | 
				
			||||||
    :return: AUR package test instance
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    return aur.Package(
 | 
					 | 
				
			||||||
        num_votes=None,
 | 
					 | 
				
			||||||
        description=package_ahriman.packages[package_ahriman.base].description,
 | 
					 | 
				
			||||||
        url_path=package_ahriman.web_url,
 | 
					 | 
				
			||||||
        last_modified=None,
 | 
					 | 
				
			||||||
        name=package_ahriman.base,
 | 
					 | 
				
			||||||
        out_of_date=None,
 | 
					 | 
				
			||||||
        id=None,
 | 
					 | 
				
			||||||
        first_submitted=None,
 | 
					 | 
				
			||||||
        maintainer=None,
 | 
					 | 
				
			||||||
        version=package_ahriman.version,
 | 
					 | 
				
			||||||
        license=package_ahriman.packages[package_ahriman.base].licenses,
 | 
					 | 
				
			||||||
        url=None,
 | 
					 | 
				
			||||||
        package_base=package_ahriman.base,
 | 
					 | 
				
			||||||
        package_base_id=None,
 | 
					 | 
				
			||||||
        category_id=None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
 | 
					def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import aur
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
@ -46,6 +47,31 @@ def anyvar(cls: Type[T], strict: bool = False) -> T:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# generic fixtures
 | 
					# generic fixtures
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def aur_package_ahriman(package_ahriman: Package) -> aur.Package:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    fixture for AUR package
 | 
				
			||||||
 | 
					    :param package_ahriman: package fixture
 | 
				
			||||||
 | 
					    :return: AUR package test instance
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return aur.Package(
 | 
				
			||||||
 | 
					        num_votes=None,
 | 
				
			||||||
 | 
					        description=package_ahriman.packages[package_ahriman.base].description,
 | 
				
			||||||
 | 
					        url_path=package_ahriman.web_url,
 | 
				
			||||||
 | 
					        last_modified=None,
 | 
				
			||||||
 | 
					        name=package_ahriman.base,
 | 
				
			||||||
 | 
					        out_of_date=None,
 | 
				
			||||||
 | 
					        id=None,
 | 
				
			||||||
 | 
					        first_submitted=None,
 | 
				
			||||||
 | 
					        maintainer=None,
 | 
				
			||||||
 | 
					        version=package_ahriman.version,
 | 
				
			||||||
 | 
					        license=package_ahriman.packages[package_ahriman.base].licenses,
 | 
				
			||||||
 | 
					        url=None,
 | 
				
			||||||
 | 
					        package_base=package_ahriman.base,
 | 
				
			||||||
 | 
					        package_base_id=None,
 | 
				
			||||||
 | 
					        category_id=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def auth(configuration: Configuration) -> Auth:
 | 
					def auth(configuration: Configuration) -> Auth:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								tests/ahriman/web/views/service/test_views_service_add.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tests/ahriman/web/views/service/test_views_service_add.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					from aiohttp.test_utils import TestClient
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must call post request correctly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/add", json={"packages": ["ahriman"]})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    add_mock.assert_called_with(["ahriman"], False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post_now(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must call post and run build
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/add", json={"packages": ["ahriman"], "build_now": True})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    add_mock.assert_called_with(["ahriman"], True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise exception on missing packages payload
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/add")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 400
 | 
				
			||||||
 | 
					    add_mock.assert_not_called()
 | 
				
			||||||
							
								
								
									
										24
									
								
								tests/ahriman/web/views/service/test_views_service_remove.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/ahriman/web/views/service/test_views_service_remove.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					from aiohttp.test_utils import TestClient
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must call post request correctly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_remove")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/remove", json={"packages": ["ahriman"]})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    add_mock.assert_called_with(["ahriman"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise exception on missing packages payload
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_remove")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/remove")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 400
 | 
				
			||||||
 | 
					    add_mock.assert_not_called()
 | 
				
			||||||
							
								
								
									
										59
									
								
								tests/ahriman/web/views/service/test_views_service_search.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								tests/ahriman/web/views/service/test_views_service_search.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					import aur
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp.test_utils import TestClient
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_get(client: TestClient, aur_package_ahriman: aur.Package, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must call get request correctly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("aur.search", return_value=[aur_package_ahriman])
 | 
				
			||||||
 | 
					    response = await client.get("/service-api/v1/search", params={"for": "ahriman"})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    assert await response.json() == ["ahriman"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_get_exception(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise 400 on empty search string
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    search_mock = mocker.patch("aur.search")
 | 
				
			||||||
 | 
					    response = await client.get("/service-api/v1/search")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 400
 | 
				
			||||||
 | 
					    search_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_get_join(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must join search args with space
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    search_mock = mocker.patch("aur.search")
 | 
				
			||||||
 | 
					    response = await client.get("/service-api/v1/search", params=[("for", "ahriman"), ("for", "maybe")])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    search_mock.assert_called_with("ahriman maybe")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_get_join_filter(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must filter search parameters with less than 3 symbols
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    search_mock = mocker.patch("aur.search")
 | 
				
			||||||
 | 
					    response = await client.get("/service-api/v1/search", params=[("for", "ah"), ("for", "maybe")])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    search_mock.assert_called_with("maybe")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_get_join_filter_empty(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must filter search parameters with less than 3 symbols (empty result)
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    search_mock = mocker.patch("aur.search")
 | 
				
			||||||
 | 
					    response = await client.get("/service-api/v1/search", params=[("for", "ah"), ("for", "ma")])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 400
 | 
				
			||||||
 | 
					    search_mock.assert_not_called()
 | 
				
			||||||
							
								
								
									
										24
									
								
								tests/ahriman/web/views/service/test_views_service_update.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/ahriman/web/views/service/test_views_service_update.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					from aiohttp.test_utils import TestClient
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must call post request correctly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_update")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/update", json={"packages": ["ahriman"]})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    add_mock.assert_called_with(["ahriman"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise exception on missing packages payload
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_update")
 | 
				
			||||||
 | 
					    response = await client.post("/service-api/v1/update")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 400
 | 
				
			||||||
 | 
					    add_mock.assert_not_called()
 | 
				
			||||||
@ -61,9 +61,6 @@ async def test_data_as_json(base: BaseView) -> None:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    json = {"key1": "value1", "key2": ["value2", "value3"], "key3": ["value4", "value5", "value6"]}
 | 
					    json = {"key1": "value1", "key2": ["value2", "value3"], "key3": ["value4", "value5", "value6"]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def get_json():
 | 
					 | 
				
			||||||
        raise ValueError()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async def get_data():
 | 
					    async def get_data():
 | 
				
			||||||
        result = MultiDict()
 | 
					        result = MultiDict()
 | 
				
			||||||
        for key, values in json.items():
 | 
					        for key, values in json.items():
 | 
				
			||||||
@ -74,5 +71,18 @@ async def test_data_as_json(base: BaseView) -> None:
 | 
				
			|||||||
                result.add(key, values)
 | 
					                result.add(key, values)
 | 
				
			||||||
        return result
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    base._request = pytest.helpers.request(base.request.app, "", "", json=get_json, data=get_data)
 | 
					    base._request = pytest.helpers.request(base.request.app, "", "", data=get_data)
 | 
				
			||||||
    assert await base.data_as_json() == json
 | 
					    assert await base.data_as_json([]) == json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_data_as_json_with_list_keys(base: BaseView) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must parse multi value form payload with forced list
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    json = {"key1": "value1"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get_data():
 | 
				
			||||||
 | 
					        return json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    base._request = pytest.helpers.request(base.request.app, "", "", data=get_data)
 | 
				
			||||||
 | 
					    assert await base.data_as_json(["key1"]) == {"key1": ["value1"]}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user