Skip to content
This repository was archived by the owner on Mar 16, 2026. It is now read-only.
Open
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
45 changes: 45 additions & 0 deletions sucuri/crud/crud_organization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from sqlalchemy.orm import Session

# IIB
from sucuri.database.dependency import get_db
from sucuri.models.models import Organization
from sucuri.schemas.schemas import OrganizationSchema


def post_organization(organization: OrganizationSchema, db: Session):
db_organization = Organization(**organization.dict())
db.add(db_organization)
db.commit()
db.refresh(db_organization)
return db_organization


def get_organization(organization_id: int, db: Session):
return db.query(Organization).filter(Organization.id == organization_id).first()


def get_organizations(db: Session, skip: int = 0, limit: int = 100):
return db.query(Organization).offset(skip).limit(limit).all()


def delete_organization(organization_id: int, db: Session):
db.query(Organization).filter(Organization.id == organization_id).delete()
db.commit()
return


def update_organization(
old_organization: Organization, organization: OrganizationSchema, db: Session
):
db_organization = Organization(**organization.dict())
old_organization.name = db_organization.name
old_organization.about = db_organization.about
old_organization.social_media = db_organization.social_media
old_organization.owner = (
db_organization.owner if db_organization.owner else old_organization.owner
)
old_organization.members = (
db_organization.members if db_organization.members else old_organization.members
)
db.commit()
return
6 changes: 5 additions & 1 deletion sucuri/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@


def get_app():
from .views import profile_view
from .views import (
profile_view,
organization_view,
)

app = FastAPI()
app.include_router(profile_view.router)
app.include_router(organization_view.router)
return app
8 changes: 3 additions & 5 deletions sucuri/schemas/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@ class Config:


class OrganizationSchema(BaseModel):
id: int
name: str
about: str
url: str
social_media: str
owner: Optional[int] = None
projects: Optional[List[int]] = None
members: Optional[List[int]] = None
social_media: List[Optional[SocialMediaSchema]] = []
owner: int
members: List[Optional[int]] = []

class Config:
orm_mode = True
Expand Down
124 changes: 124 additions & 0 deletions sucuri/tests/test_views/test_organization_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Standard Library
from unittest import mock

# pytest
import pytest

from fastapi import HTTPException
from fastapi.testclient import TestClient

# IIB
from sucuri.main import get_app


app = get_app()

client = TestClient(app)


class TestOrganizationView:
@pytest.fixture
def organization(self):
return {
"name": "Live de Python",
"about": "lives sobre temas pythônicos",
"url": "https://www.youtube.com/eduardomendes",
"social_media": [{"type": "twitter", "value": "@edumendes"}],
"owner": 1,
"members": [],
}

@pytest.fixture
def organizations(self):
return [
{
"name": "Live de Python",
"about": "lives sobre temas pythônicos",
"url": "https://www.youtube.com/eduardomendes",
"social_media": [{"type": "twitter", "value": "@edumendes"}],
"owner": 1,
"members": [],
},
{
"name": "Foo",
"about": "aulas de foo",
"url": "https://www.foo.com/",
"social_media": [{"type": "twitter", "value": "@foo"}],
"owner": 1,
"members": [],
},
{
"name": "Bar",
"about": "lives sobre bar",
"url": "https://www.bar.com/",
"social_media": [{"type": "twitter", "value": "@bar"}],
"owner": 1,
"members": [],
},
]

def test_create_organization_should_return_200(self, organization):
response = client.post("/organizations/", json=organization)
assert response.status_code == 200
assert response.json() == organization

def test_get_organization_should_return_200(self, organization):
with mock.patch(
"sucuri.views.organization_view.get_organization"
) as mock_get_organization:
mock_get_organization.return_value = organization
response = client.get("/organizations/1")
assert response.status_code == 200
assert response.json() == organization

def test_get_organization_should_return_organization_not_found(self):
with mock.patch(
"sucuri.views.organization_view.get_organization"
) as mock_get_organization:
mock_get_organization.return_value = None
response = client.get("/organizations/1")
assert response.status_code == 404
assert response.json() == {"detail": "Organization not found"}

def test_get_organizations_should_return_existent_organizations(
self, organizations
):
with mock.patch(
"sucuri.views.organization_view.get_organizations"
) as mock_get_organizations:
mock_get_organizations.return_value = organizations
response = client.get("/organizations/")
assert response.status_code == 200
assert len(response.json()) == 3

