Compare commits

..

22 Commits

Author SHA1 Message Date
Ross Scroggs
ce7e506c29 Fixed bug in gam <UserItem> print|show chatspaces asadmin fields <ChatSpaceFieldNameList>` 2025-07-31 10:59:26 -07:00
Ross Scroggs
a9d8ac27d3 Update GamUpdates.md
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-07-30 21:01:25 -07:00
Ross Scroggs
58912ae7ac Update GamUpdates.md 2025-07-30 20:56:41 -07:00
Ross Scroggs
f882439cbd Updated gam <UserTypeEntity> print|show webmastersites to handle permissionDenied 2025-07-30 19:28:59 -07:00
Ross Scroggs
56bc52aa28 Updated gam <UserTypeEntity> print|show webmastersites to handle permissionDenied 2025-07-30 19:28:47 -07:00
Ross Scroggs
416125abac Fixed bug in gam <UserTypeEntity> show webmastersites that caused a trap.
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-07-29 17:55:06 -07:00
Ross Scroggs
904292ded3 Fixed bug in gam <UserTypeEntity> show webmastersites that caused a trap. 2025-07-29 17:54:45 -07:00
Ross Scroggs
5f55bcc812 Update _Sidebar.md 2025-07-29 17:28:05 -07:00
Ross Scroggs
b35de53f5d DWD Site Verification API and Search Console API #1806 2025-07-29 16:43:30 -07:00
Ross Scroggs
3c34948678 DWD Site Verification API and Search Console API #1806
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-29 16:42:21 -07:00
Ross Scroggs
0be73db60b Update GamUpdates.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-28 18:27:37 -07:00
Ross Scroggs
5b57b51384 Added file property downloadRestrictions 2025-07-28 16:39:20 -07:00
Ross Scroggs
139896ec3b Added file property downloadRestrictions
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-28 16:35:36 -07:00
Ross Scroggs
9b52c0bf18 Update How-to-Upgrade-Legacy-GAM-to-GAM7.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-28 07:35:42 -07:00
Ross Scroggs
b9c9b59f7b Documentation cleanup 2025-07-28 07:34:18 -07:00
Ross Scroggs
0e0877e084 Removed drive_v3_native_names from gam.cfg
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-07-27 21:16:11 -07:00
Ross Scroggs
bdce13e97b Removed drive_v3_native_names from gam.cfg
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-07-27 09:17:44 -07:00
Ross Scroggs
9c4a17e12c Update gam.cfg.md
Some checks failed
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-07-26 09:05:36 -07:00
Ross Scroggs
a64f4d4a46 Update GamUpdates.md
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-07-25 13:33:50 -07:00
Ross Scroggs
c396a3b901 Update Shared Drive restriction settings 2025-07-25 12:58:57 -07:00
Ross Scroggs
78453a15af Update Shared Drive restriction settings 2025-07-25 12:58:34 -07:00
Ross Scroggs
a0282ba775 Updated gam print shareddriveorganizers; code iter() cleanup
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-07-24 16:20:58 -07:00
18 changed files with 476 additions and 324 deletions

View File

@@ -4860,8 +4860,8 @@ gam <UserTypeEntity> sendemail from <EmailAddress>
allowcontentmanagerstosharefolders| allowcontentmanagerstosharefolders|
copyrequireswriterpermission| copyrequireswriterpermission|
domainusersonly| domainusersonly|
downloadrestrictedforreaders| downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters| downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly| drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission sharingfoldersrequiresorganizerpermission
@@ -4878,7 +4878,7 @@ In these commands, the Google administrator named in oauth2.txt is used.
gam show shareddrivethemes gam show shareddrivethemes
gam create shareddrive <Name> gam create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] [(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>] [movetoorgunitdelay <Integer>]
@@ -4932,7 +4932,7 @@ In these commands, you specify an administrator and then indicate that you want
gam <UserTypeEntity> create shareddrive <Name> adminaccess gam <UserTypeEntity> create shareddrive <Name> adminaccess
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] [(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>] [movetoorgunitdelay <Integer>]
@@ -4966,7 +4966,7 @@ In these commands, you specify a user, administrator access is not used.
gam <UserTypeEntity> create shareddrive <Name> gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] [(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[movetoorgunitdelay <Integer>] [movetoorgunitdelay <Integer>]
@@ -6597,6 +6597,7 @@ gam <UserTypeEntity> print chatemojis [todrive <ToDriveAttribute>*]
(folderColorRgb <ColorValue>)| (folderColorRgb <ColorValue>)|
(indexabletext <String>)| (indexabletext <String>)|
(inheritedpermissionsdisabled [<Boolean>])| (inheritedpermissionsdisabled [<Boolean>])|
(itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>])|
(keeprevisionforever|pinned)| (keeprevisionforever|pinned)|
(lastviewedbyme <Time>)| (lastviewedbyme <Time>)|
(mimetype <MimeType>)| (mimetype <MimeType>)|
@@ -7071,6 +7072,10 @@ gam <UserTypeEntity> collect orphans
contentrestrictions.restrictiontime| contentrestrictions.restrictiontime|
contentrestrictions.type contentrestrictions.type
<DriveDownloadRestrictionsSubfieldName> ::=
downloadrestrictions.itemdownloadrestriction|
downloadrestrictions.effectivedownloadrestrictionwithcontext
<ClassificationLabelInfoSubfieldName> ::= <ClassificationLabelInfoSubfieldName> ::=
labels.id| # modifiedByMe labels.id| # modifiedByMe
labels.revisionid| # copyRequiresWriterPermission labels.revisionid| # copyRequiresWriterPermission
@@ -7164,6 +7169,8 @@ gam <UserTypeEntity> collect orphans
copyrequireswriterpermission| copyrequireswriterpermission|
createddate|createdtime| createddate|createdtime|
description| description|
downloadrestictions|
<DriveDownloadRestrictionsSubfieldName>|
driveid| driveid|
drivename| drivename|
editable| editable|
@@ -8475,8 +8482,8 @@ gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
allowcontentmanagerstosharefolders| allowcontentmanagerstosharefolders|
copyrequireswriterpermission| copyrequireswriterpermission|
domainusersonly| domainusersonly|
downloadrestrictedforreaders| downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters| downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly| drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission sharingfoldersrequiresorganizerpermission
@@ -8491,13 +8498,13 @@ sharingfoldersrequiresorganizerpermission true
gam <UserTypeEntity> show shareddrivethemes gam <UserTypeEntity> show shareddrivethemes
gam <UserTypeEntity> create shareddrive <Name> gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] [(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [hide|hidden <Boolean>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly] [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [name <Name>] gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [name <Name>]
[(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] [(theme|themeid <String>) | ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [hide|hidden <Boolean>]
gam <UserTypeEntity> delete shareddrive <SharedDriveEntity> gam <UserTypeEntity> delete shareddrive <SharedDriveEntity>
[allowitemdeletion] [allowitemdeletion]
@@ -8696,3 +8703,11 @@ gam <UserTypeEntity> print youtubechannels [todrive <ToDriveAttribute>*]
gam create|add verify|verification <DomainName> gam create|add verify|verification <DomainName>
gam update verify|verification <DomainName> cname|txt|text|site|file gam update verify|verification <DomainName> cname|txt|text|site|file
gam info verify|verification gam info verify|verification
# Web Resourses and Sites
gam <UserTypeEntity> show webresources
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> show webmastersites
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
```

View File

