Compare commits

...

27 Commits

Author SHA1 Message Date
Ross Scroggs
0c5f747c36 Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 17:13:39 -07:00
Ross Scroggs
826619857c Bump version 2025-09-29 17:09:41 -07:00
Ross Scroggs
9a2880e411 Added chat_max_results variable to 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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-29 13:33:20 -07:00
Ross Scroggs
95caeaba5e Added chat_max_results variable to gam.cfg. 2025-09-29 12:07:13 -07:00
Ross Scroggs
d8ad1b27a4 Update Reports.md 2025-09-29 10:25:55 -07:00
Ross Scroggs
fefeae7c60 Update Vault-Takeout.md 2025-09-29 07:23:45 -07:00
Ross Scroggs
65f7b82d53 Vault query updates
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-28 20:26:46 -07:00
Ross Scroggs
bebafb428d Vault query updates 2025-09-28 19:40:33 -07:00
Ross Scroggs
5e59363a0c Update Vault-Takeout.md 2025-09-28 16:11:55 -07:00
Ross Scroggs
4b2e0db720 Added commands to create, copy and delete Vault saved queries.
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-28 14:22:33 -07:00
Ross Scroggs
938b2bf5a4 Added commands to create, copy and delete Vault saved queries. 2025-09-28 13:20:50 -07:00
Ross Scroggs
34ff0329c4 Added commands to create, copy and delete Vault saved queries. 2025-09-28 13:11:21 -07:00
Ross Scroggs
bed610405b Added a variant of gam create vaultexport
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-27 14:40:12 -07:00
Ross Scroggs
1b0c8b75cb Added a variant of gam create vaultexport
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-27 13:25:39 -07:00
Ross Scroggs
6eb7e59d56 Update Vault-Takeout.md 2025-09-27 06:57:23 -07:00
Ross Scroggs
5b4cf97702 Added a variant of gam create vaulthold
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-26 22:18:49 -07:00
Ross Scroggs
997bd56bd6 Added a variant of gam create vaulthold
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
2025-09-26 21:36:21 -07:00
Ross Scroggs
e66db1a117 Update Users-Drive-Copy-Move.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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
2025-09-25 17:23:57 -07:00
Ross Scroggs
e3a5f33981 Update Users-Drive-Permissions.md 2025-09-25 17:14:25 -07:00
Ross Scroggs
877465a82f Update Users-Drive-Permissions.md 2025-09-25 17:08:41 -07:00
Ross Scroggs
7e9477c6ea Fix print users #1840
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-25 09:06:54 -07:00
Ross Scroggs
1b2fc06f6f Fix print users #1840 2025-09-25 09:00:14 -07:00
Ross Scroggs
3d3b3eac85 Fix print users #1840 2025-09-25 08:59:39 -07:00
Ross Scroggs
882b930928 Update _Sidebar.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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
2025-09-23 13:09:48 -07:00
Jay Lee
4d804177c4 Update pushwiki.yml
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-23 14:59:18 -04:00
Jay Lee
de71baff60 move old articles to legacy and remove from wiki 2025-09-23 18:53:53 +00:00
Ross Scroggs
79de854440 Bump version
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-22 18:22:46 -07:00
70 changed files with 832 additions and 264 deletions

View File

@@ -37,7 +37,7 @@ jobs:
cd GAM.wiki
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add *.md
git add -A
git commit -m "[no ci] Push Wiki changes"
git status
git push

View File

