mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Change stuff
This commit is contained in:
parent
c86504836a
commit
5cce6cfdae
9 changed files with 119 additions and 54 deletions
|
@ -1,24 +1,24 @@
|
||||||
# Imports go here!
|
# Imports go here!
|
||||||
from .api_royalnet_version import ApiRoyalnetVersionStar
|
from .api_royalnet_version import ApiRoyalnetVersionStar
|
||||||
from .api_login_royalnet import ApiLoginRoyalnetStar
|
from .api_auth_login_royalnet import ApiAuthLoginRoyalnetStar
|
||||||
from .api_token_info import ApiTokenInfoStar
|
from .api_user_passwd import ApiUserPasswd
|
||||||
from .api_token_passwd import ApiTokenPasswdStar
|
from .api_auth_token import ApiAuthTokenStar
|
||||||
from .api_token_create import ApiTokenCreateStar
|
|
||||||
from .api_user_get import ApiUserGetStar
|
from .api_user_get import ApiUserGetStar
|
||||||
from .api_user_list import ApiUserListStar
|
from .api_user_list import ApiUserListStar
|
||||||
from .api_user_find import ApiUserFindStar
|
from .api_user_find import ApiUserFindStar
|
||||||
|
from .api_user_create import ApiUserCreateStar
|
||||||
from .docs import DocsStar
|
from .docs import DocsStar
|
||||||
|
|
||||||
# Enter the PageStars of your Pack here!
|
# Enter the PageStars of your Pack here!
|
||||||
available_page_stars = [
|
available_page_stars = [
|
||||||
ApiRoyalnetVersionStar,
|
ApiRoyalnetVersionStar,
|
||||||
ApiLoginRoyalnetStar,
|
ApiAuthLoginRoyalnetStar,
|
||||||
ApiTokenInfoStar,
|
ApiUserPasswd,
|
||||||
ApiTokenPasswdStar,
|
ApiAuthTokenStar,
|
||||||
ApiTokenCreateStar,
|
|
||||||
ApiUserGetStar,
|
ApiUserGetStar,
|
||||||
ApiUserListStar,
|
ApiUserListStar,
|
||||||
ApiUserFindStar,
|
ApiUserFindStar,
|
||||||
|
ApiUserCreateStar,
|
||||||
DocsStar,
|
DocsStar,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ from ..tables.users import User
|
||||||
from ..tables.tokens import Token
|
from ..tables.tokens import Token
|
||||||
|
|
||||||
|
|
||||||
class ApiLoginRoyalnetStar(ApiStar):
|
class ApiAuthLoginRoyalnetStar(ApiStar):
|
||||||
path = "/api/login/royalnet/v1"
|
path = "/api/auth/login/royalnet/v1"
|
||||||
|
|
||||||
methods = ["POST"]
|
methods = ["POST"]
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class ApiLoginRoyalnetStar(ApiStar):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tags = ["login"]
|
tags = ["auth"]
|
||||||
|
|
||||||
async def post(self, data: ApiData) -> ru.JSON:
|
async def post(self, data: ApiData) -> ru.JSON:
|
||||||
"""Login with a Royalnet account.
|
"""Login with a Royalnet account.
|
|
@ -5,18 +5,29 @@ from royalnet.constellation.api import *
|
||||||
from ..tables.tokens import Token
|
from ..tables.tokens import Token
|
||||||
|
|
||||||
|
|
||||||
class ApiTokenCreateStar(ApiStar):
|
class ApiAuthTokenStar(ApiStar):
|
||||||
path = "/api/token/create/v1"
|
path = "/api/auth/token/v1"
|
||||||
|
|
||||||
methods = ["POST"]
|
methods = ["GET", "POST"]
|
||||||
|
|
||||||
parameters = {
|
parameters = {
|
||||||
|
"get": {},
|
||||||
"post": {
|
"post": {
|
||||||
"duration": "The duration in seconds of the new token."
|
"duration": "The duration in seconds of the new token."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tags = ["login"]
|
auth = {
|
||||||
|
"get": True,
|
||||||
|
"post": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = ["auth"]
|
||||||
|
|
||||||
|
async def get(self, data: ApiData) -> ru.JSON:
|
||||||
|
"""Get information about the current login token."""
|
||||||
|
token = await data.token()
|
||||||
|
return token.json()
|
||||||
|
|
||||||
async def post(self, data: ApiData) -> ru.JSON:
|
async def post(self, data: ApiData) -> ru.JSON:
|
||||||
"""Create a new login token for the authenticated user.
|
"""Create a new login token for the authenticated user.
|
|
@ -1,13 +0,0 @@
|
||||||
import royalnet.utils as ru
|
|
||||||
from royalnet.constellation.api import *
|
|
||||||
|
|
||||||
|
|
||||||
class ApiTokenInfoStar(ApiStar):
|
|
||||||
path = "/api/token/info/v1"
|
|
||||||
|
|
||||||
tags = ["login"]
|
|
||||||
|
|
||||||
async def get(self, data: ApiData) -> ru.JSON:
|
|
||||||
"""Get information about the current login token."""
|
|
||||||
token = await data.token()
|
|
||||||
return token.json()
|
|
50
royalnet/backpack/stars/api_user_create.py
Normal file
50
royalnet/backpack/stars/api_user_create.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from typing import *
|
||||||
|
import datetime
|
||||||
|
import royalnet.constellation.api as rca
|
||||||
|
import royalnet.utils as ru
|
||||||
|
import royalnet.backpack.tables as rbt
|
||||||
|
from ..tables import *
|
||||||
|
|
||||||
|
|
||||||
|
class ApiUserCreateStar(rca.ApiStar):
|
||||||
|
path = "/api/user/create/v1"
|
||||||
|
|
||||||
|
methods = ["POST"]
|
||||||
|
|
||||||
|
parameters = {
|
||||||
|
"post": {
|
||||||
|
"username": "The name of the user you are creating.",
|
||||||
|
"password": "The password of the user you are creating.",
|
||||||
|
"email": "(Optional) The email of the user you are creating.",
|
||||||
|
"avatar_url": "(Optional) An URL pointing to the avatar of the user you are creating.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = ["user"]
|
||||||
|
|
||||||
|
async def post(self, data: rca.ApiData) -> ru.JSON:
|
||||||
|
"""Create a new Royalnet account."""
|
||||||
|
UserT = self.alchemy.get(User)
|
||||||
|
|
||||||
|
username = data.str("username")
|
||||||
|
password = data.str("password")
|
||||||
|
email = data.str("email", optional=True)
|
||||||
|
avatar_url = data.str("avatar_url", optional=True)
|
||||||
|
|
||||||
|
# Check if the username is used by an user or an alias
|
||||||
|
user = await User.find(self.alchemy, data.session, username)
|
||||||
|
if user is not None:
|
||||||
|
raise rca.InvalidParameterError("An user with that username or alias already exists.")
|
||||||
|
|
||||||
|
# Create the user
|
||||||
|
user = UserT(
|
||||||
|
username=username,
|
||||||
|
email=email,
|
||||||
|
avatar_url=avatar_url
|
||||||
|
)
|
||||||
|
user.set_password(password)
|
||||||
|
user.add_alias(self.alchemy, username)
|
||||||
|
data.session.add(user)
|
||||||
|
await data.session_commit()
|
||||||
|
|
||||||
|
return user.json()
|
|
@ -6,12 +6,12 @@ from sqlalchemy import and_
|
||||||
from ..tables.tokens import Token
|
from ..tables.tokens import Token
|
||||||
|
|
||||||
|
|
||||||
class ApiTokenPasswdStar(ApiStar):
|
class ApiUserPasswd(ApiStar):
|
||||||
path = "/api/token/passwd/v1"
|
path = "/api/user/passwd/v1"
|
||||||
|
|
||||||
methods = ["PUT"]
|
methods = ["PUT"]
|
||||||
|
|
||||||
tags = ["token"]
|
tags = ["user"]
|
||||||
|
|
||||||
parameters = {
|
parameters = {
|
||||||
"put": {
|
"put": {
|
||||||
|
@ -19,10 +19,16 @@ class ApiTokenPasswdStar(ApiStar):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auth = {
|
||||||
|
"put": True
|
||||||
|
}
|
||||||
|
|
||||||
requires_auth = True
|
requires_auth = True
|
||||||
|
|
||||||
async def put(self, data: ApiData) -> ru.JSON:
|
async def put(self, data: ApiData) -> ru.JSON:
|
||||||
"""Change the password of the currently logged in user."""
|
"""Change the password of the currently logged in user.
|
||||||
|
|
||||||
|
This method also revokes all the issued tokens for the user."""
|
||||||
TokenT = self.alchemy.get(Token)
|
TokenT = self.alchemy.get(Token)
|
||||||
token = await data.token()
|
token = await data.token()
|
||||||
user = token.user
|
user = token.user
|
|
@ -42,11 +42,12 @@ class DocsStar(PageStar):
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Royalnet Docs</title>
|
<title>Royalnet Docs</title>
|
||||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.12.1/swagger-ui.css">
|
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.23.4/swagger-ui.css">
|
||||||
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
|
<script src="https://unpkg.com/swagger-ui-dist@3.23.4/swagger-ui-bundle.js"></script>
|
||||||
<script src="https://unpkg.com/swagger-ui-dist@3.12.1/swagger-ui-standalone-preset.js"></script>
|
<script src="https://unpkg.com/swagger-ui-dist@3.23.4/swagger-ui-standalone-preset.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div style="display: none;">{spec}</div>
|
||||||
<div id="docs"/>
|
<div id="docs"/>
|
||||||
<script>
|
<script>
|
||||||
const ui = SwaggerUIBundle({{
|
const ui = SwaggerUIBundle({{
|
||||||
|
|
|
@ -3,36 +3,36 @@ class ApiError(Exception):
|
||||||
|
|
||||||
|
|
||||||
class NotFoundError(ApiError):
|
class NotFoundError(ApiError):
|
||||||
pass
|
"""404"""
|
||||||
|
|
||||||
|
|
||||||
class UnauthorizedError(ApiError):
|
class UnauthorizedError(ApiError):
|
||||||
pass
|
"""401"""
|
||||||
|
|
||||||
|
|
||||||
class ForbiddenError(ApiError):
|
class ForbiddenError(ApiError):
|
||||||
pass
|
"""403"""
|
||||||
|
|
||||||
|
|
||||||
class BadRequestError(ApiError):
|
class BadRequestError(ApiError):
|
||||||
pass
|
"""400"""
|
||||||
|
|
||||||
|
|
||||||
class ParameterError(BadRequestError):
|
class ParameterError(BadRequestError):
|
||||||
pass
|
"""400"""
|
||||||
|
|
||||||
|
|
||||||
class MissingParameterError(ParameterError):
|
class MissingParameterError(ParameterError):
|
||||||
pass
|
"""400"""
|
||||||
|
|
||||||
|
|
||||||
class InvalidParameterError(ParameterError):
|
class InvalidParameterError(ParameterError):
|
||||||
pass
|
"""400"""
|
||||||
|
|
||||||
|
|
||||||
class MethodNotImplementedError(ApiError):
|
class MethodNotImplementedError(ApiError):
|
||||||
pass
|
"""405"""
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedError(MethodNotImplementedError):
|
class UnsupportedError(MethodNotImplementedError):
|
||||||
pass
|
"""405"""
|
||||||
|
|
|
@ -16,6 +16,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class ApiStar(PageStar, ABC):
|
class ApiStar(PageStar, ABC):
|
||||||
parameters: Dict[str, Dict[str, str]] = {}
|
parameters: Dict[str, Dict[str, str]] = {}
|
||||||
|
auth: Dict[str, bool] = {}
|
||||||
|
|
||||||
tags: List[str] = []
|
tags: List[str] = []
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ class ApiStar(PageStar, ABC):
|
||||||
except ForbiddenError as e:
|
except ForbiddenError as e:
|
||||||
return api_error(e, code=403)
|
return api_error(e, code=403)
|
||||||
except MethodNotImplementedError as e:
|
except MethodNotImplementedError as e:
|
||||||
return api_error(e, code=501)
|
return api_error(e, code=405)
|
||||||
except BadRequestError as e:
|
except BadRequestError as e:
|
||||||
return api_error(e, code=400)
|
return api_error(e, code=400)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -63,16 +64,16 @@ class ApiStar(PageStar, ABC):
|
||||||
await apidata.session_close()
|
await apidata.session_close()
|
||||||
|
|
||||||
async def get(self, data: ApiData) -> ru.JSON:
|
async def get(self, data: ApiData) -> ru.JSON:
|
||||||
raise MethodNotImplementedError()
|
raise MethodNotImplementedError("GET is not implemented on this ApiStar")
|
||||||
|
|
||||||
async def post(self, data: ApiData) -> ru.JSON:
|
async def post(self, data: ApiData) -> ru.JSON:
|
||||||
raise MethodNotImplementedError()
|
raise MethodNotImplementedError("POST is not implemented on this ApiStar")
|
||||||
|
|
||||||
async def put(self, data: ApiData) -> ru.JSON:
|
async def put(self, data: ApiData) -> ru.JSON:
|
||||||
raise MethodNotImplementedError()
|
raise MethodNotImplementedError("PUT is not implemented on this ApiStar")
|
||||||
|
|
||||||
async def delete(self, data: ApiData) -> ru.JSON:
|
async def delete(self, data: ApiData) -> ru.JSON:
|
||||||
raise MethodNotImplementedError()
|
raise MethodNotImplementedError("DELETE is not implemented on this ApiStar")
|
||||||
|
|
||||||
def __swagger_for_a_method(self, method: Callable) -> ru.JSON:
|
def __swagger_for_a_method(self, method: Callable) -> ru.JSON:
|
||||||
docstring = method.__doc__ or ""
|
docstring = method.__doc__ or ""
|
||||||
|
@ -85,16 +86,25 @@ class ApiStar(PageStar, ABC):
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"operationId": f"{self.__class__.__name__}_{method.__name__}",
|
"operationId": f"{self.__class__.__name__}_{method.__name__}",
|
||||||
"summary": ru.strip_tabs(summary) if summary is not None else None,
|
"summary": ru.strip_tabs(summary) if summary is not None else "",
|
||||||
"description": ru.strip_tabs(description) if description is not None else None,
|
"description": ru.strip_tabs(description) if description is not None else "",
|
||||||
"tags": self.tags,
|
"tags": self.tags,
|
||||||
"security": [{"RoyalnetLoginToken": ["logged_in"]}],
|
"security": [{"RoyalnetLoginToken": ["logged_in"]}] if self.auth.get(method.__name__) else [],
|
||||||
"parameters": [{
|
"parameters": [{
|
||||||
"name": parameter_name,
|
"name": parameter_name,
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"description": ru.strip_tabs(self.parameters[method.__name__][parameter_name]),
|
"description": ru.strip_tabs(self.parameters[method.__name__][parameter_name]),
|
||||||
"type": "string",
|
"schema": {},
|
||||||
} for parameter_name in self.parameters.get(method.__name__, [])]
|
} for parameter_name in self.parameters.get(method.__name__, [])],
|
||||||
|
"responses": {
|
||||||
|
"200": {"description": "✅ OK!"},
|
||||||
|
"400": {"description": "⚠️ Missing or invalid parameter."},
|
||||||
|
"401": {"description": "⚠️ Invalid password."},
|
||||||
|
"403": {"description": "⚠️ Missing or invalid token."},
|
||||||
|
"404": {"description": "⚠️ Not found."},
|
||||||
|
"405": {"description": "⚠️ Unsupported method."},
|
||||||
|
"500": {"description": "⛔️ Serverside unhandled exception!"},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def swagger(self) -> ru.JSON:
|
def swagger(self) -> ru.JSON:
|
||||||
|
|
Loading…
Reference in a new issue