@@ -1,3 +1,68 @@
7.17.03
Fixed bug in gam <UserItem> print|show chatspaces asadmin fields <ChatSpaceFieldNameList>` that caused a trap
when `isplayname` was not in `<ChatSpaceFieldNameList>`.
7.17.02
Updated `gam <UserTypeEntity> print|show webmastersites` to handle the following error
that occurs if you haven't updated your project to include the Google Search Console API.
```
ERROR: 403: permissionDenied - Google Search Console API has not been used in project 111055363999 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/searchconsole.googleapis.com/overview?project=111055363999 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
```
7.17.01
Fixed bug in `gam <UserTypeEntity> show webmastersites` that caused a trap.
7.17.00
Added commands to discover Sites and WebResources that managed users (previously unmanaged) may have access to for better governance and visibility.
These are special purpose commands and will not generally be used.
```
gam <UserTypeEntity> show webresources
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> show webmastersites
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
```
7.16.01
The Drive API now supports setting download restrictions on individual files.
Added `downloadrestictions` and `<DriveDownloadRestrictionsSubfieldName>` to `<DriveFieldName>`.
```
<DriveDownloadRestrictionsSubfieldName> ::=
downloadrestrictions.itemdownloadrestriction|
downloadrestrictions.effectivedownloadrestrictionwithcontext
```
Added `itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>]`
to `<DriveFileAttribute>`.
From the Drive API documentation:
```
itemDownloadRestriction - The download restriction of the file applied directly by the owner or organizer. This does not take into account shared drive settings or DLP rules.
effectiveDownloadRestrictionWithContext - Output only. The effective download restriction applied to this file. This considers all restriction settings and DLP rules.
restrictedForReaders - Whether download and copy is restricted for readers.
restrictedForWriters - Whether download and copy is restricted for writers. If true, download is also restricted for readers.
```
7.16.00
Removed `drive_v3_native_names` from `gam.cfg`; GAM now only uses Drive API v3 fields names on output.
If you had `drive_v3_native_names = False` in `gam.cfg` or are updating from Legacy GAM:
* See: https://github.com/GAM-team/GAM/wiki/Drive-REST-API-v3
7.15.01
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
and `downloadrestrictedforwriters` were supported (they are still supported).
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
7.15.00 7.15.00
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True` Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.15.00' __version__ = '7.17.03'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -5688,19 +5688,22 @@ def getUserEmailFromID(uid, cd):
try: try:
result = callGAPI(cd.users(), 'get', result = callGAPI(cd.users(), 'get',
throwReasons=GAPI.USER_GET_THROW_REASONS, throwReasons=GAPI.USER_GET_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
userKey=uid, fields='primaryEmail') userKey=uid, fields='primaryEmail')
return result.get('primaryEmail') return result.get('primaryEmail')
except (GAPI.userNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden, except (GAPI.userNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
GAPI.badRequest, GAPI.backendError, GAPI.systemError): GAPI.badRequest, GAPI.backendError, GAPI.systemError, GAPI.serviceNotAvailable):
return None return None
def getGroupEmailFromID(uid, cd): def getGroupEmailFromID(uid, cd):
try: try:
result = callGAPI(cd.groups(), 'get', result = callGAPI(cd.groups(), 'get',
throwReasons=GAPI.GROUP_GET_THROW_REASONS, throwReasons=GAPI.GROUP_GET_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
groupKey=uid, fields='email') groupKey=uid, fields='email')
return result.get('email') return result.get('email')
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden, GAPI.badRequest): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
GAPI.badRequest, GAPI.serviceNotAvailable):
return None return None
def getServiceAccountEmailFromID(account_id, sal=None): def getServiceAccountEmailFromID(account_id, sal=None):
@@ -7862,7 +7865,6 @@ class CSVPrintFile():
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '') GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '')
self.SetTimestampColumn(GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN]) self.SetTimestampColumn(GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN])
self.SetFormatJSON(False) self.SetFormatJSON(False)
self.SetMapDrive3Titles(False)
self.SetNodataFields(False, None, None, None, False) self.SetNodataFields(False, None, None, None, False)
self.SetFixPaths(False) self.SetFixPaths(False)
self.SetShowPermissionsLast(False) self.SetShowPermissionsLast(False)
@@ -7932,13 +7934,6 @@ class CSVPrintFile():
self.sortTitlesList = self.titlesList[:] self.sortTitlesList = self.titlesList[:]
self.sortTitlesSet = set(self.sortTitlesList) self.sortTitlesSet = set(self.sortTitlesList)
def SetMapDrive3Titles(self, mapDrive3Titles):
self.mapDrive3Titles = mapDrive3Titles
def MapDrive3TitlesToDrive2(self):
_mapDrive3TitlesToDrive2(self.titlesList, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
self.titlesSet = set(self.titlesList)
def AddJSONTitle(self, title): def AddJSONTitle(self, title):
self.JSONtitlesSet.add(title) self.JSONtitlesSet.add(title)
self.JSONtitlesList.append(title) self.JSONtitlesList.append(title)
@@ -8974,7 +8969,6 @@ class CSVPrintFile():
self.formatJSON, self.JSONtitlesList, self.formatJSON, self.JSONtitlesList,
self.columnDelimiter, self.noEscapeChar, self.quoteChar, self.columnDelimiter, self.noEscapeChar, self.quoteChar,
self.sortHeaders, self.timestampColumn, self.sortHeaders, self.timestampColumn,
self.mapDrive3Titles,
self.fixPaths, self.fixPaths,
self.mapNodataFields, self.mapNodataFields,
self.nodataFields, self.nodataFields,
@@ -9009,8 +9003,6 @@ class CSVPrintFile():
self.MovePermsToEnd() self.MovePermsToEnd()
if not self.rows and self.nodataFields is not None: if not self.rows and self.nodataFields is not None:
self.FixNodataTitles() self.FixNodataTitles()
if self.mapDrive3Titles:
self. MapDrive3TitlesToDrive2()
else: else:
self.titlesList = self.headerForce self.titlesList = self.headerForce
if self.timestampColumn: if self.timestampColumn:
@@ -9646,11 +9638,10 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
csvPF.SetQuoteChar(dataItem[7]) csvPF.SetQuoteChar(dataItem[7])
csvPF.SetSortHeaders(dataItem[8]) csvPF.SetSortHeaders(dataItem[8])
csvPF.SetTimestampColumn(dataItem[9]) csvPF.SetTimestampColumn(dataItem[9])
csvPF.SetMapDrive3Titles(dataItem[10]) csvPF.SetFixPaths(dataItem[10])
csvPF.SetFixPaths(dataItem[11]) csvPF.SetNodataFields(dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15])
csvPF.SetNodataFields(dataItem[12], dataItem[13], dataItem[14], dataItem[15], dataItem[16]) csvPF.SetShowPermissionsLast(dataItem[16])
csvPF.SetShowPermissionsLast(dataItem[17]) csvPF.SetZeroBlankMimeTypeCounts(dataItem[17])
csvPF.SetZeroBlankMimeTypeCounts(dataItem[18])
elif dataType == GM.REDIRECT_QUEUE_DATA: elif dataType == GM.REDIRECT_QUEUE_DATA:
csvPF.rows.extend(dataItem) csvPF.rows.extend(dataItem)
elif dataType == GM.REDIRECT_QUEUE_ARGS: elif dataType == GM.REDIRECT_QUEUE_ARGS:
@@ -26949,7 +26940,7 @@ def printShowChatSpaces(users):
substituteQueryTimes(queries, queryTimes) substituteQueryTimes(queries, queryTimes)
pfilter = kwargsCS['query'] = queries[0] pfilter = kwargsCS['query'] = queries[0]
kwargsCS['useAdminAccess'] = True kwargsCS['useAdminAccess'] = True
sortName = 'displayName' sortName = 'displayName' if 'displayName' in fieldsList else 'name'
else: else:
sortName = 'name' sortName = 'name'
for user in users: for user in users:
@@ -46975,8 +46966,8 @@ def doCreateSiteVerification():
printKeyValueList(['Meta HTML Header Data', webserver_meta_record['token']]) printKeyValueList(['Meta HTML Header Data', webserver_meta_record['token']])
printBlankLine() printBlankLine()
def _showSiteVerificationInfo(site): def _showSiteVerificationInfo(site, i=0, count=0):
printKeyValueList(['Site', site['site']['identifier']]) printKeyValueListWithCount(['Site', site['site']['identifier']], i, count)
Ind.Increment() Ind.Increment()
printKeyValueList(['ID', unquote(site['id'])]) printKeyValueList(['ID', unquote(site['id'])])
printKeyValueList(['Type', site['site']['type']]) printKeyValueList(['Type', site['site']['type']])
@@ -47084,11 +47075,87 @@ def doInfoSiteVerification():
checkForExtraneousArguments() checkForExtraneousArguments()
sites = callGAPIitems(verif.webResource(), 'list', 'items') sites = callGAPIitems(verif.webResource(), 'list', 'items')
if sites: if sites:
count = len(sites)
i = 0
for site in sorted(sites, key=lambda k: (k['site']['type'], k['site']['identifier'])): for site in sorted(sites, key=lambda k: (k['site']['type'], k['site']['identifier'])):
_showSiteVerificationInfo(site) i += 1
_showSiteVerificationInfo(site, i, count)
else: else:
printKeyValueList(['No Sites Verified.']) printKeyValueList(['No Sites Verified.'])
# gam <UserTypeEntity> show webresources
# gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
def printShowWebResources(users):
csvPF = CSVPrintFile(['User', 'site.identifier']) if Act.csvFormat() else None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
else:
unknownArgumentExit()
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, verif = buildGAPIServiceObject(API.SITEVERIFICATION, user, i, count)
if not verif:
continue
sites = callGAPIitems(verif.webResource(), 'list', 'items')
jcount = len(sites)
if not csvPF:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.WEB_RESOURCE, i, count)
Ind.Increment()
j = 0
for site in sorted(sites, key=lambda k: (k['site']['type'], k['site']['identifier'])):
j += 1
_showSiteVerificationInfo(site, j, jcount)
Ind.Decrement()
else:
for site in sites:
row = flattenJSON(site, flattened={'User': user})
csvPF.WriteRowTitles(row)
if csvPF:
csvPF.writeCSVfile('Web Resources')
# gam <UserTypeEntity> show webmastersites
# gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
def printShowWebMasterSites(users):
csvPF = CSVPrintFile(['User', 'siteUrl']) if Act.csvFormat() else None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
else:
unknownArgumentExit()
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, searchconsole = buildGAPIServiceObject(API.SEARCHCONSOLE, user, i, count)
if not searchconsole:
continue
try:
sites = callGAPIitems(searchconsole.sites(), 'list', 'siteEntry',
throwReasons=[GAPI.PERMISSION_DENIED])
except GAPI.permissionDenied as e:
accessErrorExitNonDirectory(API.SEARCHCONSOLE, str(e))
jcount = len(sites)
if not csvPF:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.WEB_MASTERSITE, i, count)
Ind.Increment()
j = 0
for site in sorted(sites, key=lambda k: k['siteUrl']):
j += 1
printKeyValueListWithCount(['Site', site['siteUrl']], j, jcount)
Ind.Increment()
printKeyValueList(['permissionLevel', site['permissionLevel']])
Ind.Decrement()
Ind.Decrement()
else:
for site in sites:
row = flattenJSON(site, flattened={'User': user})
csvPF.WriteRowTitles(row)
if csvPF:
csvPF.writeCSVfile('Web Master Sites')
def checkCourseExists(croom, courseId, i=0, count=0, entityType=Ent.COURSE): def checkCourseExists(croom, courseId, i=0, count=0, entityType=Ent.COURSE):
courseId = addCourseIdScope(courseId) courseId = addCourseIdScope(courseId)
try: try:
@@ -53829,6 +53896,13 @@ DRIVE_FILE_CONTENT_RESTRICTIONS_CHOICE_MAP = {
'ownerrestricted': 'ownerRestricted', 'ownerrestricted': 'ownerRestricted',
} }
DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP = {
'downloadrestrictedforreaders': 'restrictedForReaders',
'downloadrestrictedforwriters': 'restrictedForWriters',
'restrictedforreaders': 'restrictedForReaders',
'restrictedforwriters': 'restrictedForWriters',
}
def getDriveFileProperty(visibility=None): def getDriveFileProperty(visibility=None):
key = getString(Cmd.OB_PROPERTY_KEY) key = getString(Cmd.OB_PROPERTY_KEY)
value = getString(Cmd.OB_PROPERTY_VALUE, minLen=0) or None value = getString(Cmd.OB_PROPERTY_VALUE, minLen=0) or None
@@ -53880,6 +53954,20 @@ def getDriveFileAddRemoveParentAttribute(myarg, parameters):
return False return False
return True return True
def _getDriveFileDownloadRestrictions(myarg, body):
subField = myarg
if subField.startswith('downloadrestrictions.'):
_, subField = subField.split('.', 1)
if subField.startswith('itemdownloadrestriction.'):
_, subField = subField.split('.', 1)
if subField == 'itemdownloadrestriction':
subField = getChoice(DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP)
if subField in DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP:
body.setdefault('downloadRestrictions', {'itemDownloadRestriction': {}})
body['downloadRestrictions']['itemDownloadRestriction'][DRIVE_FILE_ITEM_DOWNLOAD_RESTRICTION_CHOICE_MAP[subField]] = getBoolean()
return True
return False
def getDriveFileCopyAttribute(myarg, body, parameters): def getDriveFileCopyAttribute(myarg, body, parameters):
if myarg == 'ignoredefaultvisibility': if myarg == 'ignoredefaultvisibility':
parameters[DFA_IGNORE_DEFAULT_VISIBILITY] = getBoolean() parameters[DFA_IGNORE_DEFAULT_VISIBILITY] = getBoolean()
@@ -53915,6 +54003,8 @@ def getDriveFileCopyAttribute(myarg, body, parameters):
else: else:
Cmd.Backup() Cmd.Backup()
usageErrorExit(Msg.REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE) usageErrorExit(Msg.REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE)
elif _getDriveFileDownloadRestrictions(myarg, body):
pass
elif myarg == 'inheritedpermissionsdisabled': elif myarg == 'inheritedpermissionsdisabled':
body['inheritedPermissionsDisabled'] = getBoolean() body['inheritedPermissionsDisabled'] = getBoolean()
elif myarg == 'property': elif myarg == 'property':
@@ -54605,11 +54695,6 @@ DRIVEFILE_ORDERBY_CHOICE_MAP = {
'viewedbymetime': 'viewedByMeTime', 'viewedbymetime': 'viewedByMeTime',
} }
def _mapDrive3TitlesToDrive2(titles, drive3TitlesMap):
for i, title in enumerate(titles):
if title in drive3TitlesMap:
titles[i] = drive3TitlesMap[title]
def _mapDriveUser(field): def _mapDriveUser(field):
if 'me' in field: if 'me' in field:
field['isAuthenticatedUser'] = field.pop('me') field['isAuthenticatedUser'] = field.pop('me')
@@ -54617,32 +54702,25 @@ def _mapDriveUser(field):
field['picture'] = {'url': field.pop('photoLink')} field['picture'] = {'url': field.pop('photoLink')}
def _mapDrivePermissionNames(permission): def _mapDrivePermissionNames(permission):
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
if 'displayName' in permission:
permission['name'] = permission.pop('displayName')
if 'expirationTime' in permission:
permission['expirationDate'] = formatLocalTime(permission.pop('expirationTime'))
if 'allowFileDiscovery' in permission:
permission['withLink'] = not permission.pop('allowFileDiscovery')
emailAddress = permission.get('emailAddress') emailAddress = permission.get('emailAddress')
if emailAddress: if emailAddress:
_, permission['domain'] = splitEmailAddress(emailAddress) _, permission['domain'] = splitEmailAddress(emailAddress)
def _mapDriveParents(f_file, parentsSubFields): def _mapDriveInfo(f_file, parentsSubFields, showParentsIdsAsList):
if 'parents' in f_file: if 'parents' in f_file:
parents = f_file.pop('parents') parents = f_file.pop('parents')
if len(parents) == 1 and parents[0] == ORPHANS: if showParentsIdsAsList:
return f_file['parentsIds'] = parents
f_file['parents'] = [] elif len(parents) != 1 or parents[0] != ORPHANS:
for parentId in parents: f_file['parents'] = []
parent = {} for parentId in parents:
if parentsSubFields['id']: parent = {}
parent['id'] = parentId if parentsSubFields['id']:
if parentsSubFields['isRoot']: parent['id'] = parentId
parent['isRoot'] = parentId == parentsSubFields['rootFolderId'] if parentsSubFields['isRoot']:
f_file['parents'].append(parent) parent['isRoot'] = parentId == parentsSubFields['rootFolderId']
f_file['parents'].append(parent)
def _mapDriveProperties(f_file):
appProperties = f_file.pop('appProperties', []) appProperties = f_file.pop('appProperties', [])
properties = f_file.pop('properties', []) properties = f_file.pop('properties', [])
if appProperties: if appProperties:
@@ -54654,51 +54732,10 @@ def _mapDriveProperties(f_file):
for key, value in sorted(properties.items()): for key, value in sorted(properties.items()):
f_file['properties'].append({'key': key, 'value': value, 'visibility': 'PUBLIC'}) f_file['properties'].append({'key': key, 'value': value, 'visibility': 'PUBLIC'})
def _mapDriveFieldNames(f_file, user, parentsSubFields, mapToLabels):
if mapToLabels:
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_LABELS_MAP.items():
if attrib in f_file:
f_file.setdefault('labels', {})
f_file['labels'][v2attrib] = f_file.pop(attrib)
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP.items():
if attrib in f_file:
f_file[v2attrib] = f_file.pop(attrib)
capabilities = f_file.get('capabilities')
if capabilities:
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP.items():
if attrib in capabilities:
f_file[v2attrib] = capabilities[attrib]
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP.items():
if attrib in capabilities:
capabilities[v2attrib] = capabilities.pop(attrib)
if 'spaces' in f_file:
f_file['appDataContents'] = 'appDataFolder' in f_file['spaces']
if 'lastModifyingUser' in f_file:
if 'displayName' in f_file['lastModifyingUser']:
f_file['lastModifyingUserName'] = f_file['lastModifyingUser']['displayName']
_mapDriveUser(f_file['lastModifyingUser'])
if 'owners' in f_file:
for owner in f_file['owners']:
_mapDriveUser(owner)
if 'displayName' in owner:
f_file.setdefault('ownerNames', [])
f_file['ownerNames'].append(owner['displayName'])
_mapDriveUser(f_file.get('sharingUser', {}))
_mapDriveParents(f_file, parentsSubFields)
_mapDriveProperties(f_file)
for permission in f_file.get('permissions', []): for permission in f_file.get('permissions', []):
if (permission.get('type') == 'user') and (permission.get('emailAddress', '').lower() == user) and ('role' in permission): emailAddress = permission.get('emailAddress')
f_file['userPermission'] = {'id': 'me', 'role': permission['role'], 'type': permission['type']} if emailAddress:
_mapDrivePermissionNames(permission) _, permission['domain'] = splitEmailAddress(emailAddress)
def _mapDriveRevisionNames(revision):
for attrib, v2attrib in API.DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP.items():
if attrib in revision:
revision[v2attrib] = revision.pop(attrib)
if 'lastModifyingUser' in revision:
if 'displayName' in revision['lastModifyingUser']:
revision['lastModifyingUserName'] = revision['lastModifyingUser']['displayName']
_mapDriveUser(revision['lastModifyingUser'])
DRIVEFILE_BASIC_PERMISSION_FIELDS = [ DRIVEFILE_BASIC_PERMISSION_FIELDS = [
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type', 'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
@@ -54722,6 +54759,7 @@ DRIVE_FIELDS_CHOICE_MAP = {
'createddate': 'createdTime', 'createddate': 'createdTime',
'createdtime': 'createdTime', 'createdtime': 'createdTime',
'description': 'description', 'description': 'description',
'downloadrestrictions': 'downloadRestrictions',
'driveid': 'driveId', 'driveid': 'driveId',
'drivename': 'driveId', 'drivename': 'driveId',
'editable': 'capabilities.canEdit', 'editable': 'capabilities.canEdit',
@@ -54868,6 +54906,11 @@ DRIVE_CONTENT_RESTRICTIONS_SUBFIELDS_CHOICE_MAP = {
'type': 'type', 'type': 'type',
} }
DRIVE_DOWNLOAD_RESTRICTIONS_SUBFIELDS_CHOICE_MAP = {
'itemdownloadrestriction': 'itemDownloadRestriction',
'effectivedownloadrestrictionwithcontext': 'effectiveDownloadRestrictionWithContext',
}
DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP = { DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP = {
'id': 'labels(id)', 'id': 'labels(id)',
'fields': 'labels(fields)', 'fields': 'labels(fields)',
@@ -54932,6 +54975,7 @@ DRIVE_SHORTCUTDETAILS_SUBFIELDS_CHOICE_MAP = {
DRIVE_SUBFIELDS_CHOICE_MAP = { DRIVE_SUBFIELDS_CHOICE_MAP = {
'capabilities': DRIVE_CAPABILITIES_SUBFIELDS_CHOICE_MAP, 'capabilities': DRIVE_CAPABILITIES_SUBFIELDS_CHOICE_MAP,
'contentrestrictions': DRIVE_CONTENT_RESTRICTIONS_SUBFIELDS_CHOICE_MAP, 'contentrestrictions': DRIVE_CONTENT_RESTRICTIONS_SUBFIELDS_CHOICE_MAP,
'downloadrestrictions': DRIVE_DOWNLOAD_RESTRICTIONS_SUBFIELDS_CHOICE_MAP,
'labelinfo': DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP, 'labelinfo': DRIVE_LABELINFO_SUBFIELDS_CHOICE_MAP,
'labels': DRIVE_LABEL_CHOICE_MAP, 'labels': DRIVE_LABEL_CHOICE_MAP,
'lastmodifyinguser': DRIVE_SHARINGUSER_SUBFIELDS_CHOICE_MAP, 'lastmodifyinguser': DRIVE_SHARINGUSER_SUBFIELDS_CHOICE_MAP,
@@ -54949,11 +54993,7 @@ FILEINFO_FIELDS_TITLES = ['name', 'mimeType']
FILEPATH_FIELDS_TITLES = ['name', 'id', 'mimeType', 'ownedByMe', 'parents', 'sharedWithMeTime', 'driveId'] FILEPATH_FIELDS_TITLES = ['name', 'id', 'mimeType', 'ownedByMe', 'parents', 'sharedWithMeTime', 'driveId']
FILEPATH_FIELDS = ','.join(FILEPATH_FIELDS_TITLES) FILEPATH_FIELDS = ','.join(FILEPATH_FIELDS_TITLES)
def _getDriveTimeObjects(): DRIVE_TIME_OBJECTS = {'createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime'}
timeObjects = ['createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime']
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return set(timeObjects)
def _getDriveFieldSubField(field, fieldsList, parentsSubFields): def _getDriveFieldSubField(field, fieldsList, parentsSubFields):
field, subField = field.split('.', 1) field, subField = field.split('.', 1)
@@ -55150,7 +55190,6 @@ def showFileInfo(users):
showNoParents = True showNoParents = True
includeLabels = ','.join(DFF.includeLabels) includeLabels = ','.join(DFF.includeLabels)
pathFields = FILEPATH_FIELDS pathFields = FILEPATH_FIELDS
timeObjects = _getDriveTimeObjects()
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
@@ -55244,22 +55283,14 @@ def showFileInfo(users):
if fullpath: if fullpath:
# Save simple parents list as mappings turn it into a list of dicts # Save simple parents list as mappings turn it into a list of dicts
fpparents = result['parents'][:] fpparents = result['parents'][:]
if showParentsIdsAsList and 'parents' in result: _mapDriveInfo(result, DFF.parentsSubFields, showParentsIdsAsList)
result['parentsIds'] = result.pop('parents')
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveFieldNames(result, user, DFF.parentsSubFields, True)
else:
_mapDriveParents(result, DFF.parentsSubFields)
_mapDriveProperties(result)
for permission in result.get('permissions', []):
_mapDrivePermissionNames(permission)
if not FJQC.formatJSON: if not FJQC.formatJSON:
showJSON(None, result, skipObjects=skipObjects, timeObjects=timeObjects, simpleLists=simpleLists, showJSON(None, result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS, simpleLists=simpleLists,
dictObjectsKey={'owners': 'displayName', 'fields': 'id', 'labels': 'id', 'user': 'emailAddress', 'parents': 'id', dictObjectsKey={'owners': 'displayName', 'fields': 'id', 'labels': 'id', 'user': 'emailAddress', 'parents': 'id',
'permissions': ['name', 'displayName'][GC.Values[GC.DRIVE_V3_NATIVE_NAMES]]}) 'permissions': 'displayName'})
Ind.Decrement() Ind.Decrement()
else: else:
printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=timeObjects), ensure_ascii=False, sort_keys=True)) printLine(json.dumps(cleanJSON(result, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
if fullpath: if fullpath:
# Restore simple parents list # Restore simple parents list
fileTree[fileId]['info']['parents'] = fpparents[:] fileTree[fileId]['info']['parents'] = fpparents[:]
@@ -55651,18 +55682,12 @@ FILEREVISIONS_FIELDS_CHOICE_MAP = {
'size': 'size', 'size': 'size',
} }
def _getFileRevisionsTimeObjects(): FILEREVISIONS_TIME_OBJECTS = {'modifiedTime'}
timeObjects = ['modifiedTime']
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return set(timeObjects)
def _showRevision(revision, timeObjects, i=0, count=0): def _showRevision(revision, i=0, count=0):
printEntity([Ent.DRIVE_FILE_REVISION, revision['id']], i, count) printEntity([Ent.DRIVE_FILE_REVISION, revision['id']], i, count)
Ind.Increment() Ind.Increment()
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]: showJSON(None, revision, ['id'], timeObjects=FILEREVISIONS_TIME_OBJECTS)
_mapDriveRevisionNames(revision)
showJSON(None, revision, ['id'], timeObjects)
Ind.Decrement() Ind.Decrement()
DRIVE_REVISIONS_INDEXED_TITLES = ['revisions'] DRIVE_REVISIONS_INDEXED_TITLES = ['revisions']
@@ -55686,7 +55711,6 @@ def printShowFileRevisions(users):
revisionsEntity = None revisionsEntity = None
oneItemPerRow = previewDelete = showTitles = stripCRsFromName = False oneItemPerRow = previewDelete = showTitles = stripCRsFromName = False
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP) OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -55704,7 +55728,7 @@ def printShowFileRevisions(users):
elif myarg == 'showtitles': elif myarg == 'showtitles':
showTitles = True showTitles = True
if csvPF: if csvPF:
csvPF.AddTitles(fileNameTitle) csvPF.AddTitles('name')
elif myarg == 'stripcrsfromname': elif myarg == 'stripcrsfromname':
stripCRsFromName = True stripCRsFromName = True
elif getFieldsList(myarg, FILEREVISIONS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'): elif getFieldsList(myarg, FILEREVISIONS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'):
@@ -55715,7 +55739,6 @@ def printShowFileRevisions(users):
fields = getItemFieldsFromFieldsList('revisions', fieldsList) fields = getItemFieldsFromFieldsList('revisions', fieldsList)
else: else:
fields = '*' fields = '*'
timeObjects = _getFileRevisionsTimeObjects()
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
@@ -55755,29 +55778,24 @@ def printShowFileRevisions(users):
k = 0 k = 0
for revision in results: for revision in results:
k += 1 k += 1
_showRevision(revision, timeObjects, k, kcount) _showRevision(revision, k, kcount)
Ind.Decrement() Ind.Decrement()
elif results: elif results:
if oneItemPerRow: if oneItemPerRow:
for revision in results: for revision in results:
row = {'Owner': user, 'id': fileId} row = {'Owner': user, 'id': fileId}
if showTitles: if showTitles:
row[fileNameTitle] = fileName row['name'] = fileName
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]: csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=FILEREVISIONS_TIME_OBJECTS))
_mapDriveRevisionNames(revision)
csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=timeObjects))
else: else:
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
for revision in results:
_mapDriveRevisionNames(revision)
if showTitles: if showTitles:
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, fileNameTitle: fileName}, timeObjects=timeObjects)) csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, 'name': fileName}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
else: else:
csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=timeObjects)) csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
Ind.Decrement() Ind.Decrement()
if csvPF: if csvPF:
if oneItemPerRow: if oneItemPerRow:
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle, 'revision.id']) csvPF.SetSortTitles(['Owner', 'id', 'name', 'revision.id'])
else: else:
csvPF.SetSortTitles(['Owner', 'id', 'revisions']) csvPF.SetSortTitles(['Owner', 'id', 'revisions'])
csvPF.SetIndexedTitles(DRIVE_REVISIONS_INDEXED_TITLES) csvPF.SetIndexedTitles(DRIVE_REVISIONS_INDEXED_TITLES)
@@ -56587,10 +56605,10 @@ def printFileList(users):
def _printFileInfoRow(baserow, fileInfo): def _printFileInfoRow(baserow, fileInfo):
row = baserow.copy() row = baserow.copy()
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects, csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter)) simpleLists=simpleLists, delimiter=delimiter))
else: else:
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects), row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True) ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row) csvPF.WriteRowTitlesJSONNoFilter(row)
@@ -56641,15 +56659,7 @@ def printFileList(users):
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly) fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
else: else:
addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly) addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly)
if showParentsIdsAsList and 'parents' in fileInfo: _mapDriveInfo(fileInfo, DFF.parentsSubFields, showParentsIdsAsList)
fileInfo['parentsIds'] = fileInfo.pop('parents')
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
_mapDriveFieldNames(fileInfo, user, DFF.parentsSubFields, False)
else:
_mapDriveParents(fileInfo, DFF.parentsSubFields)
_mapDriveProperties(fileInfo)
for permission in fileInfo.get('permissions', []):
_mapDrivePermissionNames(permission)
if showParentsIdsAsList and 'parentsIds' in fileInfo: if showParentsIdsAsList and 'parentsIds' in fileInfo:
fileInfo['parents'] = len(fileInfo['parentsIds']) fileInfo['parents'] = len(fileInfo['parentsIds'])
if addCSVData: if addCSVData:
@@ -56657,24 +56667,24 @@ def printFileList(users):
if not countsOnly: if not countsOnly:
if not oneItemPerRow or 'permissions' not in fileInfo: if not oneItemPerRow or 'permissions' not in fileInfo:
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects, csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter)) simpleLists=simpleLists, delimiter=delimiter))
else: else:
if 'id' in fileInfo: if 'id' in fileInfo:
row['id'] = fileInfo['id'] row['id'] = fileInfo['id']
if fileNameTitle in fileInfo: if 'name' in fileInfo:
row[fileNameTitle] = fileInfo[fileNameTitle] row['name'] = fileInfo['name']
if 'owners' in fileInfo: if 'owners' in fileInfo:
flattenJSON({'owners': fileInfo['owners']}, flattened=row, skipObjects=skipObjects) flattenJSON({'owners': fileInfo['owners']}, flattened=row, skipObjects=skipObjects)
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects), row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True) ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row) csvPF.WriteRowTitlesJSONNoFilter(row)
else: else:
baserow = row.copy() baserow = row.copy()
if 'id' in fileInfo: if 'id' in fileInfo:
baserow['id'] = fileInfo['id'] baserow['id'] = fileInfo['id']
if fileNameTitle in fileInfo: if 'name' in fileInfo:
baserow[fileNameTitle] = fileInfo[fileNameTitle] baserow['name'] = fileInfo['name']
if 'owners' in fileInfo: if 'owners' in fileInfo:
flattenJSON({'owners': fileInfo['owners']}, flattened=baserow, skipObjects=skipObjects) flattenJSON({'owners': fileInfo['owners']}, flattened=baserow, skipObjects=skipObjects)
for permission in fileInfo.pop('permissions'): for permission in fileInfo.pop('permissions'):
@@ -56688,7 +56698,7 @@ def printFileList(users):
_printFileInfoRow(baserow, fileInfo) _printFileInfoRow(baserow, fileInfo)
else: else:
if not countsRowFilter: if not countsRowFilter:
csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects, csvPFco.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=DRIVE_TIME_OBJECTS,
simpleLists=simpleLists, delimiter=delimiter), mimeTypeInfo, sizeField) simpleLists=simpleLists, delimiter=delimiter), mimeTypeInfo, sizeField)
else: else:
mimeTypeInfo.setdefault(fileInfo['mimeType'], {'count': 0, 'size': 0}) mimeTypeInfo.setdefault(fileInfo['mimeType'], {'count': 0, 'size': 0})
@@ -56955,12 +56965,6 @@ def printFileList(users):
csvPF.AddTitles('paths') csvPF.AddTitles('paths')
csvPF.SetFixPaths(True) csvPF.SetFixPaths(True)
includeLabels = ','.join(DFF.includeLabels) includeLabels = ','.join(DFF.includeLabels)
timeObjects = _getDriveTimeObjects()
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
fileNameTitle = 'title'
csvPF.SetMapDrive3Titles(True)
else:
fileNameTitle = 'name'
csvPF.RemoveTitles(['capabilities']) csvPF.RemoveTitles(['capabilities'])
if DLP.queryTimes and selectSubQuery: if DLP.queryTimes and selectSubQuery:
for queryTimeName, queryTimeValue in DLP.queryTimes.items(): for queryTimeName, queryTimeValue in DLP.queryTimes.items():
@@ -56980,9 +56984,9 @@ def printFileList(users):
if not FJQC.formatJSON: if not FJQC.formatJSON:
nodataFields = ['Owner']+list(set(DFF.fieldsList)-skipObjects) nodataFields = ['Owner']+list(set(DFF.fieldsList)-skipObjects)
else: else:
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress'] nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
else: else:
nodataFields = ['Owner', 'id', fileNameTitle, 'owners.emailAddress'] nodataFields = ['Owner', 'id', 'name', 'owners.emailAddress']
if not FJQC.formatJSON: if not FJQC.formatJSON:
nodataFields.append('permissions') nodataFields.append('permissions')
if filepath: if filepath:
@@ -57162,7 +57166,7 @@ def printFileList(users):
if not csvPF.rows: if not csvPF.rows:
setSysExitRC(NO_ENTITIES_FOUND_RC) setSysExitRC(NO_ENTITIES_FOUND_RC)
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.SetSortTitles(['Owner', 'id', fileNameTitle]) csvPF.SetSortTitles(['Owner', 'id', 'name'])
else: else:
if 'JSON' in csvPF.JSONtitlesList: if 'JSON' in csvPF.JSONtitlesList:
csvPF.MoveJSONTitlesToEnd(['JSON']) csvPF.MoveJSONTitlesToEnd(['JSON'])
@@ -57430,8 +57434,7 @@ def printShowFileComments(users):
# [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>] # [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
# [followshortcuts [<Boolean>]] # [followshortcuts [<Boolean>]]
def printShowFilePaths(users): def printShowFilePaths(users):
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name' csvPF = CSVPrintFile(['Owner', 'id', 'name', 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
csvPF = CSVPrintFile(['Owner', 'id', fileNameTitle, 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
fullpath = folderPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False fullpath = folderPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False
pathDelimiter = '/' pathDelimiter = '/'
@@ -57532,11 +57535,11 @@ def printShowFilePaths(users):
if oneItemPerRow: if oneItemPerRow:
if paths: if paths:
for path in paths: for path in paths:
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name'], 'path': path}) csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name'], 'path': path})
else: else:
csvPF.WriteRow({'Owner': user, 'id': fileId, fileNameTitle: result['name']}) csvPF.WriteRow({'Owner': user, 'id': fileId, 'name': result['name']})
else: else:
csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, fileNameTitle: result['name']})) csvPF.WriteRowTitles(flattenJSON({'paths': paths}, flattened={'Owner': user, 'id': fileId, 'name': result['name']}))
except GAPI.fileNotFound: except GAPI.fileNotFound:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], Msg.DOES_NOT_EXIST, j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], Msg.DOES_NOT_EXIST, j, jcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e: except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
@@ -57549,8 +57552,7 @@ def printShowFilePaths(users):
# gam <UserTypeEntity> print fileparenttree <DriveFileEntity> [todrive <ToDriveAttribute>*] # gam <UserTypeEntity> print fileparenttree <DriveFileEntity> [todrive <ToDriveAttribute>*]
# [stripcrsfromname] # [stripcrsfromname]
def printFileParentTree(users): def printFileParentTree(users):
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name' csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', 'name', 'parentId', 'depth', 'isRoot'], 'sortall')
csvPF = CSVPrintFile(['Owner', 'isBase', 'baseId', 'id', fileNameTitle, 'parentId', 'depth', 'isRoot'], 'sortall')
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
stripCRsFromName = False stripCRsFromName = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -57610,7 +57612,7 @@ def printFileParentTree(users):
kcount = len(fileList) kcount = len(fileList)
isBase = True isBase = True
for result in fileList: for result in fileList:
csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], fileNameTitle: result['name'], csvPF.WriteRow({'Owner': user, 'isBase': isBase, 'baseId': baseId, 'id': result['id'], 'name': result['name'],
'parentId': result['parents'][0], 'depth': kcount, 'isRoot': result['isRoot']}) 'parentId': result['parents'][0], 'depth': kcount, 'isRoot': result['isRoot']})
isBase = False isBase = False
kcount -= 1 kcount -= 1
@@ -58409,7 +58411,7 @@ def printShowFileTree(users):
userInfo['index'] += 1 userInfo['index'] += 1
row = userInfo.copy() row = userInfo.copy()
row['depth'] = depth row['depth'] = depth
row[fileNameTitle] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name'] row['name'] = ('' if noindent else Ind.SpacesSub1())+fileEntry['name']
for field in FILETREE_FIELDS_PRINT_ORDER: for field in FILETREE_FIELDS_PRINT_ORDER:
if showFields[field]: if showFields[field]:
if field == 'parents': if field == 'parents':
@@ -58417,7 +58419,7 @@ def printShowFileTree(users):
elif field == 'owners': elif field == 'owners':
row[field] = delimiter.join([owner['emailAddress'] for owner in fileEntry.get(field, [])]) row[field] = delimiter.join([owner['emailAddress'] for owner in fileEntry.get(field, [])])
elif field == 'size': elif field == 'size':
row[fileSize] = fileEntry.get(sizeField, 0) row['size'] = fileEntry.get(sizeField, 0)
else: else:
row[field] = fileEntry.get(field, '') row[field] = fileEntry.get(field, '')
csvPF.WriteRow(row) csvPF.WriteRow(row)
@@ -58518,14 +58520,6 @@ def printShowFileTree(users):
unknownArgumentExit() unknownArgumentExit()
fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)', fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)',
'shared', sizeField, 'explicitlyTrashed', 'trashed', 'webViewLink'] 'shared', sizeField, 'explicitlyTrashed', 'trashed', 'webViewLink']
if csvPF:
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
fileNameTitle = 'title'
fileSize = 'fileSize'
csvPF.SetMapDrive3Titles(True)
else:
fileNameTitle = 'name'
fileSize = 'size'
buildTree = (not fileIdEntity buildTree = (not fileIdEntity
or (not fileIdEntity['dict'] or (not fileIdEntity['dict']
and not fileIdEntity['query'] and not fileIdEntity['query']
@@ -58585,7 +58579,7 @@ def printShowFileTree(users):
if jcount == 0: if jcount == 0:
continue continue
if csvPF: if csvPF:
userInfo = {'User': user, 'index': 0, 'depth': 0, fileNameTitle: ''} userInfo = {'User': user, 'index': 0, 'depth': 0, 'name': ''}
j = 0 j = 0
Ind.Increment() Ind.Increment()
for fileId in fileIdEntity['list']: for fileId in fileIdEntity['list']:
@@ -58745,8 +58739,7 @@ def createDriveFile(users):
media_body = getMediaBody(parameters) media_body = getMediaBody(parameters)
body['mimeType'] = parameters[DFA_LOCALMIMETYPE] body['mimeType'] = parameters[DFA_LOCALMIMETYPE]
if csvPF: if csvPF:
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name' csvPF.SetTitles(['User', 'name', 'id'])
csvPF.SetTitles(['User', fileNameTitle, 'id'])
if showDetails: if showDetails:
csvPF.AddTitles(['parentId', 'mimeType']) csvPF.AddTitles(['parentId', 'mimeType'])
if addCSVData: if addCSVData:
@@ -58806,7 +58799,7 @@ def createDriveFile(users):
else: else:
entityActionPerformed(kvList, i, count) entityActionPerformed(kvList, i, count)
else: else:
row = {'User': user, fileNameTitle: result['name'], 'id': result['id']} row = {'User': user, 'name': result['name'], 'id': result['id']}
if showDetails: if showDetails:
row.update({'parentId': parentId, 'mimeType': result['mimeType']}) row.update({'parentId': parentId, 'mimeType': result['mimeType']})
if addCSVData: if addCSVData:
@@ -60309,7 +60302,7 @@ def _checkForExistingShortcut(drive, fileId, fileName, parentId):
supportsAllDrives=True, includeItemsFromAllDrives=True, supportsAllDrives=True, includeItemsFromAllDrives=True,
q=f"shortcutDetails.targetId = '{fileId}' and trashed = False", fields='files(id,name,parents)')['files'] q=f"shortcutDetails.targetId = '{fileId}' and trashed = False", fields='files(id,name,parents)')['files']
for shortcut in existingShortcuts: for shortcut in existingShortcuts:
if parentId in shortcut['parents'] and fileName == shortcut['name']: if parentId in shortcut.get('parents', []) and fileName == shortcut['name']:
return shortcut['id'] return shortcut['id']
except (GAPI.invalidQuery, GAPI.invalid, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy): except (GAPI.invalidQuery, GAPI.invalid, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
pass pass
@@ -60362,8 +60355,8 @@ copyReturnItemMap = {
# [enforceexpansiveaccess [<Boolean>]] # [enforceexpansiveaccess [<Boolean>]]
def copyDriveFile(users): def copyDriveFile(users):
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType): def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
row = {'User': user, fileNameTitle: oldName, 'id': oldId, row = {'User': user, 'name': oldName, 'id': oldId,
newFileNameTitle: newName, 'newId': newId, 'mimeType': mimeType} 'newName': newName, 'newId': newId, 'mimeType': mimeType}
if addCSVData: if addCSVData:
row.update(addCSVData) row.update(addCSVData)
csvPF.WriteRow(row) csvPF.WriteRow(row)
@@ -60753,9 +60746,7 @@ def copyDriveFile(users):
else: else:
unknownArgumentExit() unknownArgumentExit()
if csvPF: if csvPF:
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name' csvPF.SetTitles(['User', 'name', 'id', 'newName', 'newId', 'mimeType'])
newFileNameTitle = f'new{fileNameTitle.capitalize()}'
csvPF.SetTitles(['User', fileNameTitle, 'id', newFileNameTitle, 'newId', 'mimeType'])
if addCSVData: if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys())) csvPF.AddTitles(sorted(addCSVData.keys()))
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
@@ -64155,11 +64146,8 @@ def _getDriveFileACLPrintKeysTimeObjects():
printKeys = ['id', 'type', 'emailAddress', 'domain', 'role', 'permissionDetails', printKeys = ['id', 'type', 'emailAddress', 'domain', 'role', 'permissionDetails',
'expirationTime', 'photoLink', 'allowFileDiscovery', 'deleted', 'expirationTime', 'photoLink', 'allowFileDiscovery', 'deleted',
'pendingOwner', 'view'] 'pendingOwner', 'view']
timeObjects = ['expirationTime'] timeObjects = {'expirationTime'}
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]: return (printKeys, timeObjects)
_mapDrive3TitlesToDrive2(printKeys, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
_mapDrive3TitlesToDrive2(timeObjects, API.DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP)
return (printKeys, set(timeObjects))
# DriveFileACL commands utilities # DriveFileACL commands utilities
def _showDriveFilePermissionJSON(user, fileId, fileName, createdTime, permission, timeObjects): def _showDriveFilePermissionJSON(user, fileId, fileName, createdTime, permission, timeObjects):
@@ -64251,7 +64239,6 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
showDetails = True showDetails = True
csvPF = None csvPF = None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
body = {} body = {}
body['type'] = permType = getChoice(DRIVEFILE_ACL_PERMISSION_TYPES) body['type'] = permType = getChoice(DRIVEFILE_ACL_PERMISSION_TYPES)
@@ -64327,7 +64314,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects() printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
if csvPF: if csvPF:
if showTitles: if showTitles:
csvPF.AddTitles(fileNameTitle) csvPF.AddTitles('name')
csvPF.SetSortAllTitles() csvPF.SetSortAllTitles()
if FJQC.formatJSON: if FJQC.formatJSON:
csvPF.SetJSONTitles(csvPF.titlesList+['JSON']) csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
@@ -64366,7 +64353,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
if csvPF: if csvPF:
baserow = {'Owner': user, 'id': fileId} baserow = {'Owner': user, 'id': fileId}
if showTitles: if showTitles:
baserow[fileNameTitle] = fileName baserow['name'] = fileName
row = baserow.copy() row = baserow.copy()
_mapDrivePermissionNames(permission) _mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects) flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
@@ -64422,7 +64409,6 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
showDetails = True showDetails = True
csvPF = None csvPF = None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
body = {} body = {}
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -64457,7 +64443,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}') missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects() printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
if csvPF and showTitles: if csvPF and showTitles:
csvPF.AddTitles(fileNameTitle) csvPF.AddTitles('name')
csvPF.SetSortAllTitles() csvPF.SetSortAllTitles()
if FJQC.formatJSON: if FJQC.formatJSON:
csvPF.SetJSONTitles(csvPF.titlesList+['JSON']) csvPF.SetJSONTitles(csvPF.titlesList+['JSON'])
@@ -64500,7 +64486,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
if csvPF: if csvPF:
baserow = {'Owner': user, 'id': fileId} baserow = {'Owner': user, 'id': fileId}
if showTitles: if showTitles:
baserow[fileNameTitle] = fileName baserow['name'] = fileName
row = baserow.copy() row = baserow.copy()
_mapDrivePermissionNames(permission) _mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects) flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
@@ -65065,7 +65051,6 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
fieldsList = [] fieldsList = []
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP) OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
PM = PermissionMatch() PM = PermissionMatch()
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -65084,7 +65069,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
addTitle = getString(Cmd.OB_STRING) addTitle = getString(Cmd.OB_STRING)
showTitles = False showTitles = False
if csvPF: if csvPF:
csvPF.AddTitles(fileNameTitle) csvPF.AddTitles('name')
csvPF.SetSortAllTitles() csvPF.SetSortAllTitles()
elif getDriveFilePermissionsFields(myarg, fieldsList): elif getDriveFilePermissionsFields(myarg, fieldsList):
pass pass
@@ -65169,7 +65154,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
else: else:
baserow = {'Owner': user, 'id': fileId} baserow = {'Owner': user, 'id': fileId}
if showTitles or addTitle: if showTitles or addTitle:
baserow[fileNameTitle] = fileName baserow['name'] = fileName
if oneItemPerRow: if oneItemPerRow:
for permission in permissions: for permission in permissions:
_mapDrivePermissionNames(permission) _mapDrivePermissionNames(permission)
@@ -65736,7 +65721,6 @@ def doPrintShowOwnership():
customerId = GC.Values[GC.CUSTOMER_ID] customerId = GC.Values[GC.CUSTOMER_ID]
if customerId == GC.MY_CUSTOMER: if customerId == GC.MY_CUSTOMER:
customerId = None customerId = None
fileNameTitle = 'title' if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES] else 'name'
csvPF = CSVPrintFile('Owner') if Act.csvFormat() else None csvPF = CSVPrintFile('Owner') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
addCSVData = {} addCSVData = {}
@@ -65781,7 +65765,7 @@ def doPrintShowOwnership():
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if csvPF and not FJQC.formatJSON: if csvPF and not FJQC.formatJSON:
csvPF.AddTitles(['id', fileNameTitle, 'type', 'ownerIsSharedDrive', 'driveId', 'event']) csvPF.AddTitles(['id', 'name', 'type', 'ownerIsSharedDrive', 'driveId', 'event'])
if addCSVData: if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys())) csvPF.AddTitles(sorted(addCSVData.keys()))
csvPF.SetSortAllTitles() csvPF.SetSortAllTitles()
@@ -65814,7 +65798,7 @@ def doPrintShowOwnership():
elif event['name'] != 'change_owner' and item['name'] == 'owner': elif event['name'] != 'change_owner' and item['name'] == 'owner':
fileInfo['Owner'] = item['value'] fileInfo['Owner'] = item['value']
elif item['name'] == 'doc_title': elif item['name'] == 'doc_title':
fileInfo[fileNameTitle] = item['value'] fileInfo['name'] = item['value']
elif item['name'] == 'doc_type': elif item['name'] == 'doc_type':
fileInfo['type'] = item['value'] fileInfo['type'] = item['value']
elif item['name'] == 'owner_is_shared_drive': elif item['name'] == 'owner_is_shared_drive':
@@ -65827,7 +65811,7 @@ def doPrintShowOwnership():
if not csvPF: if not csvPF:
if not FJQC.formatJSON: if not FJQC.formatJSON:
printEntityKVList([Ent.OWNER, fileInfo['Owner']], printEntityKVList([Ent.OWNER, fileInfo['Owner']],
['id', fileInfo['id'], fileNameTitle, fileInfo.get(fileNameTitle, ''), ['id', fileInfo['id'], 'name', fileInfo.get('name', ''),
'type', fileInfo.get('type', ''), 'type', fileInfo.get('type', ''),
'ownerIsSharedDrive', fileInfo.get('ownerIsSharedDrive', False), 'ownerIsSharedDrive', fileInfo.get('ownerIsSharedDrive', False),
'driveId', fileInfo.get('driveId', ''), 'driveId', fileInfo.get('driveId', ''),
@@ -65885,6 +65869,10 @@ SHAREDDRIVE_RESTRICTIONS_MAP = {
'sharingfoldersrequiresorganizerpermission': 'sharingFoldersRequiresOrganizerPermission', 'sharingfoldersrequiresorganizerpermission': 'sharingFoldersRequiresOrganizerPermission',
'teammembersonly': 'driveMembersOnly', 'teammembersonly': 'driveMembersOnly',
} }
SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP = {
'restrictedforreaders': 'downloadrestrictedforreaders',
'restrictedforwriters': 'downloadrestrictedforwriters',
}
def _getSharedDriveRestrictions(myarg, body): def _getSharedDriveRestrictions(myarg, body):
def _setRestriction(restriction): def _setRestriction(restriction):
@@ -65899,7 +65887,12 @@ def _getSharedDriveRestrictions(myarg, body):
if myarg.startswith('restrictions.'): if myarg.startswith('restrictions.'):
_, subField = myarg.split('.', 1) _, subField = myarg.split('.', 1)
if subField in SHAREDDRIVE_RESTRICTIONS_MAP: if subField.startswith('downloadrestrictions.'):
_, subField = subField.split('.', 1)
if subField in SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP:
_setRestriction(SHAREDDRIVE_DOWNLOAD_RESTRICTIONS_MAP[subField])
return True
elif subField in SHAREDDRIVE_RESTRICTIONS_MAP:
_setRestriction(subField) _setRestriction(subField)
return True return True
invalidChoiceExit(subField, SHAREDDRIVE_RESTRICTIONS_MAP, True) invalidChoiceExit(subField, SHAREDDRIVE_RESTRICTIONS_MAP, True)
@@ -78384,6 +78377,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_USERLIST: doPrintUserList, Cmd.ARG_USERLIST: doPrintUserList,
Cmd.ARG_VACATION: printShowVacation, Cmd.ARG_VACATION: printShowVacation,
Cmd.ARG_VAULTHOLD: printShowUserVaultHolds, Cmd.ARG_VAULTHOLD: printShowUserVaultHolds,
Cmd.ARG_WEBMASTERSITE: printShowWebMasterSites,
Cmd.ARG_WEBRESOURCE: printShowWebResources,
Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation, Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation,
Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel, Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel,
} }
@@ -78494,6 +78489,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_TOKEN: printShowTokens, Cmd.ARG_TOKEN: printShowTokens,
Cmd.ARG_VAULTHOLD: printShowUserVaultHolds, Cmd.ARG_VAULTHOLD: printShowUserVaultHolds,
Cmd.ARG_VACATION: printShowVacation, Cmd.ARG_VACATION: printShowVacation,
Cmd.ARG_WEBMASTERSITE: printShowWebMasterSites,
Cmd.ARG_WEBRESOURCE: printShowWebResources,
Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation, Cmd.ARG_WORKINGLOCATION: printShowWorkingLocation,
Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel, Cmd.ARG_YOUTUBECHANNEL: printShowYouTubeChannel,
} }
@@ -78745,6 +78742,8 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_USERS: Cmd.ARG_USER, Cmd.ARG_USERS: Cmd.ARG_USER,
Cmd.ARG_VAULTHOLDS: Cmd.ARG_VAULTHOLD, Cmd.ARG_VAULTHOLDS: Cmd.ARG_VAULTHOLD,
Cmd.ARG_VERIFICATIONCODES: Cmd.ARG_BACKUPCODE, Cmd.ARG_VERIFICATIONCODES: Cmd.ARG_BACKUPCODE,
Cmd.ARG_WEBMASTERSITES: Cmd.ARG_WEBMASTERSITE,
Cmd.ARG_WEBRESOURCES: Cmd.ARG_WEBRESOURCE,
Cmd.ARG_WORKINGLOCATIONS: Cmd.ARG_WORKINGLOCATION, Cmd.ARG_WORKINGLOCATIONS: Cmd.ARG_WORKINGLOCATION,
Cmd.ARG_YOUTUBECHANNELS: Cmd.ARG_YOUTUBECHANNEL, Cmd.ARG_YOUTUBECHANNELS: Cmd.ARG_YOUTUBECHANNEL,
} }

