use actix_web::{HttpResponse, web}; use crate::api::response::{ApiErrorResponse, ApiResponse}; use crate::error::AppError; use crate::models::users::UserGpgKey; use crate::service::AppService; use crate::service::user::keys::AddGpgKeyParams; use crate::session::Session; /// Add a GPG key /// /// Registers a new GPG public key for the authenticated user. /// Requires authentication. /// /// Parameters: /// - public_key: ASCII-armored PGP public key block /// - key_id: Short key ID or full fingerprint /// - primary_email: Primary email associated with the key (optional) /// - expires_at: Optional expiration date for the key /// /// Effects: /// - Key fingerprint is computed and stored /// - Key is immediately usable for verifying signed commits/tags /// - Duplicate keys are rejected /// /// Returns the created GPG key with fingerprint and metadata. #[utoipa::path( post, path = "/api/v1/user/keys/gpg", tag = "User", operation_id = "userAddGpgKey", request_body( content = AddGpgKeyParams, description = "GPG key creation parameters", content_type = "application/json" ), responses( (status = 201, description = "GPG key added successfully. Returns the created key with fingerprint and metadata.", body = ApiResponse), (status = 400, description = "Invalid parameters: invalid PGP key format", body = ApiErrorResponse), (status = 401, description = "Authentication required or session expired", body = ApiErrorResponse), (status = 409, description = "GPG key with this fingerprint already exists", body = ApiErrorResponse), (status = 500, description = "Internal server error", body = ApiErrorResponse), ), security( ("session_cookie" = []) ) )] pub async fn add_gpg_key( service: web::Data, session: Session, params: web::Json, ) -> Result { let key = service .user .user_add_gpg_key(&session, params.into_inner()) .await?; Ok(HttpResponse::Created().json(ApiResponse::new(key))) }