use axum::{
extract::{Extension, Query, State},
Json,
};
use super::models::{GetRegistryCredsRequest, GetRegistryCredsResponse};
use crate::db::models::User;
use crate::db::{projects, teams as db_teams};
use crate::server::error::{ServerError, ServerErrorExt};
use crate::server::state::AppState;
use uuid::Uuid;
async fn check_deploy_permission(
state: &AppState,
project: &crate::db::models::Project,
user_id: Uuid,
) -> Result<(), ServerError> {
if let Some(owner_user_id) = project.owner_user_id {
if owner_user_id == user_id {
return Ok(());
}
}
if let Some(team_id) = project.owner_team_id {
let is_owner = db_teams::is_owner(&state.db_pool, team_id, user_id)
.await
.internal_err("Failed to check team ownership")?;
if is_owner {
return Ok(());
}
let team = db_teams::find_by_id(&state.db_pool, team_id)
.await
.internal_err("Failed to fetch team")?
.ok_or_else(|| ServerError::not_found("Team not found"))?;
return Err(ServerError::forbidden(format!(
"You must be an owner of team '{}' to deploy to this project",
team.name
)));
}
Err(ServerError::forbidden(
"You do not have permission to deploy to this project",
))
}
pub async fn get_registry_credentials(
State(state): State<AppState>,
Extension(user): Extension<User>,
Query(params): Query<GetRegistryCredsRequest>,
) -> Result<Json<GetRegistryCredsResponse>, ServerError> {
let project = projects::find_by_name(&state.db_pool, ¶ms.project)
.await
.internal_err("Failed to query project")
.map_err(|e| e.with_context("project_name", ¶ms.project))?
.ok_or_else(|| ServerError::not_found(format!("Project '{}' not found", params.project)))?;
check_deploy_permission(&state, &project, user.id).await?;
let repository = params.project.clone();
let credentials = state
.registry_provider
.get_credentials(&repository)
.await
.internal_err("Failed to get registry credentials")
.map_err(|e| {
e.with_context("project_name", ¶ms.project)
.with_context("repository", &repository)
})?;
Ok(Json(GetRegistryCredsResponse {
credentials,
repository,
}))
}