gam7 7.22.0__tar.gz → 7.22.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of gam7 might be problematic. Click here for more details.

Files changed (305) hide show
  1. {gam7-7.22.0 → gam7-7.22.4}/.github/workflows/build.yml +15 -14
  2. {gam7-7.22.0 → gam7-7.22.4}/.github/workflows/pushwiki.yml +1 -1
  3. {gam7-7.22.0 → gam7-7.22.4}/PKG-INFO +3 -2
  4. {gam7-7.22.0 → gam7-7.22.4}/pyproject.toml +3 -2
  5. {gam7-7.22.0 → gam7-7.22.4}/src/GamCommands.txt +4 -0
  6. {gam7-7.22.0 → gam7-7.22.4}/src/GamUpdate.txt +19 -0
  7. {gam7-7.22.0 → gam7-7.22.4}/src/gam/__init__.py +131 -80
  8. {gam7-7.22.0 → gam7-7.22.4}/wiki/Aliases.md +3 -1
  9. {gam7-7.22.0 → gam7-7.22.4}/wiki/Authorization.md +1 -1
  10. {gam7-7.22.0 → gam7-7.22.4}/wiki/Basic-Items.md +2 -0
  11. {gam7-7.22.0 → gam7-7.22.4}/wiki/Bulk-Processing.md +6 -0
  12. {gam7-7.22.0 → gam7-7.22.4}/wiki/Collections-of-Users.md +135 -44
  13. gam7-7.22.0/wiki/l-GAM7-FAQ.md → gam7-7.22.4/wiki/GAM7-FAQ.md +3 -3
  14. {gam7-7.22.0 → gam7-7.22.4}/wiki/GamUpdates.md +31 -3
  15. {gam7-7.22.0 → gam7-7.22.4}/wiki/Groups-Membership.md +44 -36
  16. {gam7-7.22.0 → gam7-7.22.4}/wiki/How-to-Upgrade-Legacy-GAM-to-GAM7.md +2 -2
  17. {gam7-7.22.0 → gam7-7.22.4}/wiki/Organizational-Units.md +7 -3
  18. {gam7-7.22.0 → gam7-7.22.4}/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine.md +2 -0
  19. {gam7-7.22.0 → gam7-7.22.4}/wiki/Todrive.md +4 -2
  20. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Copy-Move.md +2 -7
  21. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Files-Manage.md +4 -2
  22. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Permissions.md +25 -13
  23. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users.md +7 -5
  24. {gam7-7.22.0 → gam7-7.22.4}/wiki/Using-GAM7-with-a-YubiKey.md +3 -1
  25. gam7-7.22.4/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation.md +290 -0
  26. {gam7-7.22.0 → gam7-7.22.4}/wiki/Version-and-Help.md +6 -6
  27. {gam7-7.22.0 → gam7-7.22.4}/wiki/_Sidebar.md +3 -27
  28. gam7-7.22.0/wiki/l-Running-GAM-on-Google-Compute-Engine-(GCE)-Securely.md +0 -54
  29. gam7-7.22.0/wiki/l-Use-a-Yubikey.md +0 -49
  30. {gam7-7.22.0 → gam7-7.22.4}/.github/ISSUE_TEMPLATE/aa-question.md +0 -0
  31. {gam7-7.22.0 → gam7-7.22.4}/.github/ISSUE_TEMPLATE/za-bug-report.md +0 -0
  32. {gam7-7.22.0 → gam7-7.22.4}/.github/ISSUE_TEMPLATE/zz-feature-request.md +0 -0
  33. {gam7-7.22.0 → gam7-7.22.4}/.github/ISSUE_TEMPLATE.txt +0 -0
  34. {gam7-7.22.0 → gam7-7.22.4}/.github/actions/decrypt.sh +0 -0
  35. {gam7-7.22.0 → gam7-7.22.4}/.github/actions/entitlements.plist +0 -0
  36. {gam7-7.22.0 → gam7-7.22.4}/.github/actions/package_exclusions.txt +0 -0
  37. {gam7-7.22.0 → gam7-7.22.4}/.github/stale.yml +0 -0
  38. {gam7-7.22.0 → gam7-7.22.4}/.github/workflows/codeql-analysis.yml +0 -0
  39. {gam7-7.22.0 → gam7-7.22.4}/.github/workflows/get-cacerts.yml +0 -0
  40. {gam7-7.22.0 → gam7-7.22.4}/.github/workflows/pypi.yml +0 -0
  41. {gam7-7.22.0 → gam7-7.22.4}/LICENSE +0 -0
  42. {gam7-7.22.0 → gam7-7.22.4}/README.md +0 -0
  43. {gam7-7.22.0 → gam7-7.22.4}/src/.gitignore +0 -0
  44. {gam7-7.22.0 → gam7-7.22.4}/src/LICENSE +0 -0
  45. {gam7-7.22.0 → gam7-7.22.4}/src/README.md +0 -0
  46. {gam7-7.22.0 → gam7-7.22.4}/src/callgam.py +0 -0
  47. {gam7-7.22.0 → gam7-7.22.4}/src/gam/__main__.py +0 -0
  48. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/__init__.py +0 -0
  49. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/auth.py +0 -0
  50. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/client.py +0 -0
  51. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/core.py +0 -0
  52. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/data.py +0 -0
  53. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/http.py +0 -0
  54. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/http_core.py +0 -0
  55. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/http_interface.py +0 -0
  56. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/mock_http.py +0 -0
  57. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/mock_http_core.py +0 -0
  58. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/mock_service.py +0 -0
  59. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/service.py +0 -0
  60. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/token_store.py +0 -0
  61. {gam7-7.22.0 → gam7-7.22.4}/src/gam/atom/url.py +0 -0
  62. {gam7-7.22.0 → gam7-7.22.4}/src/gam/cacerts.pem +0 -0
  63. {gam7-7.22.0 → gam7-7.22.4}/src/gam/cbcm-v1.1beta1.json +0 -0
  64. {gam7-7.22.0 → gam7-7.22.4}/src/gam/contactdelegation-v1.json +0 -0
  65. {gam7-7.22.0 → gam7-7.22.4}/src/gam/datastudio-v1.json +0 -0
  66. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/__init__.py +0 -0
  67. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glaction.py +0 -0
  68. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glapi.py +0 -0
  69. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glcfg.py +0 -0
  70. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glclargs.py +0 -0
  71. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glentity.py +0 -0
  72. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glgapi.py +0 -0
  73. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glgdata.py +0 -0
  74. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glglobals.py +0 -0
  75. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glindent.py +0 -0
  76. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glmsgs.py +0 -0
  77. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glskus.py +0 -0
  78. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/gluprop.py +0 -0
  79. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/glverlibs.py +0 -0
  80. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gamlib/yubikey.py +0 -0
  81. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/__init__.py +0 -0
  82. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/alt/__init__.py +0 -0
  83. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/alt/app_engine.py +0 -0
  84. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/alt/appengine.py +0 -0
  85. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/__init__.py +0 -0
  86. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/audit/__init__.py +0 -0
  87. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/audit/service.py +0 -0
  88. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/contacts/__init__.py +0 -0
  89. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/contacts/service.py +0 -0
  90. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/apps/service.py +0 -0
  91. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/service.py +0 -0
  92. {gam7-7.22.0 → gam7-7.22.4}/src/gam/gdata/urlfetch.py +0 -0
  93. {gam7-7.22.0 → gam7-7.22.4}/src/gam/meet-v2beta.json +0 -0
  94. {gam7-7.22.0 → gam7-7.22.4}/src/gam/serviceaccountlookup-v1.json +0 -0
  95. {gam7-7.22.0 → gam7-7.22.4}/src/gam-install.sh +0 -0
  96. {gam7-7.22.0 → gam7-7.22.4}/src/gam-setup.bat +0 -0
  97. {gam7-7.22.0 → gam7-7.22.4}/src/gam.exe.manifest +0 -0
  98. {gam7-7.22.0 → gam7-7.22.4}/src/gam.py +0 -0
  99. {gam7-7.22.0 → gam7-7.22.4}/src/gam.spec +0 -0
  100. {gam7-7.22.0 → gam7-7.22.4}/src/gam.wxs +0 -0
  101. {gam7-7.22.0 → gam7-7.22.4}/src/license.rtf +0 -0
  102. {gam7-7.22.0 → gam7-7.22.4}/src/tools/a_atleast_b.py +0 -0
  103. {gam7-7.22.0 → gam7-7.22.4}/src/tools/gen-wix-xml-filelist.py +0 -0
  104. {gam7-7.22.0 → gam7-7.22.4}/src/tools/hooks/hook-googleapiclient.model.py +0 -0
  105. {gam7-7.22.0 → gam7-7.22.4}/src/tools/hooks/hook-httplib2.py +0 -0
  106. {gam7-7.22.0 → gam7-7.22.4}/src/tools/mkGamRef.py +0 -0
  107. {gam7-7.22.0 → gam7-7.22.4}/src/tools/openssl.props +0 -0
  108. {gam7-7.22.0 → gam7-7.22.4}/src/tools/ssd.mjs +0 -0
  109. {gam7-7.22.0 → gam7-7.22.4}/src/version_info.txt.in +0 -0
  110. {gam7-7.22.0 → gam7-7.22.4}/wiki/00scratch.md +0 -0
  111. {gam7-7.22.0 → gam7-7.22.4}/wiki/Addresses.md +0 -0
  112. {gam7-7.22.0 → gam7-7.22.4}/wiki/Administrators.md +0 -0
  113. {gam7-7.22.0 → gam7-7.22.4}/wiki/Alert-Center.md +0 -0
  114. {gam7-7.22.0 → gam7-7.22.4}/wiki/BNF-Syntax.md +0 -0
  115. {gam7-7.22.0 → gam7-7.22.4}/wiki/Business-Account-Management.md +0 -0
  116. {gam7-7.22.0 → gam7-7.22.4}/wiki/CSV-Input-Filtering.md +0 -0
  117. {gam7-7.22.0 → gam7-7.22.4}/wiki/CSV-Output-Filtering.md +0 -0
  118. {gam7-7.22.0 → gam7-7.22.4}/wiki/CSV-Special-Characters.md +0 -0
  119. {gam7-7.22.0 → gam7-7.22.4}/wiki/Calendars-Access.md +0 -0
  120. {gam7-7.22.0 → gam7-7.22.4}/wiki/Calendars-Events.md +0 -0
  121. {gam7-7.22.0 → gam7-7.22.4}/wiki/Calendars.md +0 -0
  122. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chat-Bot-Setup-Use.md +0 -0
  123. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-AUE-Counts.md +0 -0
  124. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Browser-Cloud-Management.md +0 -0
  125. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Installed-Apps.md +0 -0
  126. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Needs-Attention-Counts.md +0 -0
  127. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Policies.md +0 -0
  128. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Printers.md +0 -0
  129. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Profile-Management.md +0 -0
  130. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Version-Counts.md +0 -0
  131. {gam7-7.22.0 → gam7-7.22.4}/wiki/Chrome-Version-History.md +0 -0
  132. {gam7-7.22.0 → gam7-7.22.4}/wiki/ChromeOS-Devices.md +0 -0
  133. {gam7-7.22.0 → gam7-7.22.4}/wiki/Classroom-Courses.md +0 -0
  134. {gam7-7.22.0 → gam7-7.22.4}/wiki/Classroom-Guardians.md +0 -0
  135. {gam7-7.22.0 → gam7-7.22.4}/wiki/Classroom-Invitations.md +0 -0
  136. {gam7-7.22.0 → gam7-7.22.4}/wiki/Classroom-Membership.md +0 -0
  137. {gam7-7.22.0 → gam7-7.22.4}/wiki/Classroom-StudentGroups.md +0 -0
  138. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Channel.md +0 -0
  139. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Identity-Devices.md +0 -0
  140. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Identity-Groups-Membership.md +0 -0
  141. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Identity-Groups.md +0 -0
  142. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Identity-Policies.md +0 -0
  143. {gam7-7.22.0 → gam7-7.22.4}/wiki/Cloud-Storage.md +0 -0
  144. {gam7-7.22.0 → gam7-7.22.4}/wiki/Collections-of-ChromeOS-Devices.md +0 -0
  145. {gam7-7.22.0 → gam7-7.22.4}/wiki/Collections-of-Items.md +0 -0
  146. {gam7-7.22.0 → gam7-7.22.4}/wiki/Command-Data-From-Google-Docs-Sheets-Storage.md +0 -0
  147. {gam7-7.22.0 → gam7-7.22.4}/wiki/Command-Line-Parsing.md +0 -0
  148. {gam7-7.22.0 → gam7-7.22.4}/wiki/Command-Logging-Progress.md +0 -0
  149. {gam7-7.22.0 → gam7-7.22.4}/wiki/Context-Aware-Access-Levels.md +0 -0
  150. {gam7-7.22.0 → gam7-7.22.4}/wiki/Customer.md +0 -0
  151. {gam7-7.22.0 → gam7-7.22.4}/wiki/Domain-People-Contacts-Profiles.md +0 -0
  152. {gam7-7.22.0 → gam7-7.22.4}/wiki/Domain-SharedContacts.md +0 -0
  153. {gam7-7.22.0 → gam7-7.22.4}/wiki/Domains-Verification.md +0 -0
  154. {gam7-7.22.0 → gam7-7.22.4}/wiki/Domains.md +0 -0
  155. {gam7-7.22.0 → gam7-7.22.4}/wiki/Downloads-Installs.md +0 -0
  156. {gam7-7.22.0 → gam7-7.22.4}/wiki/Drive-File-Selection.md +0 -0
  157. {gam7-7.22.0 → gam7-7.22.4}/wiki/Drive-Items.md +0 -0
  158. {gam7-7.22.0 → gam7-7.22.4}/wiki/Drive-REST-API-v3.md +0 -0
  159. {gam7-7.22.0 → gam7-7.22.4}/wiki/Email-Audit-Monitor.md +0 -0
  160. {gam7-7.22.0 → gam7-7.22.4}/wiki/Find-File-Owner.md +0 -0
  161. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM-Public-Chat-Room.md +0 -0
  162. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM-Release-Process.md +0 -0
  163. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM-Return-Codes.md +0 -0
  164. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM-with-minimal-GCP-rights.md +0 -0
  165. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM7-on-Android-Devices.md +0 -0
  166. {gam7-7.22.0 → gam7-7.22.4}/wiki/GAM7-on-Chrome-OS-Devices.md +0 -0
  167. {gam7-7.22.0 → gam7-7.22.4}/wiki/Global-Address-List.md +0 -0
  168. {gam7-7.22.0 → gam7-7.22.4}/wiki/Google-Data-Transfers.md +0 -0
  169. {gam7-7.22.0 → gam7-7.22.4}/wiki/Google-Network-Addresses.md +0 -0
  170. {gam7-7.22.0 → gam7-7.22.4}/wiki/Groups.md +0 -0
  171. {gam7-7.22.0 → gam7-7.22.4}/wiki/HTTPS-Proxy.md +0 -0
  172. {gam7-7.22.0 → gam7-7.22.4}/wiki/Home.md +0 -0
  173. {gam7-7.22.0 → gam7-7.22.4}/wiki/How-to-Install-GAM7.md +0 -0
  174. {gam7-7.22.0 → gam7-7.22.4}/wiki/How-to-Uninstall-GAM7.md +0 -0
  175. {gam7-7.22.0 → gam7-7.22.4}/wiki/How-to-Update-GAM7.md +0 -0
  176. {gam7-7.22.0 → gam7-7.22.4}/wiki/How-to-Upgrade-GAMADV-XTD3-to-GAM7.md +0 -0
  177. {gam7-7.22.0 → gam7-7.22.4}/wiki/Inbound-SSO.md +0 -0
  178. {gam7-7.22.0 → gam7-7.22.4}/wiki/Install-GAM-as-Python-Library.md +0 -0
  179. {gam7-7.22.0 → gam7-7.22.4}/wiki/Licenses.md +0 -0
  180. {gam7-7.22.0 → gam7-7.22.4}/wiki/List-Items.md +0 -0
  181. {gam7-7.22.0 → gam7-7.22.4}/wiki/List.md +0 -0
  182. {gam7-7.22.0 → gam7-7.22.4}/wiki/Meta-Commands-and-File-Redirection.md +0 -0
  183. {gam7-7.22.0 → gam7-7.22.4}/wiki/Mobile-Devices.md +0 -0
  184. {gam7-7.22.0 → gam7-7.22.4}/wiki/Other-Resources.md +0 -0
  185. {gam7-7.22.0 → gam7-7.22.4}/wiki/Permission-Matches.md +0 -0
  186. {gam7-7.22.0 → gam7-7.22.4}/wiki/Python-Regular-Expressions.md +0 -0
  187. {gam7-7.22.0 → gam7-7.22.4}/wiki/README.md +0 -0
  188. {gam7-7.22.0 → gam7-7.22.4}/wiki/Rclone.md +0 -0
  189. {gam7-7.22.0 → gam7-7.22.4}/wiki/Reports.md +0 -0
  190. {gam7-7.22.0 → gam7-7.22.4}/wiki/Reseller.md +0 -0
  191. {gam7-7.22.0 → gam7-7.22.4}/wiki/Resources.md +0 -0
  192. {gam7-7.22.0 → gam7-7.22.4}/wiki/SSL-Root-CA-Certificates.md +0 -0
  193. {gam7-7.22.0 → gam7-7.22.4}/wiki/Schemas.md +0 -0
  194. {gam7-7.22.0 → gam7-7.22.4}/wiki/Scripts.md +0 -0
  195. {gam7-7.22.0 → gam7-7.22.4}/wiki/Send-Email.md +0 -0
  196. {gam7-7.22.0 → gam7-7.22.4}/wiki/Shared-Drives.md +0 -0
  197. {gam7-7.22.0 → gam7-7.22.4}/wiki/Sites.md +0 -0
  198. {gam7-7.22.0 → gam7-7.22.4}/wiki/Tag-Replace.md +0 -0
  199. {gam7-7.22.0 → gam7-7.22.4}/wiki/Unmanaged-Accounts.md +0 -0
  200. {gam7-7.22.0 → gam7-7.22.4}/wiki/Upgrade-Benefits.md +0 -0
  201. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Analytics-Admin.md +0 -0
  202. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Application-Specific-Passwords.md +0 -0
  203. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Backup-Verification-Codes.md +0 -0
  204. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Calendars-Access.md +0 -0
  205. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Calendars-Events.md +0 -0
  206. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Calendars.md +0 -0
  207. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Chat.md +0 -0
  208. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Classification-Labels.md +0 -0
  209. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Classroom-Profile.md +0 -0
  210. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Contacts-Delegates.md +0 -0
  211. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Contacts.md +0 -0
  212. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Deprovision.md +0 -0
  213. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Activity-Settings.md +0 -0
  214. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Cleanup.md +0 -0
  215. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Comments.md +0 -0
  216. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Files-Display.md +0 -0
  217. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Orphans.md +0 -0
  218. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Ownership.md +0 -0
  219. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Query.md +0 -0
  220. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Revisions.md +0 -0
  221. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Shortcuts.md +0 -0
  222. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Drive-Transfer.md +0 -0
  223. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Forms.md +0 -0
  224. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-CSE.md +0 -0
  225. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Delegates.md +0 -0
  226. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Filters.md +0 -0
  227. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Forwarding.md +0 -0
  228. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Labels.md +0 -0
  229. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Messages-Threads.md +0 -0
  230. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Profile.md +0 -0
  231. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-S-MIME.md +0 -0
  232. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Send-As-Signature-Vacation.md +0 -0
  233. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Gmail-Settings.md +0 -0
  234. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Group-Membership.md +0 -0
  235. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Keep-Notes.md +0 -0
  236. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Looker-Studio.md +0 -0
  237. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Meet.md +0 -0
  238. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-People-Contacts-Profiles.md +0 -0
  239. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Photo.md +0 -0
  240. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Profile-Photo.md +0 -0
  241. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Profile-Sharing.md +0 -0
  242. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Shared-Drives.md +0 -0
  243. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Signout-Turnoff2SV.md +0 -0
  244. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Spreadsheets.md +0 -0
  245. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Tag-Manager.md +0 -0
  246. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Tasks.md +0 -0
  247. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Tokens.md +0 -0
  248. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-Web-Resources-and-Sites.md +0 -0
  249. {gam7-7.22.0 → gam7-7.22.4}/wiki/Users-YouTube.md +0 -0
  250. {gam7-7.22.0 → gam7-7.22.4}/wiki/Using-GAM7-with-a-delegated-admin-service-account.md +0 -0
  251. {gam7-7.22.0 → gam7-7.22.4}/wiki/Vault-Takeout.md +0 -0
  252. {gam7-7.22.0 → gam7-7.22.4}/wiki/Verifying-a-GAM7-Build-is-Legitimate-and-Official.md +0 -0
  253. {gam7-7.22.0 → gam7-7.22.4}/wiki/gam.cfg.md +0 -0
  254. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-AdminSettingsExamples.md +0 -0
  255. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Android-Installation.md +0 -0
  256. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-BulkOperations.md +0 -0
  257. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-CalendarExamples.md +0 -0
  258. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Chat-Bot.md +0 -0
  259. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Chrome-Browser-Management.md +0 -0
  260. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Chrome-OS-Installation.md +0 -0
  261. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Chrome-Policy-Settings.md +0 -0
  262. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Cloud-Identity-Groups.md +0 -0
  263. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Calendar-Resources.md +0 -0
  264. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Calendars.md +0 -0
  265. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Definitions.md +0 -0
  266. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Drive.md +0 -0
  267. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Email.md +0 -0
  268. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Group-Attributes.md +0 -0
  269. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Groups.md +0 -0
  270. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Command-Reference-Users.md +0 -0
  271. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Context-Aware-Access-Levels.md +0 -0
  272. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Creating-client_secrets.json-and-oauth2service.json.md +0 -0
  273. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-CreatingClientSecretsFile.md +0 -0
  274. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Custom-Schemas.md +0 -0
  275. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Data-Transfers.md +0 -0
  276. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-DomainVerification.md +0 -0
  277. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-ExamplesAccountAuditing.md +0 -0
  278. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-ExamplesCSV.md +0 -0
  279. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-ExamplesEmailSettings.md +0 -0
  280. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-ExamplesOrganizations.md +0 -0
  281. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM-Discussion-Group.md +0 -0
  282. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM-on-Android-and-Chrome-OS.md +0 -0
  283. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM-options-files.md +0 -0
  284. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM-with--minimal-GCP-rights.md +0 -0
  285. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM3CSVListings.md +0 -0
  286. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM3DirectoryCommands.md +0 -0
  287. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GAM3GroupSettings.md +0 -0
  288. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Google-Vault---Takeout-Commands.md +0 -0
  289. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-GoogleDriveManagement.md +0 -0
  290. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Grouping-18-or-Older-Users.md +0 -0
  291. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Home.md +0 -0
  292. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-How-to-upgrade-from-Standard-GAM.md +0 -0
  293. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Inbound-SSO-Settings.md +0 -0
  294. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-LicenseExamples.md +0 -0
  295. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Managing-Admins.md +0 -0
  296. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Managing-CloudPrint-Printers.md +0 -0
  297. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Managing-Devices.md +0 -0
  298. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Managing-Google-Classroom.md +0 -0
  299. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-OAuthKeyManagement.md +0 -0
  300. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Printers.md +0 -0
  301. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-ResellerCommands.md +0 -0
  302. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-SecurityExamples.md +0 -0
  303. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-UnmanagedUsersExamples.md +0 -0
  304. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-Using-GAM-with-a-delegated-admin-service-account-(DASA).md +0 -0
  305. {gam7-7.22.0/wiki → gam7-7.22.4/wiki/legacy}/l-_Footer.md +0 -0
