Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
feat: Updates route permissions & telemetry (#22)
Browse files Browse the repository at this point in the history
* feat: Adds missing permission check

* feat: Updates permissions & telemetry
  • Loading branch information
frgfm authored Oct 30, 2023
1 parent 9ba44da commit 2dc830e
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/app/api/api_v1/endpoints/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async def analyze_snippet(
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
user=Security(get_current_user, scopes=[UserScope.ADMIN, UserScope.USER]),
) -> List[ComplianceResult]:
telemetry_client.capture(user.id, event="snippet-analysis", properties={"repo_id": payload.repo_id})
telemetry_client.capture(user.id, event="compute-analysis", properties={"repo_id": payload.repo_id})
# Check repo
await repos.get(payload.repo_id, strict=True)
# Fetch guidelines
Expand Down
13 changes: 8 additions & 5 deletions src/app/api/api_v1/endpoints/guidelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,28 @@ async def create_guideline(
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Guideline:
guideline = await guidelines.create(payload)
telemetry_client.capture(user.id, event="guideline-creation", properties={"repo_id": payload.repo_id})
guideline = await guidelines.create(payload)
return guideline


@router.get("/{guideline_id}", status_code=status.HTTP_200_OK)
async def get_guideline(
guideline_id: int = Path(..., gt=0),
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
_=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Guideline:
return cast(Guideline, await guidelines.get(guideline_id, strict=True))
guideline = cast(Guideline, await guidelines.get(guideline_id, strict=True))
telemetry_client.capture(user.id, event="guideline-get", properties={"repo_id": guideline.repo_id})
return guideline


@router.get("/", status_code=status.HTTP_200_OK)
async def fetch_guidelines(
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
_=Security(get_current_user, scopes=[UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> List[Guideline]:
telemetry_client.capture(user.id, event="guideline-fetch")
return [elt for elt in await guidelines.fetch_all()]


Expand Down Expand Up @@ -76,5 +79,5 @@ async def delete_guideline(
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> None:
guideline = cast(Guideline, await guidelines.get(guideline_id, strict=True))
await guidelines.delete(guideline_id)
telemetry_client.capture(user.id, event="guideline-deletion", properties={"repo_id": guideline.repo_id})
await guidelines.delete(guideline_id)
2 changes: 1 addition & 1 deletion src/app/api/api_v1/endpoints/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ async def login_with_creds(
user = await users.get_by_login(form_data.username)
if user is None or not await verify_password(form_data.password, user.hashed_password):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials.")
telemetry_client.capture(user.id, event="user-login", properties={"login": user.login})
# create access token using user user_id/user_scopes
token_data = {"sub": str(user.id), "scopes": user.scope.split()}
token = await create_access_token(token_data, settings.ACCESS_TOKEN_UNLIMITED_MINUTES)
telemetry_client.capture(user.id, event="user-login", properties={"login": user.login})

return Token(access_token=token, token_type="bearer") # nosec B106 # noqa S106

Expand Down
27 changes: 14 additions & 13 deletions src/app/api/api_v1/endpoints/repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ async def create_repo(
repos: RepositoryCRUD = Depends(get_repo_crud),
user: User = Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Repository:
telemetry_client.capture(
user.id, event="repo-creation", properties={"repo_id": payload.id, "full_name": payload.full_name}
)
# Check that user is allowed to do so
entry = await repos.get(payload.id, strict=False)
# If repo exists, set it back to active
if entry is not None:
Expand All @@ -35,18 +39,16 @@ async def create_repo(
return entry

repo = await repos.create(RepoCreation(**payload.dict(), installed_by=user.id))
telemetry_client.capture(
user.id, event="repo-creation", properties={"repo_id": payload.id, "full_name": payload.full_name}
)
return repo


@router.get("/{repo_id}", status_code=status.HTTP_200_OK)
async def get_repo(
repo_id: int = Path(..., gt=0),
repos: RepositoryCRUD = Depends(get_repo_crud),
_=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Repository:
telemetry_client.capture(user.id, event="repo-get", properties={"repo_id": repo_id})
return cast(Repository, await repos.get(repo_id, strict=True))


Expand All @@ -55,8 +57,8 @@ async def fetch_repos(
repos: RepositoryCRUD = Depends(get_repo_crud),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> List[Repository]:
entries = await repos.fetch_all() if user.scope == UserScope.ADMIN else await repos.fetch_all(("owner_id", user.id))
telemetry_client.capture(user.id, event="repo-fetch")
entries = await repos.fetch_all() if user.scope == UserScope.ADMIN else await repos.fetch_all(("owner_id", user.id))
return [elt for elt in entries]


Expand All @@ -67,6 +69,7 @@ async def reorder_guidelines(
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> List[Guideline]:
telemetry_client.capture(user.id, event="guideline-order", properties={"repo_id": repo_id})
# Ensure all IDs are unique
if len(payload.guideline_ids) != len(set(payload.guideline_ids)):
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Duplicate IDs were passed.")
Expand All @@ -77,12 +80,10 @@ async def reorder_guidelines(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Guideline IDs for that repo don't match."
)
# Update all order
guideline_list = [
return [
await guidelines.update(guideline_id, OrderUpdate(order=order_idx, updated_at=datetime.utcnow()))
for order_idx, guideline_id in enumerate(payload.guideline_ids)
]
telemetry_client.capture(user.id, event="guideline-order", properties={"repo_id": repo_id})
return guideline_list


@router.put("/{repo_id}/disable", status_code=status.HTTP_200_OK)
Expand All @@ -91,9 +92,8 @@ async def disable_repo(
repos: RepositoryCRUD = Depends(get_repo_crud),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Repository:
repo = await repos.update(repo_id, RepoUpdate(removed_at=datetime.utcnow()))
telemetry_client.capture(user.id, event="repo-disable", properties={"repo_id": repo_id})
return repo
return await repos.update(repo_id, RepoUpdate(removed_at=datetime.utcnow()))


@router.put("/{repo_id}/enable", status_code=status.HTTP_200_OK)
Expand All @@ -102,9 +102,8 @@ async def enable_repo(
repos: RepositoryCRUD = Depends(get_repo_crud),
user=Security(get_current_user, scopes=[UserScope.USER, UserScope.ADMIN]),
) -> Repository:
repo = await repos.update(repo_id, RepoUpdate(removed_at=None))
telemetry_client.capture(user.id, event="repo-enable", properties={"repo_id": repo_id})
return repo
return await repos.update(repo_id, RepoUpdate(removed_at=None))


@router.delete("/{repo_id}", status_code=status.HTTP_200_OK)
Expand All @@ -113,14 +112,16 @@ async def delete_repo(
repos: RepositoryCRUD = Depends(get_repo_crud),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> None:
await repos.delete(repo_id)
telemetry_client.capture(user.id, event="repo-delete", properties={"repo_id": repo_id})
await repos.delete(repo_id)


@router.get("/{repo_id}/guidelines", status_code=status.HTTP_200_OK)
async def fetch_guidelines_from_repo(
repo_id: int = Path(..., gt=0),
guidelines: GuidelineCRUD = Depends(get_guideline_crud),
repos: RepositoryCRUD = Depends(get_repo_crud),
user=Security(get_current_user, scopes=[UserScope.ADMIN, UserScope.USER]),
) -> List[Guideline]:
telemetry_client.capture(user.id, event="repo-fetch-guidelines", properties={"repo_id": repo_id})
return [elt for elt in await guidelines.fetch_all(("repo_id", repo_id))]
13 changes: 8 additions & 5 deletions src/app/api/api_v1/endpoints/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,32 @@ async def create_user(
users: UserCRUD = Depends(get_user_crud),
_=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> User:
telemetry_client.capture(payload.id, event="user-creation", properties={"login": payload.login})
# Hash the password
pwd = await hash_password(payload.password)

user = await users.create(
UserCreation(id=payload.id, login=payload.login, hashed_password=pwd, scope=payload.scope)
)
telemetry_client.capture(payload.id, event="user-creation", properties={"login": payload.login})
return user


@router.get("/{user_id}", status_code=status.HTTP_200_OK)
async def get_user(
user_id: int = Path(..., gt=0),
users: UserCRUD = Depends(get_user_crud),
_=Security(get_current_user, scopes=[UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> User:
telemetry_client.capture(user.id, event="user-get", properties={"user_id": user_id})
return cast(User, await users.get(user_id, strict=True))


@router.get("/", status_code=status.HTTP_200_OK)
async def fetch_users(
users: UserCRUD = Depends(get_user_crud),
_=Security(get_current_user, scopes=[UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> List[User]:
telemetry_client.capture(user.id, event="user-fetch")
return [elt for elt in await users.fetch_all()]


Expand All @@ -55,8 +57,9 @@ async def update_user_password(
payload: Cred,
user_id: int = Path(..., gt=0),
users: UserCRUD = Depends(get_user_crud),
_=Security(get_current_user, scopes=[UserScope.ADMIN]),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> User:
telemetry_client.capture(user.id, event="user-pwd", properties={"user_id": user_id})
pwd = await hash_password(payload.password)
return await users.update(user_id, CredHash(hashed_password=pwd))

Expand All @@ -67,5 +70,5 @@ async def delete_user(
users: UserCRUD = Depends(get_user_crud),
user=Security(get_current_user, scopes=[UserScope.ADMIN]),
) -> None:
telemetry_client.capture(user_id, event="user-deletion", properties={"user_id": user_id})
await users.delete(user_id)
telemetry_client.capture(user_id, event="user-deletion", properties={"login": user.login})

0 comments on commit 2dc830e

Please sign in to comment.