canvas_lms_api/resources/
content_migration.rs1use crate::{error::Result, http::Requester, pagination::PageStream};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Deserialize, Serialize)]
8pub struct ContentMigration {
9 pub id: u64,
10 pub migration_type: Option<String>,
11 pub migration_type_title: Option<String>,
12 pub course_id: Option<u64>,
13 pub account_id: Option<u64>,
14 pub group_id: Option<u64>,
15 pub user_id: Option<u64>,
16 pub workflow_state: Option<String>,
17 pub started_at: Option<DateTime<Utc>>,
18 pub finished_at: Option<DateTime<Utc>>,
19 pub pre_attachment: Option<serde_json::Value>,
20 pub progress_url: Option<String>,
21 pub migration_issues_url: Option<String>,
22 pub migration_issues_count: Option<u64>,
23 pub attachment: Option<serde_json::Value>,
24 pub settings: Option<serde_json::Value>,
25
26 #[serde(skip)]
27 pub(crate) requester: Option<Arc<Requester>>,
28}
29
30impl ContentMigration {
31 fn req(&self) -> &Arc<Requester> {
32 self.requester.as_ref().expect("requester not initialized")
33 }
34
35 fn parent_type(&self) -> &'static str {
36 if self.course_id.is_some() {
37 "course"
38 } else if self.group_id.is_some() {
39 "group"
40 } else if self.account_id.is_some() {
41 "account"
42 } else {
43 "user"
44 }
45 }
46
47 fn parent_id(&self) -> u64 {
48 self.course_id
49 .or(self.group_id)
50 .or(self.account_id)
51 .or(self.user_id)
52 .expect("ContentMigration missing parent id")
53 }
54
55 pub async fn get_migration_issue(&self, issue_id: u64) -> Result<MigrationIssue> {
60 let mut issue: MigrationIssue = self
61 .req()
62 .get(
63 &format!(
64 "{}s/{}/content_migrations/{}/migration_issues/{issue_id}",
65 self.parent_type(),
66 self.parent_id(),
67 self.id
68 ),
69 &[],
70 )
71 .await?;
72 issue.requester = self.requester.clone();
73 Ok(issue)
74 }
75
76 pub fn get_migration_issues(&self) -> PageStream<MigrationIssue> {
81 let parent_type = self.parent_type();
82 let parent_id = self.parent_id();
83 let migration_id = self.id;
84 PageStream::new_with_injector(
85 Arc::clone(self.req()),
86 &format!(
87 "{parent_type}s/{parent_id}/content_migrations/{migration_id}/migration_issues"
88 ),
89 vec![],
90 |mut issue: MigrationIssue, req| {
91 issue.requester = Some(Arc::clone(&req));
92 issue
93 },
94 )
95 }
96
97 pub async fn update(&self, params: &[(String, String)]) -> Result<ContentMigration> {
102 let mut migration: ContentMigration = self
103 .req()
104 .put(
105 &format!(
106 "{}s/{}/content_migrations/{}",
107 self.parent_type(),
108 self.parent_id(),
109 self.id
110 ),
111 params,
112 )
113 .await?;
114 migration.requester = self.requester.clone();
115 Ok(migration)
116 }
117}
118
119#[derive(Debug, Clone, Deserialize, Serialize)]
121pub struct MigrationIssue {
122 pub id: u64,
123 pub content_migration_url: Option<String>,
124 pub description: Option<String>,
125 pub workflow_state: Option<String>,
126 pub fix_issue_html_url: Option<String>,
127 pub issue_type: Option<String>,
128 pub error_report_html_url: Option<String>,
129 pub error_message: Option<String>,
130 pub created_at: Option<DateTime<Utc>>,
131 pub updated_at: Option<DateTime<Utc>>,
132
133 #[serde(skip)]
134 pub(crate) requester: Option<Arc<Requester>>,
135}
136
137impl MigrationIssue {
138 fn req(&self) -> &Arc<Requester> {
139 self.requester.as_ref().expect("requester not initialized")
140 }
141
142 pub async fn update(&self, workflow_state: &str) -> Result<MigrationIssue> {
149 let migration_url = self
150 .content_migration_url
151 .as_deref()
152 .expect("MigrationIssue missing content_migration_url");
153 let params = vec![("workflow_state".to_string(), workflow_state.to_string())];
154 let raw = format!("{}/migration_issues/{}", migration_url, self.id);
157 let endpoint = raw.trim_start_matches('/');
158 let endpoint = endpoint.strip_prefix("api/v1/").unwrap_or(endpoint);
159 let mut issue: MigrationIssue = self.req().put(endpoint, ¶ms).await?;
160 issue.requester = self.requester.clone();
161 Ok(issue)
162 }
163}
164
165#[derive(Debug, Clone, Deserialize, Serialize)]
167pub struct Migrator {
168 pub r#type: Option<String>,
169 pub requires_file_upload: Option<bool>,
170 pub name: Option<String>,
171 pub links: Option<serde_json::Value>,
172}