View File

@@ -85,6 +85,7 @@ PRINTERS = 'printers'
PUBSUB = 'pubsub' PUBSUB = 'pubsub'
REPORTS = 'reports' REPORTS = 'reports'
RESELLER = 'reseller' RESELLER = 'reseller'
SEARCHCONSOLE = 'searchconsole'
SERVICEACCOUNTLOOKUP = 'serviceaccountlookup' SERVICEACCOUNTLOOKUP = 'serviceaccountlookup'
SERVICEMANAGEMENT = 'servicemanagement' SERVICEMANAGEMENT = 'servicemanagement'
SERVICEUSAGE = 'serviceusage' SERVICEUSAGE = 'serviceusage'
@@ -198,6 +199,7 @@ PROJECT_APIS = [
'people.googleapis.com', 'people.googleapis.com',
'pubsub.googleapis.com', 'pubsub.googleapis.com',
'reseller.googleapis.com', 'reseller.googleapis.com',
'searchconsole.googleapis.com',
'sheets.googleapis.com', 'sheets.googleapis.com',
'siteverification.googleapis.com', 'siteverification.googleapis.com',
'storage-api.googleapis.com', 'storage-api.googleapis.com',
@@ -271,6 +273,7 @@ _INFO = {
PUBSUB: {'name': 'Pub / Sub API', 'version': 'v1', 'v2discovery': True}, PUBSUB: {'name': 'Pub / Sub API', 'version': 'v1', 'v2discovery': True},
REPORTS: {'name': 'Reports API', 'version': 'reports_v1', 'v2discovery': True, 'mappedAPI': 'admin'}, REPORTS: {'name': 'Reports API', 'version': 'reports_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
RESELLER: {'name': 'Reseller API', 'version': 'v1', 'v2discovery': True}, RESELLER: {'name': 'Reseller API', 'version': 'v1', 'v2discovery': True},
SEARCHCONSOLE: {'name': 'Search Console API', 'version': 'v1', 'v2discovery': True},
SERVICEACCOUNTLOOKUP: {'name': 'Service Account Lookup pseudo-API', 'version': 'v1', 'v2discovery': True, 'localjson': True}, SERVICEACCOUNTLOOKUP: {'name': 'Service Account Lookup pseudo-API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
SERVICEMANAGEMENT: {'name': 'Service Management API', 'version': 'v1', 'v2discovery': True}, SERVICEMANAGEMENT: {'name': 'Service Management API', 'version': 'v1', 'v2discovery': True},
SERVICEUSAGE: {'name': 'Service Usage API', 'version': 'v1', 'v2discovery': True}, SERVICEUSAGE: {'name': 'Service Usage API', 'version': 'v1', 'v2discovery': True},
@@ -697,10 +700,20 @@ _SVCACCT_SCOPES = [
'api': PEOPLE_OTHERCONTACTS, 'api': PEOPLE_OTHERCONTACTS,
'subscopes': [], 'subscopes': [],
'scope': 'https://www.googleapis.com/auth/contacts.other.readonly'}, 'scope': 'https://www.googleapis.com/auth/contacts.other.readonly'},
{'name': 'Search Console API - read only',
'api': SEARCHCONSOLE,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/webmasters.readonly'},
{'name': 'Sheets API', {'name': 'Sheets API',
'api': SHEETS, 'api': SHEETS,
'subscopes': READONLY, 'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/spreadsheets'}, 'scope': 'https://www.googleapis.com/auth/spreadsheets'},
{'name': 'Site Verification API',
'api': SITEVERIFICATION,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/siteverification'},
{'name': 'Tag Manager API - Accounts, Containers, Workspaces, Tags - read only', {'name': 'Tag Manager API - Accounts, Containers, Workspaces, Tags - read only',
'api': TAGMANAGER, 'api': TAGMANAGER,
'subscopes': [], 'subscopes': [],
@@ -750,56 +763,6 @@ _USER_SVCACCT_ONLY_SCOPES = [
'scope': 'https://www.googleapis.com/auth/apps.groups.migration'}, 'scope': 'https://www.googleapis.com/auth/apps.groups.migration'},
] ]
DRIVE3_TO_DRIVE2_ABOUT_FIELDS_MAP = {
'displayName': 'name',
'limit': 'quotaBytesTotal',
'usage': 'quotaBytesUsedAggregate',
'usageInDrive': 'quotaBytesUsed',
'usageInDriveTrash': 'quotaBytesUsedInTrash',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP = {
'canComment': 'canComment',
'canReadRevisions': 'canReadRevisions',
'canCopy': 'copyable',
'canEdit': 'editable',
'canShare': 'shareable',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP = {
'canChangeViewersCanCopyContent': 'canChangeRestrictedDownload',
}
DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP = {
'allowFileDiscovery': 'withLink',
'createdTime': 'createdDate',
'expirationTime': 'expirationDate',
'modifiedByMe': 'modified',
'modifiedByMeTime': 'modifiedByMeDate',
'modifiedTime': 'modifiedDate',
'name': 'title',
'restrictionTime': 'restrictionDate',
'sharedWithMeTime': 'sharedWithMeDate',
'size': 'fileSize',
'trashedTime': 'trashedDate',
'viewedByMe': 'viewed',
'viewedByMeTime': 'lastViewedByMeDate',
'webViewLink': 'alternateLink',
}
DRIVE3_TO_DRIVE2_LABELS_MAP = {
'modifiedByMe': 'modified',
'starred': 'starred',
'trashed': 'trashed',
'viewedByMe': 'viewed',
}
DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP = {
'modifiedTime': 'modifiedDate',
'keepForever': 'pinned',
'size': 'fileSize',
}
def getAPIName(api): def getAPIName(api):
return _INFO[api]['name'] return _INFO[api]['name']

View File

@@ -155,8 +155,6 @@ DRIVE_DIR = 'drive_dir'
DRIVE_MAX_RESULTS = 'drive_max_results' DRIVE_MAX_RESULTS = 'drive_max_results'
# Use Drive V3 beta # Use Drive V3 beta
DRIVE_V3_BETA = 'drive_v3_beta' DRIVE_V3_BETA = 'drive_v3_beta'
# Use Drive V3 ntive names
DRIVE_V3_NATIVE_NAMES = 'drive_v3_native_names'
# When processing email messages in batches, how many should be processed in each batch # When processing email messages in batches, how many should be processed in each batch
EMAIL_BATCH_SIZE = 'email_batch_size' EMAIL_BATCH_SIZE = 'email_batch_size'
# Enable Delegated Admin Service Account # Enable Delegated Admin Service Account
@@ -382,7 +380,6 @@ Defaults = {
ENFORCE_EXPANSIVE_ACCESS: TRUE, ENFORCE_EXPANSIVE_ACCESS: TRUE,
DRIVE_MAX_RESULTS: '1000', DRIVE_MAX_RESULTS: '1000',
DRIVE_V3_BETA: FALSE, DRIVE_V3_BETA: FALSE,
DRIVE_V3_NATIVE_NAMES: TRUE,
EMAIL_BATCH_SIZE: '50', EMAIL_BATCH_SIZE: '50',
ENABLE_DASA: FALSE, ENABLE_DASA: FALSE,
ENABLE_GCLOUD_REAUTH: FALSE, ENABLE_GCLOUD_REAUTH: FALSE,
@@ -551,7 +548,6 @@ VAR_INFO = {
ENFORCE_EXPANSIVE_ACCESS: {VAR_TYPE: TYPE_BOOLEAN}, ENFORCE_EXPANSIVE_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)}, DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN}, DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN},
DRIVE_V3_NATIVE_NAMES: {VAR_TYPE: TYPE_BOOLEAN},
EMAIL_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)}, EMAIL_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
ENABLE_DASA: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'enabledasa.txt', VAR_SFFT: (FALSE, TRUE)}, ENABLE_DASA: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'enabledasa.txt', VAR_SFFT: (FALSE, TRUE)},
ENABLE_GCLOUD_REAUTH: {VAR_TYPE: TYPE_BOOLEAN}, ENABLE_GCLOUD_REAUTH: {VAR_TYPE: TYPE_BOOLEAN},

