diff --git a/src/exceptions.py b/src/exceptions.py index 5a6ed3a..8b3629c 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -27,12 +27,3 @@ class ConflictException(HTTPException): status_code=status.HTTP_409_CONFLICT, detail=detail, ) - - -class ForbiddenException(HTTPException): - def __init__(self, message: Optional[str] = None) -> None: - detail = "Forbidden" if not message else message - super().__init__( - status_code=status.HTTP_403_FORBIDDEN, - detail=detail, - ) diff --git a/src/iam/router.py b/src/iam/router.py index 5a50f42..07bd960 100644 --- a/src/iam/router.py +++ b/src/iam/router.py @@ -23,7 +23,7 @@ from src.iam.exceptions import GroupNotFoundException from src.organisation.exceptions import OrgNotFoundException from src.schemas import GroupSummary, OrgSummary from src.service.exceptions import ServiceNotFoundException -from src.exceptions import ConflictException, ForbiddenException +from src.exceptions import ConflictException from src.database import db_dependency from src.auth.exceptions import UnauthorizedException from src.auth.service import claims_dependency @@ -75,7 +75,7 @@ from src.iam.schemas import ( IAMPutGroupInvitationRequest, IAMPutGroupInvitationAcceptRequest, ) -from src.utils import verify_email_token +from src.utils import decode_jwt router = APIRouter( tags=["IAM"], @@ -211,11 +211,6 @@ async def add_group_user( if user_model in group_model.user_rel: raise ConflictException("User already in group") - if user_model not in org_model.user_rel: - raise ForbiddenException( - "Adding users directly can only be done with org members. Use email invitation instead." - ) - group_model.user_rel.append(user_model) db.flush() response = IAMPutGroupUserResponse( @@ -378,9 +373,11 @@ async def accept_invitation( user_model: user_model_claims_dependency, request_model: IAMPutGroupInvitationAcceptRequest, ): - email_claims = await verify_email_token( - token=request_model.jwt, user_model=user_model - ) + email_claims = await decode_jwt(request_model.jwt) + claimed_email = email_claims["email"] + + if user_model.email != claimed_email: + raise UnauthorizedException("The logged in user and email do not match.") org_model = db.get(Org, email_claims["org_id"]) if org_model is None: diff --git a/src/user/router.py b/src/user/router.py index 9a3b78a..2989785 100644 --- a/src/user/router.py +++ b/src/user/router.py @@ -10,6 +10,7 @@ Endpoints: from fastapi import APIRouter, status, BackgroundTasks +from src.auth.exceptions import UnauthorizedException from src.organisation.exceptions import OrgNotFoundException from src.user.schemas import ( UserResponse, @@ -31,7 +32,7 @@ from src.auth.dependencies import ( ) from src.auth.service import claims_dependency from src.database import db_dependency -from src.utils import verify_email_token +from src.utils import decode_jwt router = APIRouter( prefix="/user", @@ -180,9 +181,11 @@ async def accept_invitation( user_model: user_model_claims_dependency, request_model: UserPostInvitationAcceptRequest, ): - email_claims = await verify_email_token( - token=request_model.jwt, user_model=user_model - ) + email_claims = await decode_jwt(request_model.jwt) + claimed_email = email_claims["email"] + + if user_model.email != claimed_email: + raise UnauthorizedException("The logged in user and email do not match.") org_model = db.get(Org, email_claims["org_id"]) if org_model is None: diff --git a/src/utils.py b/src/utils.py index 5f1df8d..0724011 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,4 +1,3 @@ -from datetime import datetime, timezone from joserfc import jwt, jwk, errors from src.auth.exceptions import UnauthorizedException @@ -22,22 +21,6 @@ async def decode_jwt(encoded): raise UnauthorizedException("Invalid JWS") -async def verify_email_token(user_model, token): - email_claims = await decode_jwt(token) - - claimed_email = email_claims["email"] - - expiry = datetime.fromtimestamp(email_claims["exp"], timezone.utc) - - if expiry < datetime.now(timezone.utc): - raise UnauthorizedException("Invitation expired.") - - if user_model.email != claimed_email: - raise UnauthorizedException("The logged in user and email do not match.") - - return email_claims - - async def send_email(recipient: str, subject: str, body: str): print(recipient) print(subject) diff --git a/test/test_iam.py b/test/test_iam.py index 7f99de9..0176f9d 100644 --- a/test/test_iam.py +++ b/test/test_iam.py @@ -4,7 +4,7 @@ import pytest from httpx import AsyncClient from src.user.models import User -from src.organisation.models import Organisation as Org, OrgUsers +from src.organisation.models import Organisation as Org from src.iam.models import Group from .conftest import generate_query_and_status @@ -468,8 +468,6 @@ async def test_put_group_user_success(default_client: AsyncClient, db_session): ) ) db_session.flush() - db_session.add(OrgUsers(user_id=2, org_id=1)) - db_session.flush() resp = await default_client.put( "/iam/group/user", json={"user_id": 2, "group_id": 1, "organisation_id": 1}