Rust implementation of OCI Distribution Spec with granular access control
at main 98 lines 3.1 kB view raw
1use crate::errors::{ErrorCode, OciErrorResponse}; 2use axum::{body::Body, http::Response, http::StatusCode, response::IntoResponse}; 3 4pub(crate) fn unauthorized(host: &str) -> Response<Body> { 5 let error = OciErrorResponse::new(ErrorCode::Unauthorized, "authentication required"); 6 7 Response::builder() 8 .status(StatusCode::UNAUTHORIZED) 9 .header( 10 "WWW-Authenticate", 11 format!("Basic realm=\"{}\", charset=\"UTF-8\"", host), 12 ) 13 .header("Content-Type", "application/json") 14 .body(Body::from(serde_json::to_string(&error).unwrap_or_else( 15 |_| { 16 r#"{"errors":[{"code":"UNAUTHORIZED","message":"authentication required"}]}"# 17 .to_string() 18 }, 19 ))) 20 .unwrap() 21} 22 23pub(crate) fn forbidden() -> Response<Body> { 24 OciErrorResponse::new(ErrorCode::Denied, "access denied: insufficient permissions") 25 .into_response() 26} 27 28pub(crate) fn not_found() -> Response<Body> { 29 OciErrorResponse::new(ErrorCode::BlobUnknown, "resource not found").into_response() 30} 31 32pub(crate) fn blob_unknown(digest: &str) -> Response<Body> { 33 OciErrorResponse::with_detail( 34 ErrorCode::BlobUnknown, 35 "blob unknown to registry", 36 format!("digest: {}", digest), 37 ) 38 .into_response() 39} 40 41pub(crate) fn manifest_unknown(reference: &str) -> Response<Body> { 42 OciErrorResponse::with_detail( 43 ErrorCode::ManifestUnknown, 44 "manifest unknown to registry", 45 format!("reference: {}", reference), 46 ) 47 .into_response() 48} 49 50pub(crate) fn digest_invalid(digest: &str) -> Response<Body> { 51 OciErrorResponse::with_detail( 52 ErrorCode::DigestInvalid, 53 "provided digest did not match uploaded content", 54 format!("digest: {}", digest), 55 ) 56 .into_response() 57} 58 59pub(crate) fn manifest_invalid(reason: &str) -> Response<Body> { 60 OciErrorResponse::with_detail(ErrorCode::ManifestInvalid, "manifest invalid", reason) 61 .into_response() 62} 63 64#[allow(dead_code)] 65pub(crate) fn name_invalid(name: &str) -> Response<Body> { 66 OciErrorResponse::with_detail(ErrorCode::NameInvalid, "invalid repository name", name) 67 .into_response() 68} 69 70pub(crate) fn blob_upload_unknown(uuid: &str) -> Response<Body> { 71 OciErrorResponse::with_detail( 72 ErrorCode::BlobUploadUnknown, 73 "upload session not found", 74 format!("uuid: {}", uuid), 75 ) 76 .into_response() 77} 78 79pub(crate) fn internal_error() -> Response<Body> { 80 Response::builder() 81 .status(StatusCode::INTERNAL_SERVER_ERROR) 82 .header("Content-Type", "application/json") 83 .body(Body::from( 84 r#"{"errors":[{"code":"UNKNOWN","message":"internal server error"}]}"#, 85 )) 86 .unwrap() 87} 88 89pub(crate) fn conflict(message: &str) -> Response<Body> { 90 Response::builder() 91 .status(StatusCode::CONFLICT) 92 .header("Content-Type", "application/json") 93 .body(Body::from(format!( 94 r#"{{"errors":[{{"code":"UNSUPPORTED","message":"{}"}}]}}"#, 95 message 96 ))) 97 .unwrap() 98}