1pub mod auth;
2pub mod schema;
3pub mod db;
4
5#[macro_use]
6extern crate diesel;
7extern crate dotenv;
8
9use diesel::prelude::*;
10use diesel::{debug_query, insert_into};
11use std::env;
12
13use schema::{files, user_files, parents, permissions};
14
15use reqwest;
16use serde::{self, Deserialize, Serialize};
17use serde_json::Value;
18use diesel::pg::upsert::*;
19use db::establish_connection;
20
21#[derive(Debug, Default, Deserialize)]
27pub struct LogEntry {
28 ip_address: Option<String>,
30 time: Option<String>,
31 actor: Option<String>,
32 actor_caller_type: Option<String>,
33 event_name: Option<String>,
35 destination_folder_id: Option<String>,
36 doc_id: Option<String>,
37 doc_title: Option<String>,
38 owner: Option<String>,
39 originating_app_id: Option<String>,
40 primary_event: Option<bool>,
41 visibility: Option<String>,
42 shared_drive_id: Option<String>,
43 new_value: Option<String>,
44 old_value: Option<String>,
45 old_visibility: Option<String>,
46 visibility_change: Option<String>,
47}
48
49pub fn list_audit_log(user: &str, start_time: Option<&str>, end_time: Option<&str>) {
53 let mut token = auth::AuthToken::default();
56 let auth_token = token.get_token_string(None);
57 let list_url = format!("https://www.googleapis.com/admin/reports/v1/activity/users/{}/applications/drive", user);
58 let query: Vec<(&str, &str)> = vec![];
59 let client = reqwest::blocking::Client::new();
60 let res = client
61 .get(&list_url)
62 .query(&query)
63 .bearer_auth(&auth_token)
64 .send()
65 .unwrap();
66}
67
68pub fn list_files(user: &str, fields: Option<&str>, drive_query: Option<&str>,page_token: Option<&str>) {
71 let mut token = auth::AuthToken::default();
72 let conn = establish_connection();
73 let list_url = "https://www.googleapis.com/drive/v3/files";
74 let mut page_token = match page_token {
76 Some(p) => p.to_string(),
77 None => String::new(),
78 };
79 loop {
80 let auth_token = token.get_token_string(Some(user)); let mut query = vec![
82 ("pageSize", "1000"), ];
84 let f = format!("nextPageToken,files({})", &fields.unwrap_or("*"));
86 query.push(( "fields", &f));
87 let mut qu = String::new();
88 if let Some(q) = drive_query {
89 qu = format!("{}", q);
90 query.push(("q", &qu));
91 }
92 if page_token != "" {
93 query.push(("pageToken", &page_token));
94 }
95 let client = reqwest::blocking::Client::new();
96 let res = client
97 .get(list_url)
98 .query(&query)
99 .bearer_auth(&auth_token)
100 .send()
101 .unwrap();
102 let response: Value = res.json().unwrap();
104 if response.get("error") != None {
107 println!("{:?}", response);
108 }
109 let files: Vec<File> = serde_json::from_value(response["files"].clone()).unwrap();
110 let iterfiles: Vec<Value> = serde_json::from_value(response["files"].clone()).unwrap();
112 insert_into(files::dsl::files)
113 .values(&files)
114 .on_conflict_do_nothing()
115 .execute(&conn)
116 .unwrap();
117 for file in iterfiles {
118 let mut user_file: UserFile = serde_json::from_value(file.clone()).unwrap();
119 user_file.user_email = Some(user.to_string());
120 insert_into(user_files::dsl::user_files)
121 .values(&user_file)
122 .on_conflict_do_nothing()
123 .execute(&conn)
124 .unwrap();
125
126 if file.get("permissions") != None {
127 let mut permissions: Vec<Permission> =
128 serde_json::from_value(file["permissions"].clone()).unwrap();
129 for mut perm in &mut permissions {
130 perm.file_id = file["id"].as_str().unwrap().to_string();
131 }
132 insert_into(permissions::dsl::permissions)
133 .values(&permissions)
134 .on_conflict_do_nothing() .execute(&conn)
136 .unwrap();
137 }
138 let iterparents: Vec<Value> =
139 serde_json::from_value(file["parents"].clone()).unwrap_or(vec![]);
140 let parents: Vec<Parent> = iterparents
141 .iter()
142 .map(|p| Parent {
143 file_id: file["id"].as_str().unwrap().to_string(),
144 parent_id: p.as_str().unwrap().to_string(),
145 })
146 .collect();
147 insert_into(parents::dsl::parents)
148 .values(&parents)
149 .on_conflict_do_nothing() .execute(&conn)
151 .unwrap();
152 }
153 if let Some(r) = response.get("nextPageToken") {
154 page_token = r.as_str().unwrap().to_string();
155 }
156 else { break };
157 }
158}
159
160#[derive(Debug, Deserialize)]
161struct Response {
162 #[serde(rename = "nextPageToken")]
163 next_page_token: Option<String>,
164 files: Vec<File>,
165}
166
167#[derive(Debug, Default, Deserialize, Insertable)]
169#[table_name = "user_files"]
170pub struct UserFile {
171 id: String,
172 user_email: Option<String>,
173 #[serde(rename = "viewedByMe")]
174 viewed_by_me: Option<bool>,
175 #[serde(rename = "viewedByMeTime")]
176 viewed_by_me_time: Option<String>,
177 #[serde(rename = "modifiedByMeTime")]
178 modified_by_me_time: Option<String>,
179 #[serde(rename = "sharedWithMeTime")]
180 shared_with_me_time: Option<String>,
181 #[serde(rename = "sharingUser")]
182 sharing_user: Option<serde_json::Value>,
183 capabilities: Option<serde_json::Value>
184}
185
186#[derive(Debug, Default, Deserialize, Insertable)]
189#[table_name = "files"]
190pub struct File {
191 id: String,
192 name: Option<String>,
193 #[serde(rename = "mimeType")]
194 mime_type: Option<String>,
195 description: Option<String>,
196 trashed: Option<bool>,
197 starred: Option<bool>,
198 #[serde(rename = "explicitlyTrashed")]
199 explicitly_trashed: Option<bool>,
200 #[serde(rename = "trashingUser")]
201 trashing_user: Option<serde_json::Value>,
202 #[serde(rename = "trashedTime")]
203 trashed_time: Option<String>,
204 properties: Option<serde_json::Value>,
205 #[serde(rename = "webContentLink")]
211 web_content_link: Option<String>,
212 #[serde(rename = "webViewLink")]
213 web_view_link: Option<String>,
214 #[serde(rename = "createdTime")]
219 created_time: Option<String>,
220 #[serde(rename = "modifiedTime")]
221 modified_time: Option<String>,
222 owners: Option<serde_json::Value>,
223 #[serde(rename = "driveId")]
224 drive_id: Option<String>,
225 #[serde(rename = "lastModifyingUser")]
226 last_modifying_user: Option<serde_json::Value>,
227 shared: Option<bool>,
228 #[serde(rename = "viewersCanCopyContent")]
229 viewers_can_copy_content: Option<bool>,
230 #[serde(rename = "copyRequiresWriterPermission")]
231 copy_requires_writer_permission: Option<bool>,
232 #[serde(rename = "writersCanShare")]
233 writers_can_share: Option<bool>,
234 #[serde(rename = "hasAugmentedPermissions")]
235 has_augmented_permissions: Option<bool>,
236 #[serde(rename = "folderColorRgb")]
237 folder_color_rgb: Option<String>,
238 #[serde(rename = "originalFilename")]
239 original_filename: Option<String>,
240 #[serde(rename = "fullFileExtension")]
241 full_file_extension: Option<String>,
242 #[serde(rename = "fileExtension")]
243 file_extension: Option<String>,
244 #[serde(rename = "md5Checksum")]
245 md5_checksum: Option<String>,
246 #[serde(rename = "headRevisionId")]
250 head_revision_id: Option<String>,
251 #[serde(rename = "imageMediaMetadata")]
253 image_media_metadata: Option<serde_json::Value>,
254 #[serde(rename = "videoMediaMetadata")]
255 video_media_metadata: Option<serde_json::Value>,
256 #[serde(rename = "isAppAuthorized")]
257 is_app_authorized: Option<bool>,
258 }
260
261#[derive(Debug, Insertable, Deserialize)]
263#[table_name = "permissions"]
264struct Permission {
265 #[serde(default)]
266 file_id: String,
267 id: String,
268 #[serde(rename = "type")]
269 perm_type: Option<String>,
270 #[serde(rename = "emailAddress")]
271 email_address: Option<String>,
272 domain: Option<String>,
273 role: Option<String>,
274 #[serde(rename = "allowFileDiscovery")]
275 allow_file_discovery: Option<bool>,
276 #[serde(rename = "displayName")]
277 display_name: Option<String>,
278 #[serde(rename = "expirationTime")]
279 expiration_time: Option<String>,
280 deleted: Option<bool>,
281 }
283
284#[derive(Debug, Insertable, Deserialize)]
285#[table_name = "parents"]
286struct Parent {
287 file_id: String,
288 parent_id: String,
289}