@@ -77,33 +77,37 @@ jobs:
77
77
  jid: 9
78
78
  goal: build
79
79
  name: Build Arm MacOS 15
80
- - os: macos-26
80
+ - os: macos-15-intel
81
81
  jid: 10
82
82
  goal: build
83
+ name: Build x86_64 macOS 15
84
+ - os: macos-26
85
+ jid: 11
86
+ goal: build
83
87
  name: Build Arm MacOS 26
84
88
  - os: windows-2025
85
- jid: 11
89
+ jid: 12
86
90
  goal: build
87
91
  name: Build Intel Windows
88
92
  - os: windows-11-arm
89
- jid: 12
93
+ jid: 13
90
94
  goal: build
91
95
  name: Build Arm Windows
92
96
  - os: ubuntu-24.04
93
97
  goal: test
94
98
  python: "3.10"
95
- jid: 13
99
+ jid: 14
96
100
  name: Test Python 3.10
97
101
  - os: ubuntu-24.04
98
102
  goal: test
99
103
  python: "3.11"
100
- jid: 14
101
- name: Test Python 3.11
102
- - os: ubuntu-24.04
103
- goal: test
104
- python: "3.12"
105
104
  jid: 15
106
- name: Test Python 3.12
105
+ name: Test Python 3.11
106
+ #- os: ubuntu-24.04
107
+ # goal: test
108
+ # python: "3.12"
109
+ # jid: 16
110
+ # name: Test Python 3.12
107
111
  #- os: ubuntu-24.04
