mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Add basic login token creation
This commit is contained in:
parent
353b94f1ba
commit
741b9f50db
11 changed files with 99 additions and 13 deletions
|
@ -1,10 +1,12 @@
|
|||
# Imports go here!
|
||||
from .api_royalnet_version import ApiRoyalnetVersionStar
|
||||
from .api_royalnet_login import ApiRoyalnetLoginStar
|
||||
|
||||
|
||||
# Enter the PageStars of your Pack here!
|
||||
available_page_stars = [
|
||||
ApiRoyalnetVersionStar,
|
||||
ApiRoyalnetLoginStar,
|
||||
]
|
||||
|
||||
# Don't change this, it should automatically generate __all__
|
||||
|
|
32
royalnet/backpack/stars/api_royalnet_login.py
Normal file
32
royalnet/backpack/stars/api_royalnet_login.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import datetime
|
||||
import royalnet.utils as ru
|
||||
from royalnet.constellation.api import *
|
||||
from ..tables.users import User
|
||||
from ..tables.aliases import Alias
|
||||
from ..tables.tokens import Token
|
||||
|
||||
|
||||
class ApiRoyalnetLoginStar(ApiStar):
|
||||
path = "/api/royalnet/login/v1"
|
||||
|
||||
async def api(self, data: ApiDataDict) -> dict:
|
||||
TokenT = self.alchemy.get(Token)
|
||||
UserT = self.alchemy.get(User)
|
||||
AliasT = self.alchemy.get(Alias)
|
||||
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
|
||||
async with self.session_acm() as session:
|
||||
user: User = await ru.asyncify(session.query(UserT).filter_by(username=username).one_or_none)
|
||||
if user is None:
|
||||
raise NotFoundException("User not found")
|
||||
pswd_check = user.test_password(password)
|
||||
if not pswd_check:
|
||||
raise ApiError("Invalid password")
|
||||
token: Token = TokenT.generate(user=user, expiration_delta=datetime.timedelta(days=7))
|
||||
session.add(token)
|
||||
await ru.asyncify(session.commit)
|
||||
response = token.json()
|
||||
|
||||
return response
|
|
@ -1,11 +1,11 @@
|
|||
import royalnet.version as rv
|
||||
from royalnet.constellation import ApiStar
|
||||
from royalnet.constellation.api import *
|
||||
|
||||
|
||||
class ApiRoyalnetVersionStar(ApiStar):
|
||||
path = "/api/royalnet/version"
|
||||
path = "/api/royalnet/version/v1"
|
||||
|
||||
async def api(self, data: dict) -> dict:
|
||||
async def api(self, data: ApiDataDict) -> dict:
|
||||
return {
|
||||
"semantic": rv.semantic
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ from .telegram import Telegram
|
|||
from .discord import Discord
|
||||
from .matrix import Matrix
|
||||
from .aliases import Alias
|
||||
from .tokens import Token
|
||||
|
||||
# Enter the tables of your Pack here!
|
||||
available_tables = {
|
||||
|
@ -11,7 +12,8 @@ available_tables = {
|
|||
Telegram,
|
||||
Discord,
|
||||
Matrix,
|
||||
Alias
|
||||
Alias,
|
||||
Token,
|
||||
}
|
||||
|
||||
# Don't change this, it should automatically generate __all__
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
import secrets
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import *
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
|
@ -26,3 +27,16 @@ class Token:
|
|||
@property
|
||||
def expired(self):
|
||||
return datetime.datetime.now() > self.expiration
|
||||
|
||||
@classmethod
|
||||
def generate(cls, user, expiration_delta: datetime.timedelta):
|
||||
# noinspection PyArgumentList
|
||||
token = cls(user=user, expiration=datetime.datetime.now() + expiration_delta, token=secrets.token_urlsafe())
|
||||
return token
|
||||
|
||||
def json(self) -> dict:
|
||||
return {
|
||||
"user": self.user.json(),
|
||||
"token": self.token,
|
||||
"expiration": self.expiration.isoformat()
|
||||
}
|
||||
|
|
|
@ -17,15 +17,9 @@ You can install them with: ::
|
|||
from .constellation import Constellation
|
||||
from .star import Star
|
||||
from .pagestar import PageStar
|
||||
from .apistar import ApiStar
|
||||
from .jsonapi import api_response, api_success, api_error
|
||||
|
||||
__all__ = [
|
||||
"Constellation",
|
||||
"Star",
|
||||
"PageStar",
|
||||
"ApiStar",
|
||||
"api_response",
|
||||
"api_success",
|
||||
"api_error",
|
||||
]
|
||||
|
|
16
royalnet/constellation/api/__init__.py
Normal file
16
royalnet/constellation/api/__init__.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from .apistar import ApiStar
|
||||
from .jsonapi import api_response, api_success, api_error
|
||||
from .apidatadict import ApiDataDict
|
||||
from .apierrors import ApiError, MissingParameterException, NotFoundException, UnauthorizedException
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ApiStar",
|
||||
"api_response",
|
||||
"api_success",
|
||||
"api_error",
|
||||
"ApiDataDict",
|
||||
"ApiError",
|
||||
"MissingParameterException",
|
||||
"NotFoundException",
|
||||
]
|
6
royalnet/constellation/api/apidatadict.py
Normal file
6
royalnet/constellation/api/apidatadict.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from .apierrors import MissingParameterException
|
||||
|
||||
|
||||
class ApiDataDict(dict):
|
||||
def __missing__(self, key):
|
||||
raise MissingParameterException(f"Missing '{key}'")
|
14
royalnet/constellation/api/apierrors.py
Normal file
14
royalnet/constellation/api/apierrors.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
class ApiError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NotFoundException(ApiError):
|
||||
pass
|
||||
|
||||
|
||||
class UnauthorizedException(ApiError):
|
||||
pass
|
||||
|
||||
|
||||
class MissingParameterException(ApiError):
|
||||
pass
|
|
@ -3,8 +3,10 @@ from json import JSONDecodeError
|
|||
from abc import *
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
from .pagestar import PageStar
|
||||
from ..pagestar import PageStar
|
||||
from .jsonapi import api_error, api_success
|
||||
from .apidatadict import ApiDataDict
|
||||
from .apierrors import ApiError, NotFoundException
|
||||
|
||||
|
||||
class ApiStar(PageStar, ABC):
|
||||
|
@ -17,9 +19,13 @@ class ApiStar(PageStar, ABC):
|
|||
except JSONDecodeError:
|
||||
data = {}
|
||||
try:
|
||||
response = await self.api(data)
|
||||
response = await self.api(ApiDataDict(data))
|
||||
except NotFoundException as e:
|
||||
return api_error(e, code=404)
|
||||
except ApiError as e:
|
||||
return api_error(e, code=400)
|
||||
except Exception as e:
|
||||
return api_error(e)
|
||||
return api_error(e, code=500)
|
||||
return api_success(response)
|
||||
|
||||
async def api(self, data: dict) -> dict:
|
Loading…
Reference in a new issue