mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-09-01 14:29:55 +00:00
Docstring update (#58)
* migrate docstrings from reST to google format * add raises note Also change behaviour of the `from_option` method to fallback to disabled instead of raising exception on unknown option * fix part of warnings for sphinx * make identation a bit more readable * review fixes * add verbose description for properties to make them parsed by sphinx extenstion * add demo sphinx generator
This commit is contained in:
@ -39,21 +39,29 @@ from ahriman.web.middlewares import HandlerType, MiddlewareType
|
||||
class AuthorizationPolicy(aiohttp_security.AbstractAuthorizationPolicy): # type: ignore
|
||||
"""
|
||||
authorization policy implementation
|
||||
:ivar validator: validator instance
|
||||
|
||||
Attributes:
|
||||
validator(Auth): validator instance
|
||||
"""
|
||||
|
||||
def __init__(self, validator: Auth) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param validator: authorization module instance
|
||||
|
||||
Args:
|
||||
validator(Auth): authorization module instance
|
||||
"""
|
||||
self.validator = validator
|
||||
|
||||
async def authorized_userid(self, identity: str) -> Optional[str]:
|
||||
"""
|
||||
retrieve authenticated username
|
||||
:param identity: username
|
||||
:return: user identity (username) in case if user exists and None otherwise
|
||||
|
||||
Args:
|
||||
identity(str): username
|
||||
|
||||
Returns:
|
||||
Optional[str]: user identity (username) in case if user exists and None otherwise
|
||||
"""
|
||||
user = UserIdentity.from_identity(identity)
|
||||
if user is None:
|
||||
@ -63,10 +71,14 @@ class AuthorizationPolicy(aiohttp_security.AbstractAuthorizationPolicy): # type
|
||||
async def permits(self, identity: str, permission: UserAccess, context: Optional[str] = None) -> bool:
|
||||
"""
|
||||
check user permissions
|
||||
:param identity: username
|
||||
:param permission: requested permission level
|
||||
:param context: URI request path
|
||||
:return: True in case if user is allowed to perform this request and False otherwise
|
||||
|
||||
Args:
|
||||
identity(str): username
|
||||
permission(UserAccess): requested permission level
|
||||
context(Optional[str], optional): URI request path (Default value = None)
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is allowed to perform this request and False otherwise
|
||||
"""
|
||||
user = UserIdentity.from_identity(identity)
|
||||
if user is None:
|
||||
@ -77,7 +89,9 @@ class AuthorizationPolicy(aiohttp_security.AbstractAuthorizationPolicy): # type
|
||||
def auth_handler() -> MiddlewareType:
|
||||
"""
|
||||
authorization and authentication middleware
|
||||
:return: built middleware
|
||||
|
||||
Returns:
|
||||
MiddlewareType: built middleware
|
||||
"""
|
||||
@middleware
|
||||
async def handle(request: Request, handler: HandlerType) -> StreamResponse:
|
||||
@ -99,9 +113,13 @@ def auth_handler() -> MiddlewareType:
|
||||
def setup_auth(application: web.Application, validator: Auth) -> web.Application:
|
||||
"""
|
||||
setup authorization policies for the application
|
||||
:param application: web application instance
|
||||
:param validator: authorization module instance
|
||||
:return: configured web application
|
||||
|
||||
Args:
|
||||
application(web.Application): web application instance
|
||||
validator(Auth): authorization module instance
|
||||
|
||||
Returns:
|
||||
web.Application: configured web application
|
||||
"""
|
||||
fernet_key = fernet.Fernet.generate_key()
|
||||
secret_key = base64.urlsafe_b64decode(fernet_key)
|
||||
|
@ -28,8 +28,12 @@ from ahriman.web.middlewares import HandlerType, MiddlewareType
|
||||
def exception_handler(logger: Logger) -> MiddlewareType:
|
||||
"""
|
||||
exception handler middleware. Just log any exception (except for client ones)
|
||||
:param logger: class logger
|
||||
:return: built middleware
|
||||
|
||||
Args:
|
||||
logger(Logger): class logger
|
||||
|
||||
Returns:
|
||||
MiddlewareType: built middleware
|
||||
"""
|
||||
@middleware
|
||||
async def handle(request: Request, handler: HandlerType) -> StreamResponse:
|
||||
@ -40,8 +44,8 @@ def exception_handler(logger: Logger) -> MiddlewareType:
|
||||
except HTTPServerError as e:
|
||||
logger.exception("server exception during performing request to %s", request.path)
|
||||
return json_response(data={"error": e.reason}, status=e.status_code)
|
||||
except HTTPException:
|
||||
raise # just raise 2xx and 3xx codes
|
||||
except HTTPException: # just raise 2xx and 3xx codes
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.exception("unknown exception during performing request to %s", request.path)
|
||||
return json_response(data={"error": str(e)}, status=500)
|
||||
|
@ -39,37 +39,38 @@ def setup_routes(application: Application, static_path: Path) -> None:
|
||||
|
||||
Available routes are:
|
||||
|
||||
GET / get build status page
|
||||
GET /index.html same as above
|
||||
* GET / get build status page
|
||||
* GET /index.html same as above
|
||||
|
||||
POST /service-api/v1/add add new packages to repository
|
||||
* POST /service-api/v1/add add new packages to repository
|
||||
|
||||
POST /service-api/v1/remove remove existing package from repository
|
||||
* POST /service-api/v1/remove remove existing package from repository
|
||||
|
||||
POST /service-api/v1/request request to add new packages to repository
|
||||
* POST /service-api/v1/request request to add new packages to repository
|
||||
|
||||
GET /service-api/v1/search search for substring in AUR
|
||||
* GET /service-api/v1/search search for substring in AUR
|
||||
|
||||
POST /service-api/v1/update update packages in repository, actually it is just alias for add
|
||||
* POST /service-api/v1/update update packages in repository, actually it is just alias for add
|
||||
|
||||
GET /status-api/v1/ahriman get current service status
|
||||
POST /status-api/v1/ahriman update service status
|
||||
* GET /status-api/v1/ahriman get current service status
|
||||
* POST /status-api/v1/ahriman update service status
|
||||
|
||||
GET /status-api/v1/packages get all known packages
|
||||
POST /status-api/v1/packages force update every package from repository
|
||||
* GET /status-api/v1/packages get all known packages
|
||||
* POST /status-api/v1/packages force update every package from repository
|
||||
|
||||
DELETE /status-api/v1/package/:base delete package base from status page
|
||||
GET /status-api/v1/package/:base get package base status
|
||||
POST /status-api/v1/package/:base update package base status
|
||||
* DELETE /status-api/v1/package/:base delete package base from status page
|
||||
* GET /status-api/v1/package/:base get package base status
|
||||
* POST /status-api/v1/package/:base update package base status
|
||||
|
||||
GET /status-api/v1/status get web service status itself
|
||||
* GET /status-api/v1/status get web service status itself
|
||||
|
||||
GET /user-api/v1/login OAuth2 handler for login
|
||||
POST /user-api/v1/login login to service
|
||||
POST /user-api/v1/logout logout from service
|
||||
* GET /user-api/v1/login OAuth2 handler for login
|
||||
* POST /user-api/v1/login login to service
|
||||
* POST /user-api/v1/logout logout from service
|
||||
|
||||
:param application: web application instance
|
||||
:param static_path: path to static files directory
|
||||
Args:
|
||||
application(Application): web application instance
|
||||
static_path(Path): path to static files directory
|
||||
"""
|
||||
application.router.add_get("/", IndexView, allow_head=True)
|
||||
application.router.add_get("/index.html", IndexView, allow_head=True)
|
||||
|
@ -38,7 +38,10 @@ class BaseView(View):
|
||||
@property
|
||||
def configuration(self) -> Configuration:
|
||||
"""
|
||||
:return: configuration instance
|
||||
get configuration instance
|
||||
|
||||
Returns:
|
||||
Configuration: configuration instance
|
||||
"""
|
||||
configuration: Configuration = self.request.app["configuration"]
|
||||
return configuration
|
||||
@ -46,7 +49,10 @@ class BaseView(View):
|
||||
@property
|
||||
def database(self) -> SQLite:
|
||||
"""
|
||||
:return: database instance
|
||||
get database instance
|
||||
|
||||
Returns:
|
||||
SQLite: database instance
|
||||
"""
|
||||
database: SQLite = self.request.app["database"]
|
||||
return database
|
||||
@ -54,7 +60,10 @@ class BaseView(View):
|
||||
@property
|
||||
def service(self) -> Watcher:
|
||||
"""
|
||||
:return: build status watcher instance
|
||||
get status watcher instance
|
||||
|
||||
Returns:
|
||||
Watcher: build status watcher instance
|
||||
"""
|
||||
watcher: Watcher = self.request.app["watcher"]
|
||||
return watcher
|
||||
@ -62,7 +71,10 @@ class BaseView(View):
|
||||
@property
|
||||
def spawner(self) -> Spawn:
|
||||
"""
|
||||
:return: external process spawner instance
|
||||
get process spawner instance
|
||||
|
||||
Returns:
|
||||
Spawn: external process spawner instance
|
||||
"""
|
||||
spawner: Spawn = self.request.app["spawn"]
|
||||
return spawner
|
||||
@ -70,7 +82,10 @@ class BaseView(View):
|
||||
@property
|
||||
def validator(self) -> Auth:
|
||||
"""
|
||||
:return: authorization service instance
|
||||
get authorization instance
|
||||
|
||||
Returns:
|
||||
Auth: authorization service instance
|
||||
"""
|
||||
validator: Auth = self.request.app["validator"]
|
||||
return validator
|
||||
@ -79,8 +94,12 @@ class BaseView(View):
|
||||
async def get_permission(cls: Type[BaseView], request: Request) -> UserAccess:
|
||||
"""
|
||||
retrieve user permission from the request
|
||||
:param request: request object
|
||||
:return: extracted permission
|
||||
|
||||
Args:
|
||||
request(Request): request object
|
||||
|
||||
Returns:
|
||||
UserAccess: extracted permission
|
||||
"""
|
||||
permission: UserAccess = getattr(cls, f"{request.method.upper()}_PERMISSION", UserAccess.Write)
|
||||
return permission
|
||||
@ -88,8 +107,13 @@ class BaseView(View):
|
||||
async def extract_data(self, list_keys: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
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
|
||||
|
||||
Args:
|
||||
list_keys(Optional[List[str]], optional): optional list of keys which must be forced to list from form data
|
||||
(Default value = None)
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: raw json object or form data converted to json
|
||||
"""
|
||||
try:
|
||||
json: Dict[str, Any] = await self.request.json()
|
||||
@ -100,8 +124,13 @@ class BaseView(View):
|
||||
async def data_as_json(self, list_keys: List[str]) -> Dict[str, Any]:
|
||||
"""
|
||||
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
|
||||
|
||||
Args:
|
||||
list_keys(List[str]): list of keys which must be forced to list from form data
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 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()
|
||||
json: Dict[str, Any] = {}
|
||||
|
@ -31,35 +31,37 @@ from ahriman.web.views.base import BaseView
|
||||
class IndexView(BaseView):
|
||||
"""
|
||||
root view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
|
||||
It uses jinja2 templates for report generation, the following variables are allowed:
|
||||
|
||||
architecture - repository architecture, string, required
|
||||
auth - authorization descriptor, required
|
||||
* authenticated - alias to check if user can see the page, boolean, required
|
||||
* control - HTML to insert for login control, HTML string, required
|
||||
* enabled - whether authorization is enabled by configuration or not, boolean, required
|
||||
* username - authenticated username if any, string, null means not authenticated
|
||||
index_url - url to the repository index, string, optional
|
||||
packages - sorted list of packages properties, required
|
||||
* base, string
|
||||
* depends, sorted list of strings
|
||||
* groups, sorted list of strings
|
||||
* licenses, sorted list of strings
|
||||
* packages, sorted list of strings
|
||||
* status, string based on enum value
|
||||
* status_color, string based on enum value
|
||||
* timestamp, pretty printed datetime, string
|
||||
* version, string
|
||||
* web_url, string
|
||||
repository - repository name, string, required
|
||||
service - service status properties, required
|
||||
* status, string based on enum value
|
||||
* status_color, string based on enum value
|
||||
* timestamp, pretty printed datetime, string
|
||||
version - ahriman version, string, required
|
||||
* architecture - repository architecture, string, required
|
||||
* auth - authorization descriptor, required
|
||||
* authenticated - alias to check if user can see the page, boolean, required
|
||||
* control - HTML to insert for login control, HTML string, required
|
||||
* enabled - whether authorization is enabled by configuration or not, boolean, required
|
||||
* username - authenticated username if any, string, null means not authenticated
|
||||
* index_url - url to the repository index, string, optional
|
||||
* packages - sorted list of packages properties, required
|
||||
* base, string
|
||||
* depends, sorted list of strings
|
||||
* groups, sorted list of strings
|
||||
* licenses, sorted list of strings
|
||||
* packages, sorted list of strings
|
||||
* status, string based on enum value
|
||||
* status_color, string based on enum value
|
||||
* timestamp, pretty printed datetime, string
|
||||
* version, string
|
||||
* web_url, string
|
||||
* repository - repository name, string, required
|
||||
* service - service status properties, required
|
||||
* status, string based on enum value
|
||||
* status_color, string based on enum value
|
||||
* timestamp, pretty printed datetime, string
|
||||
* version - ahriman version, string, required
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = HEAD_PERMISSION = UserAccess.Safe
|
||||
@ -68,7 +70,9 @@ class IndexView(BaseView):
|
||||
async def get(self) -> Dict[str, Any]:
|
||||
"""
|
||||
process get request. No parameters supported here
|
||||
:return: parameters for jinja template
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: parameters for jinja template
|
||||
"""
|
||||
# some magic to make it jinja-friendly
|
||||
packages = [
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 HTTPBadRequest, HTTPFound, Response
|
||||
from aiohttp.web import HTTPBadRequest, HTTPFound
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.base import BaseView
|
||||
@ -26,21 +26,26 @@ from ahriman.web.views.base import BaseView
|
||||
class AddView(BaseView):
|
||||
"""
|
||||
add package web view
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
POST_PERMISSION = UserAccess.Write
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
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
|
||||
}
|
||||
|
||||
:return: redirect to main page on success
|
||||
>>> {
|
||||
>>> "packages": "ahriman" # either list of packages or package name as in AUR
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if bad data is supplied
|
||||
HTTPFound: in case of success response
|
||||
"""
|
||||
try:
|
||||
data = await self.extract_data(["packages"])
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 HTTPBadRequest, HTTPFound, Response
|
||||
from aiohttp.web import HTTPBadRequest, HTTPFound
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.base import BaseView
|
||||
@ -26,21 +26,26 @@ from ahriman.web.views.base import BaseView
|
||||
class RemoveView(BaseView):
|
||||
"""
|
||||
remove package web view
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
POST_PERMISSION = UserAccess.Write
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
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
|
||||
>>> {
|
||||
>>> "packages": "ahriman", # either list of packages or package name
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if bad data is supplied
|
||||
HTTPFound: in case of success response
|
||||
"""
|
||||
try:
|
||||
data = await self.extract_data(["packages"])
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 HTTPBadRequest, HTTPFound, Response
|
||||
from aiohttp.web import HTTPBadRequest, HTTPFound
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.base import BaseView
|
||||
@ -26,21 +26,26 @@ from ahriman.web.views.base import BaseView
|
||||
class RequestView(BaseView):
|
||||
"""
|
||||
request package web view. It is actually the same as AddView, but without now
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
POST_PERMISSION = UserAccess.Read
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
request to 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
|
||||
}
|
||||
|
||||
:return: redirect to main page on success
|
||||
>>> {
|
||||
>>> "packages": "ahriman" # either list of packages or package name as in AUR
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if bad data is supplied
|
||||
HTTPFound: in case of success response
|
||||
"""
|
||||
try:
|
||||
data = await self.extract_data(["packages"])
|
||||
|
@ -29,8 +29,10 @@ from ahriman.web.views.base import BaseView
|
||||
class SearchView(BaseView):
|
||||
"""
|
||||
AUR search web view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = HEAD_PERMISSION = UserAccess.Read
|
||||
@ -41,7 +43,11 @@ class SearchView(BaseView):
|
||||
|
||||
search string (non empty) must be supplied as `for` parameter
|
||||
|
||||
:return: 200 with found package bases and descriptions sorted by base
|
||||
Returns:
|
||||
Response: 200 with found package bases and descriptions sorted by base
|
||||
|
||||
Raises:
|
||||
HTTPNotFound: if no packages found
|
||||
"""
|
||||
search: List[str] = self.request.query.getall("for", default=[])
|
||||
packages = AUR.multisearch(*search)
|
||||
|
@ -27,9 +27,11 @@ from ahriman.web.views.base import BaseView
|
||||
class AhrimanView(BaseView):
|
||||
"""
|
||||
service status web view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = HEAD_PERMISSION = UserAccess.Read
|
||||
@ -38,20 +40,25 @@ class AhrimanView(BaseView):
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current service status
|
||||
:return: 200 with service status object
|
||||
|
||||
Returns:
|
||||
Response: 200 with service status object
|
||||
"""
|
||||
return json_response(self.service.status.view())
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
update service status
|
||||
|
||||
JSON body must be supplied, the following model is used:
|
||||
{
|
||||
"status": "unknown", # service status string, must be valid `BuildStatusEnum`
|
||||
}
|
||||
|
||||
:return: 204 on success
|
||||
>>> {
|
||||
>>> "status": "unknown", # service status string, must be valid `BuildStatusEnum`
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if bad data is supplied
|
||||
HTTPNoContent: in case of success response
|
||||
"""
|
||||
try:
|
||||
data = await self.extract_data()
|
||||
|
@ -29,10 +29,12 @@ from ahriman.web.views.base import BaseView
|
||||
class PackageView(BaseView):
|
||||
"""
|
||||
package base specific web view
|
||||
:cvar DELETE_PERMISSION: delete permissions of self
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
DELETE_PERMISSION(UserAccess): (class attribute) delete permissions of self
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
DELETE_PERMISSION = POST_PERMISSION = UserAccess.Write
|
||||
@ -41,7 +43,12 @@ class PackageView(BaseView):
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current package base status
|
||||
:return: 200 with package description on success
|
||||
|
||||
Returns:
|
||||
Response: 200 with package description on success
|
||||
|
||||
Raises:
|
||||
HTTPNotFound: if no package was found
|
||||
"""
|
||||
base = self.request.match_info["package"]
|
||||
|
||||
@ -58,28 +65,33 @@ class PackageView(BaseView):
|
||||
]
|
||||
return json_response(response)
|
||||
|
||||
async def delete(self) -> Response:
|
||||
async def delete(self) -> None:
|
||||
"""
|
||||
delete package base from status page
|
||||
:return: 204 on success
|
||||
|
||||
Raises:
|
||||
HTTPNoContent: on success response
|
||||
"""
|
||||
base = self.request.match_info["package"]
|
||||
self.service.remove(base)
|
||||
|
||||
raise HTTPNoContent()
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
update package build status
|
||||
|
||||
JSON body must be supplied, the following model is used:
|
||||
{
|
||||
"status": "unknown", # package build status string, must be valid `BuildStatusEnum`
|
||||
"package": {} # package body (use `dataclasses.asdict` to generate one), optional.
|
||||
# Must be supplied in case if package base is unknown
|
||||
}
|
||||
|
||||
:return: 204 on success
|
||||
>>> {
|
||||
>>> "status": "unknown", # package build status string, must be valid `BuildStatusEnum`
|
||||
>>> "package": {} # package body (use `dataclasses.asdict` to generate one), optional.
|
||||
>>> # Must be supplied in case if package base is unknown
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if bad data is supplied
|
||||
HTTPNoContent: in case of success response
|
||||
"""
|
||||
base = self.request.match_info["package"]
|
||||
data = await self.extract_data()
|
||||
|
@ -26,9 +26,11 @@ from ahriman.web.views.base import BaseView
|
||||
class PackagesView(BaseView):
|
||||
"""
|
||||
global watcher view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = HEAD_PERMISSION = UserAccess.Read
|
||||
@ -37,7 +39,9 @@ class PackagesView(BaseView):
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current packages status
|
||||
:return: 200 with package description on success
|
||||
|
||||
Returns:
|
||||
Response: 200 with package description on success
|
||||
"""
|
||||
response = [
|
||||
{
|
||||
@ -47,10 +51,12 @@ class PackagesView(BaseView):
|
||||
]
|
||||
return json_response(response)
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
reload all packages from repository. No parameters supported here
|
||||
:return: 204 on success
|
||||
|
||||
Raises:
|
||||
HTTPNoContent: on success response
|
||||
"""
|
||||
self.service.load()
|
||||
|
||||
|
@ -29,8 +29,10 @@ from ahriman.web.views.base import BaseView
|
||||
class StatusView(BaseView):
|
||||
"""
|
||||
web service status web view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar HEAD_PERMISSION: head permissions of self
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
HEAD_PERMISSION(UserAccess): (class attribute) head permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = HEAD_PERMISSION = UserAccess.Read
|
||||
@ -38,7 +40,9 @@ class StatusView(BaseView):
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current service status
|
||||
:return: 200 with service status object
|
||||
|
||||
Returns:
|
||||
Response: 200 with service status object
|
||||
"""
|
||||
counters = Counters.from_packages(self.service.packages)
|
||||
status = InternalStatus(
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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, HTTPMethodNotAllowed, HTTPUnauthorized, Response
|
||||
from aiohttp.web import HTTPFound, HTTPMethodNotAllowed, HTTPUnauthorized
|
||||
|
||||
from ahriman.core.auth.helpers import remember
|
||||
from ahriman.models.user_access import UserAccess
|
||||
@ -28,20 +28,25 @@ from ahriman.web.views.base import BaseView
|
||||
class LoginView(BaseView):
|
||||
"""
|
||||
login endpoint view
|
||||
:cvar GET_PERMISSION: get permissions of self
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = POST_PERMISSION = UserAccess.Safe
|
||||
|
||||
async def get(self) -> Response:
|
||||
async def get(self) -> None:
|
||||
"""
|
||||
OAuth2 response handler
|
||||
|
||||
In case if code provided it will do a request to get user email. In case if no code provided it will redirect
|
||||
to authorization url provided by OAuth client
|
||||
|
||||
:return: redirect to main page
|
||||
Raises:
|
||||
HTTPFound: on success response
|
||||
HTTPMethodNotAllowed: in case if method is used, but OAuth is disabled
|
||||
HTTPUnauthorized: if case of authorization error
|
||||
"""
|
||||
from ahriman.core.auth.oauth import OAuth
|
||||
|
||||
@ -62,17 +67,20 @@ class LoginView(BaseView):
|
||||
|
||||
raise HTTPUnauthorized()
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
login user to service
|
||||
|
||||
either JSON body or form data must be supplied the following fields are required:
|
||||
{
|
||||
"username": "username" # username to use for login
|
||||
"password": "pa55w0rd" # password to use for login
|
||||
}
|
||||
|
||||
:return: redirect to main page
|
||||
>>> {
|
||||
>>> "username": "username" # username to use for login
|
||||
>>> "password": "pa55w0rd" # password to use for login
|
||||
>>> }
|
||||
|
||||
Raises:
|
||||
HTTPFound: on success response
|
||||
HTTPUnauthorized: if case of authorization error
|
||||
"""
|
||||
data = await self.extract_data()
|
||||
username = data.get("username")
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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
|
||||
from aiohttp.web import HTTPFound
|
||||
|
||||
from ahriman.core.auth.helpers import check_authorized, forget
|
||||
from ahriman.models.user_access import UserAccess
|
||||
@ -27,15 +27,19 @@ from ahriman.web.views.base import BaseView
|
||||
class LogoutView(BaseView):
|
||||
"""
|
||||
logout endpoint view
|
||||
:cvar POST_PERMISSION: post permissions of self
|
||||
|
||||
Attributes:
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
POST_PERMISSION = UserAccess.Safe
|
||||
|
||||
async def post(self) -> Response:
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
logout user from the service. No parameters supported here
|
||||
:return: redirect to main page
|
||||
|
||||
Raises:
|
||||
HTTPFound: on success response
|
||||
"""
|
||||
await check_authorized(self.request)
|
||||
await forget(self.request, HTTPFound("/"))
|
||||
|
@ -36,7 +36,9 @@ from ahriman.web.routes import setup_routes
|
||||
async def on_shutdown(application: web.Application) -> None:
|
||||
"""
|
||||
web application shutdown handler
|
||||
:param application: web application instance
|
||||
|
||||
Args:
|
||||
application(web.Application): web application instance
|
||||
"""
|
||||
application.logger.warning("server terminated")
|
||||
|
||||
@ -44,7 +46,12 @@ async def on_shutdown(application: web.Application) -> None:
|
||||
async def on_startup(application: web.Application) -> None:
|
||||
"""
|
||||
web application start handler
|
||||
:param application: web application instance
|
||||
|
||||
Args:
|
||||
application(web.Application): web application instance
|
||||
|
||||
Raises:
|
||||
InitializeException: in case if matched could not be loaded
|
||||
"""
|
||||
application.logger.info("server started")
|
||||
try:
|
||||
@ -58,7 +65,9 @@ async def on_startup(application: web.Application) -> None:
|
||||
def run_server(application: web.Application) -> None:
|
||||
"""
|
||||
run web application
|
||||
:param application: web application instance
|
||||
|
||||
Args:
|
||||
application(web.Application): web application instance
|
||||
"""
|
||||
application.logger.info("start server")
|
||||
|
||||
@ -73,10 +82,14 @@ def run_server(application: web.Application) -> None:
|
||||
def setup_service(architecture: str, configuration: Configuration, spawner: Spawn) -> web.Application:
|
||||
"""
|
||||
create web application
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param spawner: spawner thread
|
||||
:return: web application instance
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
spawner(Spawn): spawner thread
|
||||
|
||||
Returns:
|
||||
web.Application: web application instance
|
||||
"""
|
||||
application = web.Application(logger=logging.getLogger("http"))
|
||||
application.on_shutdown.append(on_shutdown)
|
||||
|
Reference in New Issue
Block a user