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

View File

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

View File

@@ -69,6 +69,8 @@ CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
CHANNEL_CUSTOMER_ID = 'channel_customer_id' CHANNEL_CUSTOMER_ID = 'channel_customer_id'
# Character set of batch, csv, data files # Character set of batch, csv, data files
CHARSET = 'charset' 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 # When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
CLASSROOM_MAX_RESULTS = 'classroom_max_results' CLASSROOM_MAX_RESULTS = 'classroom_max_results'
# Path to client_secrets.json # Path to client_secrets.json
@@ -335,6 +337,7 @@ Defaults = {
CACHE_DISCOVERY_ONLY: TRUE, CACHE_DISCOVERY_ONLY: TRUE,
CHARSET: DEFAULT_CHARSET, CHARSET: DEFAULT_CHARSET,
CHANNEL_CUSTOMER_ID: '', CHANNEL_CUSTOMER_ID: '',
CHAT_MAX_RESULTS: '100',
CLASSROOM_MAX_RESULTS: '0', CLASSROOM_MAX_RESULTS: '0',
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON, CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
CLOCK_SKEW_IN_SECONDS: '10', 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)}, 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)}, CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, 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)}, 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}, 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)}, 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_DOMAIN_NAME_LIST = 'DomainNameList'
OB_DRIVE_FILE_ENTITY = 'DriveFileEntity' OB_DRIVE_FILE_ENTITY = 'DriveFileEntity'
OB_DRIVE_FILE_ID = 'DriveFileID' OB_DRIVE_FILE_ID = 'DriveFileID'
OB_DRIVE_FILE_ID_LIST = 'DriveFileIDList'
OB_DRIVE_FILE_NAME = 'DriveFileName' OB_DRIVE_FILE_NAME = 'DriveFileName'
OB_DRIVE_FILE_PERMISSION_ENTITY = 'DriveFilePermissionEntity' OB_DRIVE_FILE_PERMISSION_ENTITY = 'DriveFilePermissionEntity'
OB_DRIVE_FILE_PERMISSION_ID = 'DriveFilePermissionID' OB_DRIVE_FILE_PERMISSION_ID = 'DriveFilePermissionID'

View File

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

View File

@@ -462,6 +462,7 @@
See: https://support.google.com/mail/answer/7190 See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String> <QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryItem> ::= <UniqueID>|<String>
<QueryMemberRestrictions> ::= <String> <QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String> <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 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 ### 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$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64 MacOS Sequoia 15.6.1 x86_64

View File

