Skip to content

Commit

Permalink
Merge pull request #770 from Arnthorny/feat/delete-invite-link
Browse files Browse the repository at this point in the history
feat: endpoint to delete invites (superadmin)
  • Loading branch information
joboy-dev authored Aug 7, 2024
2 parents a55ecef + 8e361de commit 9ce291f
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 3 deletions.
19 changes: 17 additions & 2 deletions api/v1/routes/invitations.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi import APIRouter, Depends, HTTPException, Request, status
from sqlalchemy.orm import Session
from urllib.parse import urlparse, parse_qs
from api.v1.schemas import invitations
from api.db.database import get_db as get_session
from api.v1.services import invite
from api.v1.models.user import User
from api.utils.success_response import success_response
from api.v1.services.user import user_service
import logging

Expand Down Expand Up @@ -42,4 +43,18 @@ async def add_user_to_organization(

logging.info(f"Processing invitation ID: {invite_id}")

return invite.InviteService.add_user_to_organization(invite_id, session)
return invite.InviteService.add_user_to_organization(invite_id, session)

@invites.delete("/{invite_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_invite(
invite_id: str,
db: Session = Depends(get_session),
admin: User = Depends(user_service.get_current_super_admin)
):
""" Delete invite from database """
invite_is_deleted = invite.InviteService.delete(db, invite_id)

if not invite_is_deleted:
raise HTTPException(status_code=404, detail="Invalid invitation id")

logging.info(f"Deleted invite. ID: {invite_id}")
33 changes: 32 additions & 1 deletion api/v1/services/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
from api.v1.models.user import User
from api.v1.models.associations import user_organization_association
from api.v1.schemas import invitations
from api.core.base.services import Service
from urllib.parse import urlencode


class InviteService:
class InviteService(Service):
@staticmethod
def create(
invite: invitations.InvitationCreate, request: Request, session: Session
Expand Down Expand Up @@ -139,5 +140,35 @@ def add_user_to_organization(invite_id: str, session: Session):
status_code=500,
detail="An error occurred while adding the user to the organization",
)
@staticmethod
def delete(session: Session, id: str):
"""Function to delete invite link
Args:
session(Session): The current ORM session object.
id(str): Invite id string
Returns:
True if delete is successful else False
"""
invite = (
session.query(Invitation).filter_by(id=id).first()
)

if invite is None:
return False
session.delete(invite)
session.commit()
return True

def fetch(self):
pass

def fetch_all(self):
pass

def update(self):
pass

invite_service = InviteService()
72 changes: 72 additions & 0 deletions tests/v1/invitation/test_delete_invitation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Dependencies:
# pip install pytest-mock
import pytest
from unittest.mock import patch, MagicMock
from fastapi.testclient import TestClient
from main import app
from api.v1.services.user import user_service
from api.db.database import get_db
from sqlalchemy.orm import Session
from datetime import datetime
from api.v1.services.user import oauth2_scheme


def mock_deps():
return MagicMock(id="user_id")

def mock_oauth():
return 'access_token'

def mock_db():
return MagicMock(spec=Session)

@pytest.fixture
def client():
client = TestClient(app)
yield client

DELETE_ENDPOINT = "/api/v1/invite/invite_id"
class TestCodeUnderTest:
@classmethod
def setup_class(cls):
app.dependency_overrides[user_service.get_current_super_admin] = mock_deps
app.dependency_overrides[get_db] = mock_db

@classmethod
def teardown_class(cls):
app.dependency_overrides = {}

# Successfully delete invite from to the database
def test_delete_invite_success(self, client):

response = client.delete(DELETE_ENDPOINT)

assert response.status_code == 204

# Invalid invite id
def test_delete_invite_invalid_id(self, client):


with patch('api.v1.services.invite.InviteService.delete', return_value=False) as tmp:
response = client.delete(DELETE_ENDPOINT)
assert response.status_code == 404
assert response.json()['message'] == "Invalid invitation id"

# Handling unauthorized request
def test_delete_invite_unauth(self, client):
app.dependency_overrides = {}

response = client.delete(DELETE_ENDPOINT)
assert response.status_code == 401
assert response.json()['message'] == 'Not authenticated'

# Handling forbidden request
def test_delete_invite_forbidden(self, client):
app.dependency_overrides = {}
app.dependency_overrides[get_db] = mock_db
app.dependency_overrides[oauth2_scheme] = mock_oauth

with patch('api.v1.services.user.user_service.get_current_user', return_value=MagicMock(is_super_admin=False)) as cu:
response = client.delete(DELETE_ENDPOINT)
assert response.status_code == 403
assert response.json()['message'] == 'You do not have permission to access this resource'

0 comments on commit 9ce291f

Please sign in to comment.