Jesús Pérez dd68d190ef ci: Update pre-commit hooks configuration
- Exclude problematic markdown files from linting (existing legacy issues)
- Make clippy check less aggressive (warnings only, not -D warnings)
- Move cargo test to manual stage (too slow for pre-commit)
- Exclude SVG files from end-of-file-fixer and trailing-whitespace
- Add markdown linting exclusions for existing documentation

This allows pre-commit hooks to run successfully on new code without
blocking commits due to existing issues in legacy documentation files.
2026-01-11 21:32:56 +00:00

143 lines
3.6 KiB
Rust

// Projects API endpoints
use crate::api::ApiResult;
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use vapora_shared::models::Project;
use crate::api::state::AppState;
/// List all projects for a tenant
///
/// GET /api/v1/projects
pub async fn list_projects(State(state): State<AppState>) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let projects = state.project_service.list_projects(tenant_id).await?;
Ok(Json(projects))
}
/// Get a specific project
///
/// GET /api/v1/projects/:id
pub async fn get_project(
State(state): State<AppState>,
Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let project = state.project_service.get_project(&id, tenant_id).await?;
Ok(Json(project))
}
/// Create a new project
///
/// POST /api/v1/projects
pub async fn create_project(
State(state): State<AppState>,
Json(mut project): Json<Project>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
project.tenant_id = "default".to_string();
let created = state.project_service.create_project(project).await?;
Ok((StatusCode::CREATED, Json(created)))
}
/// Update a project
///
/// PUT /api/v1/projects/:id
pub async fn update_project(
State(state): State<AppState>,
Path(id): Path<String>,
Json(updates): Json<Project>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let updated = state
.project_service
.update_project(&id, tenant_id, updates)
.await?;
Ok(Json(updated))
}
/// Delete a project
///
/// DELETE /api/v1/projects/:id
pub async fn delete_project(
State(state): State<AppState>,
Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
state.project_service.delete_project(&id, tenant_id).await?;
Ok(StatusCode::NO_CONTENT)
}
/// Add a feature to a project
///
/// POST /api/v1/projects/:id/features
pub async fn add_feature(
State(state): State<AppState>,
Path(id): Path<String>,
Json(payload): Json<serde_json::Value>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let feature = payload["feature"]
.as_str()
.ok_or_else(|| {
vapora_shared::VaporaError::InvalidInput("Missing 'feature' field".to_string())
})?
.to_string();
let updated = state
.project_service
.add_feature(&id, tenant_id, feature)
.await?;
Ok(Json(updated))
}
/// Remove a feature from a project
///
/// DELETE /api/v1/projects/:id/features/:feature
pub async fn remove_feature(
State(state): State<AppState>,
Path((id, feature)): Path<(String, String)>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let updated = state
.project_service
.remove_feature(&id, tenant_id, &feature)
.await?;
Ok(Json(updated))
}
/// Archive a project
///
/// POST /api/v1/projects/:id/archive
pub async fn archive_project(
State(state): State<AppState>,
Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
// TODO: Extract tenant_id from JWT token
let tenant_id = "default";
let updated = state
.project_service
.archive_project(&id, tenant_id)
.await?;
Ok(Json(updated))
}