View File

@@ -830,6 +830,10 @@ class GamCLArgs():
ARG_VERIFICATION = 'verification' ARG_VERIFICATION = 'verification'
ARG_VERIFICATIONCODES = 'verificationcodes' ARG_VERIFICATIONCODES = 'verificationcodes'
ARG_VERIFY = 'verify' ARG_VERIFY = 'verify'
ARG_WEBMASTERSITE = 'webmastersite'
ARG_WEBMASTERSITES = 'webmastersites'
ARG_WEBRESOURCE = 'webresource'
ARG_WEBRESOURCES = 'webresources'
ARG_WORKINGLOCATION = 'workinglocation' ARG_WORKINGLOCATION = 'workinglocation'
ARG_WORKINGLOCATIONS = 'workinglocations' ARG_WORKINGLOCATIONS = 'workinglocations'
ARG_YOUTUBECHANNEL = 'youtubechannel' ARG_YOUTUBECHANNEL = 'youtubechannel'

View File

@@ -394,6 +394,8 @@ class GamEntity():
VAULT_MATTER_ID = 'vlmi' VAULT_MATTER_ID = 'vlmi'
VAULT_OPERATION = 'vlto' VAULT_OPERATION = 'vlto'
VAULT_QUERY = 'vltq' VAULT_QUERY = 'vltq'
WEB_MASTERSITE = 'wems'
WEB_RESOURCE = 'were'
WEBCLIPS_ENABLED = 'webc' WEBCLIPS_ENABLED = 'webc'
YOUTUBE_CHANNEL = 'ytch' YOUTUBE_CHANNEL = 'ytch'
# _NAMES[0] is plural, _NAMES[1] is singular unless the item name is explicitly plural (Calendar Settings) # _NAMES[0] is plural, _NAMES[1] is singular unless the item name is explicitly plural (Calendar Settings)
@@ -752,6 +754,8 @@ class GamEntity():
VAULT_OPERATION: ['Vault Operations', 'Vault Operation'], VAULT_OPERATION: ['Vault Operations', 'Vault Operation'],
VAULT_QUERY: ['Vault Queries', 'Vault Query'], VAULT_QUERY: ['Vault Queries', 'Vault Query'],
WEBCLIPS_ENABLED: ['Web Clips Enabled', 'Web Clips Enabled'], WEBCLIPS_ENABLED: ['Web Clips Enabled', 'Web Clips Enabled'],
WEB_MASTERSITE: ['Web Master Sites', 'Web Master Site'],
WEB_RESOURCE: ['Web Resources', 'Web Resource'],
YOUTUBE_CHANNEL: ['YouTube Channels', 'YouTube Channel'], YOUTUBE_CHANNEL: ['YouTube Channels', 'YouTube Channel'],
ROLE_MANAGER: ['Managers', 'Manager'], ROLE_MANAGER: ['Managers', 'Manager'],
ROLE_MEMBER: ['Members', 'Member'], ROLE_MEMBER: ['Members', 'Member'],