@@ -43,6 +43,7 @@
<DomainNameList> ::= "<DomainName>(,<DomainName>)*" <DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*" <DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*" <DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*"
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*" <DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*" <DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*" <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>` * `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 * `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. 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. 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 ### Multiple parents
No existing parents are copied for source top/sub files/folders. 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 ### 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. 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; 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`: 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. * `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 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. * `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 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. * `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. * `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>)+ <DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName> <EmailAddress> ::= <String>@<DomainName>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<UniqueID> ::= id:<String> <UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<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. 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. 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 ### Shared Drives
@@ -447,12 +448,12 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs. 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. 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 ## 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) Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain * `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains * `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 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. 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. 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 ### Shared Drives
@@ -499,18 +504,22 @@ Replace `<Types>` as required:
Replace `<Domains>` with specification of external domain(s) Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain * `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains * `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 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. 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. 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 ## 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. 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 ### Shared Drives
@@ -546,7 +555,7 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs. 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 ## 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) Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain * `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains * `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 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. 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 ## 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. 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 ### Shared Drives
@@ -599,5 +612,5 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs. 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) - [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function - [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions) - [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Vault Matters](#vault-matters) - [Vault Matters](#vault-matters)
- [Create Vault Matters](#create-vault-matters) - [Create Vault Matters](#create-vault-matters)
- [Manage Vault Matters](#manage-vault-matters) - [Manage Vault Matters](#manage-vault-matters)
@@ -21,6 +22,9 @@
- [Display Vault Holds](#display-vault-holds) - [Display Vault Holds](#display-vault-holds)
- [Display Vault Holds Affecting a User](#display-vault-holds-affecting-a-user) - [Display Vault Holds Affecting a User](#display-vault-holds-affecting-a-user)
- [Vault Saved Queries](#vault-saved-queries) - [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) - [Display Vault Saved Queries](#display-vault-saved-queries)
- [Takeout](#takeout) - [Takeout](#takeout)
- [Copy a Takeout Bucket](#copy-a-takeoutbucket) - [Copy a Takeout Bucket](#copy-a-takeoutbucket)
@@ -54,6 +58,7 @@
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*" <EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<TimeZone> ::= <String> <TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String> <UniqueID> ::= id:<String>
@@ -66,13 +71,17 @@
<ChatSpace> ::= spaces/<String> | space/<String> | <String> <ChatSpace> ::= spaces/<String> | space/<String> | <String>
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*" <ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<DriveFileID> ::= <String>
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<ExportItem> ::= <UniqueID>|<String> <ExportItem> ::= <UniqueID>|<String>
<ExportStatus> ::= completed|failed|inprogrsss <ExportStatus> ::= completed|failed|inprogrsss
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*" <ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
<HoldItem> ::= <UniqueID>|<String> <HoldItem> ::= <UniqueID>|<String>
<MatterItem> ::= <UniqueID>|<String> <MatterItem> ::= <UniqueID>|<String>
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterState> ::= open|closed|deleted <MatterState> ::= open|closed|deleted
<MatterStateList> ::= "<MatterState>(,<MatterState>)*" <MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<QueryItem> ::= <UniqueID>|<String>
<SharedDriveID> ::= <String> <SharedDriveID> ::= <String>
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*" <SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
<URL> ::= <String> <URL> ::= <String>
@@ -135,9 +144,29 @@
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*" <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, 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. 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 ## Vault Matters
## Create Vault Matters ## Create Vault Matters
Create a Google Vault matter. Create a Google Vault matter.
@@ -201,11 +230,18 @@ Select fields to display:
* `fields <VaultMatterFieldNameList>` - Display selected fields; `matterId` and `name` are always displayed * `fields <VaultMatterFieldNameList>` - Display selected fields; `matterId` and `name` are always displayed
## Display Vault Counts ## 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 `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. * 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. * 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, 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. 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. 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>*] gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> corpus mail|groups matter <MatterItem>
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone corpus mail|groups
[(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) | [scope all_data|held_data|unprocessed_data]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) | (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))]
[scope <all_data|held_data|unprocessed_data>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>] [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>] [excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>] [wait <Integer>]
``` ```
Specify the search method, this is optional: Specify the search method, this is optional:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>` * `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>` * `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
* `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>` For `corpus mail|group`, you can specify search terms to limit the search.
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>` * `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
* `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>` For `corpus mail|group`, you can specify time limits on the search:
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>` * `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. 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 ## Vault Exports
## Create 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 gam create vaultexport|export matter <MatterItem> [name <String>]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone vaultquery <QueryItem>
(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) | [driveclientsideencryption any|encrypted|unencrypted]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) | [includeaccessinfo <Boolean>]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>))) [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] [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>] [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>] [locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>] [responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)] (covereddata calllogs|textmessages|voicemails)*
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>] [<JSONData>]
[driveclientsideencryption any|encrypted|unencrypted] [driveclientsideencryption any|encrypted|unencrypted]
[includerooms <Boolean>] [includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted] [excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>] [showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[covereddata calllogs|textmessages|voicemails]
[format ics|mbox|pst|xml] [format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly] [region any|europe|us] [showdetails|returnidonly]
``` ```
<MatterItem> specifies the matter name or ID the export should be associated with. <MatterItem> specifies the matter name or ID the export should be associated with.
Specify the name of the export: If `name <String>` is omitted, the export will be named `GAM <corpus> Export - <Time>`
* `name <String>` - The export will be named `<String>`
* `default` - The export will be named `GAM <corpus> Export - <Time>` ## Vault Query options
Specify the corpus of data, this option is required: Specify the corpus of data, this option is required:
* `calendar` * `calendar`
@@ -281,13 +335,15 @@ Specify the corpus of data, this option is required:
Specify the search method, this option is required: Specify the search method, this option is required:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>` * `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>` * `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 <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>` * `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 in `<URLList>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>` * `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: Specify the scope of data to include in the export:
* `all_data` - All available data; this is the default * `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. * 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. * 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: 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. * `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` * `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` - 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 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 * `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 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 encrypted` - Include client-side encrypted content only in search.
* `driveclientsideencryption unencrypted` - Include client-side unencrypted 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 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 * `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: For `corpus mail`, you can specify advanced search options:
* `excludedrafts False` - Do not exclude drafts, this is the default * `excludedrafts False` - Do not exclude drafts, this is the default
* `excludedrafts True` - Exclude drafts * `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 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: 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 * `format pst` - Export in PST format
For `corpus drive`, you can not specify the format of the exported data, 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: 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 mbox` - Export in MBOX format, this is the default
* `format pst` - Export in PST format * `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 calllogs` - Call logs
* `covereddata textmessages` - Voice text messages * `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail * `covereddata voicemail` - Voicemail
@@ -606,13 +664,29 @@ The `shownames` argument controls whether account and org unit names are display
## Vault Holds ## Vault Holds
## Create 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>)] [(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>] [query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>] [includeshareddrives <Boolean>]
[showdetails|returnidonly] [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 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 * `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) * `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. * `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. * `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 False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms * `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 calllogs` - Call logs
* `covereddata textmessages` - Voice text messages * `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail * `covereddata voicemail` - Voicemail
@@ -665,7 +740,7 @@ gam update vaulthold|hold <HoldItem> matter <MatterItem>
[query <QueryVaultCorpus>] [query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>] [includeshareddrives <Boolean>]
[showdetails] [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 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 * `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) * `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. * `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. * `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 False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms * `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 calllogs` - Call logs
* `covereddata textmessages` - Voice text messages * `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail * `covereddata voicemail` - Voicemail
@@ -752,6 +828,67 @@ gam <UserTypeEntity> show vaultholds|holds
``` ```
## Vault Saved Queries ## 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 ## Display Vault Saved Queries
``` ```
gam info vaultquery <QueryItem> matter <MatterItem> gam info vaultquery <QueryItem> matter <MatterItem>

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 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 Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 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 Print the current version of Gam with extended details and SSL information
``` ```
gam version extended 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 macOS Sequoia 15.7 x86_64

View File

@@ -180,29 +180,3 @@ Service Account Access
* [Users - Tasks](Users-Tasks) * [Users - Tasks](Users-Tasks)
* [Users - YouTube](Users-YouTube) * [Users - YouTube](Users-YouTube)
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites) * [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. Character set of gam batch, gam csv, gam loop files.
Default: utf-8 Default: utf-8
Environment variable: GAM_CHARSET 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 classroom_max_results
When retrieving lists of Google Classroom items from API, When retrieving lists of Google Classroom items from API,
how many should be retrieved in each API call how many should be retrieved in each API call