Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/specs/web-server/_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from models_library.rest_error import EnvelopedError, Log
from pydantic import BaseModel, Field, confloat
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.login._controller.rest.auth import (
from simcore_service_webserver.login._controller.rest.auth_schemas import (
LoginBody,
LoginNextPage,
LoginTwoFactorAuthBody,
Expand All @@ -30,7 +30,7 @@
PhoneConfirmationBody,
ResetPasswordConfirmation,
)
from simcore_service_webserver.login._controller.rest.registration import (
from simcore_service_webserver.login._controller.rest.registration_schemas import (
InvitationCheck,
InvitationInfo,
RegisterBody,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

from aiohttp.test_utils import TestClient
from servicelib.aiohttp import status
from simcore_service_webserver.login._constants import MSG_LOGGED_IN
from simcore_service_webserver.login._invitations_service import create_invitation_token
from simcore_service_webserver.login._login_repository_legacy import (
get_plugin_storage,
)
from simcore_service_webserver.login.constants import MSG_LOGGED_IN
from simcore_service_webserver.security import security_service
from yarl import URL

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
""" webserver's login subsystem


This sub-package is based on aiohttp-login https://github.com/imbolc/aiohttp-login
"""
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from ..products.models import Product
from ..security import security_service
from . import _login_service
from ._constants import MSG_UNKNOWN_EMAIL, MSG_WRONG_PASSWORD
from ._login_repository_legacy import AsyncpgStorage, get_plugin_storage
from .constants import MSG_UNKNOWN_EMAIL, MSG_WRONG_PASSWORD


async def get_user_by_email(app: web.Application, *, email: str) -> dict[str, Any]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
to_exceptions_handlers_map,
)
from ....users.exceptions import AlreadyPreRegisteredError
from ..._constants import MSG_2FA_UNAVAILABLE
from ...constants import MSG_2FA_UNAVAILABLE
from ...errors import SendingVerificationEmailError, SendingVerificationSmsError

_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
from aiohttp import web
from aiohttp.web import RouteTableDef
from models_library.authentification import TwoFactorAuthentificationMethod
from models_library.emails import LowerCaseEmailStr
from pydantic import BaseModel, Field, PositiveInt, SecretStr, TypeAdapter
from pydantic import TypeAdapter
from servicelib.aiohttp import status
from servicelib.aiohttp.requests_validation import parse_request_body_as
from servicelib.logging_utils import get_log_record_extra, log_context
Expand All @@ -21,9 +20,9 @@
session_access_required,
)
from ....users import preferences_api as user_preferences_api
from ....utils_aiohttp import NextPage
from ....web_utils import envelope_response, flash_response
from ... import _auth_service, _login_service, _security_service, _twofa_service
from ..._constants import (
from ...constants import (
CODE_2FA_EMAIL_CODE_REQUIRED,
CODE_2FA_SMS_CODE_REQUIRED,
CODE_PHONE_NUMBER_REQUIRED,
Expand All @@ -37,31 +36,17 @@
MSG_WRONG_2FA_CODE__EXPIRED,
MSG_WRONG_2FA_CODE__INVALID,
)
from ..._models import InputSchema
from ...decorators import login_required
from ...settings import LoginSettingsForProduct, get_plugin_settings
from ._rest_exceptions import handle_rest_requests_exceptions
from .auth_schemas import LoginBody, LoginTwoFactorAuthBody, LogoutBody

log = logging.getLogger(__name__)


routes = RouteTableDef()


class LoginBody(InputSchema):
email: LowerCaseEmailStr
password: SecretStr


class CodePageParams(BaseModel):
message: str
expiration_2fa: PositiveInt | None = None
next_url: str | None = None


class LoginNextPage(NextPage[CodePageParams]): ...


@routes.post(f"/{API_VTAG}/auth/login", name="auth_login")
@on_success_grant_session_access_to(
name="auth_register_phone",
Expand Down Expand Up @@ -134,7 +119,7 @@ async def login(request: web.Request):
user_2fa_authentification_method == TwoFactorAuthentificationMethod.SMS
and not user["phone"]
):
return _login_service.envelope_response(
return envelope_response(
# LoginNextPage
{
"name": CODE_PHONE_NUMBER_REQUIRED,
Expand Down Expand Up @@ -169,7 +154,7 @@ async def login(request: web.Request):
user_id=user["id"],
)

return _login_service.envelope_response(
return envelope_response(
# LoginNextPage
{
"name": CODE_2FA_SMS_CODE_REQUIRED,
Expand All @@ -196,7 +181,7 @@ async def login(request: web.Request):
product=product,
user_id=user["id"],
)
return _login_service.envelope_response(
return envelope_response(
{
"name": CODE_2FA_EMAIL_CODE_REQUIRED,
"parameters": {
Expand All @@ -208,11 +193,6 @@ async def login(request: web.Request):
)


class LoginTwoFactorAuthBody(InputSchema):
email: LowerCaseEmailStr
code: SecretStr


@routes.post(f"/{API_VTAG}/auth/validate-code-login", name="auth_login_2fa")
@session_access_required(
"auth_login_2fa",
Expand Down Expand Up @@ -259,12 +239,6 @@ async def login_2fa(request: web.Request):
return await _security_service.login_granted_response(request, user=dict(user))


class LogoutBody(InputSchema):
client_session_id: str | None = Field(
None, examples=["5ac57685-c40f-448f-8711-70be1936fd63"]
)


@routes.post(f"/{API_VTAG}/auth/logout", name="auth_logout")
@login_required
@handle_rest_requests_exceptions
Expand All @@ -282,7 +256,7 @@ async def logout(request: web.Request) -> web.Response:
f"{logout_.client_session_id=}",
extra=get_log_record_extra(user_id=user_id),
):
response = _login_service.flash_response(MSG_LOGGED_OUT, "INFO")
response = flash_response(MSG_LOGGED_OUT, "INFO")
await _login_service.notify_user_logout(
request.app, user_id, logout_.client_session_id
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from aiohttp.web import RouteTableDef
from models_library.emails import LowerCaseEmailStr
from pydantic import BaseModel, Field, PositiveInt, SecretStr

from ....utils_aiohttp import NextPage
from ..._models import InputSchema

routes = RouteTableDef()


class LoginBody(InputSchema):
email: LowerCaseEmailStr
password: SecretStr


class CodePageParams(BaseModel):
message: str
expiration_2fa: PositiveInt | None = None
next_url: str | None = None


class LoginNextPage(NextPage[CodePageParams]): ...


class LoginTwoFactorAuthBody(InputSchema):
email: LowerCaseEmailStr
code: SecretStr


class LogoutBody(InputSchema):
client_session_id: str | None = Field(
None, examples=["5ac57685-c40f-448f-8711-70be1936fd63"]
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

from aiohttp import web
from aiohttp.web import RouteTableDef
from models_library.emails import LowerCaseEmailStr
from pydantic import SecretStr, field_validator
from servicelib.aiohttp.requests_validation import parse_request_body_as
from servicelib.logging_errors import create_troubleshootting_log_kwargs
from servicelib.request_keys import RQT_USERID_KEY
Expand All @@ -18,37 +16,33 @@
from ....users import api as users_service
from ....utils import HOUR
from ....utils_rate_limiting import global_rate_limit_route
from ....web_utils import flash_response
from ... import _confirmation_service, _confirmation_web
from ..._constants import (
MSG_CANT_SEND_MAIL,
MSG_CHANGE_EMAIL_REQUESTED,
MSG_EMAIL_SENT,
MSG_OFTEN_RESET_PASSWORD,
MSG_PASSWORD_CHANGED,
MSG_WRONG_PASSWORD,
)
from ..._emails_service import get_template_path, send_email_from_template
from ..._login_repository_legacy import AsyncpgStorage, get_plugin_storage
from ..._login_service import (
ACTIVE,
CHANGE_EMAIL,
flash_response,
validate_user_status,
)
from ..._models import InputSchema, create_password_match_validator
from ...constants import (
MSG_CANT_SEND_MAIL,
MSG_CHANGE_EMAIL_REQUESTED,
MSG_EMAIL_SENT,
MSG_OFTEN_RESET_PASSWORD,
MSG_PASSWORD_CHANGED,
MSG_WRONG_PASSWORD,
)
from ...decorators import login_required
from ...settings import LoginOptions, get_plugin_options
from .change_schemas import ChangeEmailBody, ChangePasswordBody, ResetPasswordBody

_logger = logging.getLogger(__name__)


routes = RouteTableDef()


class ResetPasswordBody(InputSchema):
email: LowerCaseEmailStr


@routes.post(f"/{API_VTAG}/auth/reset-password", name="initiate_reset_password")
@global_rate_limit_route(
number_of_requests=10, interval_seconds=HOUR, error_msg=MSG_OFTEN_RESET_PASSWORD
Expand Down Expand Up @@ -221,10 +215,6 @@ def _get_error_context(
return flash_response(MSG_EMAIL_SENT.format(email=request_body.email), "INFO")


class ChangeEmailBody(InputSchema):
email: LowerCaseEmailStr


async def initiate_change_email(request: web.Request):
# NOTE: This code have been intentially disabled in https://github.com/ITISFoundation/osparc-simcore/pull/5472
db: AsyncpgStorage = get_plugin_storage(request.app)
Expand Down Expand Up @@ -272,16 +262,6 @@ async def initiate_change_email(request: web.Request):
return flash_response(MSG_CHANGE_EMAIL_REQUESTED)


class ChangePasswordBody(InputSchema):
current: SecretStr
new: SecretStr
confirm: SecretStr

_password_confirm_match = field_validator("confirm")(
create_password_match_validator(reference_field="new")
)


@routes.post(f"/{API_VTAG}/auth/change-password", name="auth_change_password")
@login_required
async def change_password(request: web.Request):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from models_library.emails import LowerCaseEmailStr
from pydantic import SecretStr, field_validator

from ..._models import InputSchema, create_password_match_validator


class ResetPasswordBody(InputSchema):
email: LowerCaseEmailStr


class ChangeEmailBody(InputSchema):
email: LowerCaseEmailStr


class ChangePasswordBody(InputSchema):
current: SecretStr
new: SecretStr
confirm: SecretStr

_password_confirm_match = field_validator("confirm")(
create_password_match_validator(reference_field="new")
)
Loading
Loading