Git · dadoum.zone
Repositories
Help
Report an Issue
apple-crates
Code
Commits
Branches
Tags
Search
Tree:
a74924e
Branches
Tags
main
apple-crates
xcode
src
v1
certificates.rs
Refactor and unify a lot of things for another project and implement airdrop support
Dadoum
commited
a74924e
at 2026-10-25 22:15:58
certificates.rs
Blame
History
Raw
use super::{BundleIDPlatform, Page, PagedDocumentLinks, base64_content, comma_separated}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum CertificateType { #[serde(rename = "APPLE_PAY")] ApplePay, #[serde(rename = "APPLE_PAY_MERCHANT_IDENTITY")] ApplePayMerchantIdentity, #[serde(rename = "APPLE_PAY_PSP_IDENTITY")] ApplePayPSPIdentity, #[serde(rename = "APPLE_PAY_RSA")] ApplePayRSA, #[serde(rename = "DEVELOPER_ID_KEXT")] DeveloperIDKext, #[serde(rename = "DEVELOPER_ID_KEXT_G2")] DeveloperIDKextG2, #[serde(rename = "DEVELOPER_ID_APPLICATION")] DeveloperIDApplication, #[serde(rename = "DEVELOPER_ID_APPLICATION_G2")] DeveloperIDApplicationG2, #[serde(rename = "DEVELOPMENT")] Development, #[serde(rename = "DISTRIBUTION")] Distribution, #[serde(rename = "IDENTITY_ACCESS")] IdentityAccess, #[serde(rename = "IOS_DEVELOPMENT")] IOSDevelopment, #[serde(rename = "IOS_DISTRIBUTION")] IOSDistribution, #[serde(rename = "MAC_APP_DISTRIBUTION")] MacAppDistribution, #[serde(rename = "MAC_INSTALLER_DISTRIBUTION")] MacInstallerDistribution, #[serde(rename = "MAC_APP_DEVELOPMENT")] MacAppDevelopment, #[serde(rename = "PASS_TYPE_ID")] PassTypeID, #[serde(rename = "PASS_TYPE_ID_WITH_NFC")] PassTypeIDWithNFC, #[serde(untagged)] Other(String), } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CertificateAttributes { pub name: String, pub certificate_type: CertificateType, pub display_name: String, pub serial_number: String, pub platform: Option<BundleIDPlatform>, pub expiration_date: String, /// DER-encoded certificate. #[serde(default, deserialize_with = "base64_content")] pub certificate_content: Vec<u8>, pub activated: Option<bool>, } #[derive(Debug, Deserialize)] pub struct Certificate { pub id: String, pub attributes: CertificateAttributes, } #[derive(Debug, Deserialize)] pub struct CertificatesResponse { pub data: Vec<Certificate>, pub links: PagedDocumentLinks, } #[derive(Debug, Deserialize)] pub struct CertificateResponse { pub data: Certificate, } #[derive(Debug, Default, Serialize)] pub struct ListCertificatesRequest { #[serde( rename = "filter[certificateType]", serialize_with = "comma_separated", skip_serializing_if = "Vec::is_empty" )] pub filter_certificate_type: Vec<CertificateType>, #[serde(flatten)] pub page: Page, } impl_developer_api_request!( ListCertificatesRequest, GET, "certificates", CertificatesResponse ); #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct CertificateCreateAttributes { /// PEM-encoded certificate signing request. pub csr_content: String, pub certificate_type: CertificateType, } #[derive(Debug, Serialize)] #[serde(tag = "type", rename = "certificates")] pub struct CreateCertificateRequest { pub attributes: CertificateCreateAttributes, } impl_developer_api_request!( CreateCertificateRequest, POST, "certificates", CertificateResponse ); #[derive(Debug, Serialize)] pub struct DeleteCertificateRequest { #[serde(skip)] pub certificate_id: String, } impl_developer_api_request!(DeleteCertificateRequest, DELETE, |request| format!( "certificates/{}", request.certificate_id )); #[cfg(test)] mod tests { use super::*; #[test] fn certificates() { let response: CertificatesResponse = serde_json::from_str( r#"{ "data": [{ "type": "certificates", "id": "Z6V8DWZ3R5", "attributes": { "name": "Apple Development: Jane Appleseed (ABCDE12345)", "certificateType": "DEVELOPMENT", "displayName": "Jane Appleseed", "serialNumber": "4E7A32C1B0D9F8E7", "platform": null, "expirationDate": "2027-10-18T05:41:12.000+00:00", "certificateContent": "MIIBAAAA", "activated": true }, "relationships": { "passTypeId": { "links": { "self": "https://api.appstoreconnect.apple.com/v1/certificates/Z6V8DWZ3R5/relationships/passTypeId", "related": "https://api.appstoreconnect.apple.com/v1/certificates/Z6V8DWZ3R5/passTypeId" } } }, "links": { "self": "https://api.appstoreconnect.apple.com/v1/certificates/Z6V8DWZ3R5" } }, { "type": "certificates", "id": "P3M7Q9X2C8", "attributes": { "name": "iOS Development: Jane Appleseed", "certificateType": "IOS_DEVELOPMENT", "displayName": "Jane Appleseed", "serialNumber": "1F2E3D4C5B6A7980", "platform": "IOS", "expirationDate": "2026-12-01T10:00:00.000+00:00", "certificateContent": "MIIBAAAA" } }], "links": { "self": "https://api.appstoreconnect.apple.com/v1/certificates", "next": "https://api.appstoreconnect.apple.com/v1/certificates?cursor=Mg.ANi1Ck4&limit=2" }, "meta": { "paging": { "total": 3, "limit": 2 } } }"#, ) .unwrap(); let attributes = &response.data[0].attributes; assert_eq!(attributes.certificate_type, CertificateType::Development); assert_eq!(attributes.platform, None); assert_eq!( attributes.certificate_content, [0x30, 0x82, 0x01, 0x00, 0x00, 0x00] ); assert_eq!(attributes.activated, Some(true)); assert_eq!( response.data[1].attributes.platform, Some(BundleIDPlatform::IOS) ); assert_eq!(response.data[1].attributes.activated, None); assert_eq!( response.links.next_page().unwrap().cursor.as_deref(), Some("Mg.ANi1Ck4") ); } #[test] fn create_certificate() { let request = CreateCertificateRequest { attributes: CertificateCreateAttributes { csr_content: String::from( "-----BEGIN CERTIFICATE REQUEST-----\nMIIB\n-----END CERTIFICATE REQUEST-----\n", ), certificate_type: CertificateType::Development, }, }; assert_eq!( serde_json::to_value(&request).unwrap(), serde_json::json!({ "type": "certificates", "attributes": { "csrContent": "-----BEGIN CERTIFICATE REQUEST-----\nMIIB\n-----END CERTIFICATE REQUEST-----\n", "certificateType": "DEVELOPMENT" } }) ); let response: CertificateResponse = serde_json::from_str( r#"{ "data": { "type": "certificates", "id": "Z6V8DWZ3R5", "attributes": { "name": "Apple Development: Jane Appleseed (ABCDE12345)", "certificateType": "DEVELOPMENT", "displayName": "Jane Appleseed", "serialNumber": "4E7A32C1B0D9F8E7", "expirationDate": "2027-10-18T05:41:12.000+00:00", "certificateContent": "MIIBAAAA" }, "links": { "self": "https://api.appstoreconnect.apple.com/v1/certificates/Z6V8DWZ3R5" } }, "links": { "self": "https://api.appstoreconnect.apple.com/v1/certificates" } }"#, ) .unwrap(); assert_eq!(response.data.attributes.serial_number, "4E7A32C1B0D9F8E7"); assert!(!response.data.attributes.certificate_content.is_empty()); } }