drive_v3/resources/
permissions.rs

1use reqwest::Method;
2use drive_v3_macros::{DriveRequestBuilder, request};
3
4use super::DriveRequestBuilder;
5use crate::{objects, Credentials};
6
7#[request(
8    method=Method::POST,
9    url="https://www.googleapis.com/drive/v3/files/{file_id}/permissions",
10    returns=objects::Permission,
11)]
12#[derive(DriveRequestBuilder)]
13/// A request builder to create a permission for a file or shared drive.
14pub struct CreateRequest {
15    /// A plain text custom message to include in the notification email.
16    #[drive_v3(parameter)]
17    email_message: Option<String>,
18
19    /// This parameter will only take effect if the item is not in a shared
20    /// drive and the request is attempting to transfer the ownership of the
21    /// item.
22    ///
23    /// If set to `true`, the item will be moved to the new owner's My Drive
24    /// root folder and all prior parents removed. If set to `false`,
25    /// parents are not changed.
26    #[drive_v3(parameter)]
27    move_to_new_owners_root: Option<bool>,
28
29    /// Whether to send a notification email when sharing to users or
30    /// groups.
31    ///
32    /// This defaults to `true` for users and groups, and is not allowed for
33    /// other requests. It must not be disabled for ownership transfers.
34    #[drive_v3(parameter)]
35    send_notification_email: Option<bool>,
36
37    /// Whether the requesting application supports both My Drives and
38    /// shared drives.
39    #[drive_v3(parameter)]
40    supports_all_drives: Option<bool>,
41
42    /// Whether to transfer ownership to the specified user and downgrade
43    /// the current owner to a writer.
44    ///
45    /// This parameter is required as an acknowledgement of the side effect.
46    #[drive_v3(parameter)]
47    transfer_ownership: Option<bool>,
48
49    /// Issue the request as a domain administrator.
50    ///
51    /// if set to `true`, then the requester will be granted access if they
52    /// are an administrator of the domain to which the shared drive
53    /// belongs.
54    #[drive_v3(parameter)]
55    use_domain_admin_access: Option<bool>,
56
57    /// The permission which will be applied.
58    #[drive_v3(body)]
59    permission: Option<objects::Permission>,
60}
61
62#[request(
63    method=Method::DELETE,
64    url="https://www.googleapis.com/drive/v3/files/{file_id}/permissions/{permission_id}",
65    returns=(),
66)]
67#[derive(DriveRequestBuilder)]
68/// A request builder to delete a permission.
69pub struct DeleteRequest {
70    /// Whether the requesting application supports both My Drives and
71    /// shared drives.
72    #[drive_v3(parameter)]
73    supports_all_drives: Option<bool>,
74
75    /// Issue the request as a domain administrator.
76    ///
77    /// if set to `true`, then the requester will be granted access if they
78    /// are an administrator of the domain to which the shared drive
79    /// belongs.
80    #[drive_v3(parameter)]
81    use_domain_admin_access: Option<bool>,
82}
83
84#[request(
85    method=Method::GET,
86    url="https://www.googleapis.com/drive/v3/files/{file_id}/permissions/{permission_id}",
87    returns=objects::Permission,
88)]
89#[derive(DriveRequestBuilder)]
90/// A request builder to get a permission by ID.
91pub struct GetRequest {
92    /// Whether the requesting application supports both My Drives and
93    /// shared drives.
94    #[drive_v3(parameter)]
95    supports_all_drives: Option<bool>,
96
97    /// Issue the request as a domain administrator.
98    ///
99    /// if set to `true`, then the requester will be granted access if they
100    /// are an administrator of the domain to which the shared drive
101    /// belongs.
102    #[drive_v3(parameter)]
103    use_domain_admin_access: Option<bool>,
104}
105
106#[request(
107    method=Method::GET,
108    url="https://www.googleapis.com/drive/v3/files/{file_id}/permissions",
109    returns=objects::PermissionList,
110)]
111#[derive(DriveRequestBuilder)]
112/// A request builder to list a file's or shared drive's permissions.
113pub struct ListRequest {
114    /// The maximum number of permissions to return per page.
115    ///
116    /// When not set for files in a shared drive, at most 100 results will
117    /// be returned. When not set for files that are not in a shared drive,
118    /// the entire list will be returned.
119    #[drive_v3(parameter)]
120    page_size: Option<i64>,
121
122    /// The token for continuing a previous list request on the next page.
123    ///
124    /// This should be set to the value of
125    /// [`next_page_token`](objects::PermissionList::next_page_token) from
126    /// the previous response.
127    #[drive_v3(parameter)]
128    page_token: Option<String>,
129
130    /// Whether the requesting application supports both My Drives and
131    /// shared drives.
132    #[drive_v3(parameter)]
133    supports_all_drives: Option<bool>,
134
135    /// Issue the request as a domain administrator.
136    ///
137    /// if set to `true`, then the requester will be granted access if they
138    /// are an administrator of the domain to which the shared drive
139    /// belongs.
140    #[drive_v3(parameter)]
141    use_domain_admin_access: Option<bool>,
142
143    /// Specifies which additional view's permissions to include in the
144    /// response.
145    ///
146    /// Only `published` is supported.
147    #[drive_v3(parameter)]
148    include_permissions_for_view: Option<String>,
149}
150
151#[request(
152    method=Method::PATCH,
153    url="https://www.googleapis.com/drive/v3/files/{file_id}/permissions/{permission_id}",
154    returns=objects::Permission,
155)]
156#[derive(DriveRequestBuilder)]
157/// A request builder to update a permission for a file or shared drive.
158pub struct UpdateRequest {
159    /// Whether to remove the expiration date.
160    #[drive_v3(parameter)]
161    remove_expiration: Option<bool>,
162
163    /// Whether the requesting application supports both My Drives and
164    /// shared drives.
165    #[drive_v3(parameter)]
166    supports_all_drives: Option<bool>,
167
168    /// Whether to transfer ownership to the specified user and downgrade
169    /// the current owner to a writer.
170    ///
171    /// This parameter is required as an acknowledgement of the side effect.
172    #[drive_v3(parameter)]
173    transfer_ownership: Option<bool>,
174
175    /// Issue the request as a domain administrator.
176    ///
177    /// if set to `true`, then the requester will be granted access if they
178    /// are an administrator of the domain to which the shared drive
179    /// belongs.
180    #[drive_v3(parameter)]
181    use_domain_admin_access: Option<bool>,
182
183    /// The permission which will be applied.
184    #[drive_v3(body)]
185    permission: Option<objects::Permission>,
186}
187
188/// Permissions for a file.
189///
190/// A permission grants a user, group, domain, or the world access to a file or
191/// a folder hierarchy.
192///
193/// Some resource methods (such as [`permissions.update`](Permissions::update))
194/// require a `permission_id`. Use the [`permissions.list`](Permissions::list)
195/// method to retrieve the ID for a file, folder, or shared drive.
196///
197/// # Examples:
198///
199/// List the permission in a file
200///
201/// ```no_run
202/// # use drive_v3::{Error, Credentials, Drive};
203/// #
204/// # let drive = Drive::new( &Credentials::from_file(
205/// #     "../.secure-files/google_drive_credentials.json",
206/// #     &["https://www.googleapis.com/auth/drive.file"],
207/// # )? );
208/// #
209/// let file_id = "some-file-id";
210/// let permission_list = drive.permissions.list(&file_id).execute()?;
211///
212/// if let Some(permissions) = permission_list.permissions {
213///     for permission in permissions {
214///         println!("{}", permission);
215///     }
216/// }
217/// # Ok::<(), Error>(())
218/// ```
219#[derive(Debug, Clone, PartialEq, Eq)]
220pub struct Permissions {
221    /// Credentials used to authenticate a user's access to this resource.
222    credentials: Credentials,
223}
224
225impl Permissions {
226    /// Creates a new [`Permissions`] resource with the given [`Credentials`].
227    pub fn new( credentials: &Credentials ) -> Self {
228        Self { credentials: credentials.clone() }
229    }
230
231    /// Creates a permission for a file or shared drive.
232    ///
233    /// See Google's
234    /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/permissions/create)
235    /// for more information.
236    ///
237    /// # Warning
238    ///
239    /// Concurrent permissions operations on the same file are not supported;
240    /// only the last update is applied.
241    ///
242    /// # Requires one of the following OAuth scopes:
243    ///
244    /// - `https://www.googleapis.com/auth/drive`
245    /// - `https://www.googleapis.com/auth/drive.file`
246    ///
247    /// # Examples:
248    ///
249    /// ```no_run
250    /// use drive_v3::objects::Permission;
251    /// # use drive_v3::{Error, Credentials, Drive};
252    /// #
253    /// # let drive = Drive::new( &Credentials::from_file(
254    /// #     "../.secure-files/google_drive_credentials.json",
255    /// #     &["https://www.googleapis.com/auth/drive.file"],
256    /// # )? );
257    ///
258    /// let permission = Permission {
259    ///     permission_type: Some( "anyone".to_string() ),
260    ///     role: Some( "reader".to_string() ),
261    ///     ..Default::default()
262    /// };
263    ///
264    /// let file_id = "some-file-id";
265    ///
266    /// let created_permission = drive.permissions.create(&file_id)
267    ///     .permission(&permission)
268    ///     .execute()?;
269    ///
270    /// assert_eq!(created_permission.permission_type, permission.permission_type);
271    /// assert_eq!(created_permission.role, permission.role);
272    /// # Ok::<(), Error>(())
273    /// ```
274    pub fn create<T: AsRef<str>> ( &self, file_id: T ) -> CreateRequest {
275        CreateRequest::new(&self.credentials, file_id)
276    }
277
278    /// Deletes a permission.
279    ///
280    /// See Google's
281    /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/permissions/delete)
282    /// for more information.
283    ///
284    /// # Warning
285    ///
286    /// Concurrent permissions operations on the same file are not supported;
287    /// only the last update is applied.
288    ///
289    /// # Requires one of the following OAuth scopes:
290    ///
291    /// - `https://www.googleapis.com/auth/drive`
292    /// - `https://www.googleapis.com/auth/drive.file`
293    ///
294    /// # Examples:
295    ///
296    /// ```no_run
297    /// # use drive_v3::{Error, Credentials, Drive};
298    /// #
299    /// # let drive = Drive::new( &Credentials::from_file(
300    /// #     "../.secure-files/google_drive_credentials.json",
301    /// #     &["https://www.googleapis.com/auth/drive.file"],
302    /// # )? );
303    /// #
304    /// let file_id = "some-file-id";
305    /// let permission_id = "some-permission-id";
306    ///
307    /// let response = drive.permissions.delete(&file_id, &permission_id).execute();
308    ///
309    /// assert!( response.is_ok() );
310    /// # Ok::<(), Error>(())
311    /// ```
312    pub fn delete<T, U> ( &self, file_id: T, permission_id: U ) -> DeleteRequest
313        where
314            T: AsRef<str>,
315            U: AsRef<str>
316    {
317        DeleteRequest::new(&self.credentials, file_id, permission_id)
318    }
319
320    /// Gets a permission by ID.
321    ///
322    /// See Google's
323    /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/permissions/get)
324    /// for more information.
325    ///
326    /// # Requires one of the following OAuth scopes:
327    ///
328    /// - `https://www.googleapis.com/auth/drive`
329    /// - `https://www.googleapis.com/auth/drive.file`
330    /// - `https://www.googleapis.com/auth/drive.metadata`
331    /// - `https://www.googleapis.com/auth/drive.metadata.readonly`
332    /// - `https://www.googleapis.com/auth/drive.photos.readonly`
333    /// - `https://www.googleapis.com/auth/drive.readonly`
334    ///
335    /// # Examples:
336    ///
337    /// ```no_run
338    /// # use drive_v3::{Error, Credentials, Drive};
339    /// #
340    /// # let drive = Drive::new( &Credentials::from_file(
341    /// #     "../.secure-files/google_drive_credentials.json",
342    /// #     &["https://www.googleapis.com/auth/drive.file"],
343    /// # )? );
344    /// #
345    /// let file_id = "some-file-id";
346    /// let permission_id = "some-permission-id";
347    ///
348    /// let permission = drive.permissions.get(&file_id, &permission_id).execute()?;
349    ///
350    /// println!("This is the file's permission:\n{}", permission);
351    /// # Ok::<(), Error>(())
352    /// ```
353    pub fn get<T, U> ( &self, file_id: T, permission_id: U ) -> GetRequest
354        where
355            T: AsRef<str>,
356            U: AsRef<str>
357    {
358        GetRequest::new(&self.credentials, file_id, permission_id)
359    }
360
361    /// Lists a file's or shared drive's permissions.
362    ///
363    /// See Google's
364    /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/permissions/list)
365    /// for more information.
366    ///
367    /// # Requires one of the following OAuth scopes:
368    ///
369    /// - `https://www.googleapis.com/auth/drive`
370    /// - `https://www.googleapis.com/auth/drive.file`
371    /// - `https://www.googleapis.com/auth/drive.metadata`
372    /// - `https://www.googleapis.com/auth/drive.metadata.readonly`
373    /// - `https://www.googleapis.com/auth/drive.photos.readonly`
374    /// - `https://www.googleapis.com/auth/drive.readonly`
375    ///
376    /// # Examples:
377    ///
378    /// ```no_run
379    /// # use drive_v3::{Error, Credentials, Drive};
380    /// #
381    /// # let drive = Drive::new( &Credentials::from_file(
382    /// #     "../.secure-files/google_drive_credentials.json",
383    /// #     &["https://www.googleapis.com/auth/drive.file"],
384    /// # )? );
385    /// #
386    /// let file_id = "some-file-id";
387    /// let permission_list = drive.permissions.list(&file_id).execute()?;
388    ///
389    /// if let Some(permissions) = permission_list.permissions {
390    ///     for permission in permissions {
391    ///         println!("{}", permission);
392    ///     }
393    /// }
394    /// # Ok::<(), Error>(())
395    /// ```
396    pub fn list<T: AsRef<str>> ( &self, file_id: T ) -> ListRequest {
397        ListRequest::new(&self.credentials, file_id)
398    }
399
400    /// Updates a permission with patch semantics.
401    ///
402    /// See Google's
403    /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/permissions/update)
404    /// for more information.
405    ///
406    /// # Warning
407    ///
408    /// Concurrent permissions operations on the same file are not supported;
409    /// only the last update is applied.
410    ///
411    /// # Requires one of the following OAuth scopes:
412    ///
413    /// - `https://www.googleapis.com/auth/drive`
414    /// - `https://www.googleapis.com/auth/drive.file`
415    ///
416    /// # Examples:
417    ///
418    /// ```no_run
419    /// use drive_v3::objects::Permission;
420    /// # use drive_v3::{Error, Credentials, Drive};
421    /// #
422    /// # let drive = Drive::new( &Credentials::from_file(
423    /// #     "../.secure-files/google_drive_credentials.json",
424    /// #     &["https://www.googleapis.com/auth/drive.file"],
425    /// # )? );
426    ///
427    /// let updated_permission = Permission {
428    ///     permission_type: Some( "anyone".to_string() ),
429    ///     role: Some( "commenter".to_string() ),
430    ///     ..Default::default()
431    /// };
432    ///
433    /// let file_id = "some-file-id";
434    /// let permission_id = "some-permission-id";
435    ///
436    /// let permission = drive.permissions.update(&file_id, &permission_id)
437    ///     .permission(&updated_permission)
438    ///     .execute()?;
439    ///
440    /// assert_eq!(permission.permission_type, updated_permission.permission_type);
441    /// assert_eq!(permission.role, updated_permission.role);
442    /// # Ok::<(), Error>(())
443    /// ```
444    pub fn update<T, U> ( &self, file_id: T, permission_id: U ) -> UpdateRequest
445        where
446            T: AsRef<str>,
447            U: AsRef<str>
448    {
449        UpdateRequest::new(&self.credentials, file_id, permission_id)
450    }
451}
452
453#[cfg(test)]
454mod tests {
455    use super::Permissions;
456    use crate::{ErrorKind, objects, resources};
457    use crate::utils::test::{INVALID_CREDENTIALS, VALID_CREDENTIALS};
458
459    fn get_resource() -> Permissions {
460        Permissions::new(&VALID_CREDENTIALS)
461    }
462
463    fn get_invalid_resource() -> Permissions {
464        Permissions::new(&INVALID_CREDENTIALS)
465    }
466
467    fn get_files_resource() -> resources::Files {
468        resources::Files::new(&VALID_CREDENTIALS)
469    }
470
471    fn delete_file( file: &objects::File ) -> crate::Result<()> {
472        get_files_resource().delete( file.clone().id.unwrap() ).execute()
473    }
474
475    fn get_test_file_metadata() -> objects::File {
476        objects::File {
477            name: Some( "test.txt".to_string() ),
478            description: Some( "a test file".to_string() ),
479            mime_type: Some( "text/plain".to_string() ),
480            ..Default::default()
481        }
482    }
483
484    fn get_test_drive_file() -> crate::Result<objects::File> {
485        let metadata = get_test_file_metadata();
486
487        get_files_resource().create()
488            .upload_type(objects::UploadType::Multipart)
489            .metadata(&metadata)
490            .content_string("content")
491            .execute()
492    }
493
494    fn get_test_permission( ) -> objects::Permission {
495        objects::Permission {
496            permission_type: Some( "anyone".to_string() ),
497            role: Some( "reader".to_string() ),
498            ..Default::default()
499        }
500    }
501
502    fn get_test_drive_permission( file: &objects::File ) -> crate::Result<objects::Permission> {
503        let test_permission = get_test_permission();
504
505        get_resource().create( &file.clone().id.unwrap() )
506            .permission(&test_permission)
507            .execute()
508    }
509
510    #[test]
511    fn new_test() {
512        let valid_resource = get_resource();
513        let invalid_resource = get_invalid_resource();
514
515        assert_eq!( valid_resource.credentials, VALID_CREDENTIALS.clone() );
516        assert_eq!( invalid_resource.credentials, INVALID_CREDENTIALS.clone() );
517    }
518
519    #[test]
520    fn create_test() {
521        let test_drive_file = get_test_drive_file().unwrap();
522        let test_permission = get_test_permission();
523
524        let response = get_resource().create( &test_drive_file.clone().id.unwrap() )
525            .permission(&test_permission)
526            .execute();
527
528        assert!( response.is_ok() );
529
530        let permission = response.unwrap();
531        assert_eq!(permission.permission_type, test_permission.permission_type);
532        assert_eq!(permission.role, test_permission.role);
533
534        delete_file(&test_drive_file).expect("Failed to cleanup created file");
535    }
536
537    #[test]
538    fn create_invalid_test() {
539        let response = get_invalid_resource().create("invalid-id")
540            .execute();
541
542        assert!( response.is_err() );
543        assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
544    }
545
546    #[test]
547    fn delete_test() {
548        let test_drive_file = get_test_drive_file().unwrap();
549        let test_drive_permission = get_test_drive_permission(&test_drive_file).unwrap();
550
551        let response = get_resource().delete(
552            &test_drive_file.clone().id.unwrap(),
553            &test_drive_permission.clone().id.unwrap(),
554            )
555            .execute();
556
557        assert!( response.is_ok() );
558
559        delete_file(&test_drive_file).expect("Failed to cleanup created file");
560    }
561
562    #[test]
563    fn delete_invalid_test() {
564        let response = get_invalid_resource().delete("invalid-id", "invalid-id")
565            .execute();
566
567        assert!( response.is_err() );
568        assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
569    }
570
571    #[test]
572    fn get_test() {
573        let test_drive_file = get_test_drive_file().unwrap();
574        let test_drive_permission = get_test_drive_permission(&test_drive_file).unwrap();
575
576        let response = get_resource().get(
577            &test_drive_file.clone().id.unwrap(),
578            &test_drive_permission.clone().id.unwrap(),
579            )
580            .execute();
581
582        assert!( response.is_ok() );
583
584        let permission = response.unwrap();
585        assert_eq!(permission, test_drive_permission);
586
587        delete_file(&test_drive_file).expect("Failed to cleanup created file");
588    }
589
590    #[test]
591    fn get_invalid_test() {
592        let response = get_invalid_resource().get("invalid-id", "invalid-id")
593            .execute();
594
595        assert!( response.is_err() );
596        assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
597    }
598
599    #[test]
600    fn list_test() {
601        let test_drive_file = get_test_drive_file().unwrap();
602        let test_drive_permission = get_test_drive_permission(&test_drive_file).unwrap();
603
604        let response = get_resource().list( &test_drive_file.clone().id.unwrap() )
605            .execute();
606
607        assert!( response.is_ok() );
608
609        let permissions = response.unwrap().permissions.unwrap();
610        assert!( permissions.contains(&test_drive_permission) );
611
612        delete_file(&test_drive_file).expect("Failed to cleanup created file");
613    }
614
615    #[test]
616    fn list_invalid_test() {
617        let response = get_invalid_resource().list("invalid-id")
618            .execute();
619
620        assert!( response.is_err() );
621        assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
622    }
623
624    #[test]
625    fn update_test() {
626        let test_drive_file = get_test_drive_file().unwrap();
627        let test_drive_permission = get_test_drive_permission(&test_drive_file).unwrap();
628
629        let updated_permission = objects::Permission {
630            role: Some( "commenter".to_string() ),
631            ..Default::default()
632        };
633
634        let response = get_resource().update(
635                &test_drive_file.clone().id.unwrap(),
636                &test_drive_permission.clone().id.unwrap(),
637            )
638            .permission(&updated_permission)
639            .execute();
640
641        assert!( response.is_ok() );
642
643        let permission = response.unwrap();
644        assert_eq!(permission.role, updated_permission.role);
645
646        delete_file(&test_drive_file).expect("Failed to cleanup created file");
647    }
648
649    #[test]
650    fn update_invalid_test() {
651        let response = get_invalid_resource().update("invalid-id", "invalid-id")
652            .execute();
653
654        assert!( response.is_err() );
655        assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
656    }
657}