@@ -565,6 +565,7 @@ If an item contains spaces, it should be surrounded by ".
See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryItem> ::= <UniqueID>|<String>
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String>
@@ -728,6 +729,7 @@ If an item contains spaces, it should be surrounded by ".
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*"
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*"
@@ -3381,6 +3383,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
gam print course-submissions [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
@@ -3402,6 +3405,7 @@ gam print course-works [todrive <ToDriveAttribute>*]
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
# Classroom - Student Groups
@@ -5410,34 +5414,48 @@ gam show vaultmatters|matters [matterstate <MatterStateList>]
[formatjson]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> corpus mail|groups
[(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone]
[(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))]
matter <MatterItem> <QueryItem>
[wait <Integer>]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem>
corpus mail|groups
[scope [all_data|held_data|unprocessed_data]]
[(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> operation <String> [wait <Integer>]
gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
gam create vaultexport|export matter <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
(covereddata calllogs|textmessages|voicemails)*
[driveclientsideencryption any|encrypted|unencrypted]
[includerooms <Boolean>]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[covereddata calllogs|textmessages|voicemails]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
gam delete vaultexport|export <ExportItem> matter <MatterItem>
@@ -5493,18 +5511,21 @@ gam show vaultexports|exports
[fields <VaultExportFieldNameList>] [shownames]
[formatjson]
gam create vaulthold|hold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails|returnidonly]
gam update vaulthold|hold <HoldItem> matter <MatterItem>
[([addaccounts|addgroups|addusers <EmailItemList>] [removeaccounts|removegroups|removeusers <EmailItemList>]) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails]
gam delete vaulthold|hold <HoldItem> matter <MatterItem>
@@ -5544,6 +5565,32 @@ gam show vaultholds|holds [matters <MatterItemList>]
gam <UserTypeEntity> print vaultholds|holds [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> show vaultholds|holds
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[shownames]
[showdetails|returnidonly|formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames]
[showdetails|returnidonly|formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
<VaultQueryFieldName> ::=
createtime |
displayname |

View File

@@ -1,7 +1,95 @@
7.23.01
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
course's materials displayed on a separate row with all of the other course fields.
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
7.23.00
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
Added option `<JSONData>` to `gam create vaultexport|vaultquery` and `gam print vaultcounts`.
7.22.06
Added commands to create, copy and delete Vault saved queries.
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[shownames] [formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames] [formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
Added a variant of `gam print vaultcounts` that gets its query parameters from a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
7.22.05
Added a variant of `gam create vaultexport` that gets its query parameters from a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
7.22.04
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
```
gam create vaulthold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
7.22.03
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
from a field name to a query option; it is now correctly interpreted as a field name.
7.22.02
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
by includinbg the pysocks library needed by the latest httplib2 library.
by including the pysocks library needed by the latest httplib2 library.
7.22.00

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.22.02'
__version__ = '7.23.00'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -18989,10 +18989,10 @@ def doPrintAliases():
pass
elif myarg == 'select':
_, users = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
elif myarg in SUSPENDED_ARGUMENTS:
isSuspended = _getIsSuspended(myarg)
elif myarg in ARCHIVED_ARGUMENTS:
isArchived = _getIsArchived(myarg)
elif myarg == 'issuspended':
isSuspended = getBoolean()
elif myarg == 'isarchived':
isArchived = getBoolean()
elif myarg in {'user','users'}:
users.extend(convertEntityToList(getString(Cmd.OB_EMAIL_ADDRESS_LIST, minLen=0)))
elif myarg in {'group', 'groups'}:
@@ -26579,7 +26579,7 @@ def printShowChatEmojis(users):
pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, filter=pfilter)
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], filter=pfilter)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue
@@ -26649,7 +26649,14 @@ def getChatSpaceParameters(myarg, body, typeChoicesMap, updateMask):
CHAT_MEMBER_ROLE_MAP = {
'member': 'ROLE_MEMBER',
'manager': 'ROLE_MANAGER'
'manager': 'ROLE_MANAGER',
'owner': 'ROLE_OWNER',
}
CHAT_ROLE_ENTITY_TYPE_MAP = {
'ROLE_MEMBER': Ent.CHAT_MEMBER_USER,
'ROLE_MANAGER': Ent.CHAT_MANAGER_USER,
'ROLE_OWNER': Ent.CHAT_OWNER_USER,
}
CHAT_MEMBER_TYPE_MAP = {
@@ -27006,7 +27013,6 @@ def _getChatSpaceSearchParms(myarg, queries, queryTimes, OBY):
return False
return True
CHAT_PAGE_SIZE = 1000
CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = {
'createtime': 'createTime',
'lastactivetime': 'lastActiveTime',
@@ -27086,7 +27092,7 @@ def printShowChatSpaces(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsCS)
fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsCS)
if showAccessSettings:
for space in spaces:
if space['spaceType'] == 'SPACE':
@@ -27152,7 +27158,7 @@ def _getChatSpaceMembers(cd, chatSpace, ciGroupName):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, 0, 0, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=chatSpace, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsUAA)
parent=chatSpace, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsUAA)
for member in members:
_getChatMemberEmail(cd, member)
gmember = {}
@@ -27289,7 +27295,7 @@ def createChatMember(users):
missingArgumentExit('space')
if not userList and not groupList:
missingArgumentExit('user|members|group|groups')
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER
userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
userMembers = []
for user in userList:
userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}})
@@ -27546,7 +27552,7 @@ def syncChatMembers(users):
unknownArgumentExit()
if not parent:
missingArgumentExit('space')
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER
userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
userMembers = {}
syncUsersSet = set()
for user in userList:
@@ -27576,7 +27582,7 @@ def syncChatMembers(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=parent, showGroups=groupsSpecified, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
parent=parent, showGroups=groupsSpecified, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
for member in members:
if 'member' in member:
if member['member']['type'] == mtype and member['role'] == role:
@@ -27777,7 +27783,7 @@ def printShowChatMembers(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=GC.Values[GC.CHAT_MAX_RESULTS],
**kwargsCS)
for space in sorted(spaces, key=lambda k: k[sortName]):
if space['spaceType'] == 'SPACE' and 'membershipCount' in space:
@@ -27794,7 +27800,7 @@ def printShowChatMembers(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=GC.Values[GC.CHAT_MAX_RESULTS],
**kwargsCS)
for space in sorted(spaces, key=lambda k: k[sortName]):
# if 'membershipCount' in space:
@@ -27825,7 +27831,7 @@ def printShowChatMembers(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=parentName, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
parent=parentName, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
for member in members:
_getChatMemberEmail(cd, member)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
@@ -28139,7 +28145,7 @@ def printShowChatMessages(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MESSAGE, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter, showDeleted=showDeleted,
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter, showDeleted=showDeleted,
fields=fields)
for message in messages:
if 'sender' in message:
@@ -28257,7 +28263,7 @@ def printShowChatEvents(users):
pageMessage=_getChatPageMessage(Ent.CHAT_EVENT, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter)
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue
@@ -41654,7 +41660,7 @@ def convertQueryNameToID(v, nameOrId, matterId, matterNameId):
query = callGAPI(v.matters().savedQueries(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
matterId=matterId, savedQueryId=cg.group(1))
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']))
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
except (GAPI.notFound, GAPI.badRequest):
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
except (GAPI.forbidden, GAPI.invalidArgument) as e:
@@ -41663,12 +41669,12 @@ def convertQueryNameToID(v, nameOrId, matterId, matterNameId):
try:
queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
matterId=matterId, fields='savedQueries(savedQueryId,displayName),nextPageToken')
matterId=matterId, fields='savedQueries(savedQueryId,displayName,query),nextPageToken')
except (GAPI.forbidden, GAPI.invalidArgument) as e:
ClientAPIAccessDeniedExit(str(e))
for query in queries:
if query['displayName'].lower() == nameOrIdlower:
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']))
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
def getMatterItem(v, state=None):
@@ -41716,6 +41722,7 @@ VAULT_SEARCH_METHODS_MAP = {
'accounts': 'ACCOUNT',
'chatspace': 'ROOM',
'chatspaces': 'ROOM',
'documentids': 'DRIVE_DOCUMENT',
'entireorg': 'ENTIRE_ORG',
'everyone': 'ENTIRE_ORG',
'org': 'ORG_UNIT',
@@ -41813,11 +41820,13 @@ VAULT_QUERY_ARGS = [
# drive
'driveclientsideencryption', 'driveversiondate', 'includeshareddrives', 'includeteamdrives', 'shareddrivesoption',
# hangoutsChat
'includerooms',
'includerooms',
# mail
'mailclientsideencryption', 'excludedrafts',
# voice
'covereddata',
# all
'json',
] + list(VAULT_SEARCH_METHODS_MAP.keys())
def _buildVaultQuery(myarg, query, corpusArgumentMap):
@@ -41831,12 +41840,14 @@ def _buildVaultQuery(myarg, query, corpusArgumentMap):
query['dataScope'] = 'ALL_DATA'
if myarg == 'corpus':
query['corpus'] = getChoice(corpusArgumentMap, mapChoice=True)
elif myarg == 'scope':
query['dataScope'] = getChoice(VAULT_EXPORT_DATASCOPE_MAP, mapChoice=True)
elif myarg in VAULT_SEARCH_METHODS_MAP:
if query.get('searchMethod'):
if query.get('method'):
Cmd.Backup()
usageErrorExit(Msg.MULTIPLE_SEARCH_METHODS_SPECIFIED.format(formatChoiceList(VAULT_SEARCH_METHODS_MAP)))
searchMethod = VAULT_SEARCH_METHODS_MAP[myarg]
query['searchMethod'] = searchMethod
query['method'] = searchMethod
if searchMethod == 'ACCOUNT':
query['accountInfo'] = {'emails': getNormalizedEmailAddressEntity()}
elif searchMethod == 'ORG_UNIT':
@@ -41851,8 +41862,8 @@ def _buildVaultQuery(myarg, query, corpusArgumentMap):
query['hangoutsChatInfo'] = {'roomId': roomIds}
elif searchMethod == 'SITES_URL':
query['sitesUrlInfo'] = {'urls': _getQueryList(Cmd.OB_URL_LIST)}
elif myarg == 'scope':
query['dataScope'] = getChoice(VAULT_EXPORT_DATASCOPE_MAP, mapChoice=True)
elif searchMethod == 'DRIVE_DOCUMENT':
query['driveDocumentInfo'] = {'documentIds': {'ids': _getQueryList(Cmd.OB_DRIVE_FILE_ID_LIST)}}
elif myarg == 'terms':
query['terms'] = getString(Cmd.OB_STRING)
elif myarg in {'start', 'starttime'}:
@@ -41891,50 +41902,73 @@ def _buildVaultQuery(myarg, query, corpusArgumentMap):
query['hangoutsChatOptions'] = {'includeRooms': getBoolean()}
# mail
elif myarg == 'excludedrafts':
query['mailOptions'] = {'excludeDrafts': getBoolean()}
query.setdefault('mailOptions', {})['excludeDrafts'] = getBoolean()
elif myarg == 'mailclientsideencryption':
query.setdefault('mailOptions', {})['clientSideEncryptedOption'] = getChoice(VAULT_CSE_OPTION_MAP, mapChoice=True)
# voice
elif myarg == 'covereddata':
query['voiceOptions'] = {'coveredData': getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)}
query.setdefault('voiceOptions', {'coveredData': []})
query['voiceOptions']['coveredData'].append(getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True))
# all
elif myarg == 'json':
jsonData = getJSON([])
if 'query' in jsonData:
query.update(jsonData['query'])
else:
query.update(jsonData)
def _validateVaultQuery(body, corpusArgumentMap):
if 'corpus' not in body['query']:
missingArgumentExit(f'corpus {formatChoiceList(corpusArgumentMap)}')
if 'searchMethod' not in body['query']:
if 'method' not in body['query']:
missingArgumentExit(formatChoiceList(VAULT_SEARCH_METHODS_MAP))
if 'exportOptions' in body:
for corpus, options in VAULT_CORPUS_OPTIONS_MAP.items():
if body['query']['corpus'] != corpus:
body['exportOptions'].pop(options, None)
# gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
# (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
# gam create vaultexport|export matter <MatterItem> [name <String>]
# vaultquery <QueryItem>
# [driveclientsideencryption any|encrypted|unencrypted]
# [includeaccessinfo <Boolean>]
# [excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
# [showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
# [format ics|mbox|pst|xml]
# [region any|europe|us] [showdetails|returnidonly]
# gam create vaultexport|export matter <MatterItem> [name <String>]
# corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
# [scope all_data|held_data|unprocessed_data]
# (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
# (documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
# (shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
# (rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
# (sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
# [scope <all_data|held_data|unprocessed_data>]
# [(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
# (sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
# [driveversiondate <Date>|<Time>]
# [includerooms <Boolean>]
# (rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
# [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
# [locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
# [responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
# [(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
# [driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
# (covereddata calllogs|textmessages|voicemails)*
# [<JSONData>]
# [driveclientsideencryption any|encrypted|unencrypted]
# [includerooms <Boolean>]
# [includeaccessinfo <Boolean>]
# [excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
# [showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
# [covereddata calllogs|textmessages|voicemails]
# [format ics|mbox|pst|xml]
# [region any|europe|us] [showdetails|returnidonly]
def doCreateVaultExport():
v = buildGAPIObject(API.VAULT)
matterId = None
body = {'query': {'dataScope': 'ALL_DATA'}, 'exportOptions': {}}
includeAccessInfo = None
exportFormat = None
formatLocation = None
useNewExport = None
showConfidentialModeContent = None
exportLinkedDriveFiles = None
returnIdOnly = showDetails = False
useNewExport = None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'matter':
@@ -41942,22 +41976,23 @@ def doCreateVaultExport():
body['matterId'] = matterId
elif myarg == 'name':
body['name'] = getString(Cmd.OB_STRING)
elif matterId is not None and myarg == 'vaultquery':
_, _, _, body['query'] = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
elif myarg in VAULT_QUERY_ARGS:
_buildVaultQuery(myarg, body['query'], VAULT_CORPUS_ARGUMENT_MAP)
elif myarg == 'includeaccessinfo':
includeAccessInfo = getBoolean()
elif myarg == 'format':
formatLocation = Cmd.Location()
exportFormat = getChoice(VAULT_EXPORT_FORMAT_MAP, mapChoice=True)
elif myarg == 'usenewexport':
useNewExport = getBoolean()
elif myarg == 'format':
exportFormat = getChoice(VAULT_EXPORT_FORMAT_MAP, mapChoice=True)
elif myarg == 'showconfidentialmodecontent':
showConfidentialModeContent = getBoolean()
elif myarg == 'exportlinkeddrivefiles':
exportLinkedDriveFiles = getBoolean()
elif myarg == 'region':
body['exportOptions']['region'] = getChoice(VAULT_EXPORT_REGION_MAP, mapChoice=True)
elif myarg == 'includeaccessinfo':
body['exportOptions'].setdefault('driveOptions', {})['includeAccessInfo'] = getBoolean()
elif myarg == 'covereddata':
body['exportOptions'].setdefault('voiceOptions', {})['coveredData'] = getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)
elif myarg == 'showdetails':
showDetails = True
returnIdOnly = False
@@ -41969,15 +42004,19 @@ def doCreateVaultExport():
if not matterId:
missingArgumentExit('matter')
_validateVaultQuery(body, VAULT_CORPUS_ARGUMENT_MAP)
if exportFormat is not None:
if not exportFormat in VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']]:
invalidChoiceExit(exportFormat, VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']], False)
elif body['query']['corpus'] != 'DRIVE':
exportFormat = VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']][0]
if 'name' not in body:
body['name'] = f'GAM {body["query"]["corpus"]} Export - {ISOformatTimeStamp(todaysTime())}'
optionsField = VAULT_CORPUS_OPTIONS_MAP[body['query']['corpus']]
if body['query']['corpus'] != 'DRIVE':
if body['query']['corpus'] == 'DRIVE':
if includeAccessInfo is not None:
body['exportOptions'][optionsField] = {'includeAccessInfo': includeAccessInfo}
else:
if exportFormat is not None:
if not exportFormat in VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']]:
Cmd.SetLocation(formatLocation)
invalidChoiceExit(exportFormat, VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']], False)
else:
exportFormat = VAULT_CORPUS_EXPORT_FORMATS[body['query']['corpus']][0]
body['exportOptions'][optionsField] = {'exportFormat': exportFormat}
if body['query']['corpus'] == 'MAIL':
if showConfidentialModeContent is not None:
@@ -42459,6 +42498,34 @@ def _showVaultHold(matterNameId, hold, cd, FJQC, k=0, kcount=0):
showJSON(None, hold, timeObjects=VAULT_HOLD_TIME_OBJECTS)
Ind.Decrement()
def _useVaultQueryForHold(v, matterId, matterNameId, body):
_, _, _, query = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
body['corpus'] = query['corpus']
method = query.get('method')
if method == 'ACCOUNT':
body['accounts'] = []
for email in query['accountInfo']['emails']:
body['accounts'].append({'email': email})
elif method == 'ORG_UNIT':
body['orgUnit'] = {'orgUnitId': query['orgUnitInfo']['orgUnitId']}
queryType = VAULT_CORPUS_QUERY_MAP[query['corpus']]
if queryType is None:
return
body['query'] = {queryType: {}}
if query['corpus'] == 'DRIVE':
body['query'][queryType]['includeSharedDriveFiles'] = query['driveOptions'].get('includeSharedDrives', False)
elif query['corpus'] in {'GROUPS', 'MAIL'}:
if query.get('terms'):
body['query'][queryType]['terms'] = query['terms']
if query.get('startTime'):
body['query'][queryType]['startTime'] = query['startTime']
if query.get('endTime'):
body['query'][queryType]['endTime'] = query['endTime']
elif query['corpus'] == 'HANGOUTS_CHAT':
body['query'][queryType]['includeRooms'] = query['hangoutsChatOptions'].get('includeRooms', False)
elif query['corpus'] == 'VOICE':
body['query'][queryType]['coveredData'] = query['voiceOptions']['coveredData']
def _getHoldQueryParameters(myarg, queryParameters):
if myarg == 'query':
queryParameters['queryLocation'] = Cmd.Location()
@@ -42474,7 +42541,8 @@ def _getHoldQueryParameters(myarg, queryParameters):
elif myarg in {'includeshareddrives', 'includeteamdrives'}:
queryParameters['includeSharedDriveFiles'] = getBoolean()
elif myarg == 'covereddata':
queryParameters['coveredData'] = getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)
queryParameters.setdefault('coveredData', [])
queryParameters['coveredData'].append(getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True))
else:
return False
return True
@@ -42509,7 +42577,11 @@ def _setHoldQuery(body, queryParameters):
if queryParameters.get('coveredData'):
body['query'][queryType]['coveredData'] = queryParameters['coveredData']
# gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
# gam create vaulthold|hold matter <MatterItem> [name <String>]
# vaultquery <QueryItem>
# [showdetails|returnidonly]
# gam create vaulthold|hold matter <MatterItem> [name <String>]
# corpus calendar|drive|mail|groups|hangouts_chat|voice
# [(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
# [query <QueryVaultCorpus>]
# [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
@@ -42523,13 +42595,16 @@ def doCreateVaultHold():
matterId = None
accounts = []
queryParameters = {}
returnIdOnly = showDetails = False
returnIdOnly = showDetails = usedVaultQuery = False
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'matter':
matterId, matterNameId = getMatterItem(v)
elif myarg == 'name':
body['name'] = getString(Cmd.OB_STRING)
elif matterId is not None and myarg == 'vaultquery':
_useVaultQueryForHold(v, matterId, matterNameId, body)
usedVaultQuery = True
elif myarg == 'corpus':
body['corpus'] = getChoice(VAULT_CORPUS_ARGUMENT_MAP, mapChoice=True)
elif myarg in {'accounts', 'users', 'groups'}:
@@ -42553,7 +42628,8 @@ def doCreateVaultHold():
missingArgumentExit(f'corpus {"|".join(VAULT_CORPUS_ARGUMENT_MAP)}')
if 'name' not in body:
body['name'] = f'GAM {body["corpus"]} Hold - {ISOformatTimeStamp(todaysTime())}'
_setHoldQuery(body, queryParameters)
if not usedVaultQuery:
_setHoldQuery(body, queryParameters)
if accounts:
body['accounts'] = []
cd = buildGAPIObject(API.DIRECTORY)
@@ -42986,6 +43062,116 @@ def _showVaultQuery(matterNameId, query, cd, drive, FJQC, k=0, kcount=0):
showJSON(None, query, timeObjects=VAULT_QUERY_TIME_OBJECTS)
Ind.Decrement()
def doCreateCopyVaultQuery(copyCmd):
v = buildGAPIObject(API.VAULT)
body = {'query': {'dataScope': 'ALL_DATA'}, 'displayName': ''}
matterId, matterNameId = getMatterItem(v)
if copyCmd:
_, queryName, _, body['query'] = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
targetId = None
cd = drive = None
FJQC = FormatJSONQuoteChar()
returnIdOnly = showDetails = False
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'name':
body['displayName'] = getString(Cmd.OB_STRING)
elif copyCmd and myarg == 'targetmatter':
targetId, targetNameId = getMatterItem(v)
elif not copyCmd and myarg in VAULT_QUERY_ARGS:
_buildVaultQuery(myarg, body['query'], VAULT_CORPUS_ARGUMENT_MAP)
elif myarg == 'shownames':
cd = buildGAPIObject(API.DIRECTORY)
_, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
if drive is None:
return
elif myarg == 'showdetails':
showDetails = True
returnIdOnly = False
elif myarg == 'returnidonly':
returnIdOnly = True
showDetails = False
else:
FJQC.GetFormatJSON(myarg)
if copyCmd:
if targetId is None:
targetId = matterId
targetNameId = matterNameId
if not body['displayName']:
body['displayName'] = f'Copy of {queryName}' if matterId == targetId else queryName
resultId = targetId
resultNameId = targetNameId
else:
_validateVaultQuery(body, VAULT_CORPUS_ARGUMENT_MAP)
if not body['displayName']:
body['displayName'] = 'GAM {body["query"]["corpus"]} Query - {ISOformatTimeStamp(todaysTime())}'
resultId = matterId
resultNameId = matterNameId
try:
result = callGAPI(v.matters().savedQueries(), 'create',
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT, GAPI.ALREADY_EXISTS],
matterId=resultId, body=body)
if not returnIdOnly:
if not FJQC.formatJSON:
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, formatVaultNameId(result['displayName'], result['savedQueryId'])])
if showDetails or FJQC.formatJSON:
_showVaultQuery(resultNameId, result, cd, drive, FJQC)
else:
writeStdout(f'{result["savedQueryId"]}\n')
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument, GAPI.alreadyExists) as e:
entityActionFailedWarning([Ent.VAULT_MATTER, resultNameId, Ent.VAULT_QUERY, body['displayName']], str(e))
# gam create vaultquery <MatterItem> [name <String>]
# corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
# [scope all_data|held_data|unprocessed_data]
# (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
# (documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
# (shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
# [(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
# (sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
# [driveversiondate <Date>|<Time>]
# [includerooms <Boolean>]
# (rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
# [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
# [locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
# [responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
# (covereddata calllogs|textmessages|voicemails)*
# [<JSONData>]
# [shownames]
# [showdetails|returnidonly|formatjson]
def doCreateVaultQuery():
doCreateCopyVaultQuery(False)
# gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
# [shownames]
# [showdetails|returnidonly|formatjson]
def doCopyVaultQuery():
doCreateCopyVaultQuery(True)
# gam delete vaultquery <QueryItem> matter <MatterItem>
# gam delete vaultquery <MatterItem> <QueryItem>
def doDeleteVaultQuery():
v = buildGAPIObject(API.VAULT)
if not Cmd.ArgumentIsAhead('matter'):
matterId, matterNameId = getMatterItem(v)
queryId, queryName, queryNameId, _ = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
else:
queryName = getString(Cmd.OB_QUERY_ITEM)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'matter':
matterId, matterNameId = getMatterItem(v)
queryId, queryName, queryNameId, _ = convertQueryNameToID(v, queryName, matterId, matterNameId)
else:
unknownArgumentExit()
try:
callGAPI(v.matters().savedQueries(), 'delete',
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
matterId=matterId, savedQueryId=queryId)
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId])
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
VAULT_QUERY_FIELDS_CHOICE_MAP = {
'createtime': 'createTime',
'displayname': 'displayName',
@@ -43006,7 +43192,7 @@ def doInfoVaultQuery():
v = buildGAPIObject(API.VAULT)
if not Cmd.ArgumentIsAhead('matter'):
matterId, matterNameId = getMatterItem(v)
queryId, queryName, queryNameId = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
queryId, queryName, queryNameId, _ = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
else:
queryName = getString(Cmd.OB_QUERY_ITEM)
cd = drive = None
@@ -43016,7 +43202,7 @@ def doInfoVaultQuery():
myarg = getArgument()
if myarg == 'matter':
matterId, matterNameId = getMatterItem(v)
queryId, queryName, queryNameId = convertQueryNameToID(v, queryName, matterId, matterNameId)
queryId, queryName, queryNameId, _ = convertQueryNameToID(v, queryName, matterId, matterNameId)
elif myarg == 'shownames':
cd = buildGAPIObject(API.DIRECTORY)
_, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
@@ -43471,14 +43657,16 @@ def doPrintShowVaultMatters():
PRINT_VAULT_COUNTS_TITLES = ['account', 'count', 'error']
# gam print vaultcounts [todrive <ToDriveAttributes>*]
# matter <MatterItem> corpus mail|groups
# (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
# (shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
# (rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
# (sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
# [scope <all_data|held_data|unprocessed_data>]
# matter <MatterItem> <QueryItem>
# [wait <Integer>]
# gam print vaultcounts [todrive <ToDriveAttributes>*]
# matter <MatterItem>
# corpus mail|groups
# [scope all_data|held_data|unprocessed_data]
# (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
# [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
# [excludedrafts <Boolean>]
# [<JSONData>]
# [wait <Integer>]
# gam print vaultcounts [todrive <ToDriveAttributes>*]
# matter <MatterItem> operation <String> [wait <Integer>]
@@ -43487,18 +43675,19 @@ def doPrintVaultCounts():
csvPF = CSVPrintFile(PRINT_VAULT_COUNTS_TITLES, 'sortall')
matterId = name = None
operationWait = 15
body = {'view': 'ALL'}
query = {}
body = {'view': 'ALL', 'query': {}}
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'matter':
matterId, _ = getMatterItem(v)
matterId, matterNameId = getMatterItem(v)
elif matterId is not None and myarg == 'vaultquery':
_, _, _, body['query'] = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
elif myarg == 'operation':
name = getString(Cmd.OB_STRING)
elif myarg in VAULT_QUERY_ARGS:
_buildVaultQuery(myarg, query, VAULT_COUNTS_CORPUS_ARGUMENT_MAP)
_buildVaultQuery(myarg, body['query'], VAULT_COUNTS_CORPUS_ARGUMENT_MAP)
elif myarg == 'wait':
operationWait = getInteger(minVal=1)
else:
@@ -43509,7 +43698,6 @@ def doPrintVaultCounts():
operation = {'name': name}
doWait = False
else:
body['query'] = query
_validateVaultQuery(body, VAULT_COUNTS_CORPUS_ARGUMENT_MAP)
try:
operation = callGAPI(v.matters(), 'count',
@@ -43533,7 +43721,7 @@ def doPrintVaultCounts():
doWait = True
response = operation.get('response', {})
query = operation['metadata']['query']
search_method = query.get('searchMethod')
search_method = query.get('method')
# ARGH count results don't include accounts with zero items.
# so we keep track of which accounts we searched and can report
# zero data for them.
@@ -45754,71 +45942,81 @@ def doPrintUsers(entityList=None):
csvPF.WriteRowNoFilter(row)
def _printUser(userEntity, i, count):
if isSuspended is None or isSuspended == userEntity.get('suspended', isSuspended):
if showValidColumn:
userEntity[showValidColumn] = True
userEmail = userEntity['primaryEmail']
if printOptions['emailParts']:
if userEmail.find('@') != -1:
userEntity['primaryEmailLocal'], userEntity['primaryEmailDomain'] = splitEmailAddress(userEmail)
if 'languages' in userEntity and not FJQC.formatJSON:
userEntity['languages'] = _formatLanguagesList(userEntity.pop('languages'), delimiter)
for location in userEntity.get('locations', []):
location['buildingName'] = _getBuildingNameById(cd, location.get('buildingId', ''))
if quotePlusPhoneNumbers:
for phone in userEntity.get('phones', []):
phoneNumber = phone.get('value', '')
if phoneNumber.startswith('+'):
phone['value'] = "'"+phoneNumber
if schemaParms['selectedSchemaFields']:
_filterSchemaFields(userEntity, schemaParms)
if printOptions['getGroupFeed']:
printGettingAllEntityItemsForWhom(Ent.GROUP_MEMBERSHIP, userEmail, i, count)
try:
groups = callGAPIpages(cd.groups(), 'list', 'groups',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
userKey=userEmail, orderBy='email', fields='nextPageToken,groups(email)')
numGroups = len(groups)
if not printOptions['groupsInColumns']:
userEntity['GroupsCount'] = numGroups
userEntity['Groups'] = delimiter.join([groupname['email'] for groupname in groups])
else:
if numGroups > printOptions['maxGroups']:
printOptions['maxGroups'] = numGroups
userEntity['Groups'] = numGroups
for j, group in enumerate(groups):
userEntity[f'Groups{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}{j}'] = group['email']
except (GAPI.invalidMember, GAPI.invalidInput):
badRequestWarning(Ent.GROUP, Ent.MEMBER, userEmail)
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
accessErrorExit(cd)
if aliasMatchPattern and 'aliases' in userEntity:
userEntity['aliases'] = [alias for alias in userEntity['aliases'] if aliasMatchPattern.match(alias)]
if printOptions['getLicenseFeed'] or printOptions['getLicenseFeedByUser']:
if printOptions['getLicenseFeed']:
u_licenses = licenses.get(userEmail.lower(), [])
if (isSuspended is None and isArchived is None):
showUser = True
elif (isSuspended is not None and isArchived is None):
showUser = isSuspended == userEntity.get('suspended', isSuspended)
elif (isSuspended is None and isArchived is not None):
showUser = isArchived == userEntity.get('archived', isArchived)
else:
showUser = ((isSuspended == userEntity.get('suspended', isSuspended)) or
(isArchived == userEntity.get('archived', isArchived)))
if not showUser:
return
if showValidColumn:
userEntity[showValidColumn] = True
userEmail = userEntity['primaryEmail']
if printOptions['emailParts']:
if userEmail.find('@') != -1:
userEntity['primaryEmailLocal'], userEntity['primaryEmailDomain'] = splitEmailAddress(userEmail)
if 'languages' in userEntity and not FJQC.formatJSON:
userEntity['languages'] = _formatLanguagesList(userEntity.pop('languages'), delimiter)
for location in userEntity.get('locations', []):
location['buildingName'] = _getBuildingNameById(cd, location.get('buildingId', ''))
if quotePlusPhoneNumbers:
for phone in userEntity.get('phones', []):
phoneNumber = phone.get('value', '')
if phoneNumber.startswith('+'):
phone['value'] = "'"+phoneNumber
if schemaParms['selectedSchemaFields']:
_filterSchemaFields(userEntity, schemaParms)
if printOptions['getGroupFeed']:
printGettingAllEntityItemsForWhom(Ent.GROUP_MEMBERSHIP, userEmail, i, count)
try:
groups = callGAPIpages(cd.groups(), 'list', 'groups',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
userKey=userEmail, orderBy='email', fields='nextPageToken,groups(email)')
numGroups = len(groups)
if not printOptions['groupsInColumns']:
userEntity['GroupsCount'] = numGroups
userEntity['Groups'] = delimiter.join([groupname['email'] for groupname in groups])
else:
u_licenses = getUserLicenses(lic, userEntity, skus)
if not oneLicensePerRow:
userEntity['LicensesCount'] = len(u_licenses)
if u_licenses:
userEntity['Licenses'] = delimiter.join(u_licenses)
userEntity['LicensesDisplay'] = delimiter.join([SKU.skuIdToDisplayName(skuId) for skuId in u_licenses])
if numGroups > printOptions['maxGroups']:
printOptions['maxGroups'] = numGroups
userEntity['Groups'] = numGroups
for j, group in enumerate(groups):
userEntity[f'Groups{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}{j}'] = group['email']
except (GAPI.invalidMember, GAPI.invalidInput):
badRequestWarning(Ent.GROUP, Ent.MEMBER, userEmail)
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
accessErrorExit(cd)
if aliasMatchPattern and 'aliases' in userEntity:
userEntity['aliases'] = [alias for alias in userEntity['aliases'] if aliasMatchPattern.match(alias)]
if printOptions['getLicenseFeed'] or printOptions['getLicenseFeedByUser']:
if printOptions['getLicenseFeed']:
u_licenses = licenses.get(userEmail.lower(), [])
else:
u_licenses = []
u_licenses = getUserLicenses(lic, userEntity, skus)
if not oneLicensePerRow:
_writeUserEntity(userEntity)
else:
userEntity['LicensesCount'] = len(u_licenses)
if u_licenses:
for skuId in u_licenses:
userEntity['License'] = skuId
userEntity['LicenseDisplay'] = SKU.skuIdToDisplayName(skuId)
_writeUserEntity(userEntity)
else:
userEntity['License'] = userEntity['LicenseDisplay'] = ''
userEntity['Licenses'] = delimiter.join(u_licenses)
userEntity['LicensesDisplay'] = delimiter.join([SKU.skuIdToDisplayName(skuId) for skuId in u_licenses])
else:
u_licenses = []
if not oneLicensePerRow:
_writeUserEntity(userEntity)
else:
if u_licenses:
for skuId in u_licenses:
userEntity['License'] = skuId
userEntity['LicenseDisplay'] = SKU.skuIdToDisplayName(skuId)
_writeUserEntity(userEntity)
else:
userEntity['License'] = userEntity['LicenseDisplay'] = ''
_writeUserEntity(userEntity)
def _updateDomainCounts(emailAddress):
nonlocal domainCounts
@@ -45911,10 +46109,10 @@ def doPrintUsers(entityList=None):
showDeleted = True
elif entityList is None and myarg == 'select':
_, entityList = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
elif myarg in SUSPENDED_ARGUMENTS:
isSuspended = _getIsSuspended(myarg)
elif myarg in ARCHIVED_ARGUMENTS:
isArchived = _getIsArchived(myarg)
elif myarg == 'issuspended':
isSuspended = getBoolean()
elif myarg == 'isarchived':
isArchived = getBoolean()
elif myarg == 'orderby':
orderBy, sortOrder = getOrderBySortOrder(USERS_ORDERBY_CHOICE_MAP)
elif myarg == 'userview':
@@ -46092,6 +46290,8 @@ def doPrintUsers(entityList=None):
# If no individual fields were specified (allfields, basic, full) or individual fields other than primaryEmail were specified, look up each user
if isSuspended is not None and fieldsList:
fieldsList.append('suspended')
if isArchived is not None and fieldsList:
fieldsList.append('archived')
if projectionSet or len(set(fieldsList)) > 1 or showValidColumn:
jcount = len(entityList)
fields = getFieldsFromFieldsList(fieldsList)
@@ -49273,6 +49473,16 @@ def doPrintCourseWM(entityIDType, entityStateType):
pass
return topicNames
def _printCourseWMrow(course, courseWM):
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects,
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'],
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects),
ensure_ascii=False, sort_keys=True)})
def _printCourseWM(course, courseWM, i, count):
if applyCourseItemFilter and not _courseItemPassesFilter(courseWM, courseItemFilter):
return
@@ -49284,14 +49494,13 @@ def doPrintCourseWM(entityIDType, entityStateType):
topicId = courseWM.get('topicId')
if topicId:
courseWM['topicName'] = topicNames.get(topicId, topicId)
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects,
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'],
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects),
ensure_ascii=False, sort_keys=True)})
if not oneItemPerRow or not courseWM.get('materials', []):
_printCourseWMrow(course, courseWM)
else:
courseMaterials = courseWM.pop('materials')
for courseMaterial in courseMaterials:
courseWM['materials'] = courseMaterial
_printCourseWMrow(course, courseWM)
croom = buildGAPIObject(API.CLASSROOM)
if entityIDType == Ent.COURSE_WORK_ID:
@@ -49329,7 +49538,7 @@ def doPrintCourseWM(entityIDType, entityStateType):
courseShowProperties = _initCourseShowProperties(['name'])
OBY = OrderBy(OrderbyChoiceMap)
creatorEmails = {}
showCreatorEmail = showTopicNames = False
oneItemPerRow = showCreatorEmail = showTopicNames = False
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
countsOnly = showStudentsAsList = False
while Cmd.ArgumentsRemaining():
@@ -49346,6 +49555,9 @@ def doPrintCourseWM(entityIDType, entityStateType):
pass
elif myarg == 'orderby':
OBY.GetChoice()
elif myarg == 'oneitemperrow':
oneItemPerRow = True
csvPF.RemoveIndexedTitles('materials')
elif myarg in {'showcreatoremails', 'creatoremail'}:
showCreatorEmail = True
elif myarg == 'showtopicnames':
@@ -49426,6 +49638,7 @@ def doPrintCourseWM(entityIDType, entityStateType):
# (orderby <CourseMaterialsOrderByFieldName> [ascending|descending])*)
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [oneitemperrow]
# [countsonly] [formatjson [quotechar <Character>]]
def doPrintCourseMaterials():
doPrintCourseWM(Ent.COURSE_MATERIAL_ID, Ent.COURSE_MATERIAL_STATE)
@@ -49437,6 +49650,7 @@ def doPrintCourseMaterials():
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
# [showstudentsaslist [<Boolean>]] [delimiter <Character>]
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [oneitemperrow]
# [countsonly] [formatjson [quotechar <Character>]]
def doPrintCourseWork():
doPrintCourseWM(Ent.COURSE_WORK_ID, Ent.COURSE_WORK_STATE)
@@ -77912,6 +78126,7 @@ MAIN_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_VAULTEXPORT: doCreateVaultExport,
Cmd.ARG_VAULTHOLD: doCreateVaultHold,
Cmd.ARG_VAULTMATTER: doCreateVaultMatter,
Cmd.ARG_VAULTQUERY: doCreateVaultQuery,
Cmd.ARG_VERIFY: doCreateSiteVerification,
}
@@ -77969,6 +78184,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
{Cmd.ARG_SHAREDDRIVEACLS: doCopySyncSharedDriveACLs,
Cmd.ARG_STORAGEBUCKET: doCopyCloudStorageBucket,
Cmd.ARG_VAULTEXPORT: doCopyVaultExport,
Cmd.ARG_VAULTQUERY: doCopyVaultQuery,
}
),
'create':
@@ -78033,6 +78249,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_VAULTEXPORT: doDeleteVaultExport,
Cmd.ARG_VAULTHOLD: doDeleteVaultHold,
Cmd.ARG_VAULTMATTER: doDeleteVaultMatter,
Cmd.ARG_VAULTQUERY: doDeleteVaultQuery,
}
),
'download':

View File

@@ -69,6 +69,8 @@ CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
CHANNEL_CUSTOMER_ID = 'channel_customer_id'
# Character set of batch, csv, data files
CHARSET = 'charset'
# When retrieving lists of Chat items from API, how many should be retrieved in each chunk
CHAT_MAX_RESULTS = 'chat_max_results'
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
CLASSROOM_MAX_RESULTS = 'classroom_max_results'
# Path to client_secrets.json
@@ -335,6 +337,7 @@ Defaults = {
CACHE_DISCOVERY_ONLY: TRUE,
CHARSET: DEFAULT_CHARSET,
CHANNEL_CUSTOMER_ID: '',
CHAT_MAX_RESULTS: '100',
CLASSROOM_MAX_RESULTS: '0',
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
CLOCK_SKEW_IN_SECONDS: '10',
@@ -502,6 +505,7 @@ VAR_INFO = {
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
CHAT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},

View File

@@ -1216,6 +1216,7 @@ class GamCLArgs():
OB_DOMAIN_NAME_LIST = 'DomainNameList'
OB_DRIVE_FILE_ENTITY = 'DriveFileEntity'
OB_DRIVE_FILE_ID = 'DriveFileID'
OB_DRIVE_FILE_ID_LIST = 'DriveFileIDList'
OB_DRIVE_FILE_NAME = 'DriveFileName'
OB_DRIVE_FILE_PERMISSION_ENTITY = 'DriveFilePermissionEntity'
OB_DRIVE_FILE_PERMISSION_ID = 'DriveFilePermissionID'

View File

@@ -96,6 +96,7 @@ class GamEntity():
CHAT_MEMBER_USER = 'chmu'
CHAT_MESSAGE = 'chms'
CHAT_MESSAGE_ID = 'chmi'
CHAT_OWNER_USER = 'chou'
CHAT_SPACE = 'chsp'
CHAT_THREAD = 'chth'
CHILD_ORGANIZATIONAL_UNIT = 'corg'
@@ -462,6 +463,7 @@ class GamEntity():
CHAT_MEMBER: ['Chat Members', 'Chat Member'],
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
CHAT_OWNER_USER: ['Chat User Owners', 'Chat User Owner'],
CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],

View File

@@ -462,6 +462,7 @@
See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryItem> ::= <UniqueID>|<String>
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String>

View File

@@ -10,9 +10,92 @@ 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
### 7.22.01
### 7.23.00
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed.
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
### 7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
Added option `<JSONData>` to `gam create vaultexport|vaultquery and `gam print vaultcounts``.
### 7.22.06
Added commands to create, copy and delete Vault saved queries.
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[shownames] [formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem"] [name <String>]
[shownames] [formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
Added a variant of `gam print vaultcounts` that gets its query parameters from a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
### 7.22.05
Added a variant of `gam create vaultexport` that gets its query parameters from a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
### 7.22.04
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
```
gam create vaulthold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
### 7.22.03
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
from a field name to a query option; it is now correctly interpreted as a field name.
### 7.22.02
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
by including the pysocks library needed by the latest httplib2 library.
### 7.22.00

View File

@@ -252,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$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.22.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64

View File

@@ -43,6 +43,7 @@
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*"
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*"

View File

@@ -378,7 +378,7 @@ Select the users for whom information is desired.
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the randaom
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the random
doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data.
Specify the report date; the default is today's date.

View File

@@ -570,17 +570,12 @@ gam config auto_batch_min 1 csv_output_row_filter "owners.0.emailAddress:notrege
### Multiple parents
No existing parents are copied for source top/sub files/folders.
### Removed options
The following options will generate an error; they were removed in 6.23.00:
* `copysubfileparents` and `copysubfolderparents`.
### Move Folder Permissions
When a folder is moved by recreating it, its permissions are not copied; these options control copying permissions for folders.
When a folder is moved by recreating it, its permissions are not copied by the Drive API; these options control copying permissions for folders.
For options of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
When recreated, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions;
The default values of options introduced in version 6.14.00 are set to match the behavior of earlier versions.
When `mergewithparent` is `true`:
* `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
@@ -594,7 +589,7 @@ When `duplicatefolders` is `merge` and a sub folder is a duplicate:
* `copymergedsubfolderpermissions false` - The permissions of the source sub folder are not not copied to the target folder.
* `copymergedsubfolderpermissions true` - The permissions of the source sub folder are copied to the target folder; this is the default action.
When `duplicatefolders` is `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
When `duplicatefolders` is `merge` or `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
* `copytopfolderpermissions true` - The permissions of the source top folder are copied to the target folder; this is the default action.
* `copytopfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder.
* `copysubfolderpermissions true` - The permissions of the source sub folders are copied to the target folder; this is the default action.

View File

@@ -29,6 +29,7 @@
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
@@ -424,12 +425,12 @@ gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv mult
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add My Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
### Shared Drives
@@ -447,12 +448,12 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add Shared Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
## Remove ACLs for all users-groups in external domains
@@ -469,18 +470,22 @@ Replace `<Types>` as required:
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm notrole owner <Types> <Domains> em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add My Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
### Shared Drives
@@ -499,18 +504,22 @@ Replace `<Types>` as required:
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename pm <Types> <Domains> inherited false em pmfilter oneitemperrow
```
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add Shared Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
## Remove domainCanFind-domainWithLink ACLs for internal domain
@@ -529,7 +538,7 @@ gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv mult
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
### Shared Drives
@@ -546,7 +555,7 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
## Remove My Drive ACLs for external domains
@@ -558,13 +567,17 @@ Get My Drive ACLs sharing to external domain(s)
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm type domain <Domains> em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
## Remove anyoneCanFind-anyoneWithLink ACLs
@@ -583,7 +596,7 @@ gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv mult
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
### Shared Drives
@@ -599,5 +612,5 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```

View File

@@ -3,6 +3,7 @@
- [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Vault Matters](#vault-matters)
- [Create Vault Matters](#create-vault-matters)
- [Manage Vault Matters](#manage-vault-matters)
@@ -21,6 +22,9 @@
- [Display Vault Holds](#display-vault-holds)
- [Display Vault Holds Affecting a User](#display-vault-holds-affecting-a-user)
- [Vault Saved Queries](#vault-saved-queries)
- [Create Vault Saved Queries](#create-vault-saved-queries)
- [Copy Vault Saved Queries](#copy-vault-saved-queries)
- [Delete Vault Saved Queries](#delete-vault-saved-queries)
- [Display Vault Saved Queries](#display-vault-saved-queries)
- [Takeout](#takeout)
- [Copy a Takeout Bucket](#copy-a-takeoutbucket)
@@ -54,6 +58,7 @@
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String>
@@ -66,13 +71,17 @@
<ChatSpace> ::= spaces/<String> | space/<String> | <String>
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<DriveFileID> ::= <String>
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<ExportItem> ::= <UniqueID>|<String>
<ExportStatus> ::= completed|failed|inprogrsss
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
<HoldItem> ::= <UniqueID>|<String>
<MatterItem> ::= <UniqueID>|<String>
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterState> ::= open|closed|deleted
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<QueryItem> ::= <UniqueID>|<String>
<SharedDriveID> ::= <String>
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
<URL> ::= <String>
@@ -135,9 +144,29 @@
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*"
```
You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name,
GAM has to make additional API calls to convert the name to an ID.
## Special quoting
You specify a single matter with `matter <MatterItem>` and a list of matters with `matters <MatterItemList>`.
As matter names can contain spaces, some care must be used when entering `<MatterItem>` and `<MatterItemList>` with names.
Suppose you have a matter `Foo Bar`. To get information about a specific export: `gam info vaultexport "Foo Bar" <ExportItem>`
The shell strips the `"` leaving a single argument `Foo Bar`; gam correctly processes the argument.
Suppose you enter the command: `gam show vaultexports matters "Foo Bar"`
The shell strips the `"` leaving a single argument `Foo Bar`; gam splits the argument on space leaving two items and then tries to process `Foo` and `Bar`, not what you want.
You must enter: `gam info show vaultexports matters "'Foo Bar'"`
The shell strips the `"` leaving a single argument `'Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `Foo Bar` and correctly processes the item.
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
## Vault Matters
## Create Vault Matters
Create a Google Vault matter.
@@ -201,11 +230,18 @@ Select fields to display:
* `fields <VaultMatterFieldNameList>` - Display selected fields; `matterId` and `name` are always displayed
## Display Vault Counts
Display item counts retained in Vault for the given users or groups.
### Display item counts retained in Vault using a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
### Display item counts retained in Vault for the given users or groups.
* The required argument `matter` specifies the matter name or ID (prefix with id:) where the count should be performed.
* The required argument `corpus` specifies whether Gmail mailbox data or Google Groups archives are queried.
* You need to specify one argument of accounts, orgunit or everyone to determine which users/groups to query.
* The `scope` argument specifies the data to be queried, `all_data` is the default and is recommended.
* You need to specify one argument of accounts, orgunit or everyone to determine which users/groups to query.
The command may take some time to complete; GAM makes repeated API calls until the operation is complete. By default,
GAM waits 15 seconds between API calls; use the `wait <Integer>` option to specify a different wait period.
@@ -213,26 +249,28 @@ GAM waits 15 seconds between API calls; use the `wait <Integer>` option to speci
This command can be useful for discovering legacy former employee accounts which no longer have any mail data retained by Vault.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> corpus mail|groups
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
[(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))]
[scope <all_data|held_data|unprocessed_data>]
matter <MatterItem>
corpus mail|groups
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>]
```
Specify the search method, this is optional:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Search for all accounts in the Shared Drives specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites in `<URLList>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>`
* `everyone|entireorg` - Search for all accounts in the organization
For `corpus mail|group`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For `corpus mail|group`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
You can specify query options with `<JSONData>`.
Check the status of a previous count operation with the name from a previous command.
```
@@ -242,32 +280,48 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
## Vault Exports
## Create Vault Exports
Create a Google Vault export request.
### Create a Google Vault export request using a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
Create a Google Vault export request by specifying the query parameters.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[driveclientsideencryption any|encrypted|unencrypted]
[includerooms <Boolean>]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[covereddata calllogs|textmessages|voicemails]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
<MatterItem> specifies the matter name or ID the export should be associated with.
Specify the name of the export:
* `name <String>` - The export will be named `<String>`
* `default` - The export will be named `GAM <corpus> Export - <Time>`
If `name <String>` is omitted, the export will be named `GAM <corpus> Export - <Time>`
## Vault Query options
Specify the corpus of data, this option is required:
* `calendar`
@@ -281,13 +335,15 @@ Specify the corpus of data, this option is required:
Specify the search method, this option is required:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization
* `everyone|entireorg` - Search for all accounts in the organization
* `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>`
* `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>`
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Search for all accounts in the Shared Drives specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites in `<URLList>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
Specify the scope of data to include in the export:
* `all_data` - All available data; this is the default
@@ -320,10 +376,6 @@ For `corpus calendar`, you can specify advanced search options:
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
* Enter the date in UTC.
For `corpus calendar`, you can specify the format of the exported data:
* `format ics` - Export in ICS format, this is the default
* `format pst` - Export in PST format
For `corpus drive`, you can specify advanced search options:
* `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date.
* `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member`
@@ -331,6 +383,16 @@ For `corpus drive`, you can specify advanced search options:
* `sharedrivesoption included` - Resources in shared drives are included in the search
* `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default
* `sharedrivesoption not_included` - Resources in shared drives are not included in the search
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
You can specify query options with `<JSONData>`.
## Vault Export options
For `corpus drive`, you can specify advanced search options:
* `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default.
* `driveclientsideencryption encrypted` - Include client-side encrypted content only in search.
* `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search.
@@ -339,10 +401,6 @@ For `corpus drive`, you can specify whether to include access information for us
* `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default
* `includeaccessinfo True` - Include access information for users with indirect access
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For `corpus mail`, you can specify advanced search options:
* `excludedrafts False` - Do not exclude drafts, this is the default
* `excludedrafts True` - Exclude drafts
@@ -365,18 +423,18 @@ For `corpus mail`, you can specify whether to enable exporting linked Drive file
See: https://support.google.com/vault/answer/4388708#new_gmail_export&zippy=%2Cfebruary-new-gmail-export-system-available
For `corpus calendar`, you can specify the format of the exported data:
* `format ics - Export in ICS format, this is the default
* `format ics` - Export in ICS format, this is the default
* `format pst` - Export in PST format
For `corpus drive`, you can not specify the format of the exported data,
For `corpus gemini`, `format xml` is the only format of the exported data,
For `corpus gemini`, `format xml` is the only supported format of the exported data,
For `corpus groups`, `corpus hangouts_chat`, `corpus mail` and `corpus voice`, you can specify the format of the exported data:
* `format mbox` - Export in MBOX format, this is the default
* `format pst` - Export in PST format
For `corpus voice` you can specify thet data covered by the export:
For `corpus voice` you can specify the data covered by the export, multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -606,13 +664,29 @@ The `shownames` argument controls whether account and org unit names are display
## Vault Holds
## Create Vault Holds
### Create a hold from a saved Vault query.
```
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
gam create vaulthold|hold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
Specify the name of the hold:
* `name <String>` - The hold will be named `<String>`
* `default` - The hold will be named `GAM <corpus> Hold - <Time>`
Use the `showdetails` option to have the full details of the hold displayed.
Use the `returnidonly` option to have only the hold ID displayed.
### Create a hold from parameters.
```
gam create vaulthold|hold matter <MatterItem> [name <String>]
corpus calendar|drive|mail|groups|hangouts_chat|voice
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails]
(covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails|returnidonly]
```
@@ -638,10 +712,10 @@ For `corpus drive`, you can specify advanced search options:
* `includeshareddrives False` - Files in shared drives are not included in the hold, this is the default
* `includeshareddrives True` - Files in shared drives are included in the hold
For `corpus mail`, you can specify search terms to limit the search.
For `corpus mail|group`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For `corpus mail`, you can specify time limits on the search:
For `corpus mail|group`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
@@ -649,7 +723,8 @@ For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For `corpus voice` you can specify the data covered by the hold:
For `corpus voice` you can specify the data covered by the hold,
multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -665,7 +740,7 @@ gam update vaulthold|hold <HoldItem> matter <MatterItem>
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails]
(covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails]
```
@@ -673,10 +748,10 @@ For a hold with `corpus drive`, you can specify advanced search options:
* `includeshareddrives False` - Files in shared drives are not included in the hold, this is the default
* `includeshareddrives True` - Files in shared drives are included in the hold
For a hold with `corpus mail`, you can specify search terms to limit the search.
For a hold with `corpus mail|groups`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For a hold with `corpus mail`, you can specify time limits on the search:
For a hold with `corpus mai|groupsl`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
@@ -684,7 +759,8 @@ For a hold with `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For a hold with `corpus voice` you can specify the data covered by the hold:
For a hold with `corpus voice` you can specify the data covered by the hold,
multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -752,6 +828,67 @@ gam <UserTypeEntity> show vaultholds|holds
```
## Vault Saved Queries
## Create Vault Saved Queries
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[shownames]
[showdetails|returnidonly|formatjson]
``
If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>`
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
See: [Vault Query options](#vault-query-options)
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Copy Vault Saved Queries
```
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames]
[showdetails|returnidonly|formatjson]
```
If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter.
If `name <String>` is omitted:
* `targetmatter <MatterItem>` specified - The copied query has the same name as the source query
* `targetmatter <MatterItem>` omitted - The copied query is named `Copy of Source Query name`
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Delete Vault Saved Queries
```
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
## Display Vault Saved Queries
```
gam info vaultquery <QueryItem> matter <MatterItem>

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAM 7.22.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.22.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64
@@ -27,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
```
gam version extended
GAM 7.22.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64

View File

@@ -180,29 +180,3 @@ Service Account Access
* [Users - Tasks](Users-Tasks)
* [Users - YouTube](Users-YouTube)
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites)
GAM Tutorials
* [Account Auditing](l-ExamplesAccountAuditing)
* [Calendar Settings](l-CalendarExamples)
* [Chat Bot commands](Chat-Bot)
* [Chrome Browser Management](l-Chrome-Browser-Management)
* [Chrome Policy Settings](l-Chrome-Policy-Settings)
* [Context Aware Access levels](Context-Aware-Access-Levels)
* [Data Transfers](l-Data-Transfers)
* [Domain Verification](l-DomainVerification)
* [Google Drive Management](l-GoogleDriveManagement)
* [Group Settings](l-GAM3GroupSettings)
* [Inbound SSO Settings](l-Inbound-SSO-Settings)
* [Managing Admins](l-Managing-Admins)
* [Managing Classroom](l-Managing-Google-Classroom)
* [Managing Custom User Schemas](l-Custom-Schemas)
* [Managing Devices](l-Managing-Devices)
* [Managing Organizations](l-ExamplesOrganizations)
* [Managing Product Licenses](l-LicenseExamples)
* [Managing Users, Groups, Aliases, Domains, Mobile and Chrome Devices, and Resource Calendars](l-GAM3DirectoryCommands)
* [OAuth Authentication Related Commands](l-OAuthKeyManagement)
* [Print Users, Groups, Aliases, Mobile and Chrome OS devices, OUs, Licenses and Reports](l-GAM3CSVListings)
* [Printers](l-Printers)
* [Unmanaged Users and Invitations](l-UnmanagedUsersExamples)
* [User Email Settings](l-ExamplesEmailSettings)
* [User Security Settings](l-SecurityExamples)

View File

@@ -109,6 +109,11 @@ charset
Character set of gam batch, gam csv, gam loop files.
Default: utf-8
Environment variable: GAM_CHARSET
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
classroom_max_results
When retrieving lists of Google Classroom items from API,
how many should be retrieved in each API call