Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
50 changes: 9 additions & 41 deletions core/services/workflow_service/controllers/project_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,15 @@ def create_project_from_template(
raise e


def read_project(project_uuid: UUID) -> Project:
logging.debug(f"Reading project with UUID: {project_uuid}")
db: Session = next(get_database())

project = db.query(Project).filter_by(uuid=project_uuid).one_or_none()

if not project:
logging.error(f"Project {project_uuid} not found")
raise HTTPException(status_code=404, detail="Project not found")

return project


def rename_project(project_uuid: UUID, new_name: str, db: Session) -> Project:
logging.debug(f"Renaming project {project_uuid} to {new_name}.")

project = db.query(Project).filter_by(uuid=project_uuid).one_or_none()

if not project:
logging.error(f"Project {project_uuid} not found.")
raise HTTPException(status_code=404, detail="Project not found")
def rename_project(db: Session, project: Project, new_name: str) -> Project:
logging.debug(f"Renaming project {project.uuid} to {new_name}.")

project.name = new_name

logging.info(f"Project {project_uuid} renamed successfully to {new_name}")
db.commit()
db.refresh(project)

logging.debug(f"Project {project.uuid} renamed successfully to {new_name}")
return project


Expand Down Expand Up @@ -154,20 +138,13 @@ def delete_user(project_uuid: UUID, user_uuid: UUID) -> None:
logging.info(f"User {user_uuid} removed from project {project_uuid}")


def delete_project(project_uuid: UUID) -> None:
logging.debug(f"Deleting project with UUID: {project_uuid}")
db: Session = next(get_database())

project = db.query(Project).filter_by(uuid=project_uuid).one_or_none()

if not project:
logging.error(f"Project {project_uuid} not found")
raise HTTPException(status_code=404, detail="Project not found")
def delete_project(db: Session, project: Project) -> None:
logging.debug(f"Deleting project with UUID: {project.uuid}")

db.delete(project)
db.commit()

logging.info(f"Project {project_uuid} deleted successfully")
logging.debug("Project deleted successfully")


def read_all_projects() -> list[Project]:
Expand All @@ -188,13 +165,4 @@ def read_projects_by_user_uuid(user_uuid: UUID) -> list[Project]:
.all()
)

if not projects:
logging.error(f"No projects found for user {user_uuid}")
raise HTTPException(
status_code=404,
detail="No projects found for user",
)

logging.info(f"Retrieved {len(projects)} projects for user {user_uuid}")