108
112
  # goal: test
109
113
  # python: "3.14-dev"
@@ -131,7 +135,7 @@ jobs:
131
135
  with:
132
136
  path: |
133
137
  cache.tar.xz
134
- key: gam-${{ matrix.jid }}-20250916
138
+ key: gam-${{ matrix.jid }}-20250922
135
139
 
136
140
  - name: Untar Cache archive
137
141
  if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -463,9 +467,6 @@ jobs:
463
467
  echo "before anything..."
464
468
  "$PYTHON" -m pip list
465
469
  "$PYTHON" -m pip install --upgrade ..[yubikey]
466
- # forcefully update all installed packages
467
- "$PYTHON" -m pip --disable-pip-version-check list --outdated --format=json | "$PYTHON" -c "import json, sys; print('\n'.join([x['name'] for x in json.load(sys.stdin)]))" | xargs -n1 "$PYTHON" -m pip install -U
468
- "$PYTHON" -m pip list
469
470
  echo "after everything..."
470
471
  "$PYTHON" -m pip list
471
472
 
@@ -37,7 +37,7 @@ jobs:
37
37
  cd GAM.wiki
38
38
  git config --local user.email "action@github.com"
39
39
  git config --local user.name "GitHub Action"
40
- git add *.md
40
+ git add -A
41
41
  git commit -m "[no ci] Push Wiki changes"