View File

@@ -1,15 +1,13 @@
!All Google Drive API calls have been converted from v2 to v3, see: https://developers.google.com/drive/v3/web/migration Legacy GAM used Drive API v2, GAM7 uses Drive API v3. See: https://developers.google.com/drive/v3/web/migration
Many of the changes are internal to Gam and have no visible effect. Google has modified/renamed many field names and these will affect scripts that parse the output from `gam print/show drivesettings/drivefileacls/fileinfo/filelist/filerevisions`. Additionally, Google has dropped some fields and their values are no longer available. On input, Gam accepts both the old and new field names. Many of the changes are internal to GAM7 and have no visible effect.
Google has modified/renamed many field names and these will affect scripts that parse the output from `gam print/show drivesettings/drivefileacls/fileinfo/filelist/filerevisions`.
Additionally, Google has dropped some fields and their values are no longer available. On input, GAM7 accepts both the old and new field names where applicable.
A variable, `drive_v3_native_names` (default value is True), has been added to `gam.cfg` to control the field names on output: when True, the v3 native field names are used; when False, the v3 native field names are mapped to the v2 field names. If you use Legacy GAM and have scripts that process the output from these print commands, you may have to make modifications to your scripts when you upgrade to GAM7.
Run your print/show commands with a version of Legacy GAM and save the output.
If you have scripts that process the output from these print commands, you may have to make modifications to your scripts. Run your print/show commands with GAM7 and compare the output to that saved in the previous run;
Run your print/show commands with a version of Legacy Gam and save the output.
With drive_v3_native_names = False, run your print/show commands with this version of Gam and compare the output to that saved in the previous run;
modify your scripts that process the output as appropriate. modify your scripts that process the output as appropriate.
There is a cost to mapping the v3 field names back to the v2 field names; you can avoid this cost by setting drive_v3_native_names = True,
running your print/show commands, comparing the output and making the appropriate script modifications.
``` ```
print/show drivesettings print/show drivesettings
Dropped fields: Dropped fields:
@@ -30,7 +28,7 @@ Dropped fields:
authKey authKey
Renamed fields (Old->New): Renamed fields (Old->New):
name->displayName name->displayName
withLink->allowFileDiscovery withLink->allowFileDiscovery - value is complemented
print/show fileinfo/filelist print/show fileinfo/filelist
Dropped fields: Dropped fields:
@@ -40,19 +38,20 @@ Dropped fields:
labels(hidden) labels(hidden)
markedViewedByMeDate markedViewedByMeDate
openWithLinks openWithLinks
selfLink ownerNames
parents(isRoot) parents(isRoot)
parents(parentLink) parents(parentLink)
parents(selfLink) parents(selfLink)
permissions(selfLink) permissions(selfLink)
selfLink selfLink
userPermission(selfLink) userPermission
Renamed fields (Old->New): Renamed fields (Old->New):
alternateLink->webViewLink alternateLink->webViewLink
capabilities(canChangeRestrictedDownload)->capabilities(canChangeViewersCanCopyContent) capabilities(canChangeRestrictedDownload)->capabilities(canChangeViewersCanCopyContent)
createdDate->createdTime createdDate->createdTime
expirationDate->expirationTime expirationDate->expirationTime
fileSize->size fileSize->size
lastModifyingUserName->lastModifyingUser(displayName)
lastViewedByMeDate->viewedByMeTime lastViewedByMeDate->viewedByMeTime
modified->modifiedByMe modified->modifiedByMe
modifiedByMeDate->modifiedByMeTime modifiedByMeDate->modifiedByMeTime
@@ -76,18 +75,3 @@ Renamed fields (Old->New):
picture.url->photoLink picture.url->photoLink
pinned->keepForever pinned->keepForever
``` ```
The parents field of a file has undergone the most change. In Drive v2 it was a list of compound items with three sub-fields per item: id, isRoot, parentLink.
In Drive v3 the parents field is a list of simple items, the parent ids. The following examples show how the parents field is output in a CSV file for a file with two parents.
```
Previous versions of Gam:
Owner,title,parents,parents.0.isRoot,parents.0.id,parents.0.parentLink,parents.1.isRoot,parents.1.id,parents.1.parentLink
testuser@domain.com,TestFile,2,True,PPPP1111,https://www.googleapis.com/drive/v2/files/PPPP1111,False,PPPP2222,https://www.googleapis.com/drive/v2/files/PPPP2222
Current version of Gam with drive_v3_name_names = false
Owner,title,parents,parents.0.id,parents.1.id
testuser@domain.com,TestFile,2,PPPP1111,PPPP2222
Current version of Gam with drive_v3_name_names = true
Owner,name,parents
testuser@domain.com,TestFile,PPPP1111 PPPP2222
```