return projects
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
compute_block_controller,
template_controller,
)
from services.workflow_service.controllers.project_controller import (
read_project,
)
from services.workflow_service.models.block import (
Block,
block_dependencies,
Expand All @@ -45,6 +42,7 @@
BlockStatus,
ConfigType,
)
from services.workflow_service.models import Project
from services.workflow_service.schemas.workflow import (
WorfklowValidationError,
WorkflowEnvsWithBlockInfo,
Expand Down Expand Up @@ -478,10 +476,9 @@ def wait_for_dag_registration(
return False


def translate_project_to_dag(project_uuid: UUID) -> str:
def translate_project_to_dag(project: Project, project_uuid: UUID) -> str:
"""Parses a project and its blocks into a DAG, validates it, and saves
it."""
project = read_project(project_uuid)
graph = create_graph(project)
templates = init_templates()
dag_id = _project_id_to_dag_id(project_uuid)
Expand Down
8 changes: 8 additions & 0 deletions core/services/workflow_service/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from .block import Block
from .entrypoint import Entrypoint
from .input_output import InputOutput
from .project import Project

__all__ = [
"Block", "Entrypoint", "InputOutput", "Project"
]
1 change: 0 additions & 1 deletion core/services/workflow_service/schemas/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class ReadAllResponse(BaseModel):


class RenameProjectRequest(BaseModel):
project_uuid: UUID
new_name: str


Expand Down
41 changes: 18 additions & 23 deletions core/services/workflow_service/views/project.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from fastapi import APIRouter, Depends, HTTPException
from uuid import UUID
from fastapi import APIRouter, Depends
from utils.errors.error import handle_error
import logging
from sqlalchemy.orm import Session
Expand All @@ -20,6 +19,7 @@
)
from utils.database.session_injector import get_database
from utils.security.token import User, get_user
from utils.security.resources import get_project

router = APIRouter(prefix="/project", tags=["project"])

Expand Down Expand Up @@ -83,41 +83,36 @@ async def read_projects_by_user(
raise handle_error(e)


@router.get("/{project_id}", response_model=Project)
@router.get("/{project_uuid}", response_model=Project)
async def read_project(
project_id: UUID | None = None,
project: Project = Depends(get_project)
):
try:
if project_id is None:
raise HTTPException(status=422, detail="Project ID is required")

project = project_controller.read_project(project_id)
return project
except Exception as e:
logging.error(f"Error reading project: {e}")
raise handle_error(e)
return project


@router.put("/", response_model=Project)
@router.put("/{project_uuid}", response_model=Project)
async def rename_project(
data: RenameProjectRequest,
project: Project = Depends(get_project),
db: Session = Depends(get_database)
):
try:
with db.begin():
updated_project = project_controller.rename_project(
data.project_uuid, data.new_name, db
)
updated_project = project_controller.rename_project(
db, project, data.new_name)
return updated_project
except Exception as e:
raise handle_error(e)


@router.delete("/{project_id}", status_code=200)
async def delete_project(project_id: UUID, _: User = Depends(get_user)):
@router.delete("/{project_uuid}", status_code=200)
async def delete_project(
project: Project = Depends(get_project),
db: Session = Depends(get_database)
):
try:
project_controller.delete_project(project_id)
workflow_controller.delete_dag_from_airflow(project_id)
project_controller.delete_project(db, project)
workflow_controller.delete_dag_from_airflow(project.uuid)
except Exception as e:
logging.exception(f"Error deleting project with id {project_id}: {e}")
logging.exception(f"Error deleting project with id {
project.uuid}: {e}")
raise handle_error(e)
12 changes: 5 additions & 7 deletions core/services/workflow_service/views/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from services.workflow_service.controllers import (
project_controller as project_controller,
)
from services.workflow_service.models import Project
from services.workflow_service.controllers import workflow_controller
from services.workflow_service.schemas.workflow import (
GetWorkflowConfigurationResponse,
Expand All @@ -27,6 +28,7 @@
from utils.database.session_injector import get_database
from utils.errors.error import handle_error
from utils.security.token import User, get_user, get_user_from_token
from utils.security.resources import get_project

router = APIRouter(prefix="/workflow", tags=["workflow"])

Expand Down Expand Up @@ -145,15 +147,11 @@ def update_workflow_configurations(

@router.post("/{project_id}", status_code=200)
def translate_project_to_dag(
project_id: UUID | None = None,
_: User = Depends(get_user),
project: Project = Depends(get_project)
):
if not project_id:
raise HTTPException(status_code=422, detail="Project ID missing")

try:
workflow_controller.validate_workflow(project_id)
dag_id = workflow_controller.translate_project_to_dag(project_id)
workflow_controller.validate_workflow(project.uuid)
dag_id = workflow_controller.translate_project_to_dag(project.uuid)
# Make sure airflow has enough time to create the dag internally
if not workflow_controller.wait_for_dag_registration(dag_id):
logging.error(f"DAG {dag_id} was not registered in time.")
Expand Down
27 changes: 27 additions & 0 deletions core/utils/security/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from fastapi import HTTPException, Depends, Path
from sqlalchemy.orm import Session
from uuid import UUID

from utils.database.session_injector import get_database
from utils.security.token import User, get_user

from services.workflow_service.models import (
Project,
)


def get_project(
project_uuid: UUID = Path(...),
user: User = Depends(get_user),
db: Session = Depends(get_database)
):
project = db.query(Project).filter_by(uuid=project_uuid).one_or_none()
if not project:
raise HTTPException(404, f"Project {project_uuid} not found")

print(project.users)
# authorize access
if user.uuid not in (project.users or []):
raise HTTPException(403, "Access to resource denied")

return project
1 change: 1 addition & 0 deletions frontend/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />

Check failure on line 3 in frontend/next-env.d.ts

View workflow job for this annotation

GitHub Actions / lint-frontend

Do not use a triple slash reference for ./.next/types/routes.d.ts, use `import` style instead

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
Loading