42
42
  git status
43
43
  git push
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gam7
3
- Version: 7.22.0
3
+ Version: 7.22.4
4
4
  Summary: CLI tool to manage Google Workspace
5
5
  Project-URL: Homepage, https://github.com/GAM-team/GAM
6
6
  Project-URL: Issues, https://github.com/GAM-team/GAM/issues
@@ -27,10 +27,11 @@ Requires-Dist: google-api-python-client>=2.167.0
27
27
  Requires-Dist: google-auth-httplib2>=0.2.0
28
28
  Requires-Dist: google-auth-oauthlib>=1.2.2
29
29
  Requires-Dist: google-auth>=2.39.0
30
- Requires-Dist: httplib2>=0.22.0
30
+ Requires-Dist: httplib2>=0.31.0
31
31
  Requires-Dist: lxml>=5.4.0
32
32
  Requires-Dist: passlib>=1.7.4
33
33
  Requires-Dist: pathvalidate>=3.2.3
34
+ Requires-Dist: pysocks>=1.7.1
34
35
  Provides-Extra: yubikey
35
36
  Requires-Dist: yubikey-manager>=5.6.1; extra == 'yubikey'
36
37
  Description-Content-Type: text/markdown
@@ -19,10 +19,11 @@ dependencies = [
19
19
  "google-auth-httplib2>=0.2.0",
20
20
  "google-auth-oauthlib>=1.2.2",
21
21
  "google-auth>=2.39.0",
22
- "httplib2>=0.22.0",
22
+ "httplib2>=0.31.0",
23
23
  "lxml>=5.4.0",
24
24
  "passlib>=1.7.4",
25
- "pathvalidate>=3.2.3"
25
+ "pathvalidate>=3.2.3",
26
+ "pysocks>=1.7.1",
26
27
  ]
