Skip to content

Commit

Permalink
feat: use enacit4r-pyutils
Browse files Browse the repository at this point in the history
  • Loading branch information
ymarcon committed Nov 12, 2024
1 parent a06bb09 commit 16636ff
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 113 deletions.
70 changes: 4 additions & 66 deletions backend/api/auth.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,7 @@
from fastapi import HTTPException, status, Security, Depends
from fastapi.security import OAuth2AuthorizationCodeBearer
from keycloak import KeycloakOpenID
from api.config import config
from api.models.auth import User
from enacit4r_auth.services.auth import KeycloakService, User


# This is used for fastapi docs authentification
oauth2_scheme = OAuth2AuthorizationCodeBearer(
authorizationUrl=f"{config.KEYCLOAK_URL}",
tokenUrl=(
f"{config.KEYCLOAK_URL}/realms/{config.KEYCLOAK_REALM}"
"/protocol/openid-connect/token"
),
)


keycloak_openid = KeycloakOpenID(
server_url=config.KEYCLOAK_URL,
client_id=config.KEYCLOAK_API_ID,
client_secret_key=config.KEYCLOAK_API_SECRET,
realm_name=config.KEYCLOAK_REALM,
verify=True,
)

# Get the payload/token from keycloak


async def get_payload(token: str = Security(oauth2_scheme)) -> dict:
try:
return keycloak_openid.decode_token(
token,
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=str(e), # "Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)


# Get user infos from the payload
async def get_user_info(payload: dict = Depends(get_payload)) -> User:
try:
return User(
id=payload.get("sub"),
username=payload.get("preferred_username"),
email=payload.get("email"),
first_name=payload.get("given_name"),
last_name=payload.get("family_name"),
realm_roles=payload.get("realm_access", {}).get("roles", []),
client_roles=payload.get("realm_access", {}).get("roles", []),
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e), # "Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)


async def require_admin(user: User = Depends(get_user_info)):
if "icebreaker-admin" not in user.realm_roles:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="You are not authorised to perform this operation",
headers={"WWW-Authenticate": "Bearer"},
)
return user
kc_service = KeycloakService(url=config.KEYCLOAK_URL, realm=config.KEYCLOAK_REALM,
client_id=config.KEYCLOAK_API_ID, client_secret=config.KEYCLOAK_API_SECRET,
admin_role="icebreaker-admin")
24 changes: 0 additions & 24 deletions backend/api/models/auth.py

This file was deleted.

2 changes: 1 addition & 1 deletion backend/api/models/campaigns.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Optional, Tuple
from pydantic import BaseModel
from enacit4r.models.files import FileRef
from enacit4r_files.models.files import FileRef


class Reference(BaseModel):
Expand Down
10 changes: 5 additions & 5 deletions backend/api/services/s3.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from api.config import config
from enacit4r.services.s3 import S3Service
from enacit4r_files.services.s3 import S3Service

s3_client = S3Service(config.S3_ENDPOINT_PROTOCOL + config.S3_ENDPOINT_HOSTNAME,
config.S3_ACCESS_KEY_ID,
config.S3_SECRET_ACCESS_KEY,config.S3_REGION,
config.S3_BUCKET,
config.S3_PATH_PREFIX)
config.S3_ACCESS_KEY_ID,
config.S3_SECRET_ACCESS_KEY, config.S3_REGION,
config.S3_BUCKET,
config.S3_PATH_PREFIX)
6 changes: 3 additions & 3 deletions backend/api/views/campaigns.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from fastapi_cache.decorator import cache
from api.services.campaigns import CampaignsService
from api.models.campaigns import Campaign
from api.auth import require_admin, User
from api.auth import kc_service, User
from api.config import config

router = APIRouter()
Expand All @@ -23,7 +23,7 @@ async def get_campaigns(
@router.post("/campaigns", status_code=201, response_model=List[Campaign])
async def create_or_update_campaigns(
campaigns: List[Campaign],
user: User = Depends(require_admin),
user: User = Depends(kc_service.require_admin()),
):
"""Create or update campaigns, move temporary files to there final location"""
service = CampaignsService()
Expand All @@ -45,7 +45,7 @@ async def get_campaign(
@router.delete("/campaign/{identifier}", response_model=List[Campaign])
async def delete_campaign(
identifier: str,
user: User = Depends(require_admin),
user: User = Depends(kc_service.require_admin()),
) -> List[Campaign]:
"""Delete a campaign and associated files"""
service = CampaignsService()
Expand Down
6 changes: 3 additions & 3 deletions backend/api/views/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from fastapi import Depends, Query, APIRouter, HTTPException
from fastapi.responses import Response
from api.utils.file_size import size_checker
from api.auth import require_admin, User
from api.auth import kc_service, User
from pydantic import BaseModel
from api.config import config

Expand Down Expand Up @@ -56,8 +56,8 @@ async def upload_temp_files(
status_code=204,
description="Delete asset present in S3",
)
async def delete_file(file_path: str, user: User = Depends(require_admin)):
async def delete_file(file_path: str, user: User = Depends(kc_service.require_admin())):
# delete path if it contains /tmp/
if file_path.startswith(config.S3_PATH_PREFIX):
await s3_client.delete_file(file_path)
return Response(status_code=204)
return Response(status_code=204)
40 changes: 31 additions & 9 deletions backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ dynaconf = "^3.2.6"
timezonefinder = "^6.5.2"
pandas = "^2.2.2"
openpyxl = "^3.1.5"
python-keycloak = "^4.6.2"
enacit4r = {git = "https://github.com/EPFL-ENAC/enacit4r-pyutils", rev = "0.1.0"}
uvicorn = "^0.32.0"
python-multipart = "^0.0.17"
redis = "^5.2.0"
fastapi-cache2 = "^0.2.2"
enacit4r-files = {git = "https://github.com/EPFL-ENAC/enacit4r-pyutils", rev = "0.3.0", subdirectory = "files"}
enacit4r-auth = {git = "https://github.com/EPFL-ENAC/enacit4r-pyutils", rev = "0.3.0", subdirectory = "auth"}


[build-system]
Expand Down

0 comments on commit 16636ff

Please sign in to comment.