View File

@@ -10,6 +10,73 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.17.02
Updated `gam <UserTypeEntity> print|show webmastersites` to handle the following error
that occurs if you haven't updated your project to include the Google Search Console API.
```
ERROR: 403: permissionDenied - Google Search Console API has not been used in project 111055363999 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/searchconsole.googleapis.com/overview?project=111055363999 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
```
### 7.17.01
Fixed bug in `gam <UserTypeEntity> show webmastersites` that caused a trap.
### 7.17.00
Added commands to discover Sites and WebResources that managed users (previously unmanaged) may have access to for better governance and visibility.
These are special purpose commands and will not generally be used.
```
gam <UserTypeEntity> show webresources
gam <UserTypeEntity> print webresources [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> show webmastersites
gam <UserTypeEntity> print webmastersites [todrive <ToDriveAttribute>*]
```
### 7.16.01
The Drive API now supports setting download restrictions on individual files.
Added `downloadrestictions` and `<DriveDownloadRestrictionsSubfieldName>` to `<DriveFieldName>`.
```
<DriveDownloadRestrictionsSubfieldName> ::=
downloadrestrictions.itemdownloadrestriction|
downloadrestrictions.effectivedownloadrestrictionwithcontext
```
Added `itemdownloadrestriction (restrictedforreaders [<Boolean>]) (restrictedforwriters [<Boolean>])`
to `<DriveFileAttribute>`.
From the Drive API documentation:
```
itemDownloadRestriction - The download restriction of the file applied directly by the owner or organizer. This does not take into account shared drive settings or DLP rules.
effectiveDownloadRestrictionWithContext - Output only. The effective download restriction applied to this file. This considers all restriction settings and DLP rules.
restrictedForReaders - Whether download and copy is restricted for readers.
restrictedForWriters - Whether download and copy is restricted for writers. If true, download is also restricted for readers.
```
### 7.16.00
Removed `drive_v3_native_names` from `gam.cfg`; GAM now only uses Drive API v3 fields names on output.
If you had `drive_v3_native_names = False` in `gam.cfg` or are updating from Legacy GAM:
* See: https://github.com/GAM-team/GAM/wiki/Drive-REST-API-v3
### 7.15.01
Added `downloadrestrictions.restrictedforreaders` and `downloadrestrictions.restrictedforwriters`
to `<SharedDriveRestrictionsSubfieldName>`; previously, only the abbreviations `downloadrestrictedforreaders`
and `downloadrestrictedforwriters` were supported (they are still supported).
Updated `gam <UserTypeEntity> copy drivefile` to handle unexpected data returned by Google that caused a trap.
### 7.15.00
Updated `gam print shareddriveorganizers` to make `shownoorganizerdrives` default to `True`
as documented; it was defaulting to `False`.
Cleaned up code for processing Python dictionary structures; this should have no noticable effect.
### 7.14.04 ### 7.14.04
Fixed bug in `gam print|show cigroups cimember <UserItem>` that generated the following error: Fixed bug in `gam print|show cigroups cimember <UserItem>` that generated the following error:

View File

@@ -2,6 +2,7 @@
Use these steps if you have used any version of GAM in your domain. They will update your GAM project Use these steps if you have used any version of GAM in your domain. They will update your GAM project
and all necessary authentications. and all necessary authentications.
- [Drive API v2 to Drive API v3](Drive-REST-v3)
- [Downloads-Installs](Downloads-Installs) - [Downloads-Installs](Downloads-Installs)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell) - [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows) - [Windows](#windows)
@@ -251,7 +252,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -989,7 +990,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.14.04 - https://github.com/GAM-team/GAM - pythonsource GAM 7.17.02 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -203,8 +203,8 @@
allowcontentmanagerstosharefolders| allowcontentmanagerstosharefolders|
copyrequireswriterpermission| copyrequireswriterpermission|
domainusersonly| domainusersonly|
downloadrestrictedforreaders| downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters| downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly| drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission sharingfoldersrequiresorganizerpermission
@@ -247,7 +247,7 @@ The user that creates a Shared Drive is given the permission role organizer for
gam [<UserTypeEntity>] create shareddrive <Name> gam [<UserTypeEntity>] create shareddrive <Name>
[(theme|themeid <String>)| [(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly] [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
@@ -259,7 +259,7 @@ gam [<UserTypeEntity>] create shareddrive <Name>
* `<Float>` - Y coordinate, typically 0.0 * `<Float>` - Y coordinate, typically 0.0
* `<Float>` - width, typically 1.0 * `<Float>` - width, typically 1.0
* `color` - set the Shared Drive color * `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions * `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hide <Boolean>` - Set Shared Drive visibility * `hide <Boolean>` - Set Shared Drive visibility
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes. If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
@@ -333,13 +333,13 @@ gam [<UserTypeEntity>] update shareddrive <SharedDriveEntity> [name <Name>]
[adminaccess|asadmin] [adminaccess|asadmin]
[(theme|themeid <String>)| [(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
``` ```
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes` * `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives * `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `color` - set the Shared Drive color * `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions * `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hidden <Boolean>` - Set Shared Drive visibility * `hidden <Boolean>` - Set Shared Drive visibility
* `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html * `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html

View File

@@ -157,12 +157,16 @@
contentrestrictions.restrictiontime| contentrestrictions.restrictiontime|
contentrestrictions.type contentrestrictions.type
<DriveLabelInfoSubfieldName> ::= <DriveDownloadRestrictionsSubfieldName> ::=
downloadrestrictions.itemdownloadrestriction|
downloadrestrictions.effectivedownloadrestrictionwithcontext
<ClassificationLabelInfoSubfieldName> ::=
labels.id| # modifiedByMe labels.id| # modifiedByMe
labels.revisionid| # copyRequiresWriterPermission labels.revisionid| # copyRequiresWriterPermission
labels.fields # viewedByMe labels.fields # viewedByMe
<DriveLabelsSubfieldName> ::= <ClassificationLabelsSubfieldName~> ::=
labels.modified| # modifiedByMe labels.modified| # modifiedByMe
labels.restricted| # copyRequiresWriterPermission labels.restricted| # copyRequiresWriterPermission
labels.starred| # starred labels.starred| # starred
@@ -251,6 +255,8 @@
copyrequireswriterpermission| copyrequireswriterpermission|
createddate|createdtime| createddate|createdtime|
description| description|
downloadrestictions|
<DriveDownloadRestrictionsSubfieldName>|
driveid| driveid|
drivename| drivename|
editable| editable|
@@ -269,9 +275,9 @@
inheritedpermissionsdisabled| inheritedpermissionsdisabled|
isappauthorized| isappauthorized|
labelinfo| labelinfo|
<DriveLabelInfoSubfieldName>| <ClassificationLabelInfoSubfieldName>|
labels| labels|
<DriveLabelsSubfieldName>| <ClassificationLabelsSubfieldName>|
lastmodifyinguser| lastmodifyinguser|
<DriveLastModifyingUserSubfieldName>| <DriveLastModifyingUserSubfieldName>|
lastmodifyingusername| lastmodifyingusername|

View File

@@ -125,6 +125,7 @@
(folderColorRgb <ColorValue>)| (folderColorRgb <ColorValue>)|
(indexabletext <String>)| (indexabletext <String>)|
(inheritedpermissionsdisabled [<Boolean>])| (inheritedpermissionsdisabled [<Boolean>])|
(itemdownloadrestriction restrictedforreaders|restrictedforwriters [<Boolean>])|
(keeprevisionforever|pinned)| (keeprevisionforever|pinned)|
(lastviewedbyme <Time>)| (lastviewedbyme <Time>)|
(mimetype <MimeType>)| (mimetype <MimeType>)|

View File

@@ -181,8 +181,8 @@
allowcontentmanagerstosharefolders| allowcontentmanagerstosharefolders|
copyrequireswriterpermission| copyrequireswriterpermission|
domainusersonly| domainusersonly|
downloadrestrictedforreaders| downloadrestrictedforreaders|downloadrestrictions.restrictedforreaders|
downloadrestrictedforwriters| downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly| drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission sharingfoldersrequiresorganizerpermission
@@ -217,7 +217,7 @@ The user that creates a Shared Drive is given the permission role organizer for
gam <UserTypeEntity> create shareddrive <Name> gam <UserTypeEntity> create shareddrive <Name>
[(theme|themeid <String>)| [(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>] [errorretries <Integer>] [updateinitialdelay <Integer>] [updateretrydelay <Integer>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly] [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
@@ -228,7 +228,7 @@ gam <UserTypeEntity> create shareddrive <Name>
* `<Float>` - Y coordinate, typically 0.0 * `<Float>` - Y coordinate, typically 0.0
* `<Float>` - width, typically 1.0 * `<Float>` - width, typically 1.0
* `color` - set the Shared Drive color * `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions * `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hide <Boolean>` - Set Shared Drive visibility * `hide <Boolean>` - Set Shared Drive visibility
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes. If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
@@ -284,13 +284,13 @@ This command is used to set basic Shared Drive settings.
gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [adminaccess|asadmin] [name <Name>] gam <UserTypeEntity> update shareddrive <SharedDriveEntity> [adminaccess|asadmin] [name <Name>]
[(theme|themeid <String>)| [(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])] ([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)* ([restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>] [hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
``` ```
* `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes` * `themeid` - a Shared Drive themeId obtained from `show shareddrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives * `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `color` - set the Shared Drive color * `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions * `[restrictions.]<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hidden <Boolean>` - Set Shared Drive visibility * `hidden <Boolean>` - Set Shared Drive visibility
This option is only available when the command is run as an administrator. This option is only available when the command is run as an administrator.

View File

@@ -0,0 +1,48 @@
# Users - Web Resources and Sites
- [API documentation](#api-documentation)
- [Introduction](#introduction)
- [Definitions](#definitions)
- [Display Web Resources](#display-web-resources)
- [Display Web Sites](#display-web-sites)
## API documentation
* [Web Resources](https://developers.google.com/site-verification/v1/webResource/list)
* [Web Sites](https://developers.google.com/webmaster-tools/v1/sites/list)
## Introduction
These features were added in version 7.17.00.
To use these commands you add the 'Search Console API' to your project and update your service account authorization.
```
gam update project
gam user user@domain.com update serviceaccount
...
[*] 39) Search Console API - read only
[*] 42) Site Verification API
```
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
## Display Web Resources
```
gam <UserItem> show webresources
```
Gam displays the information as an indented list of keys and values.
```
gam <UserItem> print webresources [todrive <ToDriveAttribute>*]
```
Gam displays the information as columns of fields.
## Display Web Sites
```
gam <UserItem> show websites
```
Gam displays the information as an indented list of keys and values.
```
gam <UserItem> print websites [todrive <ToDriveAttribute>*]
```
Gam displays the information as columns of fields.

View File

@@ -1,10 +1,9 @@
k
# Version and Help # Version and Help
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -16,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -28,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAM 7.14.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.17.02 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -65,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 7.14.04 Latest: 7.17.02
echo $? echo $?
1 1
``` ```
@@ -73,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
7.14.04 7.17.02
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -83,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 7.14.04 - https://github.com/GAM-team/GAM GAM 7.17.02 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64

View File

@@ -174,6 +174,7 @@ Service Account Access
* [Users - Tag Manager](Users-Tag-Manager) * [Users - Tag Manager](Users-Tag-Manager)
* [Users - Tasks](Users-Tasks) * [Users - Tasks](Users-Tasks)
* [Users - YouTube](Users-YouTube) * [Users - YouTube](Users-YouTube)
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites)
GAM Tutorials GAM Tutorials
* [Account Auditing](l-ExamplesAccountAuditing) * [Account Auditing](l-ExamplesAccountAuditing)

View File

@@ -412,9 +412,8 @@ never_time
has the value "1970-01-01T00:00:00.000Z" has the value "1970-01-01T00:00:00.000Z"
Default: Never Default: Never
no_browser no_browser
If no_browser is True, GAM won't open a browser if todrive is set If no_browser is True, GAM won't open a browser when it prints a link
when creating CSV files and GAM prints a link and waits for and waits for the verification code when oauth2.txt is being created/updated
the verification code when oauth2.txt is being created
Signal file: OldGamPath/nobrowser.txt Signal file: OldGamPath/nobrowser.txt
no_cache no_cache
Disable GAM API caching Disable GAM API caching