Skip to content

Commit

Permalink
Allow owners and admins to modify/delete datasets
Browse files Browse the repository at this point in the history
  • Loading branch information
dmannarino committed May 7, 2024
1 parent 8a602d0 commit 98808ab
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 11 deletions.
17 changes: 13 additions & 4 deletions app/routes/datasets/dataset.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"""Datasets are just a bucket, for datasets which share the same core
metadata."""

from typing import Any, Dict, List

from fastapi import APIRouter, Depends, HTTPException, Response
from fastapi.responses import ORJSONResponse
from sqlalchemy.schema import CreateSchema, DropSchema

from ...application import db
from ...authentication.token import get_manager, is_admin
from ...authentication.token import get_manager
from ...crud import datasets, versions
from ...errors import RecordAlreadyExistsError, RecordNotFoundError
from ...models.orm.datasets import Dataset as ORMDataset
Expand All @@ -26,6 +25,16 @@
router = APIRouter()


async def get_owner(
dataset: str = Depends(dataset_dependency), user: User = Depends(get_manager)
) -> User:
dataset_row: ORMDataset = await datasets.get_dataset(dataset)
owner: str = dataset_row.owner_id
if owner != user.id:
raise HTTPException(status_code=401, detail="Unauthorized")
return user


@router.get(
"/{dataset}",
response_class=ORJSONResponse,
Expand Down Expand Up @@ -94,7 +103,7 @@ async def update_dataset(
*,
dataset: str = Depends(dataset_dependency),
request: DatasetUpdateIn,
is_authorized: bool = Depends(is_admin),
is_authorized: User = Depends(get_owner),
) -> DatasetResponse:
"""Partially update a dataset.
Expand All @@ -118,7 +127,7 @@ async def update_dataset(
async def delete_dataset(
*,
dataset: str = Depends(dataset_dependency),
is_authorized: bool = Depends(is_admin),
is_authorized: User = Depends(get_owner),
) -> DatasetResponse:
"""Delete a dataset.
Expand Down
79 changes: 73 additions & 6 deletions tests_v2/unit/app/routes/datasets/test_dataset.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from typing import Any, Dict, Tuple
from typing import Tuple

import pytest
from httpx import AsyncClient

from app.models.pydantic.datasets import DatasetResponse, Dataset
from app.models.pydantic.metadata import DatasetMetadata
from tests_v2.unit.app.routes.utils import assert_jsend
from app.authentication.token import get_manager
from app.models.pydantic.datasets import DatasetResponse
from app.routes.datasets.dataset import get_owner
from tests_v2.fixtures.metadata.dataset import DATASET_METADATA
from tests_v2.unit.app.routes.utils import assert_jsend
from tests_v2.utils import get_manager_mocked, raises_401


@pytest.mark.asyncio
Expand Down Expand Up @@ -35,8 +37,73 @@ def test_update_dataset():
pass


def test_delete_dataset():
pass
@pytest.mark.asyncio
async def test_delete_dataset_requires_creds_fail(db, init_db) -> None:
dataset_name: str = "my_first_dataset"

from app.main import app

# Create a dataset
app.dependency_overrides[get_manager] = get_manager_mocked

async with AsyncClient(
app=app,
base_url="http://test",
trust_env=False,
headers={"Origin": "https://www.globalforestwatch.org"},
) as async_client:
create_resp = await async_client.put(
f"/dataset/{dataset_name}", json={"metadata": DATASET_METADATA}
)
assert create_resp.status_code == 201

app.dependency_overrides = {}
app.dependency_overrides[get_owner] = raises_401

async with AsyncClient(
app=app,
base_url="http://test",
trust_env=False,
headers={"Origin": "https://www.globalforestwatch.org"},
) as async_client:
delete_resp = await async_client.delete(f"/dataset/{dataset_name}")
assert delete_resp.json()["message"] == "Unauthorized"
assert delete_resp.status_code == 401

app.dependency_overrides = {}


@pytest.mark.asyncio
async def test_delete_dataset_requires_creds_succeed(db, init_db, monkeypatch) -> None:
dataset_name: str = "my_first_dataset"

from app.main import app

# Create a dataset
app.dependency_overrides[get_manager] = get_manager_mocked

async with AsyncClient(
app=app,
base_url="http://test",
trust_env=False,
headers={"Origin": "https://www.globalforestwatch.org"},
) as async_client:
create_resp = await async_client.put(
f"/dataset/{dataset_name}", json={"metadata": DATASET_METADATA}
)
assert create_resp.status_code == 201

app.dependency_overrides = {}
app.dependency_overrides[get_owner] = get_manager_mocked

async with AsyncClient(
app=app,
base_url="http://test",
trust_env=False,
headers={"Origin": "https://www.globalforestwatch.org"},
) as async_client:
delete_resp = await async_client.delete(f"/dataset/{dataset_name}")
assert delete_resp.status_code == 200


def test__dataset_response():
Expand Down
7 changes: 6 additions & 1 deletion tests_v2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import httpx
from _pytest.monkeypatch import MonkeyPatch
from fastapi.exceptions import HTTPException

from app.application import ContextEngine
from app.models.pydantic.authentication import User
Expand Down Expand Up @@ -40,7 +41,7 @@ async def get_admin_mocked() -> Tuple[str, str]:
return "adminid_123", "ADMIN"


async def get_manager_mocked() -> str:
async def get_manager_mocked() -> User:
return User(
id="mr_manager123",
name="Mr. Manager",
Expand Down Expand Up @@ -157,3 +158,7 @@ async def custom_raster_version(
yield version_name
finally:
pass


async def raises_401() -> None:
raise HTTPException(status_code=401, detail="Unauthorized")

0 comments on commit 98808ab

Please sign in to comment.