mirror of
https://github.com/nab138/isideload.git
synced 2026-03-02 22:46:15 +01:00
first commit
This commit is contained in:
698
src/developer_session.rs
Normal file
698
src/developer_session.rs
Normal file
@@ -0,0 +1,698 @@
|
||||
// This file was made using https://github.com/Dadoum/Sideloader as a reference for the apple private endpoints
|
||||
|
||||
use crate::Error;
|
||||
use icloud_auth::{AppleAccount, Error as ICloudError};
|
||||
use plist::{Date, Dictionary, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct DeveloperSession {
|
||||
pub account: Arc<AppleAccount>,
|
||||
team: Option<DeveloperTeam>,
|
||||
}
|
||||
|
||||
impl DeveloperSession {
|
||||
pub fn new(account: Arc<AppleAccount>) -> Self {
|
||||
DeveloperSession {
|
||||
account,
|
||||
team: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_developer_request(
|
||||
&self,
|
||||
url: &str,
|
||||
body: Option<Dictionary>,
|
||||
) -> Result<Dictionary, Error> {
|
||||
let mut request = Dictionary::new();
|
||||
request.insert(
|
||||
"clientId".to_string(),
|
||||
Value::String("XABBG36SBA".to_string()),
|
||||
);
|
||||
request.insert(
|
||||
"protocolVersion".to_string(),
|
||||
Value::String("QH65B2".to_string()),
|
||||
);
|
||||
request.insert(
|
||||
"requestId".to_string(),
|
||||
Value::String(Uuid::new_v4().to_string().to_uppercase()),
|
||||
);
|
||||
request.insert(
|
||||
"userLocale".to_string(),
|
||||
Value::Array(vec![Value::String("en_US".to_string())]),
|
||||
);
|
||||
if let Some(body) = body {
|
||||
for (key, value) in body {
|
||||
request.insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
let response = self
|
||||
.account
|
||||
.send_request(url, Some(request))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
if let ICloudError::AuthSrpWithMessage(code, message) = e {
|
||||
Error::DeveloperSession(code, format!("Developer request failed: {}", message))
|
||||
} else {
|
||||
Error::Generic
|
||||
}
|
||||
})?;
|
||||
|
||||
let status_code = response
|
||||
.get("resultCode")
|
||||
.and_then(|v| v.as_unsigned_integer())
|
||||
.unwrap_or(0);
|
||||
if status_code != 0 {
|
||||
let description = response
|
||||
.get("userString")
|
||||
.and_then(|v| v.as_string())
|
||||
.or_else(|| response.get("resultString").and_then(|v| v.as_string()))
|
||||
.unwrap_or("(null)");
|
||||
return Err(Error::DeveloperSession(
|
||||
status_code as i64,
|
||||
description.to_string(),
|
||||
));
|
||||
}
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn list_teams(&self) -> Result<Vec<DeveloperTeam>, Error> {
|
||||
let url = "https://developerservices2.apple.com/services/QH65B2/listTeams.action?clientId=XABBG36SBA";
|
||||
let response = self.send_developer_request(url, None).await?;
|
||||
|
||||
let teams = response
|
||||
.get("teams")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for team in teams {
|
||||
let dict = team.as_dictionary().ok_or(Error::Parse)?;
|
||||
let name = dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let team_id = dict
|
||||
.get("teamId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
result.push(DeveloperTeam {
|
||||
_name: name,
|
||||
team_id,
|
||||
});
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn get_team(&self) -> Result<DeveloperTeam, Error> {
|
||||
if let Some(team) = &self.team {
|
||||
return Ok(team.clone());
|
||||
}
|
||||
let teams = self.list_teams().await?;
|
||||
if teams.is_empty() {
|
||||
return Err(Error::DeveloperSession(
|
||||
-1,
|
||||
"No developer teams found".to_string(),
|
||||
));
|
||||
}
|
||||
// TODO: Handle multiple teams
|
||||
Ok(teams[0].clone())
|
||||
}
|
||||
|
||||
pub fn set_team(&mut self, team: DeveloperTeam) {
|
||||
self.team = Some(team);
|
||||
}
|
||||
|
||||
pub async fn list_devices(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
) -> Result<Vec<DeveloperDevice>, Error> {
|
||||
let url = dev_url(device_type, "listDevices");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let devices = response
|
||||
.get("devices")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for device in devices {
|
||||
let dict = device.as_dictionary().ok_or(Error::Parse)?;
|
||||
let device_id = dict
|
||||
.get("deviceId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let name = dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let device_number = dict
|
||||
.get("deviceNumber")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
result.push(DeveloperDevice {
|
||||
_device_id: device_id,
|
||||
_name: name,
|
||||
device_number,
|
||||
});
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn add_device(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
device_name: &str,
|
||||
udid: &str,
|
||||
) -> Result<DeveloperDevice, Error> {
|
||||
let url = dev_url(device_type, "addDevice");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert("name".to_string(), Value::String(device_name.to_string()));
|
||||
body.insert("deviceNumber".to_string(), Value::String(udid.to_string()));
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let device_dict = response
|
||||
.get("device")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let device_id = device_dict
|
||||
.get("deviceId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let name = device_dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let device_number = device_dict
|
||||
.get("deviceNumber")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
|
||||
Ok(DeveloperDevice {
|
||||
_device_id: device_id,
|
||||
_name: name,
|
||||
device_number,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn list_all_development_certs(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
) -> Result<Vec<DevelopmentCertificate>, Error> {
|
||||
let url = dev_url(device_type, "listAllDevelopmentCerts");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let certs = response
|
||||
.get("certificates")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for cert in certs {
|
||||
let dict = cert.as_dictionary().ok_or(Error::Parse)?;
|
||||
let name = dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let certificate_id = dict
|
||||
.get("certificateId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let serial_number = dict
|
||||
.get("serialNumber")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let machine_name = dict
|
||||
.get("machineName")
|
||||
.and_then(|v| v.as_string())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let cert_content = dict
|
||||
.get("certContent")
|
||||
.and_then(|v| v.as_data())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_vec();
|
||||
|
||||
result.push(DevelopmentCertificate {
|
||||
name: name,
|
||||
certificate_id,
|
||||
serial_number: serial_number,
|
||||
machine_name: machine_name,
|
||||
cert_content,
|
||||
});
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn revoke_development_cert(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
serial_number: &str,
|
||||
) -> Result<(), Error> {
|
||||
let url = dev_url(device_type, "revokeDevelopmentCert");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert(
|
||||
"serialNumber".to_string(),
|
||||
Value::String(serial_number.to_string()),
|
||||
);
|
||||
|
||||
self.send_developer_request(&url, Some(body)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn submit_development_csr(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
csr_content: String,
|
||||
) -> Result<String, Error> {
|
||||
let url = dev_url(device_type, "submitDevelopmentCSR");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert("csrContent".to_string(), Value::String(csr_content));
|
||||
body.insert(
|
||||
"machineId".to_string(),
|
||||
Value::String(uuid::Uuid::new_v4().to_string().to_uppercase()),
|
||||
);
|
||||
body.insert(
|
||||
"machineName".to_string(),
|
||||
Value::String("YCode".to_string()),
|
||||
);
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
let cert_dict = response
|
||||
.get("certRequest")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
let id = cert_dict
|
||||
.get("certRequestId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub async fn list_app_ids(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
) -> Result<ListAppIdsResponse, Error> {
|
||||
let url = dev_url(device_type, "listAppIds");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let app_ids = response
|
||||
.get("appIds")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for app_id in app_ids {
|
||||
let dict = app_id.as_dictionary().ok_or(Error::Parse)?;
|
||||
let name = dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let app_id_id = dict
|
||||
.get("appIdId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let identifier = dict
|
||||
.get("identifier")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let features = dict
|
||||
.get("features")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
let expiration_date = if dict.contains_key("expirationDate") {
|
||||
Some(
|
||||
dict.get("expirationDate")
|
||||
.and_then(|v| v.as_date())
|
||||
.ok_or(Error::Parse)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
result.push(AppId {
|
||||
name,
|
||||
app_id_id,
|
||||
identifier,
|
||||
features: features.clone(),
|
||||
expiration_date,
|
||||
});
|
||||
}
|
||||
|
||||
let max_quantity = response
|
||||
.get("maxQuantity")
|
||||
.and_then(|v| v.as_unsigned_integer())
|
||||
.ok_or(Error::Parse)?;
|
||||
let available_quantity = response
|
||||
.get("availableQuantity")
|
||||
.and_then(|v| v.as_unsigned_integer())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
Ok(ListAppIdsResponse {
|
||||
app_ids: result,
|
||||
max_quantity,
|
||||
available_quantity,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn add_app_id(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
name: &str,
|
||||
identifier: &str,
|
||||
) -> Result<(), Error> {
|
||||
let url = dev_url(device_type, "addAppId");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert("name".to_string(), Value::String(name.to_string()));
|
||||
body.insert(
|
||||
"identifier".to_string(),
|
||||
Value::String(identifier.to_string()),
|
||||
);
|
||||
|
||||
self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_app_id(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
app_id: &AppId,
|
||||
features: &Dictionary,
|
||||
) -> Result<Dictionary, Error> {
|
||||
let url = dev_url(device_type, "updateAppId");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert(
|
||||
"appIdId".to_string(),
|
||||
Value::String(app_id.app_id_id.clone()),
|
||||
);
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
|
||||
for (key, value) in features {
|
||||
body.insert(key.clone(), value.clone());
|
||||
}
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
let cert_dict = response
|
||||
.get("appId")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
let feats = cert_dict
|
||||
.get("features")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
Ok(feats.clone())
|
||||
}
|
||||
|
||||
pub async fn delete_app_id(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
app_id_id: String,
|
||||
) -> Result<(), Error> {
|
||||
let url = dev_url(device_type, "deleteAppId");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert("appIdId".to_string(), Value::String(app_id_id.clone()));
|
||||
|
||||
self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn list_application_groups(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
) -> Result<Vec<ApplicationGroup>, Error> {
|
||||
let url = dev_url(device_type, "listApplicationGroups");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let app_groups = response
|
||||
.get("applicationGroupList")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or(Error::Parse)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for app_group in app_groups {
|
||||
let dict = app_group.as_dictionary().ok_or(Error::Parse)?;
|
||||
let application_group = dict
|
||||
.get("applicationGroup")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let name = dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let identifier = dict
|
||||
.get("identifier")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
|
||||
result.push(ApplicationGroup {
|
||||
application_group,
|
||||
_name: name,
|
||||
identifier,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn add_application_group(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
group_identifier: &str,
|
||||
name: &str,
|
||||
) -> Result<ApplicationGroup, Error> {
|
||||
let url = dev_url(device_type, "addApplicationGroup");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert("name".to_string(), Value::String(name.to_string()));
|
||||
body.insert(
|
||||
"identifier".to_string(),
|
||||
Value::String(group_identifier.to_string()),
|
||||
);
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
let app_group_dict = response
|
||||
.get("applicationGroup")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
let application_group = app_group_dict
|
||||
.get("applicationGroup")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let name = app_group_dict
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let identifier = app_group_dict
|
||||
.get("identifier")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
|
||||
Ok(ApplicationGroup {
|
||||
application_group,
|
||||
_name: name,
|
||||
identifier,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn assign_application_group_to_app_id(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
app_id: &AppId,
|
||||
app_group: &ApplicationGroup,
|
||||
) -> Result<(), Error> {
|
||||
let url = dev_url(device_type, "assignApplicationGroupToAppId");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert(
|
||||
"appIdId".to_string(),
|
||||
Value::String(app_id.app_id_id.clone()),
|
||||
);
|
||||
body.insert(
|
||||
"applicationGroups".to_string(),
|
||||
Value::String(app_group.application_group.clone()),
|
||||
);
|
||||
|
||||
self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn download_team_provisioning_profile(
|
||||
&self,
|
||||
device_type: DeveloperDeviceType,
|
||||
team: &DeveloperTeam,
|
||||
app_id: &AppId,
|
||||
) -> Result<ProvisioningProfile, Error> {
|
||||
let url = dev_url(device_type, "downloadTeamProvisioningProfile");
|
||||
let mut body = Dictionary::new();
|
||||
body.insert("teamId".to_string(), Value::String(team.team_id.clone()));
|
||||
body.insert(
|
||||
"appIdId".to_string(),
|
||||
Value::String(app_id.app_id_id.clone()),
|
||||
);
|
||||
|
||||
let response = self.send_developer_request(&url, Some(body)).await?;
|
||||
|
||||
let profile = response
|
||||
.get("provisioningProfile")
|
||||
.and_then(|v| v.as_dictionary())
|
||||
.ok_or(Error::Parse)?;
|
||||
let name = profile
|
||||
.get("name")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let provisioning_profile_id = profile
|
||||
.get("provisioningProfileId")
|
||||
.and_then(|v| v.as_string())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_string();
|
||||
let encoded_profile = profile
|
||||
.get("encodedProfile")
|
||||
.and_then(|v| v.as_data())
|
||||
.ok_or(Error::Parse)?
|
||||
.to_vec();
|
||||
|
||||
Ok(ProvisioningProfile {
|
||||
_name: name,
|
||||
_provisioning_profile_id: provisioning_profile_id,
|
||||
encoded_profile,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DeveloperDeviceType {
|
||||
Any,
|
||||
Ios,
|
||||
Tvos,
|
||||
Watchos,
|
||||
}
|
||||
|
||||
impl DeveloperDeviceType {
|
||||
pub fn url_segment(&self) -> &'static str {
|
||||
match self {
|
||||
DeveloperDeviceType::Any => "",
|
||||
DeveloperDeviceType::Ios => "ios/",
|
||||
DeveloperDeviceType::Tvos => "tvos/",
|
||||
DeveloperDeviceType::Watchos => "watchos/",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dev_url(device_type: DeveloperDeviceType, endpoint: &str) -> String {
|
||||
format!(
|
||||
"https://developerservices2.apple.com/services/QH65B2/{}{}.action?clientId=XABBG36SBA",
|
||||
device_type.url_segment(),
|
||||
endpoint
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeveloperDevice {
|
||||
pub _device_id: String,
|
||||
pub _name: String,
|
||||
pub device_number: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeveloperTeam {
|
||||
pub _name: String,
|
||||
pub team_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DevelopmentCertificate {
|
||||
pub name: String,
|
||||
pub certificate_id: String,
|
||||
pub serial_number: String,
|
||||
pub machine_name: String,
|
||||
pub cert_content: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AppId {
|
||||
pub app_id_id: String,
|
||||
pub identifier: String,
|
||||
pub name: String,
|
||||
pub features: Dictionary,
|
||||
pub expiration_date: Option<Date>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ListAppIdsResponse {
|
||||
pub app_ids: Vec<AppId>,
|
||||
pub max_quantity: u64,
|
||||
pub available_quantity: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ApplicationGroup {
|
||||
pub application_group: String,
|
||||
pub _name: String,
|
||||
pub identifier: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ProvisioningProfile {
|
||||
pub _provisioning_profile_id: String,
|
||||
pub _name: String,
|
||||
pub encoded_profile: Vec<u8>,
|
||||
}
|
||||
Reference in New Issue
Block a user