def test_get_organizations_should_return_empty_list(self):
with mock.patch(
"sucuri.views.organization_view.get_organizations"
) as mock_get_organizations:
mock_get_organizations.return_value = []
response = client.get("/organizations/")
assert response.status_code == 200
assert len(response.json()) == 0

def test_delete_organization_should_return_200(self):
with mock.patch(
"sucuri.views.organization_view.delete_organization"
) as mock_delete_organization:
mock_delete_organization.return_value = None
response = client.delete("/organizations/1")
assert response.status_code == 200

def test_update_organization_should_return_200(self, organization):
response = client.put("/organizations/1", json=organization)
assert response.status_code == 200

def test_update_organization_should_return_organization_not_found(
self, organization
):
with mock.patch(
"sucuri.views.organization_view.get_organization"
) as mock_get_organization:
mock_get_organization.return_value = None
response = client.put("/organizations/1", json=organization)
assert response.status_code == 404
assert response.json() == {"detail": "Organization not found"}
15 changes: 7 additions & 8 deletions sucuri/tests/test_views/test_profile_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@ def profile(self):
"name": "Zoey",
"social_media": [{"type": "instagram", "value": "@zoey"}],
}

@pytest.fixture
def profile_only_name(self):
return {
"name": "Zoey",
"social_media": []
}
return {"name": "Zoey", "social_media": []}

@pytest.fixture
def broken_profile(self):
Expand All @@ -47,15 +44,17 @@ def profiles(self):
{"name": "John", "social_media": [{"type": "twitter", "value": "@john"}]},
{"name": "Paul", "social_media": [{"type": "instagram", "value": "@paul"}]},
{"name": "Zoey", "social_media": [{"type": "instagram", "value": "@zoey"}]},
{"name": "Anthony", "social_media": []}
{"name": "Anthony", "social_media": []},
]

def test_create_profile_should_return_200(self, profile):
response = client.post("/profiles/", json=profile,)
assert response.status_code == 200
assert response.json() == profile

def test_create_profile_should_return_200_without_social_media(self, profile_only_name):

def test_create_profile_should_return_200_without_social_media(
self, profile_only_name
):
response = client.post("/profiles/", json=profile_only_name)
assert response.status_code == 200
assert response.json() == profile_only_name
Expand Down
Empty file added sucuri/views/__init__.py
Empty file.
62 changes: 62 additions & 0 deletions sucuri/views/organization_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Standard Library
from typing import List

from fastapi import APIRouter
from fastapi import Depends
from fastapi import HTTPException
from sqlalchemy.orm import Session

# IIB
from sucuri.crud.crud_organization import delete_organization
from sucuri.crud.crud_organization import get_organization
from sucuri.crud.crud_organization import get_organizations
from sucuri.crud.crud_organization import post_organization
from sucuri.crud.crud_organization import update_organization
from sucuri.database.dependency import get_db
from sucuri.models.models import Organization
from sucuri.schemas.schemas import OrganizationSchema


router = APIRouter()


@router.post("/organizations/", response_model=OrganizationSchema)
async def create_organization(
organization: OrganizationSchema, db: Session = Depends(get_db)
):
return post_organization(organization=organization, db=db)


@router.get("/organizations/{organization_id}", response_model=OrganizationSchema)
async def get_organization_by_id(organization_id: int, db: Session = Depends(get_db)):
organization = get_organization(organization_id, db)
if organization is None:
raise HTTPException(status_code=404, detail="Organization not found")
return organization


@router.get("/organizations/", response_model=List[OrganizationSchema])
async def get_all_organizations(
skip: int = 0, limit: int = 100, db: Session = Depends(get_db)
):
organizations = get_organizations(db=db, skip=skip, limit=limit)
return organizations


@router.delete("/organizations/{organization_id}", response_model=OrganizationSchema)
async def delete_organization_by_id(
organization_id: int, db: Session = Depends(get_db)
):
return delete_organization(organization_id, db)


@router.put("/organizations/{organization_id}", response_model=OrganizationSchema)
async def update_organization_by_id(
organization_id: int,
organization: OrganizationSchema,
db: Session = Depends(get_db),
):
old_organization = get_organization(organization_id, db)
if old_organization is None:
raise HTTPException(status_code=404, detail="Organization not found")
return update_organization(old_organization, organization, db)