Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 48
feat(server): migrate controls routes to auth framework#212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
c6dc723587ce391b17f470e70c6ba9dfc423cd0ee1File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -33,7 +33,7 @@ | ||
| from sqlalchemy.exc import IntegrityError | ||
| from sqlalchemy.ext.asyncio import AsyncSession | ||
| from ..auth import require_admin_key | ||
| from ..auth_framework import Operation, Principal, require_operation | ||
| from ..db import get_async_db | ||
| from ..errors import ( | ||
| APIValidationError, | ||
| @@ -443,9 +443,11 @@ async def _validate_control_definition( | ||
| summary="Render a control template preview", | ||
| response_description="Rendered control preview", | ||
| ) | ||
| # Rendering is part of the authoring flow, so require create access. | ||
| async def render_control_template( | ||
| request: RenderControlTemplateRequest, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_CREATE)), | ||
| ) -> RenderControlTemplateResponse: | ||
| """Render a template-backed control without persisting it.""" | ||
| control_def = await _render_and_validate_template_input( | ||
| @@ -461,13 +463,14 @@ async def render_control_template( | ||
| @router.put( | ||
| "", | ||
| dependencies=[Depends(require_admin_key)], | ||
| response_model=CreateControlResponse, | ||
| summary="Create a new control", | ||
| response_description="Created control ID", | ||
| ) | ||
| async def create_control( | ||
| request: CreateControlRequest, db: AsyncSession = Depends(get_async_db) | ||
| request: CreateControlRequest, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_CREATE)), | ||
| ) -> CreateControlResponse: | ||
| """ | ||
| Create a new control with a unique name. | ||
| @@ -549,6 +552,7 @@ async def create_control( | ||
| summary="Get control definition JSON schema", | ||
| response_description="JSON schema for ControlDefinition", | ||
| ) | ||
| # Public schema metadata: no tenant state, no auth operation. | ||
abhinav-galileo marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| async def get_control_schema() -> GetControlSchemaResponse: | ||
| """Return the canonical JSON schema for ControlDefinition.""" | ||
| return GetControlSchemaResponse( | ||
| @@ -563,7 +567,9 @@ async def get_control_schema() -> GetControlSchemaResponse: | ||
| response_description="Control metadata and configuration", | ||
| ) | ||
| async def get_control( | ||
| control_id: int, db: AsyncSession = Depends(get_async_db) | ||
| control_id: int, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_READ)), | ||
abhinav-galileo marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ) -> GetControlResponse: | ||
| """ | ||
| Retrieve a control by ID including its name and configuration data. | ||
| @@ -600,7 +606,9 @@ async def get_control( | ||
| response_description="Control data payload", | ||
| ) | ||
| async def get_control_data( | ||
| control_id: int, db: AsyncSession = Depends(get_async_db) | ||
| control_id: int, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_READ)), | ||
| ) -> GetControlDataResponse: | ||
| """ | ||
| Retrieve the configuration data for a control. | ||
| @@ -640,6 +648,7 @@ async def list_control_versions( | ||
| ), | ||
| limit: int = Query(_DEFAULT_PAGINATION_LIMIT, ge=1, le=_MAX_PAGINATION_LIMIT), | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_READ)), | ||
| ) -> ListControlVersionsResponse: | ||
| """List control versions ordered newest-first using cursor-based pagination.""" | ||
| page = await ControlService(db).list_versions(control_id, cursor=cursor, limit=limit) | ||
| @@ -673,6 +682,7 @@ async def get_control_version( | ||
| control_id: int, | ||
| version_num: int, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_READ)), | ||
| ) -> GetControlVersionResponse: | ||
| """Return a specific control version, including its raw persisted snapshot.""" | ||
| version = await ControlService(db).get_version_or_404(control_id, version_num) | ||
| @@ -687,7 +697,6 @@ async def get_control_version( | ||
| @router.put( | ||
| "/{control_id}/data", | ||
| dependencies=[Depends(require_admin_key)], | ||
| response_model=SetControlDataResponse, | ||
| summary="Update control configuration data", | ||
| response_description="Success confirmation", | ||
| @@ -696,6 +705,7 @@ async def set_control_data( | ||
| control_id: int, | ||
| request: SetControlDataRequest, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_UPDATE)), | ||
| ) -> SetControlDataResponse: | ||
| """ | ||
| Update the configuration data for a control. | ||
| @@ -757,8 +767,11 @@ async def set_control_data( | ||
| summary="Validate control configuration", | ||
| response_description="Validation result", | ||
| ) | ||
| # Validation uses the authoring path, so require create access. | ||
| async def validate_control_data( | ||
| request: ValidateControlDataRequest, db: AsyncSession = Depends(get_async_db) | ||
| request: ValidateControlDataRequest, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_CREATE)), | ||
| ) -> ValidateControlDataResponse: | ||
| """ | ||
| Validate control configuration data without saving it. | ||
| @@ -798,6 +811,7 @@ async def list_controls( | ||
| execution: str | None = Query(None, description="Filter by execution ('server' or 'sdk')"), | ||
| tag: str | None = Query(None, description="Filter by tag"), | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_READ)), | ||
| ) -> ListControlsResponse: | ||
| """ | ||
| List all controls with optional filtering and cursor-based pagination. | ||
| @@ -884,7 +898,6 @@ async def list_controls( | ||
| @router.delete( | ||
| "/{control_id}", | ||
| dependencies=[Depends(require_admin_key)], | ||
| response_model=DeleteControlResponse, | ||
| summary="Delete a control", | ||
| response_description="Deletion confirmation with dissociation info", | ||
| @@ -897,6 +910,7 @@ async def delete_control( | ||
| "If false, fail if control is associated with any policy or agent.", | ||
| ), | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_DELETE)), | ||
| ) -> DeleteControlResponse: | ||
| """ | ||
| Delete a control by ID. | ||
| @@ -1035,7 +1049,6 @@ async def delete_control( | ||
| @router.patch( | ||
| "/{control_id}", | ||
| dependencies=[Depends(require_admin_key)], | ||
| response_model=PatchControlResponse, | ||
| summary="Update control metadata", | ||
| response_description="Updated control information", | ||
| @@ -1044,6 +1057,7 @@ async def patch_control( | ||
| control_id: int, | ||
| request: PatchControlRequest, | ||
| db: AsyncSession = Depends(get_async_db), | ||
| _principal: Principal = Depends(require_operation(Operation.CONTROLS_UPDATE)), | ||
| ) -> PatchControlResponse: | ||
| """ | ||
| Update control metadata (name and/or enabled status). | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.