27
28
  description = "CLI tool to manage Google Workspace"
28
29
  readme = "README.md"
@@ -565,6 +565,7 @@ If an item contains spaces, it should be surrounded by ".
565
565
  See: https://support.google.com/mail/answer/7190
566
566
  <QueryGroup> ::= <String>
567
567
  See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
568
+ <QueryItem> ::= <UniqueID>|<String>
568
569
  <QueryMemberRestrictions> ::= <String>
569
570
  See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
570
571
  <QueryMobile> ::= <String>
@@ -5493,6 +5494,9 @@ gam show vaultexports|exports
5493
5494
  [fields <VaultExportFieldNameList>] [shownames]
5494
5495
  [formatjson]
5495
5496
 
5497
+ gam create vaulthold|hold matter <MatterItem> [name <String>]
5498
+ vaultquery <QueryItem>
5499
+ [showdetails|returnidonly]
5496
5500
  gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
5497
5501
  [(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
5498
5502
  [query <QueryVaultCorpus>]
@@ -1,3 +1,22 @@
1
+ 7.22.04
2
+
3
+ Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
4
+ ```
5
+ gam create vaulthold matter <MatterItem> [name <String>]
6
+ vaultquery <QueryItem>
7
+ [showdetails|returnidonly]
8
+ ```
9
+
10
+ 7.22.03
11
+
12
+ Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
13
+ from a field name to a query option; it is now correctly interpreted as a field name.
14
+
15
+ 7.22.02
16
+
17
+ An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
18
+ by including the pysocks library needed by the latest httplib2 library.
19
+
1
20
  7.22.00
2
21
 
3
22
  Expanded `<UserTypeEntity>` to allow specification of non-archived/archived users.
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
25
25
  """
26
26
 
27
27
  __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
28
- __version__ = '7.22.00'
28
+ __version__ = '7.22.04'
29
29
  __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
30
30
 
31
31
  #pylint: disable=wrong-import-position
@@ -18989,10 +18989,10 @@ def doPrintAliases():
18989
18989
  pass
18990
18990
  elif myarg == 'select':
18991
18991
  _, users = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
18992
- elif myarg in SUSPENDED_ARGUMENTS:
18993
- isSuspended = _getIsSuspended(myarg)
18994
- elif myarg in ARCHIVED_ARGUMENTS:
18995
- isArchived = _getIsArchived(myarg)
18992
+ elif myarg == 'issuspended':
18993
+ isSuspended = getBoolean()
18994
+ elif myarg == 'isarchived':
18995
+ isArchived = getBoolean()
18996
18996
  elif myarg in {'user','users'}:
18997
18997
  users.extend(convertEntityToList(getString(Cmd.OB_EMAIL_ADDRESS_LIST, minLen=0)))
18998
18998
  elif myarg in {'group', 'groups'}:
@@ -41654,7 +41654,7 @@ def convertQueryNameToID(v, nameOrId, matterId, matterNameId):
41654
41654
  query = callGAPI(v.matters().savedQueries(), 'get',
41655
41655
  throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
41656
41656
  matterId=matterId, savedQueryId=cg.group(1))
41657
- return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']))
41657
+ return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
41658
41658
  except (GAPI.notFound, GAPI.badRequest):
41659
41659
  entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
41660
41660
  except (GAPI.forbidden, GAPI.invalidArgument) as e:
@@ -41663,12 +41663,12 @@ def convertQueryNameToID(v, nameOrId, matterId, matterNameId):
41663
41663
  try:
41664
41664
  queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
41665
41665
  throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
41666
- matterId=matterId, fields='savedQueries(savedQueryId,displayName),nextPageToken')
41666
+ matterId=matterId, fields='savedQueries(savedQueryId,displayName,query),nextPageToken')
41667
41667
  except (GAPI.forbidden, GAPI.invalidArgument) as e:
41668
41668
  ClientAPIAccessDeniedExit(str(e))
41669
41669
  for query in queries:
41670
41670
  if query['displayName'].lower() == nameOrIdlower:
41671
- return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']))
41671
+ return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
41672
41672
  entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
41673
41673
 
41674
41674
  def getMatterItem(v, state=None):
@@ -41896,7 +41896,8 @@ def _buildVaultQuery(myarg, query, corpusArgumentMap):
41896
41896
  query.setdefault('mailOptions', {})['clientSideEncryptedOption'] = getChoice(VAULT_CSE_OPTION_MAP, mapChoice=True)
41897
41897
  # voice
41898
41898
  elif myarg == 'covereddata':
41899
- query['voiceOptions'] = {'coveredData': getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)}
41899
+ query.setdefault('voiceOptions', {'coveredData': []})
41900
+ query['voiceOptions']['coveredData'].append(getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True))
41900
41901
 
41901
41902
  def _validateVaultQuery(body, corpusArgumentMap):
41902
41903
  if 'corpus' not in body['query']:
@@ -41957,7 +41958,8 @@ def doCreateVaultExport():
41957
41958
  elif myarg == 'includeaccessinfo':
41958
41959
  body['exportOptions'].setdefault('driveOptions', {})['includeAccessInfo'] = getBoolean()
41959
41960
  elif myarg == 'covereddata':
41960
- body['exportOptions'].setdefault('voiceOptions', {})['coveredData'] = getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)
41961
+ body['exportOptions'].setdefault('voiceOptions', {'coveredData': []})
41962
+ body['exportOptions']['voiceOptions']['coveredData'].append(getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True))
41961
41963
  elif myarg == 'showdetails':
41962
41964
  showDetails = True
41963
41965
  returnIdOnly = False
@@ -42459,6 +42461,34 @@ def _showVaultHold(matterNameId, hold, cd, FJQC, k=0, kcount=0):
42459
42461
  showJSON(None, hold, timeObjects=VAULT_HOLD_TIME_OBJECTS)
42460
42462
  Ind.Decrement()
42461
42463
 
42464
+ def _useVaultQuery(v, matterId, matterNameId, body):
42465
+ _, _, _, query = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
42466
+ body['corpus'] = query['corpus']
42467
+ method = query.get('method')
42468
+ if method == 'ACCOUNT':
42469
+ body['accounts'] = []
42470
+ for email in query['accountInfo']['emails']:
42471
+ body['accounts'].append({'email': email})
42472
+ elif method == 'ORG_UNIT':
42473
+ body['orgUnit'] = {'orgUnitId': query['orgUnitInfo']['orgUnitId']}
42474
+ queryType = VAULT_CORPUS_QUERY_MAP[query['corpus']]
42475
+ if queryType is None:
42476
+ return
42477
+ body['query'] = {queryType: {}}
42478
+ if query['corpus'] == 'DRIVE':
42479
+ body['query'][queryType]['includeSharedDriveFiles'] = query['driveOptions'].get('includeSharedDrives', False)
42480
+ elif query['corpus'] in {'GROUPS', 'MAIL'}:
42481
+ if query.get('terms'):
42482
+ body['query'][queryType]['terms'] = query['terms']
42483
+ if query.get('startTime'):
42484
+ body['query'][queryType]['startTime'] = query['startTime']
42485
+ if query.get('endTime'):
42486
+ body['query'][queryType]['endTime'] = query['endTime']
42487
+ elif query['corpus'] == 'HANGOUTS_CHAT':
42488
+ body['query'][queryType]['includeRooms'] = query['hangoutsChatOptions'].get('includeRooms', False)
42489
+ elif query['corpus'] == 'VOICE':
42490
+ body['query'][queryType]['coveredData'] = query['voiceOptions']['coveredData']
42491
+
42462
42492
  def _getHoldQueryParameters(myarg, queryParameters):
42463
42493
  if myarg == 'query':
42464
42494
  queryParameters['queryLocation'] = Cmd.Location()
@@ -42474,7 +42504,8 @@ def _getHoldQueryParameters(myarg, queryParameters):
42474
42504
  elif myarg in {'includeshareddrives', 'includeteamdrives'}:
42475
42505
  queryParameters['includeSharedDriveFiles'] = getBoolean()
42476
42506
  elif myarg == 'covereddata':
42477
- queryParameters['coveredData'] = getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True)
42507
+ queryParameters.setdefault('coveredData', [])
42508
+ queryParameters['coveredData'].append(getChoice(VAULT_VOICE_COVERED_DATA_MAP, mapChoice=True))
42478
42509
  else:
42479
42510
  return False
42480
42511
  return True
@@ -42509,7 +42540,11 @@ def _setHoldQuery(body, queryParameters):
42509
42540
  if queryParameters.get('coveredData'):
42510
42541
  body['query'][queryType]['coveredData'] = queryParameters['coveredData']
42511
42542
 
42512
- # gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
42543
+ # gam create vaulthold|hold matter <MatterItem> [name <String>]
42544
+ # vaultquery <QueryItem>
42545
+ # [showdetails|returnidonly]
42546
+ # gam create vaulthold|hold matter <MatterItem> [name <String>]
42547
+ # corpus calendar|drive|mail|groups|hangouts_chat|voice
42513
42548
  # [(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
42514
42549
  # [query <QueryVaultCorpus>]
42515
42550
  # [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
@@ -42523,13 +42558,16 @@ def doCreateVaultHold():
42523
42558
  matterId = None
42524
42559
  accounts = []
42525
42560
  queryParameters = {}
42526
- returnIdOnly = showDetails = False
42561
+ returnIdOnly = showDetails = usedVaultQuery = False
42527
42562
  while Cmd.ArgumentsRemaining():
42528
42563
  myarg = getArgument()
42529
42564
  if myarg == 'matter':
42530
42565
  matterId, matterNameId = getMatterItem(v)
42531
42566
  elif myarg == 'name':
42532
42567
  body['name'] = getString(Cmd.OB_STRING)
42568
+ elif matterId is not None and myarg == 'vaultquery':
42569
+ _useVaultQuery(v, matterId, matterNameId, body)
42570
+ usedVaultQuery = True
42533
42571
  elif myarg == 'corpus':
42534
42572
  body['corpus'] = getChoice(VAULT_CORPUS_ARGUMENT_MAP, mapChoice=True)
42535
42573
  elif myarg in {'accounts', 'users', 'groups'}:
@@ -42553,7 +42591,8 @@ def doCreateVaultHold():
42553
42591
  missingArgumentExit(f'corpus {"|".join(VAULT_CORPUS_ARGUMENT_MAP)}')
42554
42592
  if 'name' not in body:
42555
42593
  body['name'] = f'GAM {body["corpus"]} Hold - {ISOformatTimeStamp(todaysTime())}'
42556
- _setHoldQuery(body, queryParameters)
42594
+ if not usedVaultQuery:
42595
+ _setHoldQuery(body, queryParameters)
42557
42596
  if accounts:
42558
42597
  body['accounts'] = []
42559
42598
  cd = buildGAPIObject(API.DIRECTORY)
@@ -43006,7 +43045,7 @@ def doInfoVaultQuery():
43006
43045
  v = buildGAPIObject(API.VAULT)
43007
43046
  if not Cmd.ArgumentIsAhead('matter'):
43008
43047
  matterId, matterNameId = getMatterItem(v)
43009
- queryId, queryName, queryNameId = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
43048
+ queryId, queryName, queryNameId, _ = convertQueryNameToID(v, getString(Cmd.OB_QUERY_ITEM), matterId, matterNameId)
43010
43049
  else:
43011
43050
  queryName = getString(Cmd.OB_QUERY_ITEM)
43012
43051
  cd = drive = None
@@ -43016,7 +43055,7 @@ def doInfoVaultQuery():
43016
43055
  myarg = getArgument()
43017
43056
  if myarg == 'matter':
43018
43057
  matterId, matterNameId = getMatterItem(v)
43019
- queryId, queryName, queryNameId = convertQueryNameToID(v, queryName, matterId, matterNameId)
43058
+ queryId, queryName, queryNameId, _ = convertQueryNameToID(v, queryName, matterId, matterNameId)
43020
43059
  elif myarg == 'shownames':
43021
43060
  cd = buildGAPIObject(API.DIRECTORY)
43022
43061
  _, drive = buildGAPIServiceObject(API.DRIVE3, _getAdminEmail())
@@ -45754,71 +45793,81 @@ def doPrintUsers(entityList=None):
45754
45793
  csvPF.WriteRowNoFilter(row)
45755
45794
 
45756
45795
  def _printUser(userEntity, i, count):
45757
- if isSuspended is None or isSuspended == userEntity.get('suspended', isSuspended):
45758
- if showValidColumn:
45759
- userEntity[showValidColumn] = True
45760
- userEmail = userEntity['primaryEmail']
45761
- if printOptions['emailParts']:
45762
- if userEmail.find('@') != -1:
45763
- userEntity['primaryEmailLocal'], userEntity['primaryEmailDomain'] = splitEmailAddress(userEmail)
45764
- if 'languages' in userEntity and not FJQC.formatJSON:
45765
- userEntity['languages'] = _formatLanguagesList(userEntity.pop('languages'), delimiter)
45766
- for location in userEntity.get('locations', []):
45767
- location['buildingName'] = _getBuildingNameById(cd, location.get('buildingId', ''))
45768
- if quotePlusPhoneNumbers:
45769
- for phone in userEntity.get('phones', []):
45770
- phoneNumber = phone.get('value', '')
45771
- if phoneNumber.startswith('+'):
45772
- phone['value'] = "'"+phoneNumber
45773
- if schemaParms['selectedSchemaFields']:
45774
- _filterSchemaFields(userEntity, schemaParms)
45775
- if printOptions['getGroupFeed']:
45776
- printGettingAllEntityItemsForWhom(Ent.GROUP_MEMBERSHIP, userEmail, i, count)
45777
- try:
45778
- groups = callGAPIpages(cd.groups(), 'list', 'groups',
45779
- pageMessage=getPageMessageForWhom(),
45780
- throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
45781
- retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
45782
- userKey=userEmail, orderBy='email', fields='nextPageToken,groups(email)')
45783
- numGroups = len(groups)
45784
- if not printOptions['groupsInColumns']:
45785
- userEntity['GroupsCount'] = numGroups
45786
- userEntity['Groups'] = delimiter.join([groupname['email'] for groupname in groups])
45787
- else:
45788
- if numGroups > printOptions['maxGroups']:
45789
- printOptions['maxGroups'] = numGroups
45790
- userEntity['Groups'] = numGroups
45791
- for j, group in enumerate(groups):
45792
- userEntity[f'Groups{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}{j}'] = group['email']
45793
- except (GAPI.invalidMember, GAPI.invalidInput):
45794
- badRequestWarning(Ent.GROUP, Ent.MEMBER, userEmail)
45795
- except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
45796
- accessErrorExit(cd)
45797
- if aliasMatchPattern and 'aliases' in userEntity:
45798
- userEntity['aliases'] = [alias for alias in userEntity['aliases'] if aliasMatchPattern.match(alias)]
45799
- if printOptions['getLicenseFeed'] or printOptions['getLicenseFeedByUser']:
45800
- if printOptions['getLicenseFeed']:
45801
- u_licenses = licenses.get(userEmail.lower(), [])
45796
+ if (isSuspended is None and isArchived is None):
45797
+ showUser = True
45798
+ elif (isSuspended is not None and isArchived is None):
45799
+ showUser = isSuspended == userEntity.get('suspended', isSuspended)
45800
+ elif (isSuspended is None and isArchived is not None):
45801
+ showUser = isArchived == userEntity.get('archived', isArchived)
45802
+ else:
45803
+ showUser = ((isSuspended == userEntity.get('suspended', isSuspended)) or
45804
+ (isArchived == userEntity.get('archived', isArchived)))
45805
+ if not showUser:
45806
+ return
45807
+ if showValidColumn:
45808
+ userEntity[showValidColumn] = True
45809
+ userEmail = userEntity['primaryEmail']
45810
+ if printOptions['emailParts']:
45811
+ if userEmail.find('@') != -1:
45812
+ userEntity['primaryEmailLocal'], userEntity['primaryEmailDomain'] = splitEmailAddress(userEmail)
45813
+ if 'languages' in userEntity and not FJQC.formatJSON:
45814
+ userEntity['languages'] = _formatLanguagesList(userEntity.pop('languages'), delimiter)
45815
+ for location in userEntity.get('locations', []):
45816
+ location['buildingName'] = _getBuildingNameById(cd, location.get('buildingId', ''))
45817
+ if quotePlusPhoneNumbers:
45818
+ for phone in userEntity.get('phones', []):
45819
+ phoneNumber = phone.get('value', '')
45820
+ if phoneNumber.startswith('+'):
45821
+ phone['value'] = "'"+phoneNumber
45822
+ if schemaParms['selectedSchemaFields']:
45823
+ _filterSchemaFields(userEntity, schemaParms)
45824
+ if printOptions['getGroupFeed']:
45825
+ printGettingAllEntityItemsForWhom(Ent.GROUP_MEMBERSHIP, userEmail, i, count)
45826
+ try:
45827
+ groups = callGAPIpages(cd.groups(), 'list', 'groups',
45828
+ pageMessage=getPageMessageForWhom(),
45829
+ throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
45830
+ retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
45831
+ userKey=userEmail, orderBy='email', fields='nextPageToken,groups(email)')
45832
+ numGroups = len(groups)
45833
+ if not printOptions['groupsInColumns']:
45834
+ userEntity['GroupsCount'] = numGroups
45835
+ userEntity['Groups'] = delimiter.join([groupname['email'] for groupname in groups])
45802
45836
  else:
45803
- u_licenses = getUserLicenses(lic, userEntity, skus)
45804
- if not oneLicensePerRow:
45805
- userEntity['LicensesCount'] = len(u_licenses)
45806
- if u_licenses:
45807
- userEntity['Licenses'] = delimiter.join(u_licenses)
45808
- userEntity['LicensesDisplay'] = delimiter.join([SKU.skuIdToDisplayName(skuId) for skuId in u_licenses])
45837
+ if numGroups > printOptions['maxGroups']:
45838
+ printOptions['maxGroups'] = numGroups
45839
+ userEntity['Groups'] = numGroups
45840
+ for j, group in enumerate(groups):
45841
+ userEntity[f'Groups{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}{j}'] = group['email']
45842
+ except (GAPI.invalidMember, GAPI.invalidInput):
45843
+ badRequestWarning(Ent.GROUP, Ent.MEMBER, userEmail)
45844
+ except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
45845
+ accessErrorExit(cd)
45846
+ if aliasMatchPattern and 'aliases' in userEntity:
45847
+ userEntity['aliases'] = [alias for alias in userEntity['aliases'] if aliasMatchPattern.match(alias)]
45848
+ if printOptions['getLicenseFeed'] or printOptions['getLicenseFeedByUser']:
45849
+ if printOptions['getLicenseFeed']:
45850
+ u_licenses = licenses.get(userEmail.lower(), [])
45809
45851
  else:
45810
- u_licenses = []
45852
+ u_licenses = getUserLicenses(lic, userEntity, skus)
45811
45853
  if not oneLicensePerRow:
45812
- _writeUserEntity(userEntity)
45813
- else:
45854
+ userEntity['LicensesCount'] = len(u_licenses)
45814
45855
  if u_licenses:
45815
- for skuId in u_licenses:
45816
- userEntity['License'] = skuId
45817
- userEntity['LicenseDisplay'] = SKU.skuIdToDisplayName(skuId)
45818
- _writeUserEntity(userEntity)
45819
- else:
45820
- userEntity['License'] = userEntity['LicenseDisplay'] = ''
45856
+ userEntity['Licenses'] = delimiter.join(u_licenses)
45857
+ userEntity['LicensesDisplay'] = delimiter.join([SKU.skuIdToDisplayName(skuId) for skuId in u_licenses])
45858
+ else:
45859
+ u_licenses = []
45860
+ if not oneLicensePerRow:
45861
+ _writeUserEntity(userEntity)
45862
+ else:
45863
+ if u_licenses:
45864
+ for skuId in u_licenses:
45865
+ userEntity['License'] = skuId
45866
+ userEntity['LicenseDisplay'] = SKU.skuIdToDisplayName(skuId)
45821
45867
  _writeUserEntity(userEntity)
45868
+ else:
45869
+ userEntity['License'] = userEntity['LicenseDisplay'] = ''
45870
+ _writeUserEntity(userEntity)
45822
45871
 
45823
45872
  def _updateDomainCounts(emailAddress):
45824
45873
  nonlocal domainCounts
@@ -45911,10 +45960,10 @@ def doPrintUsers(entityList=None):
45911
45960
  showDeleted = True
45912
45961
  elif entityList is None and myarg == 'select':
45913
45962
  _, entityList = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
45914
- elif myarg in SUSPENDED_ARGUMENTS:
45915
- isSuspended = _getIsSuspended(myarg)
45916
- elif myarg in ARCHIVED_ARGUMENTS:
45917
- isArchived = _getIsArchived(myarg)
45963
+ elif myarg == 'issuspended':
45964
+ isSuspended = getBoolean()
45965
+ elif myarg == 'isarchived':
45966
+ isArchived = getBoolean()
45918
45967
  elif myarg == 'orderby':
45919
45968
  orderBy, sortOrder = getOrderBySortOrder(USERS_ORDERBY_CHOICE_MAP)
45920
45969
  elif myarg == 'userview':
@@ -46092,6 +46141,8 @@ def doPrintUsers(entityList=None):
46092
46141
  # If no individual fields were specified (allfields, basic, full) or individual fields other than primaryEmail were specified, look up each user
46093
46142
  if isSuspended is not None and fieldsList:
46094
46143
  fieldsList.append('suspended')
46144
+ if isArchived is not None and fieldsList:
46145
+ fieldsList.append('archived')
46095
46146
  if projectionSet or len(set(fieldsList)) > 1 or showValidColumn:
46096
46147
  jcount = len(entityList)
46097
46148
  fields = getFieldsFromFieldsList(fieldsList)
@@ -103,7 +103,7 @@ gam print aliases [todrive <ToDriveAttribute>*]
103
103
  [limittoou <OrgUnitItem>])
104
104
  [user|users <EmailAddressList>] [group|groups <EmailAddressList>]
105
105
  [select <UserTypeEntity>]
106
- [aliasmatchpattern <REMatchPattern>]
106
+ [issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
107
107
  [shownoneditable] [nogroups] [nousers]
108
108
  [onerowpertarget] [delimiter <Character>]
109
109
  [suppressnoaliasrows]
@@ -117,6 +117,8 @@ By default, group and user aliases in all domains in the account are selected; t
117
117
  * `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`
118
118
  * `select <UserTypeEntity>` - Print aliases for users in `<UserTypeEntity>`
119
119
  * `group|groups <EmailAddressList>` - Print aliases for groups in `<EmailAddressList`
120
+ * `issuspended <Boolean>` - Limit users based on their status
121
+ * `isarchived <Boolean>` - Limit users based on their status
120
122
  * `aliasmatchpattern <REMatchPattern>` - Print aliases that match a pattern
121
123
  * `nogroups` - Print only user aliases
122
124
  * `nousers` - Print only group aliases
@@ -184,7 +184,7 @@ perform these steps and then retry the create project command.
184
184
 
185
185
  ## Authorize Service Account Key Uploads
186
186
 
187
- *IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [running GAM on Google Compute Engine Securely](https://github.com/GAM-team/GAM/wiki/l-Running-GAM-on-Google-Compute-Engine-(GCE)-Securely) so that service account keys are not necessary.
187
+ *IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [Running GAM7 securely on a Google Compute Engine](https://github.com/GAM-team/GAM/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine) (if running in Google Cloud) or [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) (if running outside Google Cloud) so that service account keys are not necessary.
188
188
 
189
189
  If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxxxx`,
190
190
  perform these steps and then you should be able to authorize and use your project.
@@ -325,6 +325,8 @@
325
325
  <CourseWorkState> ::= draft|published|deleted
326
326
  <CrOSID> ::= <String>
327
327
  <CustomerID> ::= <String>
328
+ <DateTimeFormat> ::= <String>
329
+ See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
328
330
  <DeliverySetting> ::=
329
331
  allmail|
330
332
  abridged|daily|
@@ -18,6 +18,9 @@ The variables `num_threads`, `num_tbatch_threads` and `auto_batch_min` in `gam.c
18
18
  * [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
19
19
  `gdoc <UserGoogleDoc>` and `gsheet <UserGoogleSheet>`
20
20
 
21
+ <DateTimeFormat> ::= <String>
22
+ See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
23
+
21
24
  ## Batch files
22
25
  There are two types of batch processing, one that uses processes and one that uses threads. Using processes is higher performance but `gam csv` commands are not supported.
23
26
  * `gam batch` - gam commands are run as processes, gam csv commands are not allowed in the batch file
@@ -45,6 +48,9 @@ Batch files can contain the following types of lines:
45
48
  * sleep \<Integer\> - Batch processing will suspend for \<Integer\> seconds before the next command line is processed
46
49
  * To be effective, this should immediately follow commit-batch
47
50
  * print \<String\> - Print \<String\> on stderr
51
+ * datetime \<DateTimeFormat\>
52
+ * The current time is formatted with \<DateTimeFormat\> and subsequent lines will have `%datetime%` replaced with the formatted time value.
53
+ * See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
48
54
  * set \<KeywordString\> \<ValueString\>
49
55
  * Subsequent lines will have %\<KeywordString\>% replaced with \<ValueString\>
50
56
  * clear \<KeywordString\>