Skip to content

Commit

Permalink
Syntax and refresh revision
Browse files Browse the repository at this point in the history
  • Loading branch information
na-stewart committed Jun 23, 2024
1 parent b217153 commit f405f72
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 36 deletions.
30 changes: 12 additions & 18 deletions sanic_security/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@


async def register(
request: Request, verified: bool = False, disabled: bool = False
request: Request, verified: bool = False, disabled: bool = False
) -> Account:
"""
Registers a new account that can be logged into.
Expand All @@ -65,14 +65,14 @@ async def register(
if await Account.filter(email=email_lower).exists():
raise CredentialsError("An account with this email may already exist.", 409)
elif await Account.filter(
username=validate_username(request.form.get("username"))
username=validate_username(request.form.get("username"))
).exists():
raise CredentialsError("An account with this username may already exist.", 409)
elif (
request.form.get("phone")
and await Account.filter(
phone=validate_phone(request.form.get("phone"))
).exists()
request.form.get("phone")
and await Account.filter(
phone=validate_phone(request.form.get("phone"))
).exists()
):
raise CredentialsError(
"An account with this phone number may already exist.", 409
Expand All @@ -90,7 +90,7 @@ async def register(


async def login(
request: Request, account: Account = None, require_second_factor: bool = False
request: Request, account: Account = None, require_second_factor: bool = False
) -> AuthenticationSession:
"""
Login with email or username (if enabled) and password.
Expand Down Expand Up @@ -195,7 +195,7 @@ async def fulfill_second_factor(request: Request) -> AuthenticationSession:
return authentication_session


async def authenticate(request: Request) -> AuthenticationSession:
async def authenticate(request: Request) -> tuple[bool, AuthenticationSession]:
"""
Validates client's authentication session and account.
Expand All @@ -220,11 +220,8 @@ async def authenticate(request: Request) -> AuthenticationSession:
authentication_session.validate()
if not authentication_session.anonymous:
authentication_session.bearer.validate()
except ExpiredError as e:
if security_config.AUTHENTICATION_REFRESH_AUTO:
authentication_session = await authentication_session.refresh(request)
else:
raise e
except ExpiredError:
authentication_session = await authentication_session.refresh(request)
return authentication_session


Expand Down Expand Up @@ -258,10 +255,7 @@ async def wrapper(request, *args, **kwargs):

return wrapper

if callable(arg):
return decorator(arg)
else:
return decorator
return decorator(arg) if callable(arg) else decorator


def create_initial_admin_account(app: Sanic) -> None:
Expand Down Expand Up @@ -356,7 +350,7 @@ def validate_phone(phone: str) -> str:
CredentialsError
"""
if phone and not re.search(
r"^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$", phone
r"^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$", phone
):
raise CredentialsError("Please use a valid phone number.", 400)
return phone
Expand Down
4 changes: 0 additions & 4 deletions sanic_security/configuration.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from os import environ

from sanic.utils import str_to_bool
from sanic.log import logger

"""
Copyright (c) 2020-present Nicholas Aidan Stewart
Expand Down Expand Up @@ -41,7 +40,6 @@
"TWO_STEP_SESSION_EXPIRATION": 300,
"AUTHENTICATION_SESSION_EXPIRATION": 86400,
"AUTHENTICATION_REFRESH_EXPIRATION": 2592000,
"AUTHENTICATION_REFRESH_AUTO": True,
"ALLOW_LOGIN_WITH_USERNAME": False,
"INITIAL_ADMIN_EMAIL": "[email protected]",
"INITIAL_ADMIN_PASSWORD": "admin123",
Expand All @@ -68,7 +66,6 @@ class Config(dict):
TWO_STEP_SESSION_EXPIRATION (int): The amount of seconds till two-step session expiration on creation. Setting to 0 will disable expiration.
AUTHENTICATION_SESSION_EXPIRATION (int): The amount of seconds till authentication session expiration on creation. Setting to 0 will disable expiration.
AUTHENTICATION_REFRESH_EXPIRATION (int): The amount of seconds till authentication session refresh expiration.
AUTHENTICATION_REFRESH_AUTO (bool): Expired sessions will be automatically refreshed and passed into endpoint on authentication attempt, requires session to be re-encoded.
ALLOW_LOGIN_WITH_USERNAME (bool): Allows login via username and email.
INITIAL_ADMIN_EMAIL (str): Email used when creating the initial admin account.
INITIAL_ADMIN_PASSWORD (str): Password used when creating the initial admin account.
Expand All @@ -89,7 +86,6 @@ class Config(dict):
TWO_STEP_SESSION_EXPIRATION: int
AUTHENTICATION_SESSION_EXPIRATION: int
AUTHENTICATION_REFRESH_EXPIRATION: int
AUTHENTICATION_REFRESH_AUTO: bool
ALLOW_LOGIN_WITH_USERNAME: bool
INITIAL_ADMIN_EMAIL: str
INITIAL_ADMIN_PASSWORD: str
Expand Down
14 changes: 9 additions & 5 deletions sanic_security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,12 +526,12 @@ class AuthenticationSession(Session):
Attributes:
requires_second_factor (bool): Determines if session requires a second factor.
refresh_expiration_date (bool): Date and time the session can no longer be refreshed.
is_refresh (bool): Will only be true for the first time session is created during refresh.
is_refresh (bool): Will only be true in the instance the session is created during refresh.
"""

requires_second_factor: bool = fields.BooleanField(default=False)
refresh_expiration_date: datetime.datetime = fields.DatetimeField(null=True)
is_refresh: bool
is_refresh: bool = False

def validate(self) -> None:
"""
Expand Down Expand Up @@ -571,13 +571,15 @@ async def refresh(self, request: Request):
):
self.active = False
await self.save(update_fields=["active"])
return await self.new(request, self.bearer, is_refresh=True)
return await self.new(request, self.bearer, True)
else:
raise e

@classmethod
async def new(cls, request: Request, account: Account = None, **kwargs):
return await AuthenticationSession.create(
async def new(
cls, request: Request, account: Account = None, is_refresh=False, **kwargs
):
authentication_session = await AuthenticationSession.create(
**kwargs,
bearer=account,
ip=get_ip(request),
Expand All @@ -588,6 +590,8 @@ async def new(cls, request: Request, account: Account = None, **kwargs):
security_config.AUTHENTICATION_REFRESH_EXPIRATION
),
)
authentication_session.is_refresh = is_refresh
return authentication_session

class Meta:
table = "authentication_session"
Expand Down
2 changes: 1 addition & 1 deletion sanic_security/test/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ async def on_authenticate(request):
if not authentication_session.anonymous
else None
),
"refresh": authentication_session.is_refresh
"refresh": authentication_session.is_refresh,
},
)
if authentication_session.is_refresh:
Expand Down
13 changes: 10 additions & 3 deletions sanic_security/test/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,15 @@ def test_authentication_refresh(self):
assert login_response.status_code == 200, login_response.text
expire_response = self.client.post("http://127.0.0.1:8000/api/test/auth/expire")
assert expire_response.status_code == 200, expire_response.text
authenticate_response = self.client.post(
authenticate_refresh_response = self.client.post(
"http://127.0.0.1:8000/api/test/auth",
)
assert authenticate_response.status_code == 200, authenticate_response.text

assert (
json.loads(authenticate_refresh_response.text)["data"]["refresh"] is True
), authenticate_refresh_response.text
authenticate_response = self.client.post(
"http://127.0.0.1:8000/api/test/auth",
) # Since session refresh handling is complete, it will be returned as a regular session now.
assert (
json.loads(authenticate_response.text)["data"]["refresh"] is False
), authenticate_response.text
4 changes: 3 additions & 1 deletion sanic_security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ def get_code() -> str:
return "".join(random.choices(string.digits + string.ascii_uppercase, k=6))


def json(message: str, data, status_code: int = 200) -> HTTPResponse: # May be causing fixture error bc of json property
def json(
message: str, data, status_code: int = 200
) -> HTTPResponse: # May be causing fixture error bc of json property
"""
A preformatted Sanic json response.
Expand Down
5 changes: 1 addition & 4 deletions sanic_security/verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ async def wrapper(request, *args, **kwargs):

return wrapper

if callable(arg):
return decorator(arg)
else:
return decorator
return decorator(arg) if callable(arg) else decorator


async def verify_account(request: Request) -> TwoStepSession:
Expand Down

0 comments on commit f405f72

Please sign in to comment.