Compare commits

...

57 Commits

Author SHA1 Message Date
Ross Scroggs
d8d68e8eb0 Updated gam create|update adminrole 2026-02-12 09:53:34 -08:00
Ross Scroggs
2196e70e7b Added variable csv_output_header_required to gam.cfg
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-11 16:19:28 -08:00
Ross Scroggs
4f79a29155 Added variable csv_output_header_required to gam.cfg
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-11 16:19:03 -08:00
Ross Scroggs
0290f0d0ce Replace teamdrive with shareddrive
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-10 21:31:07 -08:00
Ross Scroggs
b7c96a8172 Fixed bug in gam [<UserTypeEntity>] sendemail
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-10 14:01:06 -08:00
Ross Scroggs
fed1662eb4 Fixed bug in gam [<UserTypeEntity>] sendemail 2026-02-10 12:58:16 -08:00
Ross Scroggs
077747be99 Update No-Owner-Secondary-Calendars.md 2026-02-09 08:41:21 -08:00
Ross Scroggs
9eee475b4a Update No-Owner-Secondary-Calendars.md
Some checks failed
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2026-02-09 08:28:09 -08:00
Ross Scroggs
2636dd9827 Added hideinvitationssetting to <UserCalendarSettingsField>
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
CodeQL / Analyze (python) (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2026-02-07 06:55:26 -08:00
Ross Scroggs
e18a70e55b Added hideinvitationssetting to <UserCalendarSettingsField> 2026-02-07 06:55:07 -08:00
Ross Scroggs
e11123fccd Update Users-Gmail-Delegates.md 2026-02-07 06:51:43 -08:00
Ross Scroggs
536ea84321 Update No-Owner-Secondary-Calendars.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-06 12:45:36 -08:00
Ross Scroggs
4d953ac09b Update No-Owner-Secondary-Calendars.md 2026-02-06 12:43:54 -08:00
Ross Scroggs
d9ce0acd83 Secondary Calendars with no Owner 2026-02-06 12:42:07 -08:00
Ross Scroggs
f735e5e268 Added option shownopolicy to gam print chromepolicies
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
CodeQL / Analyze (python) (push) Has been cancelled
2026-02-05 12:14:11 -08:00
Ross Scroggs
97358d15ef Added option shownopolicy to `gam print chromepolicies 2026-02-05 11:27:19 -08:00
Ross Scroggs
ea0886229e Update gam.cfg.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-03 13:53:45 -08:00
Ross Scroggs
4e5462c704 Added variable developer_preview_apis to gam.cfg
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
CodeQL / Analyze (python) (push) Has been cancelled
2026-02-03 10:17:24 -08:00
Ross Scroggs
ed2291bedf Added variable developer_preview_apis to gam.cfg 2026-02-03 10:16:51 -08:00
Ross Scroggs
44ff2eba62 Added option includepermissionsforview published to print filelist/show fileinfo
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
CodeQL / Analyze (python) (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2026-01-31 10:16:26 -08:00
Ross Scroggs
77fb2d0693 Added option includepermissionsforview published to print filelist/show fileinfo 2026-01-31 09:58:40 -08:00
Ross Scroggs
cea5a33856 Added option includepermissionsforview published to print filelist/show fileinfo 2026-01-31 09:58:28 -08:00
Ross Scroggs
3a7f84e49d Update Cloud-Identity-Groups-Membership.md 2026-01-31 08:53:41 -08:00
Ross Scroggs
5136c0a268 Update Cloud-Identity-Groups-Membership.md 2026-01-31 08:49:48 -08:00
Ross Scroggs
8e877a938e Update Cloud-Identity-Groups-Membership.md 2026-01-31 08:45:47 -08:00
Ross Scroggs
ed695b234f Update GamUpdates.md
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2026-01-29 20:07:00 -08:00
Ross Scroggs
83179be184 Allow filtering on modifiedTime in copy drivefile 2026-01-29 19:36:04 -08:00
Ross Scroggs
8e105091d4 Allow filtering on modifiedTime in copy drivefile 2026-01-29 19:35:38 -08:00
Ross Scroggs
428be889a2 Merge branch 'main' of https://github.com/GAM-team/GAM
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-29 14:34:18 -08:00
Ross Scroggs
758519b1b3 Update Users-Calendars.md 2026-01-29 14:34:14 -08:00
Jay Lee
47e2ba95eb Change cryptography dependency version
Updated cryptography dependency version to 46.0.3. See if this works around win ARM64 issue:

https://github.com/pyca/cryptography/pull/14216
2026-01-29 16:28:52 -05:00
Ross Scroggs
881cbbea61 Force rebuild to see in Windows Arm openssl builds
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-29 09:43:45 -08:00
Ross Scroggs
3ebfb98a98 print messages bug fix - info user license update 2026-01-28 13:39:38 -08:00
Ross Scroggs
0dbd95832f print messages bug fix - info user license update 2026-01-28 12:48:08 -08:00
Ross Scroggs
78acf64f7b print messages bug fix - info user license update
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-28 12:45:28 -08:00
Ross Scroggs
4c7f03da7d Classroom student groups in general release
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-27 13:41:29 -08:00
Ross Scroggs
3ac28ef231 Classroom student groups in general release
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-27 13:40:30 -08:00
Ross Scroggs
7100abab12 Merge branch 'main' of https://github.com/GAM-team/GAM 2026-01-27 13:38:15 -08:00
Ross Scroggs
1d531d13e4 Classroom student groups in general release 2026-01-27 13:38:12 -08:00
Jay Lee
df5af20b49 actions: rebuild for OpenSSL 3.6.1
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-27 10:27:51 -05:00
Ross Scroggs
cfe6376c28 Update Users-Gmail-Send-As-Signature-Vacation.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2026-01-26 08:45:25 -08:00
Ross Scroggs
e271e18feb Update GamUpdates.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-25 20:47:09 -08:00
Ross Scroggs
33d579985a Added template to gam <UserTypeEntity> show signature 2026-01-25 20:34:17 -08:00
Ross Scroggs
887628ef87 Added template to gam <UserTypeEntity> show signature 2026-01-25 19:53:54 -08:00
Ross Scroggs
4a969e716e Add Code Wiki
Some checks failed
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2026-01-23 07:53:05 -08:00
Ross Scroggs
363c041bbb Update Other-Resources.md 2026-01-23 07:49:44 -08:00
Ross Scroggs
2e151eb81b Update Cloud-Identity-Groups-Membership.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-21 14:44:21 -08:00
Ross Scroggs
b7fe258aaf Update Cloud-Identity-Groups-Membership.md 2026-01-21 14:28:15 -08:00
Ross Scroggs
7a10f6627c Added variable oauth2_txt_lock_mode to gam.cfg
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-21 11:07:53 -08:00
Ross Scroggs
613cae987f Added variable oauth2_txt_lock_mode to gam.cfg 2026-01-21 09:55:50 -08:00
Ross Scroggs
cd34c3d1e2 Update Reports.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2026-01-20 14:34:14 -08:00
Ross Scroggs
899200399c Update ChromeOS-Devices.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-20 06:46:40 -08:00
Ross Scroggs
46c3f88280 Added addcsvdata to CrOS commands
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2026-01-18 21:47:40 -08:00
Ross Scroggs
3ddef79cbf Added addcsvdata to CrOS commands 2026-01-18 20:54:20 -08:00
Ross Scroggs
546f31c123 Update ChromeOS-Devices.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-18 20:42:11 -08:00
Ross Scroggs
443fca3f00 Update ChromeOS-Devices.md 2026-01-18 20:36:14 -08:00
Ross Scroggs
720d667b61 Multiple updates
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-01-18 10:05:39 -08:00
50 changed files with 1269 additions and 641 deletions

View File

@@ -153,7 +153,7 @@ jobs:
with:
path: |
cache.tar.xz
key: gam-${{ matrix.jid }}-20251218
key: gam-${{ matrix.jid }}-20260129
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'

View File

@@ -12,7 +12,7 @@ authors = [
dependencies = [
"arrow>=1.3.0",
"chardet>=5.2.0",
"cryptography>=44.0.2",
"cryptography==46.0.3",
"distro; sys_platform=='linux'",
"filelock>=3.18.0",
"google-api-python-client>=2.167.0",

View File

@@ -2472,13 +2472,17 @@ gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requir
take_a_screenshot
gam issuecommand cros <CrOSEntity> command <CrOSCommand>
[times_to_check_status <Integer>] [csv] [doit]
[times_to_check_status <Integer>] [doit]
[csv (addcsvdata <FieldName> <String>)*]
gam <CrOSTypeEntity> issuecommand command <CrOSCommand>
[times_to_check_status <Integer>] [csv] [doit]
[times_to_check_status <Integer>] [doit]
[csv (addcsvdata <FieldName> <String>)*]
gam getcommand cros <CrOSEntity> commandid <CommandID>
[times_to_check_status <Integer>] [csv]
[times_to_check_status <Integer>]
[csv (addcsvdata <FieldName> <String>)*]
gam <CrOSTypeEntity> getcommand commandid <CommandID>
[times_to_check_status <Integer>] [csv]
[times_to_check_status <Integer>]
[csv (addcsvdata <FieldName> <String>)*]
<CrOSAttribute> ::=
(asset|assetid|tag <String>)|
@@ -2785,21 +2789,23 @@ gam create chromepolicyimage <ChromePolicyImageSchemaName> <FileName>
gam update chromepolicy [convertcrnl]
(<SchemaName> ((<Field> <Value>)+ | <JSONData>))+
((ou|orgunit <OrgUnitItem>)|(cigroup <GroupItem>))
((ou|orgunit <OrgUnitItem>)|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
gam delete chromepolicy
(<SchemaName> [<JSONData>])+
((ou|orgunit <OrgUnitItem>)|(cigroup <GroupItem>))
((ou|orgunit <OrgUnitItem>)|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
gam show chromepolicies
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(cigroup <GroupItem>))
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
(filter <StringList>)* (namespace <NamespaceList>)*
[show all|direct|inherited]
[formatjson]
gam print chromepolicies [todrive <ToDriveAttribute>*]
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(cigroup <GroupItem>))
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
(filter <StringList>)* (namespace <NamespaceList>)*
[show all|direct|inherited] [shownopolicy]
[[formatjson [quotechar <Character>]]
<ChromePolicySchemaFieldName> ::=
@@ -6162,6 +6168,7 @@ Display a users calendar settings
defaulteventlength|
format24hourtime|
hideinvitations|
hideinvitationssetting|
hideweekends|
locale|
remindonrespondedeventsonly|
@@ -6884,6 +6891,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
[skipids <DriveFileEntity>]
[copysubfiles [<Boolean>]] [filenamematchpattern <REMatchPattern>]
[filemimetype [not] <MimeTypeList>] [filemimetype category <MimeTypeNameList>]
[([start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>])|(range <Date>|<Time> <Date>|<Time>)]|
[copysubfilesownedby
any|me|others|
users <EmailAddressList>|
@@ -6969,6 +6977,7 @@ gam <UserTypeEntity> info drivefile <DriveFileEntity>
[returnidonly]
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
[includepermissionsforview published]
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[showdrivename] [showshareddrivepermissions]
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
@@ -7452,6 +7461,7 @@ gam <UserTypeEntity> show fileinfo <DriveFileEntity>
[returnidonly]
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
[includepermissionsforview published]
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[showdrivename] [showshareddrivepermissions]
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
@@ -7565,6 +7575,7 @@ gam <UserTypeEntity> print filelist [todrive <ToDriveAttribute>*]
[sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>]
[filenamematchpattern <REMatchPattern>]
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] [pmfilter] [oneitemperrow]
[includepermissionsforview published]
[excludetrashed]
[maxfiles <Integer>] [nodataheaders <String>]
[countsonly [summary none|only|plus] [summaryuser <String>]
@@ -8036,7 +8047,7 @@ gam <UserTypeEntity> signature|sig
[html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
[name <String>]
[primary]
gam <UserTypeEntity> show signature|sig [compact|format|html]
gam <UserTypeEntity> show signature|sig [compact|format|html|template]
[primary|default] [verifyonly]
gam <UserTypeEntity> print signature [compact]
[primary|default] [verifyonly] [todrive <ToDriveAttribute>*]

View File

@@ -1,3 +1,130 @@
7.34.01
Updated `gam create|update adminrole` to handle the following errors:
```
ERROR: 400: invalid - Invalid Role privileges
ERROR: 400: required - Required parameter: [resource.privileges[n].service_id]
```
7.34.00
Added variable `csv_output_header_required` to `gam.cfg` that is a comma separated list of `<Strings>`
that are required to be in the list of column headers in the CSV file written by a gam print command.
This will typically be used to specify headers that are required in subsequent commands that process
the CSV file even if the API didn't return any data for those columns.
Updated the following commands to not require the `Directory API - Domains` scope
unless the `internal` or `external` options are used to request the member category.
```
gam info|print groups
gam print|show group-members
gam info|print cigroups
gam print|show cigroup-members
gam <UserTypeEntity> print|show filesharecounts
```
7.33.03
Fixed bug in `gam [<UserTypeEntity>] sendemail ... from <EmailAddress> replyto <EmailAddress>`
where an `<EmailAddress>` of the form `Text <user@domain.com>` had the `Text` removed.
7.33.02
Added `hideinvitationssetting` to `<UserCalendarSettingsField>` used by
`gam <UserTypeEntity> print|show calsettings`.
7.33.01
Added option `shownopolicy` to `gam print chromepolicies` that will display output like the following
if no policies apply to the selected OU or group.
```
gam print chromepolicies ou /Test appid chrome:emidddocikgklceeeifefomdnbkldhng namespace chrome.users.apps shownopolicy
Getting all Chrome Policies that match query (chrome.users.apps.*) for /Test
Got 0 Chrome Policies that matched query (chrome.users.apps.*) for /Test...
name,orgUnitPath,parentOrgUnitPath,direct,appId
noPolicy,/Test,/,False,chrome:emidddocikgklceeeifefomdnbkldhng
```
7.33.00
Added variable `developer_preview_apis` to `gam.cfg` that is a comma separated list of APIs requiring a Developer Preview key.
Currently, `chat` is the only API that requires a Developer Preview key; it is required for the User Sections commands.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#introduction
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-user-sections
7.32.07
Added option `includepermissionsforview published` to `gam <UserTypeEntity> print filelist` and
`gam <UserTypeEntity> show fileinfo`. From the Drive API documentation:
```
Specifies which additional view's permissions to include in the response. Only published is supported.
```
7.32.06
Added options to `gam <UserTypeEntity> copy drivefile ... copysubfiles` to limit copying
to files whose `modifiedTime` meets specified requirements.
* `start|starttime <Date>|<Time>` - If specified, `modifiedTime` must be >= the value
* `end|endtime <Date>|<Time>` - If specified, `modifiedTime` must be <= the value
* `range <Date>|<Time> <Date>|<Time>` - first value <= `modifiedTime` <= second value
7.32.05
Fixed bug in `gam <UserTypeEntity> print messages|threads ... headers <SMTPHeaderList>` where
headers other than those specified in `<SMTPHeaderList>` were displayed.
Updated `gam info users <UserTypeEntity>` to display the following data when the Licensing API
does not return data due to quota limits. Previously, no License data was displayed and
there was no way to know if it was omitted due to API quota limits vs the user has no license?
```
Licenses: (1)
Not available/incomplete
```
If a user has no licenses, this will be displayed.
```
Licenses: (0)
```
You should use `license_skus = <SKUIDList>` in `gam.cfg` to list all of the licensing SKUs
used in your workspace. Without this list, GAM has to make 70+ API calls to get the licenses
for a user; this can cause quota limit errors.
7.32.04
Support for student groups in Google Classroom no longer requires Developer Preview membership.
Upgraded to OpenSSL 3.6.1.
7.32.03
Added option `template` as an additional formating option for `gam <UserTypeEntity> show signature`
that displays just the HTML data; this simplifies capturing the data for use as input to GAM.
```
$ gam redirect stdout ./SigTemplate.html user user@domain.com show signature template
$ more SigTemplate.html
<div dir="ltr"><div dir="ltr"><div dir="ltr">
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Email: {Email}{/RT}</span></p>
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Phone: {Phone}{/RT}</span></p>
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Mobile: {Mobile}{/RT}</span></p>
</div><br></div>\n</div>
```
7.32.02
Added variable `oauth2_txt_lock_mode` to `gam.cfg`, the default is 644 and valid values are: 644, 664, 666.
This value is used to set the file permissions on the `oauth2.txt.lock` file. In very special cases where
daemon processes, e.g. Apache/httpd, are running GAM, the value 666 may have to be used.
7.32.01
Added option `(addcsvdata <FieldName> <String>)*` to `gam <CrOSTypeEntity> issuecommand command <CrOSCommand> csv`
and `gam <CrOSTypeEntity> getcommand commandid <CommandID> csv` that adds additional columns of data to the CSV file output.
* See: https://github.com/GAM-team/GAM/wiki/ChromeOS-Devices#bulk-action-example
7.32.00
Added option `verifyallowexternal` to `gam print cigroup-members|group-members` that causes
@@ -33,7 +160,7 @@ Fixed bug in `gam sendemail ... replyto <EmailAddress>` that caused a message de
Added support for users's chat sections.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-users-sections
* This is in Deveoper Preview.
* This is in Deveoper Preview; you must have a `developer_preview_api_key` in `gam.cfg` to use these commands.
7.31.06

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.32.00'
__version__ = '7.34.01'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
# pylint: disable=wrong-import-position
@@ -1331,6 +1331,8 @@ def validateEmailAddressOrUID(emailAddressOrUID, checkPeople=True, ciGroupsAPI=F
return emailAddressOrUID
return emailAddressOrUID.find('@') != 0 and emailAddressOrUID.count('@') <= 1
NAME_EMAIL_ADDRESS_PATTERN = re.compile(r'^(.*)<(.+)>$')
# Normalize user/group email address/uid
# uid:12345abc -> 12345abc
# foo -> foo@domain
@@ -1349,6 +1351,10 @@ def normalizeEmailAddressOrUID(emailAddressOrUID, noUid=False, checkForCustomerI
return cg.group(1)
if ciGroupsAPI and emailAddressOrUID.startswith('groups/'):
return emailAddressOrUID
if emailAddressOrUID.find('<') >= 0:
match = NAME_EMAIL_ADDRESS_PATTERN.match(emailAddressOrUID)
if match:
emailAddressOrUID = match.group(2)
atLoc = emailAddressOrUID.find('@')
if atLoc == 0:
return emailAddressOrUID[1:].lower() if not noLower else emailAddressOrUID[1:]
@@ -2308,10 +2314,10 @@ def getMatchSkipFields(fieldNames):
def checkMatchSkipFields(row, fieldnames, matchFields, skipFields):
for matchField, matchPattern in matchFields.items():
if (matchField not in row) or not matchPattern.search(row[matchField]):
if (matchField not in row) or not matchPattern.search(str(row[matchField])):
return False
for skipField, matchPattern in skipFields.items():
if (skipField in row) and matchPattern.search(row[skipField]):
if (skipField in row) and matchPattern.search(str(row[skipField])):
return False
if fieldnames and (GC.Values[GC.CSV_INPUT_ROW_FILTER] or GC.Values[GC.CSV_INPUT_ROW_DROP_FILTER]):
return RowFilterMatch(row, fieldnames,
@@ -3752,6 +3758,15 @@ def SetGlobalVariables():
if (productId, sku) not in GM.Globals[GM.LICENSE_SKUS]:
GM.Globals[GM.LICENSE_SKUS].append((productId, sku))
def _validateDeveloperPreviewAPIs(sectionName, itemName, apiList):
GM.Globals[GM.DEVELOPER_PREVIEW_APIS] = set()
validAPIs = API.getAPIsList()
for api in apiList.split(','):
if api in validAPIs:
GM.Globals[GM.DEVELOPER_PREVIEW_APIS].add(api)
else:
_printValueError(sectionName, itemName, api, f'{Msg.EXPECTED}: {",".join(sorted(validAPIs))}')
def _getCfgString(sectionName, itemName):
value = _stripStringQuotes(GM.Globals[GM.PARSER].get(sectionName, itemName))
if itemName == GC.DOMAIN:
@@ -3760,6 +3775,8 @@ def SetGlobalVariables():
if ((minLen is None) or (len(value) >= minLen)) and ((maxLen is None) or (len(value) <= maxLen)):
if itemName == GC.LICENSE_SKUS and value:
_validateLicenseSKUs(sectionName, itemName, value)
elif itemName == GC.DEVELOPER_PREVIEW_APIS and value:
_validateDeveloperPreviewAPIs(sectionName, itemName, value.lower())
return value
_printValueError(sectionName, itemName, f'"{value}"', f'{Msg.EXPECTED}: {integerLimits(minLen, maxLen, Msg.STRING_LENGTH)}')
return ''
@@ -4136,7 +4153,7 @@ def SetGlobalVariables():
GC.Values[itemName] = _getCfgPassword(sectionName, itemName)
elif varType == GC.TYPE_STRING:
GC.Values[itemName] = _getCfgString(sectionName, itemName)
elif varType in {GC.TYPE_STRINGLIST, GC.TYPE_HEADERFORCE, GC.TYPE_HEADERORDER}:
elif varType in {GC.TYPE_STRINGLIST, GC.TYPE_HEADERFORCEREQUIRED, GC.TYPE_HEADERORDER}:
GC.Values[itemName] = _getCfgStringList(sectionName, itemName)
elif varType == GC.TYPE_FILE:
GC.Values[itemName] = _getCfgFile(sectionName, itemName)
@@ -4160,6 +4177,7 @@ def SetGlobalVariables():
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER] = _getCfgHeaderFilter(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_FILTER)
GC.Values[GC.CSV_OUTPUT_HEADER_DROP_FILTER] = _getCfgHeaderFilter(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_DROP_FILTER)
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER] = _getCfgStringList(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_ORDER)
GC.Values[GC.CSV_OUTPUT_HEADER_REQUIRED] = _getCfgStringList(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_REQUIRED)
GC.Values[GC.CSV_OUTPUT_ROW_FILTER] = _getCfgRowFilter(outputFilterSectionName, GC.CSV_OUTPUT_ROW_FILTER)
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE] = _getCfgChoice(outputFilterSectionName, GC.CSV_OUTPUT_ROW_FILTER_MODE)
GC.Values[GC.CSV_OUTPUT_ROW_DROP_FILTER] = _getCfgRowFilter(outputFilterSectionName, GC.CSV_OUTPUT_ROW_DROP_FILTER)
@@ -4279,7 +4297,7 @@ def SetGlobalVariables():
if GM.Globals[GM.PID] == 0:
for itemName, itemEntry in sorted(GC.VAR_INFO.items()):
varType = itemEntry[GC.VAR_TYPE]
if varType in {GC.TYPE_HEADERFILTER, GC.TYPE_HEADERFORCE, GC.TYPE_HEADERORDER, GC.TYPE_ROWFILTER}:
if varType in {GC.TYPE_HEADERFILTER, GC.TYPE_HEADERFORCEREQUIRED, GC.TYPE_HEADERORDER, GC.TYPE_ROWFILTER}:
GM.Globals[GM.PARSER].set(sectionName, itemName, '')
elif (varType == GC.TYPE_INTEGER) and itemName in {GC.CSV_INPUT_ROW_LIMIT, GC.CSV_OUTPUT_ROW_LIMIT}:
GM.Globals[GM.PARSER].set(sectionName, itemName, '0')
@@ -4294,6 +4312,8 @@ def SetGlobalVariables():
GC.Values[GC.CSV_OUTPUT_HEADER_FORCE] = GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE][:]
if not GC.Values[GC.CSV_OUTPUT_HEADER_ORDER]:
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER] = GM.Globals[GM.CSV_OUTPUT_HEADER_ORDER][:]
if not GC.Values[GC.CSV_OUTPUT_HEADER_REQUIRED]:
GC.Values[GC.CSV_OUTPUT_HEADER_REQUIRED] = GM.Globals[GM.CSV_OUTPUT_HEADER_REQUIRED][:]
if not GC.Values[GC.CSV_OUTPUT_ROW_FILTER]:
GC.Values[GC.CSV_OUTPUT_ROW_FILTER] = GM.Globals[GM.CSV_OUTPUT_ROW_FILTER][:]
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE] = GM.Globals[GM.CSV_OUTPUT_ROW_FILTER_MODE]
@@ -4748,7 +4768,7 @@ def getClientCredentials(forceRefresh=False, forceWrite=False, filename=None, ap
"""Gets OAuth2 credentials which are guaranteed to be fresh and valid.
Locks during read and possible write so that only one process will
attempt refresh/write when running in parallel. """
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK])
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], mode=GC.Values[GC.OAUTH2_TXT_LOCK_MODE])
with lock:
writeCreds, credentials = getOauth2TxtCredentials(api=api, noDASA=noDASA, refreshOnly=refreshOnly, noScopes=noScopes)
if not credentials:
@@ -4820,11 +4840,12 @@ def getService(api, httpObj):
triesLimit = 3
for n in range(1, triesLimit+1):
try:
if api not in {API.CHAT, API.CLASSROOM} or not GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]:
if api not in GM.Globals[GM.DEVELOPER_PREVIEW_APIS] or not GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]:
discoveryServiceUrl = DISCOVERY_URIS[v2discovery]
developerKey = ''
else:
discoveryServiceUrl = DEVELOPER_PREVIEW_DISCOVERY_URI
developerKey = GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]
developerKey = GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]
service = googleapiclient.discovery.build(api, version, http=httpObj, cache_discovery=False,
discoveryServiceUrl=discoveryServiceUrl, developerKey=developerKey, static_discovery=False)
GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {})
@@ -6066,7 +6087,7 @@ def _checkMemberCategory(member, memberDisplayOptions):
if memberDisplayOptions['showCategory']:
member['category'] = category
if memberDisplayOptions['checkCategory']:
return True if memberDisplayOptions[category] else False
return bool(memberDisplayOptions[category])
return True
def _checkCIMemberCategory(member, memberDisplayOptions):
@@ -6079,7 +6100,7 @@ def _checkCIMemberCategory(member, memberDisplayOptions):
if memberDisplayOptions['showCategory']:
member['category'] = category
if memberDisplayOptions['checkCategory']:
return True if memberDisplayOptions[category] else False
return bool(memberDisplayOptions[category])
return True
def getCIGroupMemberRoleFixType(member):
@@ -7316,8 +7337,6 @@ def _addEmbeddedImagesToMessage(message, embeddedImages):
except (IOError, UnicodeDecodeError) as e:
usageErrorExit(f'{imageFilename}: {str(e)}')
NAME_EMAIL_ADDRESS_PATTERN = re.compile(r'^.*<(.+)>$')
# Send an email
def send_email(msgSubject, msgBody, msgTo, i=0, count=0, clientAccess=False, msgFrom=None, msgReplyTo=None,
html=False, charset=UTF8, attachments=None, embeddedImages=None,
@@ -7339,8 +7358,11 @@ def send_email(msgSubject, msgBody, msgTo, i=0, count=0, clientAccess=False, msg
def cleanAddr(emailAddr):
match = NAME_EMAIL_ADDRESS_PATTERN.match(emailAddr)
if match:
return match.group(1)
return emailAddr
emailName = match.group(1)
emailAddr = normalizeEmailAddressOrUID(match.group(2), noUid=True, noLower=True)
return (f'{emailName} <{emailAddr}>', emailAddr)
emailAddr = normalizeEmailAddressOrUID(emailAddr, noUid=True, noLower=True)
return (emailAddr, emailAddr)
if msgFrom is None:
msgFrom = _getAdminEmail()
@@ -7360,9 +7382,9 @@ def send_email(msgSubject, msgBody, msgTo, i=0, count=0, clientAccess=False, msg
if embeddedImages:
_addEmbeddedImagesToMessage(message, embeddedImages)
message['Subject'] = msgSubject
message['From'] = normalizeEmailAddressOrUID(cleanAddr(msgFrom), noUid=True, noLower=True)
message['From'], msgFromAddr = cleanAddr(msgFrom)
if msgReplyTo is not None:
message['Reply-To'] = normalizeEmailAddressOrUID(cleanAddr(msgReplyTo), noUid=True, noLower=True)
message['Reply-To'], _ = cleanAddr(msgReplyTo)
if ccRecipients:
message['Cc'] = ccRecipients.lower()
if bccRecipients:
@@ -7372,8 +7394,8 @@ def send_email(msgSubject, msgBody, msgTo, i=0, count=0, clientAccess=False, msg
if header not in {'Subject', 'From', 'To', 'Reply-To', 'Cc', 'Bcc'}:
message[header] = value
if mailBox is None:
mailBox = msgFrom
mailBoxAddr = normalizeEmailAddressOrUID(cleanAddr(mailBox), noUid=True, noLower=True)
mailBox = msgFromAddr
_, mailBoxAddr = cleanAddr(mailBox)
action = Act.Get()
Act.Set(Act.SENDEMAIL)
if not GC.Values[GC.SMTP_HOST]:
@@ -7903,6 +7925,7 @@ class CSVPrintFile():
self.JSONtitlesList = []
self.sortHeaders = []
self.SetHeaderForce(GC.Values[GC.CSV_OUTPUT_HEADER_FORCE])
self.SetHeaderRequired(GC.Values[GC.CSV_OUTPUT_HEADER_REQUIRED])
if not self.headerForce and titles is not None:
self.SetTitles(titles)
self.SetJSONTitles(titles)
@@ -8619,6 +8642,9 @@ class CSVPrintFile():
self.SetTitles(headerForce)
self.SetJSONTitles(headerForce)
def SetHeaderRequired(self, headerRequired):
self.headerRequired = headerRequired
def SetHeaderOrder(self, headerOrder):
self.headerOrder = headerOrder
@@ -9062,6 +9088,8 @@ class CSVPrintFile():
extrasaction = 'raise'
if not self.formatJSON:
if not self.headerForce:
if self.headerRequired:
self.AddTitles(self.headerRequired)
self.SortTitles()
self.SortIndexedTitles(self.titlesList)
if self.fixPaths:
@@ -9079,6 +9107,17 @@ class CSVPrintFile():
titlesList = self.titlesList
else:
if not self.headerForce:
if self.headerRequired:
for i, v in enumerate(self.JSONtitlesList):
if v.startswith('JSON'):
j = i
for title in self.headerRequired:
self.JSONtitlesList.insert(j, title)
self.JSONtitlesSet.add(title)
j += 1
break
else:
self.AddJSONTitles(self.headerRequired)
if self.fixPaths:
self.FixPathsTitles(self.JSONtitlesList)
if not self.rows and self.nodataFields is not None:
@@ -9888,7 +9927,7 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
csvColumnDelimiter, csvNoEscapeChar, csvQuoteChar,
csvSortHeaders, csvTimestampColumn,
csvHeaderFilter, csvHeaderDropFilter,
csvHeaderForce, csvHeaderOrder,
csvHeaderForce, csvHeaderOrder, csvHeaderRequired,
csvRowFilter, csvRowFilterMode, csvRowDropFilter, csvRowDropFilterMode,
csvRowLimit,
showGettings, showGettingsGotNL,
@@ -9913,6 +9952,7 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER] = csvHeaderFilter[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE] = csvHeaderForce[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_ORDER] = csvHeaderOrder[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_REQUIRED] = csvHeaderRequired[:]
GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = csvQuoteChar
GM.Globals[GM.CSV_OUTPUT_ROW_DROP_FILTER] = csvRowDropFilter[:]
GM.Globals[GM.CSV_OUTPUT_ROW_DROP_FILTER_MODE] = csvRowDropFilterMode
@@ -10137,6 +10177,7 @@ def MultiprocessGAMCommands(items, showCmds):
GC.Values[GC.CSV_OUTPUT_HEADER_DROP_FILTER],
GC.Values[GC.CSV_OUTPUT_HEADER_FORCE],
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER],
GC.Values[GC.CSV_OUTPUT_HEADER_REQUIRED],
GC.Values[GC.CSV_OUTPUT_ROW_FILTER],
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE],
GC.Values[GC.CSV_OUTPUT_ROW_DROP_FILTER],
@@ -10760,7 +10801,7 @@ Continue to authorization by entering a 'c'
menu = oauth2_menu % tuple(range(numScopes))
selectedScopes = ['*'] * numScopes
if currentScopes is None and clientAccess:
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK])
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], mode=GC.Values[GC.OAUTH2_TXT_LOCK_MODE])
with lock:
_, credentials = getOauth2TxtCredentials(exitOnError=False)
if credentials and credentials.scopes is not None:
@@ -11258,7 +11299,7 @@ def doOAuthRequest(currentScopes, login_hint, verifyScopes=False):
access_type='offline',
login_hint=login_hint,
open_browser=not GC.Values[GC.NO_BROWSER])
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK])
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], mode=GC.Values[GC.OAUTH2_TXT_LOCK_MODE])
with lock:
writeClientCredentials(credentials, GC.Values[GC.OAUTH2_TXT])
entityActionPerformed([Ent.OAUTH2_TXT_FILE, GC.Values[GC.OAUTH2_TXT]])
@@ -11308,7 +11349,7 @@ def exitIfNoOauth2Txt():
def doOAuthDelete():
checkForExtraneousArguments()
exitIfNoOauth2Txt()
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], timeout=10)
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], mode=GC.Values[GC.OAUTH2_TXT_LOCK_MODE], timeout=10)
with lock:
_, credentials = getOauth2TxtCredentials(noScopes=True)
if not credentials:
@@ -11392,7 +11433,7 @@ def doOAuthUpdate():
login_hint = getEmailAddress(noUid=True, optional=True)
checkForExtraneousArguments()
exitIfNoOauth2Txt()
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK])
lock = FileLock(GM.Globals[GM.OAUTH2_TXT_LOCK], mode=GC.Values[GC.OAUTH2_TXT_LOCK_MODE])
with lock:
jsonData = readFile(GC.Values[GC.OAUTH2_TXT], continueOnError=True, displayError=False)
if not jsonData:
@@ -16951,12 +16992,13 @@ def doCreateUpdateAdminRoles():
if not updateCmd:
result = callGAPI(cd.roles(), 'insert',
throwReasons=[GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED]+[GAPI.DUPLICATE],
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED]+[GAPI.DUPLICATE, GAPI.INVALID, GAPI.REQUIRED],
customer=GC.Values[GC.CUSTOMER_ID], body=body, fields=fieldsList)
else:
result = callGAPI(cd.roles(), 'patch',
throwReasons=[GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED]+[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.CONFLICT],
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED]+[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION,
GAPI.CONFLICT, GAPI.INVALID, GAPI.REQUIRED],
customer=GC.Values[GC.CUSTOMER_ID], roleId=roleId, body=body, fields=fieldsList)
if not csvPF:
entityActionPerformed([Ent.ADMIN_ROLE, f"{result['roleName']}({result['roleId']})"])
@@ -16974,7 +17016,7 @@ def doCreateUpdateAdminRoles():
row.update(addCSVData)
row['JSON'] = json.dumps(cleanJSON(result), ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
except GAPI.duplicate as e:
except (GAPI.duplicate, GAPI.invalid, GAPI.required) as e:
entityActionFailedWarning([Ent.ADMIN_ROLE, f"{body['roleName']}"], str(e))
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.conflict) as e:
entityActionFailedWarning([Ent.ADMIN_ROLE, roleId], str(e))
@@ -24022,7 +24064,7 @@ CROS_KIOSK_COMMANDS = {'REBOOT', 'SET_VOLUME', 'TAKE_A_SCREENSHOT'}
CROS_COMMAND_FINAL_STATES = {'EXPIRED', 'CANCELLED', 'EXECUTED_BY_CLIENT'}
CROS_COMMAND_TIME_OBJECTS = {'executeTime', 'issueTime', 'commandExpireTime'}
def displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF=None):
def displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF, addCSVData):
Ind.Increment()
try:
for _ in range(0, checkResultRetries):
@@ -24032,6 +24074,8 @@ def displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, cou
customerId=GC.Values[GC.CUSTOMER_ID], deviceId=deviceId, commandId=commandId)
if csvPF:
result['deviceId'] = deviceId
if addCSVData:
result.update(addCSVData)
csvPF.WriteRowTitles(flattenJSON(result, timeObjects=CROS_COMMAND_TIME_OBJECTS))
return
showJSON(None, result, timeObjects=CROS_COMMAND_TIME_OBJECTS)
@@ -24042,11 +24086,21 @@ def displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, cou
entityActionFailedWarning([Ent.CROS_DEVICE, deviceId, Ent.COMMAND_ID, commandId], str(e), i, count)
Ind.Decrement()
def writeCrOSCommandResults(csvPF, addCSVData):
sortTitles = ['deviceId']
if addCSVData:
sortTitles.extend(sorted(addCSVData.keys()))
sortTitles.append('commandId')
csvPF.SetSortTitles(sortTitles)
csvPF.writeCSVfile('CrOS Commands')
# gam <CrOSTypeEntity> issuecommand command <CrOSCommand>
# [times_to_check_status <Integer>] [csv] [doit]
# [times_to_check_status <Integer>] [doit]
# [csv (addcsvdata <FieldName> <String>)*]
def issueCommandCrOSDevices(entityList):
cd = buildGAPIObject(API.DIRECTORY)
csvPF = None
addCSVData = {}
body = {}
checkResultRetries = 1
doit = False
@@ -24059,7 +24113,9 @@ def issueCommandCrOSDevices(entityList):
elif myarg == 'timestocheckstatus':
checkResultRetries = getInteger(minVal=0)
elif myarg == 'csv':
csvPF = CSVPrintFile(['deviceId'], 'sortall')
csvPF = CSVPrintFile(['deviceId'])
elif csvPF and myarg == 'addcsvdata':
getAddCSVData(addCSVData)
elif myarg == 'doit':
doit = True
else:
@@ -24078,7 +24134,7 @@ def issueCommandCrOSDevices(entityList):
customerId=GC.Values[GC.CUSTOMER_ID], deviceId=deviceId, body=body)
commandId = result.get('commandId')
entityActionPerformed([Ent.CROS_DEVICE, deviceId, Ent.ACTION, body['commandType'], Ent.COMMAND_ID, commandId], i, count)
displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF)
displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF, addCSVData)
except GAPI.invalidArgument as e:
errMsg = str(e)
if body['commandType'] in CROS_KIOSK_COMMANDS:
@@ -24087,18 +24143,21 @@ def issueCommandCrOSDevices(entityList):
except GAPI.notFound as e:
entityActionFailedWarning([Ent.CROS_DEVICE, deviceId], str(e), i, count)
if csvPF:
csvPF.writeCSVfile('CrOS Commands')
writeCrOSCommandResults(csvPF, addCSVData)
# gam issuecommand <CrOSEntity> command <CrOSCommand>
# [times_to_check_status <Integer>] [csv] [doit]
# [times_to_check_status <Integer>] [doit]
# [csv (addcsvdata <FieldName> <String>)*]
def doIssueCommandCrOSDevices():
issueCommandCrOSDevices(getCrOSDeviceEntity())
# gam <CrOSTypeEntity> getcommand commandid <CommandID>
# [times_to_check_status <Integer>] [csv]
# [csv (addcsvdata <FieldName> <String>)*]
def getCommandResultCrOSDevices(entityList):
cd = buildGAPIObject(API.DIRECTORY)
csvPF = None
addCSVData = {}
commandId = ''
checkResultRetries = 1
while Cmd.ArgumentsRemaining():
@@ -24108,7 +24167,9 @@ def getCommandResultCrOSDevices(entityList):
elif myarg == 'timestocheckstatus':
checkResultRetries = getInteger(minVal=0)
elif myarg == 'csv':
csvPF = CSVPrintFile(['deviceId'], 'sortall')
csvPF = CSVPrintFile(['deviceId'])
elif csvPF and myarg == 'addcsvdata':
getAddCSVData(addCSVData)
else:
unknownArgumentExit()
if not commandId:
@@ -24117,12 +24178,13 @@ def getCommandResultCrOSDevices(entityList):
for deviceId in entityList:
i += 1
printEntity([Ent.CROS_DEVICE, deviceId, Ent.COMMAND_ID, commandId], i, count)
displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF)
displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, count, csvPF, addCSVData)
if csvPF:
csvPF.writeCSVfile('CrOS Commands')
writeCrOSCommandResults(csvPF, addCSVData)
# gam getcommand <CrOSEntity> commandid <CommandID>
# [times_to_check_status <Integer>] [csv]
# [csv (addcsvdata <FieldName> <String>)*]
def doGetCommandResultCrOSDevices():
getCommandResultCrOSDevices(getCrOSDeviceEntity())
@@ -27043,6 +27105,8 @@ def createUpdateChatSection(users):
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
continue
except AttributeError:
systemErrorExit(GOOGLE_API_ERROR_RC, Msg.DEVELOPER_PREVIEW_REQUIRED)
# gam <UserTypeEntity> delete chatsection <ChatSection>
def deleteChatSection(users):
@@ -27073,6 +27137,8 @@ def deleteChatSection(users):
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
continue
except AttributeError:
systemErrorExit(GOOGLE_API_ERROR_RC, Msg.DEVELOPER_PREVIEW_REQUIRED)
# gam <UserTypeEntity> show chatsections
# [formatjson]
@@ -27107,6 +27173,8 @@ def printShowChatSections(users):
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
continue
except AttributeError:
systemErrorExit(GOOGLE_API_ERROR_RC, Msg.DEVELOPER_PREVIEW_REQUIRED)
jcount = len(sections)
if jcount == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC)
@@ -27161,6 +27229,8 @@ def moveShowChatSectionItem(users):
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
continue
except AttributeError:
systemErrorExit(GOOGLE_API_ERROR_RC, Msg.DEVELOPER_PREVIEW_REQUIRED)
# gam <UserTypeEntity> show chatsectionitems <ChatSection>
# [space <ChatSpace>]
@@ -27232,6 +27302,8 @@ def printShowChatSectionItems(users):
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
continue
except AttributeError:
systemErrorExit(GOOGLE_API_ERROR_RC, Msg.DEVELOPER_PREVIEW_REQUIRED)
jcount = len(sectionItems)
if jcount == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC)
@@ -30047,7 +30119,7 @@ CHROME_POLICY_SHOW_CHOICE_MAP = {
# ((ou|orgunit <OrgUnitItem>)|(group <GroupItem>))
# [(printerid <PrinterID>)|(appid <AppID>)]
# (filter <StringList>)* (namespace <NamespaceList>)*
# [show all|direct|inherited]
# [show all|direct|inherited] [shownopolicy]
# [[formatjson [quotechar <Character>]]
def doPrintShowChromePolicies():
def normalizedPolicy(policy):
@@ -30118,25 +30190,54 @@ def doPrintShowChromePolicies():
showJSON(None, policy, sortDictKeys=False)
Ind.Decrement()
def _printPolicyRow(policy):
row = flattenJSON(policy)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(row):
if entityType == Ent.ORGANIZATIONAL_UNIT:
csvPF.WriteRowNoFilter({'name': policy['name'],
'orgUnitPath': policy['orgUnitPath'],
'parentOrgUnitPath': policy['parentOrgUnitPath'],
'direct': policy['direct'],
'JSON': json.dumps(cleanJSON(policy),
ensure_ascii=False, sort_keys=True)})
else:
csvPF.WriteRowNoFilter({'name': policy['name'],
'group': policy['group'],
'JSON': json.dumps(cleanJSON(policy),
ensure_ascii=False, sort_keys=True)})
def _printPolicy(policy):
nonlocal policiesShown
policy = normalizedPolicy(policy)
if (entityType == Ent.GROUP) or showPolicies in (CHROME_POLICY_SHOW_ALL, policy['direct']):
row = flattenJSON(policy)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(row):
if entityType == Ent.ORGANIZATIONAL_UNIT:
csvPF.WriteRowNoFilter({'name': policy['name'],
'orgUnitPath': policy['orgUnitPath'],
'parentOrgUnitPath': policy['parentOrgUnitPath'],
'direct': policy['direct'],
'JSON': json.dumps(cleanJSON(policy),
ensure_ascii=False, sort_keys=True)})
else:
csvPF.WriteRowNoFilter({'name': policy['name'],
'group': policy['group'],
'JSON': json.dumps(cleanJSON(policy),
ensure_ascii=False, sort_keys=True)})
policiesShown += 1
_printPolicyRow(policy)
def _printNoPolicy():
nonlocal targetName
policy = {'name': 'noPolicy'}
if app_id:
policy['appId'] = app_id
elif printer_id:
policy['printerId'] = printer_id
if entityType == Ent.ORGANIZATIONAL_UNIT:
policy['orgUnitPath'] = targetName
if targetName == '/':
policy['parentOrgUnitPath'] = '/'
else:
targetName = makeOrgUnitPathRelative(targetName)
policy['parentOrgUnitPath'] = callGAPI(cd.orgunits(), 'get',
throwReasons=GAPI.ORGUNIT_GET_THROW_REASONS,
customerId=GC.Values[GC.CUSTOMER_ID],
orgUnitPath=encodeOrgUnitPath(targetName),
fields='parentOrgUnitPath')['parentOrgUnitPath']
policy['direct'] = False
else:
policy['group'] = targetName
_printPolicyRow(policy)
cp = buildGAPIObject(API.CHROMEPOLICY)
cd = buildGAPIObject(API.DIRECTORY)
@@ -30148,6 +30249,8 @@ def doPrintShowChromePolicies():
app_id = groupEmail = orgUnit = printer_id = targetResource = None
showPolicies = CHROME_POLICY_SHOW_ALL
psFilters = []
showNoPolicy = False
policiesShown = 0
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -30171,6 +30274,8 @@ def doPrintShowChromePolicies():
psFilters.append(f'{psFilter}.*')
elif myarg == 'show':
showPolicies = getChoice(CHROME_POLICY_SHOW_CHOICE_MAP, mapChoice=True)
elif csvPF and myarg == 'shownopolicy':
showNoPolicy = True
else:
FJQC.GetFormatJSONQuoteChar(myarg, False)
checkPolicyArgs(targetResource, printer_id, app_id)
@@ -30260,7 +30365,8 @@ def doPrintShowChromePolicies():
else:
for policy in policies:
_printPolicy(policy)
if csvPF:
if showNoPolicy and policiesShown == 0:
_printNoPolicy()
csvPF.writeCSVfile(f'Chrome Policies - {targetName}')
CHROME_IMAGE_SCHEMAS_MAP = {
@@ -34763,13 +34869,14 @@ def finalizeInternalDomains(cd, internalDomains):
return internalDomains
def finalizeIPSGMGroupRolesMemberDisplayOptions(cd, memberDisplayOptions, verifyAllowExternal):
memberDisplayOptions['internalDomains'] = finalizeInternalDomains(cd, memberDisplayOptions['internalDomains'])
if verifyAllowExternal:
memberDisplayOptions['external'] = memberDisplayOptions['checkCategory'] = memberDisplayOptions['showCategory'] = True
memberDisplayOptions['internal'] = False
if memberDisplayOptions['showCategory']:
memberDisplayOptions['gs'] = buildGAPIObject(API.GROUPSSETTINGS)
memberDisplayOptions['checkShowCategory'] = memberDisplayOptions['checkCategory'] or memberDisplayOptions['showCategory']
if memberDisplayOptions['checkShowCategory']:
memberDisplayOptions['internalDomains'] = finalizeInternalDomains(cd, memberDisplayOptions['internalDomains'])
return memberDisplayOptions['showCategory'], memberDisplayOptions['checkShowCategory']
GROUP_FIELDS_CHOICE_MAP = {
@@ -45885,6 +45992,20 @@ def verifyUserPrimaryEmail(cd, user, createIfNotFound, i, count):
entityUnknownWarning(Ent.USER, user, i, count)
return False
# gam create guestuser <EmailAddress>
def doCreateGuestUser():
cd = buildGAPIObject(API.DIRECTORY)
body = {'primaryGuestEmail': getEmailAddress(noUid=True),
'customer': GC.Values[GC.CUSTOMER_ID]}
checkForExtraneousArguments()
try:
result = callGAPI(cd.users(), 'createGuest',
throwReasons=[GAPI.FAILED_PRECONDITION],
body=body)
entityActionPerformed([Ent.GUEST_USER, result['primaryGuestEmail']])
except (GAPI.failedPrecondition) as e:
entityActionFailedExit([Ent.GUEST_USER, body['primaryGuestEmail']], str(e))
# gam <UserTypeEntity> update user <UserAttribute>*
# [verifynotinvitable|alwaysevict] [noactionifalias]
# [updateprimaryemail <RESEarchPattern> <RESubstitution>]
@@ -46364,6 +46485,7 @@ def getUserLicenses(lic, user, skus):
if sku_calls:
if try_count >= 5:
# give up and return what we have
licenses.append('Not available/incomplete')
return licenses
time.sleep(5)
return licenses
@@ -47016,7 +47138,7 @@ def infoUsers(entityList):
if max(seen_group_count.values()) > 1:
printLine(f'{Ind.Spaces()}* {Msg.USER_HAS_MULTIPLE_DIRECT_OR_INHERITED_MEMBERSHIPS_IN_GROUP}')
Ind.Decrement()
if licenses:
if getLicenses:
printEntitiesCount(Ent.LICENSE, licenses)
Ind.Increment()
for u_license in licenses:
@@ -52812,7 +52934,6 @@ def doCreateCourseStudentGroups():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
**kwargs)
kvList[-1] = f"{studentGroup['title']}({studentGroup['id']})"
if not csvPF:
@@ -52859,7 +52980,6 @@ def doUpdateCourseStudentGroups():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
**kwargs)
kvList[-1] = f"{studentGroup['title']}({studentGroup['id']})"
entityActionPerformed(kvList)
@@ -52893,7 +53013,6 @@ def doDeleteCourseStudentGroups():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
**kwargs)
entityActionPerformed(kvList, i, count)
except GAPI.notFound as e:
@@ -52938,7 +53057,6 @@ def doClearCourseStudentGroups():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
courseId=courseId)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
@@ -52959,7 +53077,6 @@ def doClearCourseStudentGroups():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
**kwargs)
entityActionPerformed(kvList, j, jcount)
except GAPI.notFound as e:
@@ -53033,7 +53150,6 @@ def doPrintCourseStudentGroups(showMembers=False):
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
courseId=courseId)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
@@ -53068,7 +53184,6 @@ def doPrintCourseStudentGroups(showMembers=False):
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
courseId=courseId, studentGroupId=studentGroupId)
if showItemCountOnly:
itemCount += len(students)
@@ -53136,7 +53251,6 @@ def doProcessCourseStudentGroupMembers():
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
courseId=courseId, studentGroupId=studentGroupId)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], str(e))
@@ -53172,7 +53286,6 @@ def doProcessCourseStudentGroupMembers():
GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
previewVersion='V1_20250630_PREVIEW',
**kwargs)
entityActionPerformed(kvList, i, count)
except (GAPI.alreadyExists, GAPI.notFound) as e:
@@ -54099,6 +54212,7 @@ USER_CALENDAR_SETTINGS_FIELDS_CHOICE_MAP = {
'defaulteventlength': 'defaultEventLength',
'format24hourtime': 'format24HourTime',
'hideinvitations': 'hideInvitations',
'hideinvitationssetting': 'hideInvitationsSetting',
'hideweekends': 'hideWeekends',
'locale': 'locale',
'remindonrespondedeventsonly': 'remindOnRespondedEventsOnly',
@@ -57268,6 +57382,31 @@ FILEPATH_FIELDS = ','.join(FILEPATH_FIELDS_TITLES)
DRIVE_TIME_OBJECTS = {'createdTime', 'viewedByMeTime', 'modifiedByMeTime', 'modifiedTime', 'restrictionTime', 'sharedWithMeTime', 'trashedTime'}
def _getIncludeLabels(includeLabels):
labelIds = getEntityList(Cmd.OB_CLASSIFICATION_LABEL_ID, shlexSplit=True)
for labelId in labelIds:
includeLabels.add(normalizeDriveLabelID(labelId))
def _finalizeIncludeLabels(includeLabels):
if includeLabels:
return ','.join(includeLabels)
return None
DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES = ['published']
def _getIncludePermissionsForView(includePermissionsForView):
ipfwList = getEntityList(Cmd.OB_STRING_LIST)
for ipfw in ipfwList:
if ipfw in DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES:
includePermissionsForView.add(ipfw)
else:
invalidChoiceExit(ipfw, DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES, True)
def _finalizeIncludePermissionsForView(includePermissionsForView):
if includePermissionsForView:
return ','.join(includePermissionsForView)
return None
def _getDriveFieldSubField(field, fieldsList, parentsSubFields):
field, subField = field.split('.', 1)
if field in DRIVE_SUBFIELDS_CHOICE_MAP:
@@ -57294,7 +57433,8 @@ class DriveFileFields():
self.allFields = False
self.OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
self.fieldsList = []
self.includeLabels = []
self.includeLabels = set()
self.includePermissionsForView = set()
self.parentsSubFields = {'id': False, 'isRoot': False, 'rootFolderId': None}
def SetAllParentsSubFields(self):
@@ -57328,9 +57468,9 @@ class DriveFileFields():
else:
_getDriveFieldSubField(field, self.fieldsList, self.parentsSubFields)
elif myarg == 'includelabels':
labelIds = getEntityList(Cmd.OB_CLASSIFICATION_LABEL_ID, shlexSplit=True)
for labelId in labelIds:
self.includeLabels.append(normalizeDriveLabelID(labelId))
_getIncludeLabels(self.includeLabels)
elif myarg == 'includepermissionsforview':
_getIncludePermissionsForView(self.includePermissionsForView)
elif myarg.find('.') != -1:
_getDriveFieldSubField(myarg, self.fieldsList, self.parentsSubFields)
elif myarg == 'orderby':
@@ -57390,6 +57530,7 @@ def _formatFileDriveLabels(showLabels, labels, result, printMode, delimiter):
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [showdrivename] [showshareddrivepermissions]
# [(showlabels details|ids)|(includelabels <DriveLabelIDList>)]
# [includepermissionsforview published]
# [showparentsidsaslist] [followshortcuts [<Boolean>]]
# [stripcrsfromname] [formatjson]
# gam <UserTypeEntity> show fileinfo <DriveFileEntity>
@@ -57399,6 +57540,7 @@ def _formatFileDriveLabels(showLabels, labels, result, printMode, delimiter):
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [showdrivename] [showshareddrivepermissions]
# [(showlabels details|ids)|(includelabels <DriveLabelIDList>)]
# [includepermissionsforview published]
# [showparentsidsaslist] [followshortcuts [<Boolean>]]
# [stripcrsfromname] [formatjson]
def showFileInfo(users):
@@ -57461,7 +57603,8 @@ def showFileInfo(users):
DFF.SetAllParentsSubFields()
skipObjects = skipObjects.union(DEFAULT_SKIP_OBJECTS)
showNoParents = True
includeLabels = ','.join(DFF.includeLabels)
includeLabels = _finalizeIncludeLabels(DFF.includeLabels)
includePermissionsForView = _finalizeIncludePermissionsForView(DFF.includePermissionsForView)
pathFields = FILEPATH_FIELDS
i, count, users = getEntityArgument(users)
for user in users:
@@ -57500,12 +57643,14 @@ def showFileInfo(users):
try:
result = callGAPI(drive.files(), 'get',
throwReasons=GAPI.DRIVE_GET_THROW_REASONS+[GAPI.INVALID],
fileId=fileId, includeLabels=includeLabels, fields=fields, supportsAllDrives=True)
fileId=fileId, includeLabels=includeLabels, includePermissionsForView=includePermissionsForView,
fields=fields, supportsAllDrives=True)
if followShortcuts and result['mimeType'] == MIMETYPE_GA_SHORTCUT:
fileId = result['shortcutDetails']['targetId']
result = callGAPI(drive.files(), 'get',
throwReasons=GAPI.DRIVE_GET_THROW_REASONS+[GAPI.INVALID],
fileId=fileId, includeLabels=includeLabels, fields=fields, supportsAllDrives=True)
fileId=fileId, includeLabels=includeLabels, includePermissionsForView=includePermissionsForView,
fields=fields, supportsAllDrives=True)
if stripCRsFromName:
result['name'] = _stripControlCharsFromName(result['name'])
driveId = result.get('driveId')
@@ -58833,6 +58978,7 @@ SIZE_FIELD_CHOICE_MAP = {
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
# [showdrivename] [showshareddrivepermissions]
# (showlabels details|ids)|(includelabels <DriveLabelIDList>)]
# [includepermissionsforview published]
# [showparentsidsaslist] [showpermissionslast]
# (orderby <DriveFileOrderByFieldName> [ascending|descending])* [delimiter <Character>]
# [stripcrsfromname]
@@ -59013,7 +59159,8 @@ def printFileList(users):
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.INVALID_QUERY, GAPI.INVALID,
GAPI.BAD_REQUEST],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.UNKNOWN_ERROR],
q=q, orderBy=DFF.orderBy, includeLabels=includeLabels, fields=pagesFields,
q=q, orderBy=DFF.orderBy, includeLabels=includeLabels, includePermissionsForView=includePermissionsForView,
fields=pagesFields,
pageSize=GC.Values[GC.DRIVE_MAX_RESULTS], includeItemsFromAllDrives=True, supportsAllDrives=True)
for childEntryInfo in children:
childFileId = childEntryInfo['id']
@@ -59030,8 +59177,12 @@ def printFileList(users):
_printFileInfo(drive, user, childEntryInfo.copy(), stripCRsFromName)
if childEntryInfo['mimeType'] == MIMETYPE_GA_FOLDER and (maxdepth == -1 or depth < maxdepth):
_printChildDriveFolderContents(drive, childEntryInfo, user, i, count, depth+1)
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest):
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE, None], invalidQuery(selectSubQuery), i, count)
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest) as e:
errMsg = str(e)
if 'Invalid field selection' in errMsg or "Only a 'published' value is supported." in errMsg:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], errMsg, i, count)
else:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE, None], invalidQuery(selectSubQuery), i, count)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userDriveServiceNotEnabledWarning(user, str(e), i, count)
@@ -59253,7 +59404,8 @@ def printFileList(users):
if filepath and not countsOnly:
csvPF.AddTitles('paths')
csvPF.SetFixPaths(True)
includeLabels = ','.join(DFF.includeLabels)
includeLabels = _finalizeIncludeLabels(DFF.includeLabels)
includePermissionsForView = _finalizeIncludePermissionsForView(DFF.includePermissionsForView)
csvPF.RemoveTitles(['capabilities'])
if DLP.queryTimes and selectSubQuery:
for queryTimeName, queryTimeValue in DLP.queryTimes.items():
@@ -59326,7 +59478,8 @@ def printFileList(users):
GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND,
GAPI.NOT_FOUND, GAPI.TEAMDRIVE_MEMBERSHIP_REQUIRED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.UNKNOWN_ERROR],
q=DLP.fileIdEntity['query'], orderBy=DFF.orderBy, includeLabels=includeLabels,
q=DLP.fileIdEntity['query'], orderBy=DFF.orderBy,
includeLabels=includeLabels, includePermissionsForView=includePermissionsForView,
fields=pagesFields, pageSize=GC.Values[GC.DRIVE_MAX_RESULTS], **btkwargs)
for files in feed:
if showLabels is not None:
@@ -59357,7 +59510,7 @@ def printFileList(users):
DLP.GetLocationFileIdsFromTree(fileTree, fileIdEntity)
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest) as e:
errMsg = str(e)
if 'Invalid field selection' in errMsg:
if 'Invalid field selection' in errMsg or "Only a 'published' value is supported." in errMsg:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], errMsg, i, count)
break
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], invalidQuery(DLP.fileIdEntity['query']), i, count)
@@ -59389,8 +59542,9 @@ def printFileList(users):
else:
try:
fileEntryInfo = callGAPI(drive.files(), 'get',
throwReasons=GAPI.DRIVE_GET_THROW_REASONS,
fileId=fileId, includeLabels=includeLabels, fields=fields, supportsAllDrives=True)
throwReasons=GAPI.DRIVE_GET_THROW_REASONS+[GAPI.INVALID],
fileId=fileId, includeLabels=includeLabels, includePermissionsForView=includePermissionsForView,
fields=fields, supportsAllDrives=True)
if stripCRsFromName:
fileEntryInfo['name'] = _stripControlCharsFromName(fileEntryInfo['name'])
if showLabels is not None:
@@ -59401,6 +59555,9 @@ def printFileList(users):
_formatFileDriveLabels(showLabels, labels, fileEntryInfo, True, delimiter)
if filepath:
fileTree[fileId] = {'info': fileEntryInfo}
except GAPI.invalid as e:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, fileId], str(e), j, jcount)
continue
except GAPI.fileNotFound:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, fileId], Msg.NOT_FOUND, j, jcount)
continue
@@ -61928,6 +62085,8 @@ def initCopyMoveOptions(copyCmd):
'copySubFilesOwnedBy': {},
'copyPermissionRoles': set(DRIVEFILE_ACL_ROLES_MAP.values()),
'copyPermissionTypes': set(DRIVEFILE_ACL_PERMISSION_TYPES),
'checkModifiedTime': False,
'startEndTime': StartEndTime(),
}
DUPLICATE_FILE_CHOICES = {
@@ -62086,6 +62245,9 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
copyMoveOptions['copySubFilesOwnedBy']['value'] = set(getString(Cmd.OB_EMAIL_ADDRESS_LIST).replace(',', ' ').lower().split())
elif copyMoveOptions['copySubFilesOwnedBy']['mode'] in {'regex', 'notregex'}:
copyMoveOptions['copySubFilesOwnedBy']['value'] = getREPattern(re.IGNORECASE)
elif myarg in {'start', 'starttime', 'end', 'endtime', 'range'}:
copyMoveOptions['startEndTime'].Get(myarg)
copyMoveOptions['checkModifiedTime'] = True
else:
return False
return True
@@ -62642,6 +62804,7 @@ copyReturnItemMap = {
# notusers <EmailAddressList>|
# regex <REMatchPattern>|
# notregex <REMatchPattern>]
# [([start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>])|(range <Date>|<Time> <Date>|<Time>)]|
# [copysubfolders [<Boolean>]] [foldernamematchpattern <REMatchPattern>]
# [copysubshortcuts [<Boolean>]] [shortcutnamematchpattern <REMatchPattern>]
# [duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
@@ -62878,6 +63041,14 @@ def copyDriveFile(users):
return False
if not copyMoveOptions['mimeTypeCheck'].Check(childMimeType):
return False
if copyMoveOptions['checkModifiedTime']:
childModifiedTime = child.get('modifiedTime', None)
if not childModifiedTime:
return False
childModifiedTime = formatLocalTime(childModifiedTime)
if ((copyMoveOptions['startEndTime'].startTime is not None and childModifiedTime < copyMoveOptions['startEndTime'].startTime) or
(copyMoveOptions['startEndTime'].endTime is not None and childModifiedTime > copyMoveOptions['startEndTime'].endTime)):
return False
nameMatchPattern = copyMoveOptions['fileNameMatchPattern']
return not nameMatchPattern or nameMatchPattern.match(childName)
@@ -67370,8 +67541,6 @@ def infoDriveFileACLs(users, useDomainAdminAccess=False):
def doInfoDriveFileACLs():
infoDriveFileACLs([_getAdminEmail()], True)
DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES = ['published']
def getDriveFilePermissionsFields(myarg, fieldsList):
if myarg in DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP:
fieldsList.append(DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP[myarg])
@@ -67426,7 +67595,7 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
addTitle = None
roles = set()
oneItemPerRow = pmselect = showTitles = False
includePermissionsForView = None
includePermissionsForView = set()
fieldsList = []
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
PM = PermissionMatch()
@@ -67461,13 +67630,14 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
elif PM.ProcessArgument(myarg):
pass
elif myarg == 'includepermissionsforview':
includePermissionsForView = getChoice(DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES)
_getIncludePermissionsForView(includePermissionsForView)
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
if fieldsList:
if roles:
fieldsList.append('role')
includePermissionsForView = _finalizeIncludePermissionsForView(includePermissionsForView)
fields = getItemFieldsFromFieldsList('permissions', fieldsList, True)
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
i, count, users = getEntityArgument(users)
@@ -74793,7 +74963,10 @@ def printShowMessagesThreads(users, entityType):
csvPF.SetTitles(sortTitles)
else:
sortTitles = ['User', 'threadId', 'id']
sortTitles.extend(defaultHeaders)
if show_all_headers:
sortTitles.extend(defaultHeaders)
elif headersToShow:
sortTitles.extend([SMTP_HEADERS_MAP.get(header, header) for header in headersToShow])
if show_size:
sortTitles.append('SizeEstimate')
if show_labels:
@@ -76490,10 +76663,14 @@ def printShowLanguage(users):
SIG_REPLY_HTML = 0
SIG_REPLY_COMPACT = 1
SIG_REPLY_FORMAT = 2
SIG_REPLY_TEMPLATE = 3 # Does not go in MAP
SIG_REPLY_OPTIONS_MAP = {'html': SIG_REPLY_HTML, 'compact': SIG_REPLY_COMPACT, 'format': SIG_REPLY_FORMAT}
SMTPMSA_DISPLAY_FIELDS = ['host', 'port', 'securityMode']
def _showSendAs(result, j, jcount, sigReplyFormat, verifyOnly=False):
if sigReplyFormat == SIG_REPLY_TEMPLATE:
writeStdout(f"{escapeCRsNLs(result.get('signature', 'None'))}\n")
return
if result['displayName']:
printEntity([Ent.SENDAS_ADDRESS, f'{result["displayName"]} <{result["sendAsEmail"]}>'], j, jcount)
else:
@@ -76758,7 +76935,7 @@ def printShowSendAs(users):
# gam <UserTypeEntity> print signature [compact]
# [primary] [verifyonly] [todrive <ToDriveAttribute>*]
# gam <UserTypeEntity> show signature|sig [compact|format|html]
# gam <UserTypeEntity> show signature|sig [compact|format|html|template]
# [primary] [verifyonly]
def printShowSignature(users):
csvPF = CSVPrintFile(['User', 'displayName', 'sendAsEmail', 'replyToAddress',
@@ -76779,6 +76956,8 @@ def printShowSignature(users):
verifyOnly = True
elif (not csvPF and myarg in SIG_REPLY_OPTIONS_MAP) or (csvPF and myarg == 'compact'):
sigReplyFormat = SIG_REPLY_OPTIONS_MAP[myarg]
elif not csvPF and myarg == 'template':
sigReplyFormat = SIG_REPLY_TEMPLATE
else:
unknownArgumentExit()
i, count, users = getEntityArgument(users)
@@ -79465,6 +79644,7 @@ MAIN_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_GROUP: doCreateGroup,
Cmd.ARG_GUARDIAN: doInviteGuardian,
Cmd.ARG_GUARDIANINVITATION: doInviteGuardian,
Cmd.ARG_GUESTUSER: doCreateGuestUser,
Cmd.ARG_INBOUNDSSOASSIGNMENT: doCreateInboundSSOAssignment,
Cmd.ARG_INBOUNDSSOCREDENTIAL: doCreateInboundSSOCredential,
Cmd.ARG_INBOUNDSSOPROFILE: doCreateInboundSSOProfile,
@@ -81198,6 +81378,7 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_GUARDIANINVITATIONS: Cmd.ARG_GUARDIANINVITATION,
Cmd.ARG_GUARDIANINVITE: Cmd.ARG_GUARDIANINVITATION,
Cmd.ARG_GUARDIANS: Cmd.ARG_GUARDIAN,
Cmd.ARG_GUESTUSERS: Cmd.ARG_GUESTUSER,
Cmd.ARG_HOLD: Cmd.ARG_VAULTHOLD,
Cmd.ARG_HOLDS: Cmd.ARG_VAULTHOLD,
Cmd.ARG_IMAP4: Cmd.ARG_IMAP,

View File

@@ -812,6 +812,12 @@ def getVersion(api):
api = _INFO[api].get('mappedAPI', api)
return (api, version, v2discovery)
def getAPIsList():
apisList = set()
for api, value in _INFO.items():
apisList.add(value.get('mappedAPI', api))
return apisList
def getClientScopesSet(api):
return {scope['scope'] for scope in _CLIENT_SCOPES if scope['api'] == api}

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2025 Ross Scroggs All Rights Reserved.
# Copyright (C) 2026 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
@@ -123,6 +123,8 @@ CSV_OUTPUT_HEADER_DROP_FILTER = 'csv_output_header_drop_filter'
CSV_OUTPUT_HEADER_FORCE = 'csv_output_header_force'
# Orde output column headers
CSV_OUTPUT_HEADER_ORDER = 'csv_output_header_order'
# Required output column headers
CSV_OUTPUT_HEADER_REQUIRED = 'csv_output_header_required'
# Line terminator in CSV output file
CSV_OUTPUT_LINE_TERMINATOR = 'csv_output_line_terminator'
# Quote character in CSV output file
@@ -151,6 +153,8 @@ CUSTOMER_ID = 'customer_id'
DEBUG_LEVEL = 'debug_level'
# redact sensitive credentials from debug output
DEBUG_REDACTION = 'debug_redaction'
# Developer Preview APIs
DEVELOPER_PREVIEW_APIS = 'developer_preview_apis'
# Developer Preview API Key
DEVELOPER_PREVIEW_API_KEY = 'developer_preview_api_key'
# When retrieving lists of ChromeOS devices from API, how many should be retrieved in each chunk
@@ -218,6 +222,8 @@ NUM_TBATCH_THREADS = 'num_tbatch_threads'
NUM_THREADS = 'num_threads'
# Path to oauth2.txt
OAUTH2_TXT = 'oauth2_txt'
# File permissions for oauth2.txt.lock
OAUTH2_TXT_LOCK_MODE = 'oauth2_txt_lock_mode'
# Path to oauth2service.json
OAUTH2SERVICE_JSON = 'oauth2service_json'
# Output date format, empty defalts to ISOFormat
@@ -325,6 +331,7 @@ CSV_INPUT_ROW_FILTER_ITEMS = {CSV_INPUT_ROW_FILTER, CSV_INPUT_ROW_FILTER_MODE,
CSV_OUTPUT_ROW_FILTER_ITEMS = {CSV_OUTPUT_HEADER_FILTER, CSV_OUTPUT_HEADER_DROP_FILTER,
CSV_OUTPUT_HEADER_FORCE, CSV_OUTPUT_HEADER_ORDER,
CSV_OUTPUT_HEADER_REQUIRED,
CSV_OUTPUT_ROW_FILTER, CSV_OUTPUT_ROW_FILTER_MODE,
CSV_OUTPUT_ROW_DROP_FILTER, CSV_OUTPUT_ROW_DROP_FILTER_MODE,
CSV_OUTPUT_ROW_LIMIT}
@@ -369,6 +376,7 @@ Defaults = {
CSV_OUTPUT_HEADER_DROP_FILTER: '',
CSV_OUTPUT_HEADER_FORCE: '',
CSV_OUTPUT_HEADER_ORDER: '',
CSV_OUTPUT_HEADER_REQUIRED: '',
CSV_OUTPUT_LINE_TERMINATOR: 'lf',
CSV_OUTPUT_QUOTE_CHAR: '\'"\'',
CSV_OUTPUT_ROW_FILTER: '',
@@ -383,6 +391,7 @@ Defaults = {
CUSTOMER_ID: MY_CUSTOMER,
DEBUG_LEVEL: '0',
DEBUG_REDACTION: TRUE,
DEVELOPER_PREVIEW_APIS: '',
DEVELOPER_PREVIEW_API_KEY: '',
DEVICE_MAX_RESULTS: '200',
DOMAIN: '',
@@ -416,6 +425,7 @@ Defaults = {
NUM_TBATCH_THREADS: '2',
NUM_THREADS: '5',
OAUTH2_TXT: FN_OAUTH2_TXT,
OAUTH2_TXT_LOCK_MODE: '644',
OAUTH2SERVICE_JSON: FN_OAUTH2SERVICE_JSON,
OUTPUT_DATEFORMAT: '',
OUTPUT_TIMEFORMAT: '',
@@ -481,7 +491,7 @@ TYPE_EMAIL_OPTIONAL = 'emao'
TYPE_FILE = 'file'
TYPE_FLOAT = 'floa'
TYPE_HEADERFILTER = 'heaf'
TYPE_HEADERFORCE = 'hefo'
TYPE_HEADERFORCEREQUIRED = 'hefr'
TYPE_HEADERORDER = 'heor'
TYPE_INTEGER = 'inte'
TYPE_LANGUAGE = 'lang'
@@ -538,8 +548,9 @@ VAR_INFO = {
CSV_OUTPUT_FIELD_DELIMITER: {VAR_TYPE: TYPE_CHARACTER},
CSV_OUTPUT_HEADER_FILTER: {VAR_TYPE: TYPE_HEADERFILTER},
CSV_OUTPUT_HEADER_DROP_FILTER: {VAR_TYPE: TYPE_HEADERFILTER},
CSV_OUTPUT_HEADER_FORCE: {VAR_TYPE: TYPE_HEADERFORCE},
CSV_OUTPUT_HEADER_FORCE: {VAR_TYPE: TYPE_HEADERFORCEREQUIRED},
CSV_OUTPUT_HEADER_ORDER: {VAR_TYPE: TYPE_HEADERORDER},
CSV_OUTPUT_HEADER_REQUIRED: {VAR_TYPE: TYPE_HEADERFORCEREQUIRED},
CSV_OUTPUT_LINE_TERMINATOR: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'cr': '\r', 'lf': '\n', 'crlf': '\r\n'}},
CSV_OUTPUT_QUOTE_CHAR: {VAR_TYPE: TYPE_CHARACTER},
CSV_OUTPUT_ROW_FILTER: {VAR_TYPE: TYPE_ROWFILTER},
@@ -554,6 +565,7 @@ VAR_INFO = {
CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'CUSTOMER_ID', VAR_LIMITS: (0, None)},
DEBUG_LEVEL: {VAR_TYPE: TYPE_INTEGER, VAR_SIGFILE: 'debug.gam', VAR_LIMITS: (0, None), VAR_SFFT: ('0', '4')},
DEBUG_REDACTION: {VAR_TYPE: TYPE_BOOLEAN},
DEVELOPER_PREVIEW_APIS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
DEVELOPER_PREVIEW_API_KEY: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
DEVICE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
DOMAIN: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_DOMAIN', VAR_LIMITS: (0, None)},
@@ -587,6 +599,7 @@ VAR_INFO = {
NUM_TBATCH_THREADS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
NUM_THREADS: {VAR_TYPE: TYPE_INTEGER, VAR_ENVVAR: 'GAM_THREADS', VAR_LIMITS: (1, 1000)},
OAUTH2_TXT: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'OAUTHFILE', VAR_ACCESS: os.R_OK | os.W_OK},
OAUTH2_TXT_LOCK_MODE: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'644': 0o644, '664': 0o664, '666': 0o666}},
OAUTH2SERVICE_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'OAUTHSERVICEFILE', VAR_ACCESS: os.R_OK | os.W_OK},
OUTPUT_DATEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
OUTPUT_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},

View File

@@ -928,6 +928,8 @@ class GamCLArgs():
ARG_GUARDIANINVITE = 'guardianinvite'
ARG_GUARDIANINVITATION = 'guardianinvitation'
ARG_GUARDIANINVITATIONS = 'guardianinvitations'
ARG_GUESTUSER = 'guestuser'
ARG_GUESTUSERS = 'guestusers'
ARG_HOLD = 'hold'
ARG_HOLDS = 'holds'
ARG_IMAP = 'imap'

View File

@@ -253,6 +253,7 @@ class GamEntity():
GUARDIAN = 'guar'
GUARDIAN_INVITATION = 'gari'
GUARDIAN_AND_INVITATION = 'gani'
GUEST_USER = 'gstu'
IAM_POLICY = 'iamp'
IMAP_ENABLED = 'imap'
INBOUND_SSO_ASSIGNMENT = 'insa'
@@ -358,7 +359,7 @@ class GamEntity():
SNIPPETS_ENABLED = 'snip'
SSO_KEY = 'ssok'
SSO_SETTINGS = 'ssos'
SOURCE_USER = 'src'
SOURCE_USER = 'srcu'
SPREADSHEET = 'sprd'
SPREADSHEET_RANGE = 'ssrn'
START_TIME = 'strt'
@@ -620,6 +621,7 @@ class GamEntity():
GROUP_MEMBERSHIP_TREE: ['Group Membership Trees', 'Group Membership Tree'],
GROUP_SETTINGS: ['Group Settings', 'Group Settings'],
GROUP_TREE: ['Group Trees', 'Group Tree'],
GUEST_USER: ['Guest Users', 'Guest User'],
GUARDIAN: ['Guardians', 'Guardian'],
GUARDIAN_INVITATION: ['Guardian Invitations', 'Guardian Invitation'],
GUARDIAN_AND_INVITATION: ['Guardians and Invitations', 'Guardian and Invitation'],

View File

@@ -69,6 +69,8 @@ CSV_OUTPUT_HEADER_FILTER = 'cohf'
CSV_OUTPUT_HEADER_FORCE = 'cofh'
# Order output column headers
CSV_OUTPUT_HEADER_ORDER = 'coho'
# Required output column headers
CSV_OUTPUT_HEADER_REQUIRED = 'corh'
# No escape character in CSV output file
CSV_OUTPUT_NO_ESCAPE_CHAR = 'cone'
# Quote character in CSV output file
@@ -111,6 +113,8 @@ DEBUG_LEVEL = 'dbgl'
DEBUG_REDACTION = 'dbrd'
# Decoded ID token
DECODED_ID_TOKEN = 'didt'
# Developer Preview APIs
DEVELOPER_PREVIEW_APIS = 'dapi'
# Index of start of <UserTypeEntity> in command line
ENTITY_CL_DELAY_START = 'ecld'
ENTITY_CL_START = 'ecls'
@@ -246,6 +250,7 @@ Globals = {
CSV_OUTPUT_HEADER_FILTER: [],
CSV_OUTPUT_HEADER_FORCE: [],
CSV_OUTPUT_HEADER_ORDER: [],
CSV_OUTPUT_HEADER_REQUIRED: [],
CSV_OUTPUT_NO_ESCAPE_CHAR: None,
CSV_OUTPUT_QUOTE_CHAR: None,
CSV_OUTPUT_ROW_DROP_FILTER: [],
@@ -267,6 +272,7 @@ Globals = {
DEBUG_LEVEL: 0,
DEBUG_REDACTION: True,
DECODED_ID_TOKEN: None,
DEVELOPER_PREVIEW_APIS: set(),
ENTITY_CL_DELAY_START: 1,
ENTITY_CL_START: 1,
EXTRA_ARGS_LIST: [],

View File

@@ -236,6 +236,7 @@ DATA_TRANSFER_COMPLETED = 'Data Transfer completed: {0}\n'
DATA_UPLOADED_TO_DRIVE_FILE = 'Data uploaded to Drive File'
DEFAULT_SMIME = 'Default S/MIME'
DELETED = 'Deleted'
DEVELOPER_PREVIEW_REQUIRED = 'Developer Preview is required for this command\n'
DEVICE_LIST_BUG = 'GAM hit Google internal bug 237397223. Please file a Google Support ticket stating that you are encountering this bug.'
DEVICE_LIST_BUG_WORKAROUND_NOT_POSSIBLE = 'GAM workaround for this issue only works if orderby argument is not used and query does not contain \'register\'.'
DEVICE_LIST_BUG_ATTEMPTING_WORKAROUND = 'GAM is attempting to work around the bug by filtering for devices created on or after the newest we\'ve seen ({0})...\n'

View File

@@ -283,6 +283,8 @@
<ChatEmoji> ::= emojiname <ChatEmojiName> | customemojis/<String>
<ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSection> ::= users/<String>/sections/<String> | sections/<String> | section <String>
<ChatSectionItem> ::= users/<String>/sections/<String>/items/<String> | sections/<String>/items/<String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>
<ChatThread> ::= spaces/<String>/threads/<String>
<ChromeProfilePermanentID> ::= <String>

View File

@@ -14,8 +14,9 @@
There are seven values in `gam.cfg` that can be used to filter the output from `gam print` commands.
* `csv_output_header_filter` - A list of `<RegularExpressions>` used to select specific column headers to include
* `csv_output_header_drop_filter` - A list of `<RegularExpressions>` used to select specific column headers to exclude
* `csv_output_header_force` - A list of <Strings> used to specify the exact column headers to include
* `csv_output_header_order` - A list of <Strings> used to specify the column header order; any headers in the file but not in the list will appear after the headers in the list.
* `csv_output_header_force` - A list of `<Strings>` used to specify the exact column headers to include
* `csv_output_header_order` - A list of `<Strings>` used to specify the column header order; any headers in the file but not in the list will appear after the header* `csv_output_header_required` - A list of `<Strings>` used to specify column headers that are included even if the print command doesn't return them
s in the list.
* `csv_output_row_filter` - A list or JSON dictionary used to include specific rows based on column values
* `csv_output_row_drop_filter` - A list or JSON dictionary used to exclude specific rows based on column values
* `csv_output_row_limit` - A limit on the number of rows written

View File

@@ -595,7 +595,7 @@ By default, Gam displays event details, use `countsonly` to display only the num
```
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[fields <EventFieldNameList>] [showdayofweek] [attendeeslist]
(addcsvdata <FieldName> <String>)*
[eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
@@ -609,6 +609,10 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
By default, each attendee is displayed in a separate column; `attendeeslist` causes GAM to display
the attendee email addresses in a single column `attendeesList`; no attendee details are displayed.
The email addresses are separated by `csv_output_field_delimiter` from `gam.cfg`.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`

View File

@@ -282,10 +282,11 @@ gam show chromepolicies
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
[filter <StringList>] [namespace <NamespaceList>]
[show all|direct|inherited]
[formatjson]
```
By default, all Chrome policies for the OU or group are displayed.
* `filter <String>` - Display policies based on fields like its resource name, description and additionalTargetKeyNames.
* `filter <StringList>` - Display policies based on fields like its resource name, description and additionalTargetKeyNames.
* `show all` - For OUs, display policies regardless of where set; this is the default
* `show direct` - For OUs, display policies set directly in the OU
* `show inherited` - For OUs, display policies set in a parent OU
@@ -329,15 +330,25 @@ By default, Gam displays the information as an indented list of keys and values.
gam print chromepolicies [todrive <ToDriveAttribute>*]
((ou|orgunit <OrgUnitItem> [show all|direct|inherited])|(group <GroupItem>))
[(printerid <PrinterID>)|(appid <AppID>)]
[filter <String>] [namespace <NamespaceList>]
[filter <StringList>] [namespace <NamespaceList>]
[show all|direct|inherited] [shownopolicy]
[[formatjson [quotechar <Character>]]
```
By default, all Chrome policies for the OU or group are displayed.
* `filter <String>` - Display policies based on fields like its resource name, description and additionalTargetKeyNames.
* `filter <StringList>` - Display policies based on fields like its resource name, description and additionalTargetKeyNames.
* `show all` - For OUs, display policies regardless of where set; this is the default
* `show direct` - For OUs, display policies set directly in the OU
* `show inherited` - For OUs, display policies set in a parent OU
Use option `shownopolicy` to display output like the following if no policies apply to the OU or group.
```
gam print chromepolicies ou /Test appid chrome:emidddocikgklceeeifefomdnbkldhng namespace chrome.users.apps shownopolicy
Getting all Chrome Policies that match query (chrome.users.apps.*) for /Test
Got 0 Chrome Policies that matched query (chrome.users.apps.*) for /Test...
name,orgUnitPath,parentOrgUnitPath,direct,appId
noPolicy,/Test,/,False,chrome:emidddocikgklceeeifefomdnbkldhng
```
These are the default namespaces; use `namespace <NamespaceList>` to override.
* `default`
* chrome.users

View File

@@ -14,6 +14,7 @@
- [Action ChromeOS devices](#action-chromeos-devices)
- [Send remote commands to ChromeOS devices](#send-remote-commands-to-chromeos-devices)
- [Action Examples](#action-examples)
- [Bulk Action Example](#bulk-action-example)
- [ChromeOS device lists](#chromeos-device-lists)
- [Display information about ChromeOS devices](#display-information-about-chromeos-devices)
- [Print ChromeOS devices](#print-chromeos-devices)
@@ -445,12 +446,19 @@ is configurable from 0 to some large number. If the status reaches `EXPIRED`, `C
wipe_users|
take_a_screenshot
gam <CrOSTypeEntity> issuecommand command <CrOSCommand> [times_to_check_status <Integer>] [doit]
gam <CrOSTypeEntity> issuecommand command <CrOSCommand>
[times_to_check_status <Integer>] [csv] [doit]
```
By default, when a Chrome command is issued, GAM outputs details of the command status as indented keywords and values.
* `csv` - Output the details in CSV format.
If the final status is not reached before GAM exits, you can issue the following commands to continue checking the status.
```
gam <CrOSTypeEntity> getcommand commandid <CommandID> [times_to_check_status <Integer>]
gam <CrOSTypeEntity> getcommand commandid <CommandID>
[times_to_check_status <Integer>] [csv]
```
By default, when a Chrome command status is read, GAM outputs details of the command status as indented keywords and values.
* `csv` - Output the details in CSV format.
### Action Examples
Remove user profile data from the device; the device will remain enrolled and connected.
@@ -476,6 +484,40 @@ Use `wipe_users` if that's going to create too much work for you.
```
gam cros_ou /StudentCarts issuecommand command remote_powerwash times_to_check_status 0 doit
```
### Bulk Action example
You want to issue commands to many ChromeOS devices and monitor the results.
Assume a Google Sheet with two tabs: Commands and Results
The Commands tab has at least two columns: serialNumber and command
```
serialNumber,command
abc123def123,reboot
abc123def456,remote_powerwash
abc123def789,wipe_users
```
Here is the URL for the Commands tab
```
https://docs.google.com/spreadsheets/d/12349lNWvZwzJhwxyz/edit?gid=1588227640#gid=1588227640
<SheetFileID> = 12349lNWvZwzJhwxyz
<CommandTabID> = 1588227640
Here is the URL for the Commands tab
https://docs.google.com/spreadsheets/d/12349lNWvZwzJhwxyz/edit?gid=2102420937#gid=2102420937
<SheetFileID> = 12349lNWvZwzJhwxyz
<ResultsTabID> = 2102420937
```
Replace `user@domain.com` with the email address of the Google Sheet owner.
Issue the commands from the Commands tab and write the results to the Results tab; copy the `serialNumber` to the Results tab.
```
gam config num_threads 20 redirect csv - multiprocess sortheaders serialNumber todrive tduser user@domain.com tdfileID <SheetFileID> tdsheet id:<ResultsTabID> tdupdatesheet tdretaintitle redirect stderr - multiprocess csv gsheet user@domain.com <SheetFileID> id:<CommandsTabID> gam cros_sn "~serialNumber" issuecommand command "~command" doit csv addcsvdata serialNumber "~serialNumber"
```
Monitor the results by reading and updating the results from/to the Results tab; copy the `serialNumber` to the Results tab.
```
gam config num_threads 20 redirect csv - multiprocess sortheaders serialNumber todrive tduser user@domain.com tdfileID <SheetFileID> tdsheet id:<ResultsTabID> tdupdatesheet tdretaintitle redirect stderr - multiprocess csv gsheet user@domain.com <SheetFileID> id:<ResultsTabID> gam cros "~deviceId" getcommand commandid "~commandId" csv addcsvdata serialNumber "~serialNumber"
```
You can use additional `addcsvdata` options to copy device identifying information from the source to the destination.
## ChromeOS device lists
ChromeOS devices have lists of data: `<CrOSListFieldName>`, `<CrOSActivityListFieldName>`, `<CrOSTelemetryListFieldName>`.
All lists except `recentusers` are in ascending order (oldest to newest). As these lists can contain many entries,

View File

@@ -12,33 +12,8 @@
- [Display student group membership counts](#display-student-group-membership-counts)
## Notes
These commands wera added in version 7.20.00.
To use these commands your project must be enrolled the Developer Preview program.
* https://developers.google.com/workspace/preview
You will need your GAM project number.
* Login as an existing super admin at console.cloud.google.com
* In the upper left click the three lines to the left of Google Cloud and select IAM & Admin
* Under IAM & Admin select IAM
* Click in the box to the right of Google Cloud
* Click the three dots at the right and select Manage Resources
* Click the three dots at the end of the line for your GAM project
* Click Settings
* You will see the Project number; save it
You will need an API key
* In the upper left click the three lines to the left of Google Cloud and select APIs & Services
* Under APIs & Services select Credentials
* If you already have an API key, click Show key at the end of the line and save the value
* If you don't have an API key, click +Credentials and select API key
* Save the displayed API key
* Click close
Issue the following GAM command:
`gam config developer_preview_api_key <API Key Value> save`
Once you get an email from Google saying that your project has been registered you can use these commands.
These commands were added in version 7.20.00 and required enrollment in the Developer Preview program.
As of 7.32.04 Developer Preview enrollment is no longer required.
## API documentation
* [Google Classroom API](https://developers.google.com/classroom/reference/rest)
@@ -122,7 +97,7 @@ gam clear course-studentgroups
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
```
When creating student groups, the API does not check for duplicate titles; you can have multiple student grpups
When creating student groups, the API does not check for duplicate titles; you can have multiple student groups
with the same title; they will have unique `<StudentGroupID>s`.
The `update|delete course-studentgroups` commands manage a specific course.

View File

@@ -13,7 +13,7 @@
- [Display user group member options](#display-user-group-member-options)
- [Display group membership in CSV format](#display-group-membership-in-csv-format)
- [Display group membership in hierarchical format](#display-group-membership-in-hierarchical-format)
- [Manage external users in groups with allowExternalMembers False](#manage-external-users-in-groups-with-allowexternalmembers-false)
## API documentation
* [Cloud Identity Groups Overview](https://cloud.google.com/identity/docs/groups)
* [Cloud Identity Groups API - Groups](https://cloud.google.com/identity/docs/reference/rest/v1/groups)
@@ -349,7 +349,8 @@ gam print cigroup-members [todrive <ToDriveAttribute>*]
[emailmatchpattern [not] <REMatchPattern>] [namematchpattern [not] <REMatchPattern>]
[descriptionmatchpattern [not] <REMatchPattern>]
[roles <GroupRoleList>] [members] [managers] [owners]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[verifyallowexternal [<Boolean>]]
[types <CIGroupMemberTypeList>]
<CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
[minimal|basic|full]
@@ -381,11 +382,23 @@ By default, all members, managers and owners in the group are displayed; these o
By default, all types of members (cbcmbrowser, chromeosdevice, customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupMemberTypeList>` - Display specified types
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered `internal`.
When the `internal` or `external` options are specified, GAM adds the column `allowExternalMembers`
that shows that setting for the group and adds the column `category` that shows whether the member
is `external` or `internal`.
The option `verifyallowexternal` causes GAM to only display `external` users in groups with `allowExternalMembers=False'.
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
@@ -442,9 +455,10 @@ gam show cigroup-members
[emailmatchpattern [not] <REMatchPattern>] [namematchpattern [not] <REMatchPattern>]
[descriptionmatchpattern [not] <REMatchPattern>]
[roles <GroupRoleList>] [members] [managers] [owners]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[types <CIGroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
[minimal|basic|full]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
[(depth <Number>) | includederivedmembership]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
@@ -470,6 +484,18 @@ By default, all members, managers and owners in the group are displayed; these o
By default, all types of members (cbcmbrowser, chromeosdevice, customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupMemberTypeList>` - Display specified types
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
@@ -507,3 +533,41 @@ To show the structure of all groups you can do the following; it will be time co
```
gam redirect stdout ./groups.txt show cigroup-members types group
```
## Manage external users in groups with allowExternalMembers False
* See: https://support.google.com/a/answer/16778447
Get external members of groups with allowExternalMembers = False
```
gam redirect csv ./ExternalMembersGroupsWithAEMFalse.csv print cigroup-members verifyallowexternal
```
Update selected groups to allowExternalMembers = True
* Add a column labelled `update` to ExternalMembersGroupsWithAEMFalse.csv
* For groups to be updated, add an x to the `update` column for any member of the group to be updated
```
gam redirect stdout ./UpdateGroupsWithAEMFalseToAEMTrue.txt redirect stderr stdout update group csvkmd ExternalMembersGroupsWithAEMFalse.csv keyfield group matchfield update x allowexternalmembers true
```
Update all groups to allowExternalMembers = True
**Caution, be sure that this is what you want**
```
gam redirect stdout ./UpdateGroupsWithAEMFalseToEMTrue.txt redirect stderr stdout update group csvkmd ExternalMembersGroupsWithAEMFalse.csv keyfield group allowexternalmembers true
```
Delete selected external members from groups with allowExternalMembers = False
* Add a column labelled `delete` to ExternalMembersGroupsWithAEMFalse.csv
* For exernal members to be deleted, add an x to the `delete` column
* The `preview` option let's you verify what external members are to be deleted, remove it to do the deletions
```
gam redirect csv ./DeletedMembersFromGroupsWithAEMFalse.csv redirect stdout ./DeleteMembersFromGroupsWithAEMFalse.txt redirect stderr stdout update group csvkmd ExternalMembersGroupsWithAEMFalse.csv keyfield group matchfield delete x datafield email delete preview actioncsv csvdata email
```
Delete all external members from groups with allowExternalMembers = False
**Caution, be sure that this is what you want**
* The `preview` option let's you verify what external members are to be deleted, remove it to do the deletions
```
gam redirect csv ./DeletedMembersFromGroupsWithAEMFalse.csv redirect stdout ./DeleteMembersFromGroupsWithAEMFalse.txt redirect stderr stdout update group csvkmd ExternalMembersGroupsWithAEMFalse.csv keyfield group datafield email delete preview actioncsv csvdata email
```

View File

@@ -267,7 +267,7 @@ gam info cigroups <GroupEntity>
[nosecurity|nosecuritysettings]
[allfields|<CIGroupFieldName>*|(fields <CIGroupFieldNameList>)]
[roles <GroupRoleList>] [members] [managers] [owners]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[types <CIGroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
[formatjson]
@@ -283,13 +283,17 @@ By default, all direct members, managers and owners in the group are displayed;
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
@@ -317,7 +321,7 @@ gam print cigroups [todrive <ToDriveAttribute>*]
[descriptionmatchpattern [not] <REMatchPattern>]
[basic|allfields|(<CIGroupFieldName>* [fields <CIGroupFieldNameList>])]
[roles <GroupRoleList>] [memberrestrictions]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[members|memberscount] [managers|managerscount] [owners|ownerscount] [totalcount] [countsonly]
[types <CIGroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
@@ -374,13 +378,20 @@ By default, no members, managers or owners in the group are displayed; these opt
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
When the `internal` or `external` options are specified, GAM adds the column `allowExternalMembers`
that shows that setting for the group.
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed

View File

@@ -319,6 +319,8 @@ Data fields identified in a `csvkmd` argument.
(select <ProjectIDList> | <FileSelector> | <CSVFileSelector>)
<PrinterIDEntity> ::=
<PrinterIDList> | <FileSelector> | <CSVFileSelector>
<QueryDriveFile> :: = <String> See: https://developers.google.com/workspace/drive/api/guides/search-files
<QuerySharedDrive> ::= <String> See: https://developers.google.com/workspace/drive/api/guides/search-shareddrives
<RecipientEntity> ::=
<EmailAddressEntity> | (select <UserTypeEntity>)
<ResourceEntity> ::=
@@ -329,22 +331,22 @@ Data fields identified in a `csvkmd` argument.
<SerialNumberList> | <FileSelector> | <CSVFileSelector>
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
(shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
(shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>) | (teamdriveadminquery:<QueryTeamDrive>)
(shareddriveadminquery <QuerySharedDrive>) | (shareddriveadminquery:<QuerySharedDrive>)
<SharedDriveEntityAdmin> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>|
<SharedDriveAdminQueryEntity>
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
(shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
<SharedDriveFileQueryEntity> ::=
(teamdrivequery <QueryDriveFile>) | (teamdrivequery:<QueryDriveFile>)
(shareddrivequery <QueryDriveFile>) | (shareddrivequery:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
<SiteACLScopeEntity> ::=

View File

@@ -114,9 +114,9 @@ ous_and_children_na_ns
(anydrivefilename <DriveFileName>)|(anydrivefilename:<DriveFileName>)
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveIDEntity> ::= (shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>

View File

@@ -49,7 +49,8 @@
<DriveFolderID> ::= <String>
<DriveFolderIDList> ::= "<DriveFolderID>(,<DriveFolderID>)*"
<DriveFolderName> ::= <String>
<QueryDriveFile> :: = <String> See: https://developers.google.com/drive/api/v3/search-files
<QueryDriveFile> :: = <String> See: https://developers.google.com/workspace/drive/api/guides/search-files
<QuerySharedDrive> ::= <String> See: https://developers.google.com/workspace/drive/api/guides/search-shareddrives
<DriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>)
<DriveFileQueryShortcut> ::=
@@ -90,15 +91,15 @@
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <SharedDriveID>) | (teamdriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveIDEntity> ::= (shareddriveid <SharedDriveID>) | (shareddriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>) | (teamdriveadminquery:<QueryTeamDrive>)
(shareddriveadminquery <QuerySharedDrive>) | (shareddriveadminquery:<QuerySharedDrive>)
<SharedDriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
@@ -335,13 +336,13 @@ Select a Shared Drive file by giving its unique ID.
```
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
(shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
```
### Examples
```
gam user testuser show fileinfo 1234ABCD
gam user testuser show fileinfo id 1234ABCD
gam user testuser show fileinfo teamdriveid 1234ABCD
gam user testuser show fileinfo shareddriveid 1234ABCD
```
## Select Shared Drive file by name
If you have the name, a search must be performed to find the ID that matches the name.
@@ -350,16 +351,16 @@ You must specify the Shared Drive, either by ID or name, and the name of the fil
Remember, searching for a file by name may return several file IDs if you have multiple files with the same name.
```
<SharedDriveIDEntity> ::=
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
(shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
(shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
(shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
```
### Examples
```
gam user testuser show fileinfo teamdriveid 1234ABCD teamdrivefilename "Test File"
gam user testuser show fileinfo teamdrive "Shared Drive 1" teamdrivefilename "Test File"
gam user testuser show fileinfo shareddriveid 1234ABCD shareddrivefilename "Test File"
gam user testuser show fileinfo shareddrive "Shared Drive 1" shareddrivefilename "Test File"
```
## Select Shared Drive file by query
You can use a query to find a file ID. You perform the query on all Shared Drives or a specific Shared Drive.
@@ -367,7 +368,7 @@ You can use a query to find a file ID. You perform the query on all Shared Drive
See: [Drive Query](https://developers.google.com/drive/api/v3/search-files)
```
<SharedDriveFileQueryEntity> ::=
(teamdrivequery <QueryDriveFile>) | (teamdrivequery:<QueryDriveFile>)
(shareddrivequery <QueryDriveFile>) | (shareddrivequery:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
```
@@ -380,32 +381,32 @@ Keyword to query mappings for `<DriveFileQueryShortcut>`:
### Examples
```
gam user testuser show fileinfo teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdriveid 1234ABCD teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdrive teamdrive "Shared Drive 1" teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdriveid 1234ABCD all_non_google_files
gam user testuser show fileinfo shareddrivequery "name='Test File'"
gam user testuser show fileinfo shareddriveid 1234ABCD shareddrivequery "name='Test File'"
gam user testuser show fileinfo shareddrive shareddrive "Shared Drive 1" shareddrivequery "name='Test File'"
gam user testuser show fileinfo shareddriveid 1234ABCD all_non_google_files
```
## Select root folder of a Shared Drive by ID
The root folder of a Shared Drive is a folder, you select it by giving its unique ID.
```
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
(shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
```
### Examples
```
gam user testuser show fileinfo 1234ABCD
gam user testuser show fileinfo teamdriveid 1234ABCD
gam user testuser show fileinfo shareddriveid 1234ABCD
```
## Select root folder of a Shared Drive by name
If you have a Shared Drive name, a search must be performed to find the ID that matches the name.
```
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
(shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
```
### Examples
```
gam user testuser show fileinfo teamdrive "Shared Drive 1"
gam user testuser show fileinfo shareddrive "Shared Drive 1"
```

View File

@@ -27,13 +27,13 @@
(anydrivefilename <DriveFileName>) | (anydrivefilename:<DriveFileName>)
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
(shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
<SharedDriveName> ::= <String>
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
(shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
(shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
```

View File

@@ -10,6 +10,161 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.34.00
Added variable `csv_output_header_required` to `gam.cfg` that is a comma separated list of `<Strings>`
that are required to be in the list of column headers in the CSV file written by a gam print command.
This will typically be used to specify headers that are required in subsequent commands that process
the CSV file even if the API didn't return any data for those columns.
Updated the following commands to not require the `Directory API - Domains` scope
unless the `internal` or `external` options are used to request the member category.
```
gam info|print groups
gam print|show group-members
gam info|print cigroups
gam print|show cigroup-members
gam <UserTypeEntity> print|show filesharecounts
```
### 7.33.03
Fixed bug in `gam [<UserTypeEntity>] sendemail ... from <EmailAddress> replyto <EmailAddress>`
where an `<EmailAddress>` of the form `Text <user@domain.com>` had the `Text` removed.
### 7.33.02
Added `hideinvitationssetting` to `<UserCalendarSettingsField>` used by
`gam <UserTypeEntity> print|show calsettings`.
### 7.33.01
Added option `shownopolicy` to `gam print chromepolicies` that will display output like the following
if no policies apply to the selected OU or group.
```
gam print chromepolicies ou /Test appid chrome:emidddocikgklceeeifefomdnbkldhng namespace chrome.users.apps shownopolicy
Getting all Chrome Policies that match query (chrome.users.apps.*) for /Test
Got 0 Chrome Policies that matched query (chrome.users.apps.*) for /Test...
name,orgUnitPath,parentOrgUnitPath,direct,appId
noPolicy,/Test,/,False,chrome:emidddocikgklceeeifefomdnbkldhng
```
### 7.33.00
Added variable `developer_preview_apis` to `gam.cfg` that is a comma separated list of APIs requiring a Developer Preview key.
Currently, `chat` is the only API that requires a Developer Preview key; it is required for the User Sections commands.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#introduction
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-user-sections
### 7.32.07
Added option `includepermissionsforview published` to `gam <UserTypeEntity> print filelist` and
`gam <UserTypeEntity> show fileinfo`. From the Drive API documentation:
```
Specifies which additional view's permissions to include in the response. Only published is supported.
```
### 7.32.06
Added options to `gam <UserTypeEntity> copy drivefile ... copysubfiles` to limit copying
to files whose `modifiedTime` meets specified requirements.
* `start|starttime <Date>|<Time>` - If specified, `modifiedTime` must be >= the value
* `end|endtime <Date>|<Time>` - If specified, `modifiedTime` must be <= the value
* `range <Date>|<Time> <Date>|<Time>` - first value <= `modifiedTime` <= second value
### 7.32.05
Fixed bug in `gam <UserTypeEntity> print messages|threads ... headers <SMTPHeaderList>` where
headers other than those specified in `<SMTPHeaderList>` were displayed.
Updated `gam info users <UserTypeEntity>` to display the following data when the Licensing API
does not return data due to quota limits. Previously, no License data was displayed and
there was no way to know if it was omitted due to API quota limits vs the user has no license?
```
Licenses: (1)
Not available/incomplete
```
If a user has no licenses, this will be displayed.
```
Licenses: (0)
```
You should use `license_skus = <SKUIDList>` in `gam.cfg` to list all of the licensing SKUs
used in your workspace. Without this list, GAM has to make 70+ API calls to get the licenses
for a user; this can cause quota limit errors.
### 7.32.04
Support for student groups in Google Classroom no longer requires Developer Preview membership.
Upgraded to OpenSSL 3.6.1.
### 7.32.03
Added option `template` as an additional formating option for `gam <UserTypeEntity> show signature`
that displays just the HTML data; this simplifies capturing the data for use as input to GAM.
```
$ gam redirect stdout ./SigTemplate.html user user@domain.com show signature template
$ more SigTemplate.html
<div dir="ltr"><div dir="ltr"><div dir="ltr">
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Email: {Email}{/RT}</span></p>
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Phone: {Phone}{/RT}</span></p>
<p style="margin:0px;font-size-adjust:none;font-stretch:normal;font-size:12px;line-height:normal;font-family:Monaco;color:rgb(0,0,0)">
<span style="background-color:rgb(82,208,206)">{RT}Mobile: {Mobile}{/RT}</span></p>
</div><br></div>\n</div>
```
### 7.32.02
Added variable `oauth2_txt_lock_mode` to `gam.cfg`, the default is 644 and valid values are: 644, 664, 666.
This value is used to set the file permissions on the `oauth2.txt.lock` file. In very special cases where
daemon processes, e.g. Apache/httpd, are running GAM, the value 666 may have to be used.
### 7.32.01
Added option `(addcsvdata <FieldName> <String>)*` to `gam <CrOSTypeEntity> issuecommand command <CrOSCommand> csv`
and `gam <CrOSTypeEntity> getcommand commandid <CommandID> csv` that adds additional columns of data to the CSV file output.
* See: https://github.com/GAM-team/GAM/wiki/ChromeOS-Devices#bulk-action-example
### 7.32.00
Added option `verifyallowexternal` to `gam print cigroup-members|group-members` that causes
GAM to only display external members in groups with `allowExternalMembers=False'.
This option can be used to help verify that internal-only groups don't have external members.
Updated option `internaldomains` for the following commands:
```
gam info|print groups
gam print|show group-members
gam info|print cigroups
gam print|show cigroup-members
gam <UserTypeEntity> print|show filesharecounts
```
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Added option `csv` to `gam <CrOSTypeEntity> issuecommand command <CrOSCommand>`
and `gam <CrOSTypeEntity> getcommand commandid <CommandID>` so that command details are displayed in CSV format.
This can be used to log commands issued to devices and then monitor the results.
Added option `filemimetype category <MimeTypeNameList>` to `gam <UserTypeEntity> copy drivefile` to support
copying of files based on their MimeType category.
Added option `attendeeslist` to `gam calendars <CalendarEntity> print events` and `gam <UserTypeEntity> print events`
that causes GAM to display the attendee email addresses in a single column `attendeesList`; no attendee details
are displayed. The email addresses are separated by `csv_output_field_delimiter` from `gam.cfg`.
Fixed bug in `gam sendemail ... replyto <EmailAddress>` that caused a message delivery error if
`<EmailAddress>` did not include a domain name.
Added support for users's chat sections.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-users-sections
* This is in Deveoper Preview; you must have a `developer_preview_api_key` in `gam.cfg` to use these commands.
### 7.31.06
Added option `batchsize <Integer>` to `gam calendar <CalendarEntity> delete|purge events` and
@@ -2925,7 +3080,7 @@ Added option `showmimetype category <MimeTypeNameList>` to `gam <UserTypeEntity>
<MimeTypeName> ::= application|audio|font|image|message|model|multipart|text|video
<MimeTypeNameList> ::= "<MimeTypeName>(,<MimeTypeName>)*"
gam user user@domain.com print filelist fields id,name,mimetype showmimetype prefixes audio,video
gam user user@domain.com print filelist fields id,name,mimetype showmimetype category audio,video
```
### 6.71.11

View File

@@ -615,7 +615,7 @@ gam print group-members [todrive <ToDriveAttribute>*]
[descriptionmatchpattern [not] <REMatchPattern>]
[admincreatedmatch <Boolean>]
[roles <GroupRoleList>] [members] [managers] [owners]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[membernames] [showdeliverysettings]
<MembersFieldName>* [fields <MembersFieldNameList>]
[notsuspended|suspended] [notarchived|archived]
@@ -682,13 +682,21 @@ By default, when displaying members from a group, all members, whether suspended
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended members, this is not common but allows creating groups that allow easy identification of suspended users
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, are considered `internal`.
When the `internal` or `external` options are specified, GAM adds the column `allowExternalMembers`
that shows that setting for the group and adds the column `category` that shows whether the member
is `external` or `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
@@ -756,7 +764,7 @@ gam show group-members
[descriptionmatchpattern [not] <REMatchPattern>]
[admincreatedmatch <Boolean>]
[roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[notsuspended|suspended] [notarchived|archived]
[types <GroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
@@ -809,232 +817,17 @@ By default, when displaying members from a group, all members, whether suspended
By default, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, are considered internal.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, members of type GROUP are recursively expanded to show their constituent members. (Members of
type CUSTOMER are not expanded.) The `depth <Number>` argument controls the depth to which nested groups are displayed.
* `depth -1` - all groups in the selected group and below are displayed; this is the default.
* `depth 0` - the groups within a selected group are displayed, no descendants are displayed.
* `depth N` - the groups within the selected group and those groups N levels below the selected group are displayed.
The `includederivedmembership` option causes the API to expand type GROUP and type CUSTOMER
members to display their constituent members while still displaying the original member.
The options `types user` and `includederivedmembership types user` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show hierarchy.
Expanding a member of type CUSTOMER may produce a large volume of data as it will display all users in your domain.
### Display group structure
To see a group's structure of nested groups use the `type group` option.
```
$ gam show group-members group testgroup5 types group
Group: testgroup5@domain.com
MEMBER, GROUP, testgroup1@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup3@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup4@domain.com, ACTIVE
```
To show the structure of all groups you can do the following; it will be time consuming for a large number of groups.
```
gam redirect stdout ./groups.txt show group-members types group
```
### Examples
#### Print a CSV of all members of a group regardless of role, all fields
```
gam print group-members <GroupEntity>
```
#### Print a CSV containing all managers emails
```
gam print group-members <GroupEntity> role manager fields email
```
#### Print a CSV output of all members and their emails only
```
gam print group-members <GroupEntity> role member fields email
```
#### Display group owners in your domain, but excluding groups where the email starts with a 4 digit code
```
gam print group-members domain <Your Domain> emailmatchpattern not '^1234.*' roles owners
```
These options further limit the list of groups selected above:
* `emailmatchpattern <REMatchPattern>` - Limit display to groups whose email address matches `<REMatchPattern>`
* `emailmatchpattern not <REMatchPattern>` - Limit display to groups whose email address does not match `<REMatchPattern>`
* `namematchpattern <REMatchPattern>` - Limit display to groups whose name matches `<REMatchPattern>`
* `namematchpattern not <REMatchPattern>` - Limit display to groups whose name does not match `<REMatchPattern>`
* `descriptionmatchpattern <REMatchPattern>` - Limit display to groups whose description matches `<REMatchPattern>`
* `descriptionmatchpattern not <REMatchPattern>` - Limit display to groups whose description does not match `<REMatchPattern>`
* `admincreatedmatch True` - Limit display to groups created by administrators
* `admincreatedmatch False` - Limit display to groups created by users
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupMemberTypeList>` - Display specified types
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
When `recursive` is specified, the default is to only display type user members; this option modifies those behaviors:
* `types <GroupMemberTypeList>` - Display specified types
By default, when displaying members from a group, all members, whether suspended/archived or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Do not include archived members
* `archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived members
* `suspended archived` - Include only suspended or archived members
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended members, this is not common but allows creating groups that allow easy identification of suspended users
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Members without an email address, e.g. `customer`, are considered internal.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, the ID, role, email address, type and status of each member are displayed along with the group email address;
these options specify which fields to display:
* `membernames` - Display members full name; an additional API call per member is required
* `showdeliverysettings` - Display delivery settings; an additional API call per member is required
* `<MembersFieldName>*` - Individual field names
* `fields <MembersFieldNameList>` - A comma separated list of field names
* `delivery|deliverysettings` - Specify this field to get delivery information; an additional API call per member is required
For members that are users, you can specify additional information to display; an additional API call per member is required
* `userfields <UserFieldNameList>` - Display specific user fields
* `allschemas|(schemas|custom|customschemas <SchemaNameList>)` - Display all or specific custom schema values
The additional API calls can be reduced with the `cachememberinfo` option; a single API call is made for each user/group
and the data is cached to eliminate to need to repeat the API call; this consumes more memory but dramatically reduces the number of API calls.
If member names are requested, names are not available for users not in the domain; you can request that GAM use the People API to retrieve
names for these users. Names are not retrieved in all cases and success is dependent on what user is used to perform the retrievals.
* `peoplelookup` - Use the administrator named in oauth2.txt to perform the retrievals
* `peoplelookupuser <EmailAddress>` - Use `<EmailAddress>` to perform the retrievals
By default, when `membernames` is specified, GAM displays `Unknown` for members whose names can not be determined.
Use `unknownname <String>` to specify an alternative value.
By default, the group email address is always shown, you can suppress it with the `nogroupemail` option.
The `recursive` option adds two columns, level and subgroup, to the output:
* `level` - At what level of the expansion does the user appear; level 0 is the top level
* `subgroup` - The group that contained the user
Displaying membership of multiple groups or recursive expansion may result in multiple instances of the same user being displayed; these multiple instances can be reduced to one entry.
* `noduplicates` - Reduce multiple instances of the same user to the first instance
The `includederivedmembership` option is an alternative to `recursive`; it causes the API to expand type GROUP and type CUSTOMER
members to display their constituent members while still displaying the original member.
The API produces inconsistent results, use with caution.
The options `recursive noduplicates` and `includederivedmembership types user noduplicates` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show level and subgroup information.
Expanding a member of type CUSTOMER may produce a large volume of data as it will display all users in your domain.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Display group membership in hierarchical format
```
gam show group-members
[([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryGroupList>)]))|
(group|group_ns|group_susp <GroupItem>)|
(select <GroupEntity>)]
[emailmatchpattern [not] <REMatchPattern>] [namematchpattern [not] <REMatchPattern>]
[descriptionmatchpattern [not] <REMatchPattern>]
[admincreatedmatch <Boolean>]
[roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
[internal] [internaldomains <DomainNameList>] [external]
[notsuspended|suspended] [notarchived|archived]
[types <GroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
[includederivedmembership]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain
* `group <GroupItem>` - Limit display to the single group `<GroupItem>`
* `group_ns <GroupItem>` - Limit display to the single group `<GroupItem>`, display non-suspended members
* `group_susp <GroupItem>` - Limit display to the single group `<GroupItem>`, display suspended members
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
When using `query <QueryGroup>` with the `name:{PREFIX}*` query, `PREFIX` must contain at least three characters.
You can identify groups with the `All users in the organization` member with:
* `query "memberKey=<CustomerID>"`
* `member id:<CustomerID>`
These options further limit the list of groups selected above:
* `emailmatchpattern <REMatchPattern>` - Limit display to groups whose email address matches `<REMatchPattern>`
* `emailmatchpattern not <REMatchPattern>` - Limit display to groups whose email address does not match `<REMatchPattern>`
* `namematchpattern <REMatchPattern>` - Limit display to groups whose name matches `<REMatchPattern>`
* `namematchpattern not <REMatchPattern>` - Limit display to groups whose name does not match `<REMatchPattern>`
* `descriptionmatchpattern <REMatchPattern>` - Limit display to groups whose description matches `<REMatchPattern>`
* `descriptionmatchpattern not <REMatchPattern>` - Limit display to groups whose description does not match `<REMatchPattern>`
* `admincreatedmatch True` - Limit display to groups created by administrators
* `admincreatedmatch False` - Limit display to groups created by users
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, when displaying members from a group, all members, whether suspended/archived or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Do not include archived members
* `archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived members
* `suspended archived` - Include only suspended or archived members
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended members, this is not common but allows creating groups that allow easy identification of suspended users
By default, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Members without an email address, e.g. `customer`, are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, are considered `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed

View File

@@ -396,7 +396,7 @@ gam info group|groups <GroupEntity>
[basic] <GroupFieldName>* [fields <GroupFieldNameList>] [nodeprecated]
[ciallfields|(cifields <CIGroupFieldNameList>)]
[roles <GroupRoleList>] [members] [managers] [owners]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains All|<DomainNameList>] [external]
[notsuspended|suspended] [notarchived|archived]
[types <GroupMemberTypeList>]
[memberemaildisplaypattern|memberemailskippattern <REMatchPattern>]
@@ -423,13 +423,17 @@ By default, when displaying members from a group, all members, whether suspended
By default, when displaying members from a group, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your primary workspace domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, are considered `internal`.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
@@ -467,7 +471,7 @@ gam print groups [todrive <ToDriveAttribute>*]
[ciallfields|(cifields <CIGroupFieldNameList>)]
[nodeprecated]
[roles <GroupRoleList>]
[internal] [internaldomains <DomainNameList>] [external]
[internal] [internaldomains all|primary|<DomainNameList>] [external]
[members|memberscount] [managers|managerscount] [owners|ownerscount] [totalcount] [countsonly]
[includederivedmembership]
[notsuspended|suspended] [notarchived|archived]
@@ -558,13 +562,20 @@ By default, when displaying members from a group, all members, whether suspended
By default, when displaying members from a group, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupMemberTypeList>` - Display specified types
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
Members without an email address, e.g. `customer`, are considered internal.
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal` - Display members whose domain matches a value in `internaldomains`
* `external` - Display members whose domain does not match value in `internaldomains`
* `internal external` - Display all members, indicate their category: `internal` or `external`
Members without an email address, e.g. `customer`, are considered `internal`.
When the `internal` or `external` options are specified, GAM adds the column `allowExternalMembers`
that shows that setting for the group.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed

View File

@@ -252,7 +252,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.31.06 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
macOS Tahoe 26.2 x86_64
@@ -550,6 +550,7 @@ Section: DEFAULT
cache_discovery_only = true
channel_customer_id = ''
charset = utf-8
chat_max_results = 100
classroom_max_results = 0
client_secrets_json = client_secrets.json ; /Users/admin/GAMConfig/client_secrets.json
clock_skew_in_seconds = 10
@@ -559,6 +560,7 @@ Section: DEFAULT
config_dir = /Users/admin/GAMConfig
contact_max_results = 100
csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"'
csv_input_row_drop_filter = ''
csv_input_row_drop_filter_mode = anymatch
@@ -571,32 +573,48 @@ Section: DEFAULT
csv_output_header_drop_filter = ''
csv_output_header_filter = ''
csv_output_header_force = ''
csv_output_header_order = ''
csv_output_header_required = ''
csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"'
csv_output_row_drop_filter = ''
csv_output_row_drop_filter_mode = anymatch
csv_output_row_filter = ''
csv_output_row_filter_mode = allmatch
csv_output_row_limit = 0
csv_output_sort_headers = ''
csv_output_subfield_delimiter = '.'
csv_output_timestamp_column = ''
csv_output_users_audit = false
customer_id = C01234567
debug_level = 0
debug_redaction = true
developer_preview_api_key = ''
developer_preview_apis = ''
device_max_results = 200
domain = domain.com
drive_dir = /Users/admin/GAMWork
drive_max_results = 1000
drive_v3_native_names = true
email_batch_size = 50
enable_dasa = false
enable_gcloud_reauth = false
enforce_expansive_access = true
event_max_results = 250
extra_args = ''
gmail_cse_incert_dir = ''
gmail_cse_inkey_dir = ''
input_dir = .
inter_batch_wait = 0
license_max_results = 100
license_skus = ''
member_max_results = 200
member_max_results_ci_basic = 1000
member_max_results_ci_full = 500
message_batch_size = 50
message_max_results = 500
mobile_max_results = 100
multiprocess_pool_limit = 0
never_time = Never
no_browser = false
no_cache = false
@@ -606,13 +624,15 @@ Section: DEFAULT
num_threads = 5
oauth2_txt = oauth2.txt ; /Users/admin/GAMConfig/oauth2.txt
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
output_dateformat = ''
output_timeformat = ''
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False
quick_info_user = false
reseller_id = ''
retry_api_service_not_available = false
section = ''
@@ -629,12 +649,13 @@ Section: DEFAULT
smtp_username = ''
timezone = local
tls_max_version = ''
tls_min_version = 'TLSv1_2'
tls_min_version = 'TLSv1_3'
todrive_clearfilter = false
todrive_clientaccess = false
todrive_conversion = true
todrive_localcopy = false
todrive_locale = ''
todrive_no_escape_char = true
todrive_nobrowser = false
todrive_noemail = true
todrive_parent = root
@@ -647,6 +668,8 @@ Section: DEFAULT
todrive_user = ''
truncate_client_id = false
update_cros_ou_with_id = false
use_chat_admin_access = false
use_course_owner_access = false
use_projectid_as_name = false
user_max_results = 500
user_service_account_access_only = false
@@ -751,6 +774,7 @@ Section: DEFAULT
cache_discovery_only = true
channel_customer_id = ''
charset = utf-8
chat_max_results = 100
classroom_max_results = 0
client_secrets_json = client_secrets.json ; C:\GAMConfig\client_secrets.json
clock_skew_in_seconds = 10
@@ -760,6 +784,7 @@ Section: DEFAULT
config_dir = C:\GAMConfig
contact_max_results = 100
csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"'
csv_input_row_drop_filter = ''
csv_input_row_drop_filter_mode = anymatch
@@ -772,32 +797,48 @@ Section: DEFAULT
csv_output_header_drop_filter = ''
csv_output_header_filter = ''
csv_output_header_force = ''
csv_output_header_order = ''
csv_output_header_required = ''
csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"'
csv_output_row_drop_filter = ''
csv_output_row_drop_filter_mode = anymatch
csv_output_row_filter = ''
csv_output_row_filter_mode = allmatch
csv_output_row_limit = 0
csv_output_sort_headers = ''
csv_output_subfield_delimiter = '.'
csv_output_timestamp_column = ''
csv_output_users_audit = false
customer_id = my_customer
debug_level = 0
debug_redaction = true
developer_preview_api_key = ''
developer_preview_apis = ''
device_max_results = 200
domain = ''
drive_dir = C:\GAMWork
drive_max_results = 1000
drive_v3_native_names = true
email_batch_size = 50
enable_dasa = false
enable_gcloud_reauth = false
enforce_expansive_access = true
event_max_results = 250
extra_args = ''
gmail_cse_incert_dir = ''
gmail_cse_inkey_dir = ''
input_dir = .
inter_batch_wait = 0
license_max_results = 100
license_skus = ''
member_max_results = 200
member_max_results_ci_basic = 1000
member_max_results_ci_full = 500
message_batch_size = 50
message_max_results = 500
mobile_max_results = 100
multiprocess_pool_limit = 0
never_time = Never
no_browser = false
no_cache = false
@@ -807,13 +848,15 @@ Section: DEFAULT
num_threads = 5
oauth2_txt = oauth2.txt ; C:\GAMConfig\oauth2.txt
oauth2service_json = oauth2service.json ; C:\GAMConfig\oauth2service.json
output_dateformat = ''
output_timeformat = ''
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False
quick_info_user = false
reseller_id = ''
retry_api_service_not_available = false
section = ''
@@ -830,12 +873,13 @@ Section: DEFAULT
smtp_username = ''
timezone = utc
tls_max_version = ''
tls_min_version = 'TLSv1_2'
tls_min_version = 'TLSv1_3'
todrive_clearfilter = false
todrive_clientaccess = false
todrive_conversion = true
todrive_localcopy = false
todrive_locale = ''
todrive_no_escape_char = true
todrive_nobrowser = false
todrive_noemail = true
todrive_parent = root
@@ -848,6 +892,8 @@ Section: DEFAULT
todrive_user = ''
truncate_client_id = false
update_cros_ou_with_id = false
use_chat_admin_access = false
use_course_owner_access = false
use_projectid_as_name = false
user_max_results = 500
user_service_account_access_only = false
@@ -990,7 +1036,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.31.06 - https://github.com/GAM-team/GAM - pythonsource
GAM 7.34.00 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
Windows 11 10.0.26200 AMD64
@@ -1289,6 +1335,7 @@ Section: DEFAULT
cache_discovery_only = true
channel_customer_id = ''
charset = utf-8
chat_max_results = 100
classroom_max_results = 0
client_secrets_json = client_secrets.json ; C:\GAMConfig\client_secrets.json
clock_skew_in_seconds = 10
@@ -1298,6 +1345,7 @@ Section: DEFAULT
config_dir = C:\GAMConfig
contact_max_results = 100
csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"'
csv_input_row_drop_filter = ''
csv_input_row_drop_filter_mode = anymatch
@@ -1310,32 +1358,48 @@ Section: DEFAULT
csv_output_header_drop_filter = ''
csv_output_header_filter = ''
csv_output_header_force = ''
csv_output_header_order = ''
csv_output_header_required = ''
csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"'
csv_output_row_drop_filter = ''
csv_output_row_drop_filter_mode = anymatch
csv_output_row_filter = ''
csv_output_row_filter_mode = allmatch
csv_output_row_limit = 0
csv_output_sort_headers = ''
csv_output_subfield_delimiter = '.'
csv_output_timestamp_column = ''
csv_output_users_audit = false
customer_id = C01234567
debug_level = 0
debug_redaction = true
developer_preview_api_key = ''
developer_preview_apis = ''
device_max_results = 200
domain = domain.com
drive_dir = C:\GAMWork
drive_max_results = 1000
drive_v3_native_names = true
email_batch_size = 50
enable_dasa = false
enable_gcloud_reauth = false
enforce_expansive_access = true
event_max_results = 250
extra_args = ''
gmail_cse_incert_dir = ''
gmail_cse_inkey_dir = ''
input_dir = .
inter_batch_wait = 0
license_max_results = 100
license_skus = ''
member_max_results = 200
member_max_results_ci_basic = 1000
member_max_results_ci_full = 500
message_batch_size = 50
message_max_results = 500
mobile_max_results = 100
multiprocess_pool_limit = 0
never_time = Never
no_browser = false
no_cache = false
@@ -1353,7 +1417,7 @@ Section: DEFAULT
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False
quick_info_user = false
reseller_id = ''
retry_api_service_not_available = false
section = ''
@@ -1370,12 +1434,13 @@ Section: DEFAULT
smtp_username = ''
timezone = local
tls_max_version = ''
tls_min_version = 'TLSv1_2'
tls_min_version = 'TLSv1_3'
todrive_clearfilter = false
todrive_clientaccess = false
todrive_conversion = true
todrive_localcopy = false
todrive_locale = ''
todrive_no_escape_char = true
todrive_nobrowser = false
todrive_noemail = true
todrive_parent = root
@@ -1388,6 +1453,8 @@ Section: DEFAULT
todrive_user = ''
truncate_client_id = false
update_cros_ou_with_id = false
use_chat_admin_access = false
use_course_owner_access = false
use_projectid_as_name = false
user_max_results = 500
user_service_account_access_only = false

View File

@@ -56,6 +56,7 @@ The only `<VariableNames>` recognized in this `<Section>` are:
* `csv_output_header_drop_filter`
* `csv_output_header_force`
* `csv_output_header_order`
* `csv_output_header_required`
* `csv_output_row_filter`
* `csv_output_row_filter_mode`
* `csv_output_row_drop_filter`

View File

@@ -0,0 +1,34 @@
# Secondary Calendars with no Owner
Here's a start on how to get information for non-owned secondary calendars
Save the CSV file that Google sent you as NoOwnerSecCals.csv
Get calendar description and summary for non-owned secondary calendars.
* There will be one row per calendar.
```
gam config num_threads 10 csv_output_header_force "calendarId,description,summary" redirect csv ./NOSC_Details.csv multiprocess redirect stderr - multiprocess csv NoOwnerSecCals.csv gam calendar "~Secondary calendar email" print settings fields description,summary
```
Get event counts for non-owned secondary calendars.
* There will be one row per calendar.
```
gam config num_threads 10 redirect csv ./NOSC_EventCounts.csv multiprocess redirect stderr - multiprocess csv NOSC_Details.csv gam calendar "~calendarId" print events countsonly addcsvdata description "~description" addcsvdata summary "~summary"
```
Get summary for non-owned secondary calendars - Contains details, counts, ACLs
* There will be one row per calendar/ACL combination
```
gam config num_threads 10 redirect csv ./NOSC_Summary.csv multiprocess redirect stderr - multiprocess csv NOSC_EventCounts.csv gam calendar "~calendarId" print acls noselfowner addcsvdata description "~description" addcsvdata summary "~summary" addcsvdata events "~events"
```
You can add an owner.
* Replace `admin@domain.com` with a super admin other than the one from: `gam oauth info`
```
gam config num_threads 10 redirect stdout ./Add_NOSC_Owner.txt multiprocess redirect stderr stdout csv NoOwnerSecCals.csv gam calendar "~Secondary calendar email" add acls owner admin@domain.com sendnotifications false
```
After inspecting NOSC_Summary.csv, you can delete the calendars if desired.
* Replace `admin@domain.com` with the super admin specified in the previous step
```
gam config num_threads 10 redirect stdout ./Delete_NOSC.txt multiprocess redirect stderr stdout csv NoOwnerSecCals.csv gam user admin@domain.com remove calendar "~Secondary calendar email"
``

View File

@@ -125,7 +125,7 @@ Limit the time period.
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
For `gam report gmail`, `start <Time>` and `end <Time>`should both be provided, and the scan duration should not be greater than 30 days.
For `gam report gmail`, `start <Time>` and `end <Time>` should both be provided, and the scan duration should not be greater than 30 days.
GAM will supply missing values:
* No time information provided - GAM sets `range -30d today`
* Only `start <Time>` provided - GAM sets `end <Time>+30d`
@@ -134,6 +134,11 @@ GAM will supply missing values:
For `gam report gmail`, `gmaileventtypes <NumberRangeList>` can be used to limit the event types displayed.
* See: https://developers.google.com/workspace/admin/reports/v1/appendix/activity/gmail
You can use the following filter to select a specific event; replace `X` with your desired value.
```
filter "event_info.mail_event_type==X"
```
Apply API filters.
* `filter|filters <String>` - `<String>` is a comma separated list of filter expressions.

View File

@@ -171,7 +171,7 @@
withlink
<DrivePermissionsFieldNameList> ::= "<DrivePermissionsFieldName>(,<DrivePermissionsFieldName>)*"
<QueryTeamDrive> ::= <String> See: https://developers.google.com/drive/api/v3/search-parameters
<QuerySharedDrive> ::= <String> See: https://developers.google.com/workspace/drive/api/guides/search-shareddrives
<SharedDriveACLRole> ::=
manager|organizer|owner|
contentmanager|fileorganizer|
@@ -183,8 +183,8 @@
<SharedDriveName> ::= <String>
<SharedDriveEntity> ::=
<SharedDriveID>|
(teamdriveid <SharedDriveID>)|(teamdriveid:<SharedDriveID>)|
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
(shareddriveid <SharedDriveID>)|(shareddriveid:<SharedDriveID>)|
(shareddrive <SharedDriveName>)|(shareddrive:<SharedDriveName>)
<SharedDriveFieldName> ::=
backgroundimagefile|
@@ -199,11 +199,11 @@
<SharedDriveFieldNameList> ::= "<SharedDriveFieldName>(,<SharedDriveFieldName>)*"
<SharedDriveIDEntity> ::=
<DriveFileItem>|(teamdriveid <DriveFileItem>)|(teamdriveid:<DriveFileItem>)
<DriveFileItem>|(shareddriveid <DriveFileItem>)|(shareddriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
(shareddrive <SharedDriveName>)|(shareddrive:<SharedDriveName>)
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>)|(teamdriveadminquery:<QueryTeamDrive>)
(shareddriveadminquery <QuerySharedDrive>)|(shareddriveadminquery:<QuerySharedDrive>)
<SharedDriveEntityAdmin> ::=
<SharedDriveIDEntity> |
@@ -327,11 +327,11 @@ When either of these options is chosen, no infomation about Shared Drive restric
To retrieve the Shared Drive ID with `returnidonly`:
```
Linux/MacOS
teamDriveId=$(gam create shareddrive ... returnidonly)
shareddriveId=$(gam create shareddrive ... returnidonly)
Windows PowerShell
$teamDriveId = & gam create shareddrive ... returnidonly
$shareddriveId = & gam create shareddrive ... returnidonly
Windows Command Prompt
for /f "delims=" %a in ('gam create shareddrive ... returnidonly') do set teamDriveId=%a
for /f "delims=" %a in ('gam create shareddrive ... returnidonly') do set shareddriveId=%a
```
## Bulk Create Shared Drives
@@ -422,14 +422,14 @@ By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam [<UserTypeEntity>] show shareddrives
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[fields <SharedDriveFieldNameList>]
[showwebviewlink text|hyperlink]
[formatjson]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -441,14 +441,14 @@ By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam [<UserTypeEntity>] print shareddrives [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[fields <SharedDriveFieldNameList>]
[showwebviewlink text|hyperlink]
[formatjson [quotechar <Character>]]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -498,7 +498,7 @@ Options `shareddriveadminquery|query` and `shareddrives|teamdrives` are mutually
Options `shareddriveadminquery|query` and `orgunit|org|ou` require `adminaccess|asadmin`.
By default, organizers for all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `shareddrives|teamdrives <SharedDriveIDList>` - Select the Shared Drive IDs specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Select the Shared Drive IDs specified in `<FileSelector>|<CSVFileSelector>`
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -535,12 +535,12 @@ gam print shareddrives query "organizerCount = 0"
Display the number of Shared Drives.
```
gam [<UserTypeEntity>] show|print shareddrives
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
showitemcountonly
```
By default, all Shared Drives are counted; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -758,7 +758,7 @@ gam config csv_output_header_drop_filter "User,createdTime,permission.photoLink,
## Display Shared Drive access for selected Shared Drives
```
gam [<UserTypeEntity>] show shareddriveacls
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
@@ -767,7 +767,7 @@ gam [<UserTypeEntity>] show shareddriveacls
[formatjson]
gam [<UserTypeEntity>] print shareddriveacls [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[adminaccess|asadmin] [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
@@ -777,7 +777,7 @@ gam [<UserTypeEntity>] print shareddriveacls [todrive <ToDriveAttribute>*]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
* `<PermissionMatch>* [<PermissionMatchAction>] pmselect` - Use permission matching to select Shared Drives; all ACLs are displayed for the selected Shared Drives
@@ -927,12 +927,12 @@ gam redirect stdout ./DeleteSharedDrives.txt multiprocess redirect stderr stdout
## Delete old empty Shared Drives
```
# Get a list of Shared Drives organizers for Shared Drives created before one year ago; alter date<-1y as required.
gam config csv_output_row_filter "createdTime:date<-1y" redirect csv ./TeamDriveOrganizers.csv print shareddriveorganizers domainlist mydomain.com includetypes user oneorganizer shownoorganizerdrives
gam config csv_output_row_filter "createdTime:date<-1y" redirect csv ./ShareddriveOrganizers.csv print shareddriveorganizers domainlist mydomain.com includetypes user oneorganizer shownoorganizerdrives
# Inspect shareddriveOrganizers.csv, you'll have to deal with Shared Drives with no organizer/manager
# Get old empty Shared Drives
gam config num_threads 10 csv_input_row_filter "organizers:regex:^.+$" csv_output_row_filter "Total:count=0" redirect csv ./OldEmptySharedDrives.csv multiprocess redirect stderr - multiprocess csv ./TeamDriveOrganizers.csv gam user "~organizers" print filecounts select shareddriveid "~id" showsize
gam config num_threads 10 csv_input_row_filter "organizers:regex:^.+$" csv_output_row_filter "Total:count=0" redirect csv ./OldEmptySharedDrives.csv multiprocess redirect stderr - multiprocess csv ./ShareddriveOrganizers.csv gam user "~organizers" print filecounts select shareddriveid "~id" showsize
# Inspect OldEmptySharedDrives.csv, if you're confident of the results, proceed

View File

@@ -681,9 +681,10 @@ By default, Gam displays event details, use `countsonly` to display only the num
```
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[fields <EventFieldNameList>] [showdayofweek] [attendeeslist]
(addcsvdata <FieldName> <String>)*
[eventrowfilter] [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
[eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -694,6 +695,10 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
By default, each attendee is displayed in a separate column; `attendeeslist` causes GAM to display
the attendee email addresses in a single column `attendeesList`; no attendee details are displayed.
The email addresses are separated by `csv_output_field_delimiter` from `gam.cfg`.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`

View File

@@ -1,4 +1,4 @@
# Users - Calendars
Users - Calendars
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Calendar colors](#calendar-colors)
@@ -74,8 +74,8 @@
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>) | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)
(calendars <CalendarList> | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
<UserCalendarEntity> ::=
@@ -90,8 +90,8 @@
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>) | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)|
(calendars <CalendarList> | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)|
<CalendarSelectProperty>*
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
@@ -101,6 +101,7 @@
defaulteventlength|
format24hourtime|
hideinvitations|
hideinvitationssetting|
hideweekends|
locale|
remindonrespondedeventsonly|

View File

@@ -37,7 +37,9 @@ gam user user@domain.com update serviceaccount
[*] 11) Chat API - User Sections (supports readonly)
```
`Chat API - User Sections` is in Developer Preview.
`Chat API - User Sections` is in Developer Preview; you must have a the following variables set in `gam.cfg` to use these commands.
* `developer_preview_apis = chat`
* `developer_preview_api_key = <String>`
Added `use_chat_admin_access` Boolean variable to `gam.cfg`.
```
@@ -484,14 +486,22 @@ gam <UserTypeEntity> move chatsectionitem <ChatSectionItem> to <ChatSection>
### Display information about a user's chat section items
```
gam <UserTypeEntity> show chatsectionitems <ChatSection>
[space <ChatSpace>]
[formatjson]
```
You can search for a chat section that contains a chat space with:
`show chatsectionitems sections/- space <ChatSpace>`
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print chatsectionitems <ChatSection> [todrive <ToDriveAttribute>*]
[space <ChatSpace>]
[formatjson [quotechar <Character>]]
```
You can search for a chat section that contains a chat space with:
`print chatsectionitems sections/- space <ChatSpace>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.

View File

@@ -18,8 +18,8 @@
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveEntity> ::=
<SharedDriveID>|(teamdriveid <SharedDriveID>)|(teamdriveid:<SharedDriveID>)|
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
<SharedDriveID>|(shareddriveid <SharedDriveID>)|(shareddriveid:<SharedDriveID>)|
(shareddrive <SharedDriveName>)|(shareddrive:<SharedDriveName>)
```
## Display empty folders
```

View File

@@ -42,6 +42,7 @@
<RESubstitution> ::= <String>>
<MimeTypeName> ::= application|audio|font|image|message|model|multipart|text|video
<MimeTypeNameList> ::= "<MimeTypeName>(,<MimeTypeName>)*"
<MimeType> ::= <MimeTypeName>/<String>
<MimeTypeList> ::= "<MimeType>(,<MimeType>)*"
@@ -67,10 +68,10 @@
(parentid <DriveFolderID>)|
(parentname <DriveFolderName>)|
(anyownerparentname <DriveFolderName>)|
(teamdriveparentid <DriveFolderID>)|
(teamdriveparent <SharedDriveName>)|
(teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>)|
(teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>)
(shareddriveparentid <DriveFolderID>)|
(shareddriveparent <SharedDriveName>)|
(shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>)|
(shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>)
<DriveFileCopyAttribute> ::=
(contentrestrictions readonly false)|
@@ -103,13 +104,14 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
<DriveFileCopyAttribute>*
[skipids <DriveFileEntity>]
[copysubfiles [<Boolean>]] [filenamematchpattern <REMatchPattern>]
[filemimetype [not] <MimeTypeList>]
[filemimetype [not] <MimeTypeList>] [filemimetype category <MimeTypeNameList>]
[copysubfilesownedby
any|me|others|
users <EmailAddressList>|
notusers <EmailAddressList>|
regex <REMatchPattern>|
notregex <REMatchPattern>]
[([start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>])|(range <Date>|<Time> <Date>|<Time>)]|
[copysubfolders [<Boolean>]] [foldernamematchpattern <REMatchPattern>]
[copysubshortcuts [<Boolean>]] [shortcutnamematchpattern <REMatchPattern>]
[duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
@@ -181,14 +183,17 @@ You can specify whether sub files, folders and shortcuts are copied. If sub fold
* `copysubshortcuts false` - Sub shortcuts are not copied
* `copysubshortcuts [true]` - Sub shortcuts are copied; this is the default
By default, GAM displays a message referencing files and folders not selected for copying by the options above.
* `suppressnotselectedmessages false` - Do not suppress these messages; this is the default
* `suppressnotselectedmessages [true]` - Suppress these messages
### By default, when copying sub files, all files, regardless of MIME type, are copied.
You can specify restrictions on the MIME types to be copied.
* `filemimetypes <MimeTypeList>` - Copy sub files with the specified MIME types
* `filemimetypes not <MimeTypeList>` - Copy sub files with MIME types other than those specified
* `filemimetypes category <MimeTypeNameList>` - Copy sub files with the specified MIME type categories
### By default, when copying sub files, all files, regardless of their `modifiedTime`, are copied.
You can specify restrictions on the `modifiedTime` to be copied.
* `start|starttime <Date>|<Time>` - If specified, `modifiedTime` must be >= the value
* `end|endtime <Date>|<Time>` - If specified, `modifiedTime` must be <= the value
* `range <Date>|<Time> <Date>|<Time>` - first value <= `modifiedTime` <= second value
### By default, when copying sub files, folders and shortcuts, all are copied.
You can specify `<REMatchPattern>` patterns that limit the items copied based on their name.
@@ -205,6 +210,10 @@ You can specify `<REMatchPattern>` patterns that limit the items copied based on
* `copysubfilesownedby regex <REMatchPattern>` - Only files owned by users whose email addresses match `<REMatchPattern>` are copied.
* `copysubfilesownedby notregex <REMatchPattern>` - Only files owned by users whose email addresses do not match `<REMatchPattern>` are copied.
### By default, GAM displays a message referencing files and folders not selected for copying by the options above.
* `suppressnotselectedmessages false` - Do not suppress these messages; this is the default
* `suppressnotselectedmessages [true]` - Suppress these messages
### Specify a new name for the file/folder
* `newfilename <DriveFileName>` - The copied file/folder will be named `<DriveFileName>`
* If `stripnameprefix <String>` is specified, `<String>` will be stripped from the front of `<DriveFileName>`
@@ -222,10 +231,10 @@ and "Template" is replaced by "NewCustomer" in all copied sub files and folders
* `parentid <DriveFolderID>` - The target folder is identified by `<DriveFolderID>` which must be writable by `<UserTypeEntity>`.
* `parentname <DriveFolderName>` - A search is performed for a folder named `<DriveFolderName>` owned by `<UserTypeEntity>`.
* `anyownerparentname <DriveFolderName>` - A search is performed for a folder named `<DriveFolderName>` owned by any user but must be writable by `<UserTypeEntity>`.
* `teamdriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specific Shared Drive folder.
* `teamdriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `shareddriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specific Shared Drive folder.
* `shareddriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* If none of the parent options are specified, the copied file/folder will be located in the source folder.
### Duplicate files
@@ -405,15 +414,15 @@ Specify the target location on the Shared Drive, either the ID of the Shared Dri
Files/folders in root of My Drive will be merged into `<DriveFolderID>`
```
gam user user@domain.com copy drivefile root recursive teamdriveparentid <DriveFolderID> mergewithparent true
gam user user@domain.com copy drivefile root recursive shareddriveparentid <DriveFolderID> mergewithparent true
```
Files/folders in root of My Drive will be in a new folder named `My Drive` created in `<DriveFolderID>`
```
gam user user@domain.com copy drivefile root recursive teamdriveparentid <DriveFolderID> mergewithparent false
gam user user@domain.com copy drivefile root recursive shareddriveparentid <DriveFolderID> mergewithparent false
```
Files/folders in root of My Drive will be in a new folder named `<String>` created in `<DriveFolderID>`
```
gam user user@domain.com copy drivefile root recursive teamdriveparentid <SharedDriveID> mergewithparent false newfilename <String>
gam user user@domain.com copy drivefile root recursive shareddriveparentid <SharedDriveID> mergewithparent false newfilename <String>
```
### Copy content of a Shared Drive to another Shared Drive
@@ -429,7 +438,7 @@ The example is assuming that the target drive is empty.
* Non-inherited sub folder permissions are copied.
* Non-inherited file permissions are copied.
```
gam user user@domain.com copy drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX mergewithparent recursive
gam user user@domain.com copy drivefile shareddriveid 0AC_1AB shareddriveparentid 0AE_9ZX mergewithparent recursive
copymergewithparentfolderpermissions true
copytopfolderinheritedpermissions false
copytopfoldernoninheritedpermissions always
@@ -449,7 +458,7 @@ Suppose that the source drive has been updated and you want to refresh the targe
* Non-inherited file permissions are copied.
* Files and folders that have been deleted from the source drive will remain on the target drive
```
gam user user@domain.com copy drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX mergewithparent recursive
gam user user@domain.com copy drivefile shareddriveid 0AC_1AB shareddriveparentid 0AE_9ZX mergewithparent recursive
copymergewithparentfolderpermissions true
copytopfolderinheritedpermissions false
copytopfoldernoninheritedpermissions syncallfolders
@@ -469,7 +478,7 @@ gam redirect csv ./TopSDItems.csv user user@domain.com print filelist select 0AC
```
Copy the top level items to target Shared Drive; append desired permission options
```
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive teamdriveparentid 0AE_9ZX
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive shareddriveparentid 0AE_9ZX
```
### Copy content of a source Shared Drive folder to a target Shared Drive with parallel Processing
@@ -479,31 +488,31 @@ gam redirect csv ./TopSDItems.csv user user@domain.com print filelist select 1Bx
```
Create a folder on target Shared Drive with ID 0AE_9ZX, replace "New Folder Name" as desired.
```
gam user user@domain.com create drivefile mimetype gfolder teamdriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly
gam user user@domain.com create drivefile mimetype gfolder shareddriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly
```
Copy the folder top level items to target Shared Drive folder, assume ID 2CY-45G was returned in previous step
```
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive teamdriveparentid 2CY-45G
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive shareddriveparentid 2CY-45G
```
You can script the steps:
Linux/MacOS
```
gam redirect csv ./TopSDItems.csv user user@domain.com print filelist select 1Bx-8W3 fields id,name,mimetype depth 0
targetFolderId=$(gam user user@domain.com create drivefile mimetype gfolder teamdriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly)
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive teamdriveparentid $targetFolderId
targetFolderId=$(gam user user@domain.com create drivefile mimetype gfolder shareddriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly)
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive shareddriveparentid $targetFolderId
```
Windows PowerShell
```
gam redirect csv ./TopSDItems.csv user user@domain.com print filelist select 1Bx-8W3 fields id,name,mimetype depth 0
$targetFolderId = & gam user user@domain.com create drivefile mimetype gfolder teamdriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive teamdriveparentid $targetFolderId
$targetFolderId = & gam user user@domain.com create drivefile mimetype gfolder shareddriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive shareddriveparentid $targetFolderId
```
Windows Command Prompt
```
gam redirect csv ./TopSDItems.csv user user@domain.com print filelist select 1Bx-8W3 fields id,name,mimetype depth 0
for /f "delims=" %a in ('gam user user@domain.com create drivefile mimetype gfolder teamdriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly') do set taregtFolderId=%a
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive teamdriveparentid %targetFolderId%
for /f "delims=" %a in ('gam user user@domain.com create drivefile mimetype gfolder shareddriveparentid 0AE-9ZX drivefilename "New Folder Name" returnidonly') do set taregtFolderId=%a
gam redirect stdout ./CopySharedDrive.txt multiprocess redirect stderr stdout csv TopSDItems.csv gam user user@domain.com copy drivefile "~id" recursive shareddriveparentid %targetFolderId%
```
## Move files and folders
@@ -605,10 +614,10 @@ This is the default mode.
* `parentid <DriveFolderID>` - The target folder is identified by `<DriveFolderID>` which must be writable by `<UserTypeEntity>`.
* `parentname <DriveFolderName>` - A search is performed for a folder named `<DriveFolderName>` owned by `<UserTypeEntity>`.
* `anyownerparentname <DriveFolderName>` - A search is performed for a folder named `<DriveFolderName>` owned by any user but must be writable by `<UserTypeEntity>`.
* `teamdriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specific Shared Drive folder.
* `teamdriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `shareddriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specific Shared Drive folder.
* `shareddriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* If none of the parent options are specified, the moved file/folder will be located in the source folder.
### Duplicate files
@@ -752,14 +761,14 @@ The following command will change the parents of the top level files and folders
* No permissions are processed.
```
gam user user@domain.com move drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX mergewithparent
gam user user@domain.com move drivefile shareddriveid 0AC_1AB shareddriveparentid 0AE_9ZX mergewithparent
```
If you want the source Shared Drive with ID 0AC_1AB to be contained in a top level folder of the target Shared Drive with ID 0AE_9ZX, omit the `mergewithparent` argument.
The folder on the target Shared Drive will have the same name as the name of the source Shared Drive; use the `newfilename <DriveFileName>` to use a different name.
```
gam user user@domain.com move drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX
gam user user@domain.com move drivefile teamdriveid 0AC_1AB teamdriveparentid 0AE_9ZX newfilename "Copy of source Shared Drive"
gam user user@domain.com move drivefile shareddriveid 0AC_1AB shareddriveparentid 0AE_9ZX
gam user user@domain.com move drivefile shareddriveid 0AC_1AB shareddriveparentid 0AE_9ZX newfilename "Copy of source Shared Drive"
```
### Inter-workspace moves
@@ -769,7 +778,7 @@ Due to a restructuring, you want to move data from Shared Drive A in domaina.com
* `user@domaina.com` is a manager of both Shared Drives.
```
$ gam user user@domaina move drivefile teamdriveid <SharedDriveAID> teamdriveparentid <SharedDriveBID> mergewithparent
$ gam user user@domaina move drivefile shareddriveid <SharedDriveAID> shareddriveparentid <SharedDriveBID> mergewithparent
User: user@domaina.com, Move 1 Drive File/Folder
User: user@domaina.com, Drive Folder: Shared Drive A(<SharedDriveAID>), Move(Merge) contents with Drive Folder: Shared Drive B(<SharedDriveBID>)
User: user@domaina.com, Drive File: Filename(<FileID>), Move Failed: Bad Request. User message: "shareOutNotPermitted"
@@ -785,13 +794,13 @@ The following command will change the parents of the top level files and folders
* No permissions are processed.
```
gam user user@domain.com move drivefile teamdriveid 0AC_1AB parentid root mergewithparent
gam user user@domain.com move drivefile shareddriveid 0AC_1AB parentid root mergewithparent
```
If you want the contents of Shared Drive with ID 0AC_1AB to be contained in a top level folder of the My Drive, omit the `mergewithparent` argument.
The folder on the My Drive will have the same name as the name of the Shared Drive; use the `newfilename <DriveFileName>` to use a different name.
```
gam user user@domain.com move drivefile teamdriveid 0AC_1AB parentid root
gam user user@domain.com move drivefile teamdriveid 0AC_1AB parentid root newfilename "Copy of Shared Drive"
gam user user@domain.com move drivefile shareddriveid 0AC_1AB parentid root
gam user user@domain.com move drivefile shareddriveid 0AC_1AB parentid root newfilename "Copy of Shared Drive"
```

View File

@@ -65,9 +65,9 @@
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <SharedDriveID>) | (teamdriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveIDEntity> ::= (shareddriveid <SharedDriveID>) | (shareddriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
@@ -315,8 +315,8 @@
size|
spaces|
starred|
teamdriveid|
teamdrivename|
shareddriveid|
shareddrivename|
thumbnaillink|
thumbnailversion|
title|
@@ -430,6 +430,7 @@ gam <UserTypeEntity> show fileinfo <DriveFileEntity>
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[showdrivename] [showshareddrivepermissions]
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
[includepermissionsforview published]
[showparentsidsaslist] [followshortcuts [<Boolean>]]
[stripcrsfromname]
[formatjson]
@@ -440,6 +441,7 @@ gam <UserTypeEntity> info drivefile <DriveFileEntity>
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[showdrivename] [showshareddrivepermissions]
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
[includepermissionsforview published]
[showparentsidsaslist] [followshortcuts [<Boolean>]]
[stripcrsfromname]
[formatjson]
@@ -880,11 +882,11 @@ Print or show the share type counts of a user's files. These fields are displaye
```
gam <UserTypeEntity> print filesharecounts [todrive <ToDriveAttribute>*]
[excludetrashed]
[internaldomains <DomainNameList>]
[internaldomains all|primary|<DomainNameList>]
[summary none|only|plus] [summaryuser <String>]
gam <UserTypeEntity> show filesharecounts
[excludetrashed]
[internaldomains <DomainNameList>]
[internaldomains all|primary|<DomainNameList>]
[summary none|only|plus] [summaryuser <String>]
```
@@ -892,8 +894,10 @@ By default, print|show filesharecounts displays share type counts of all files o
Use the `excludetrashed` option to suppress counting files in the trash.
By default, `internaldomains <DomainNameList>` defaults to your primary domain; if you have other domains that
you consider internal, list all of them in `<DomainNameList>`.
Which domains are considered internal domains:
* `internaldomains all` - All of your workspace domains; this is the default
* `internaldomains primary` - Your workspace primary domain
* `internaldomains <DomainNameList>` - A list of domain names
By default, share type counts for individual users are displayed; the `summary` option offers alternatives
that can display a summarization of share type counts across all users specified in the command.
@@ -1100,6 +1104,7 @@ gam <UserTypeEntity> print|show filelist [todrive <ToDriveAttribute>*]
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
[showdrivename] [showshareddrivepermissions]
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
[includepermissionsforview published]
[showparentsidsaslist] [showpermissionslast]
(orderby <DriveFileOrderByFieldName> [ascending|descending])* [delimiter <Character>]
[stripcrsfromname]

View File

@@ -149,10 +149,10 @@
(parentid <DriveFolderID>)|
(parentname <DriveFolderName>)|
(anyownerparentname <DriveFolderName>)|
(teamdriveparentid <DriveFolderID>)|
(teamdriveparent <SharedDriveName>)|
(teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>)|
(teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>)
(shareddriveparentid <DriveFolderID>)|
(shareddriveparent <SharedDriveName>)|
(shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>)|
(shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>)
<DriveFileCreateAttribute> ::=
<DriveFileAttribute>|
@@ -196,10 +196,10 @@ You can specify where the new file is to be located:
* `parentid <DriveFolderID>` - Folder ID.
* `parentname <DriveFolderName>` - Folder name; the folder must be owned by `<UserTypeEntity>`.
* `anyownerparentname <DriveFolderName>` - Folder name; the folder can be owned by any user, `<UserTypeEntity>` must be able to write to the folder.
* `teamdriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `teamdriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `shareddriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `shareddriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* If none of the parent options are specified, the parent folder is the root folder.
By default, Google assigns the current time to the attributes `createdTime` and `modifiedTime`; you can assign your own values
@@ -290,7 +290,7 @@ This will create a three column CSV file SharedDriveNamesIDs.csv with columns: U
You are building student folders on a Shared Drive as an admin and want to add ACLs to the folders
allowing the student write access and you want a shortcut on the student's My Drive pointing to the folder.
By adding the student's primary email address to the CSV output, it can be used in subsequent commands.
Sustitute for admin@domain.com and `<TeamDriveID>`.
Sustitute for admin@domain.com and `<SharedDriveID>`.
```
Students.csv
primaryEmail,Name
@@ -299,7 +299,7 @@ mary@domain.com, Mary Smith
...
# Create the student folders on the Shared Drive
gam redirect csv ./StudentFolders.csv multiprocess csv Students.csv gam user admin@domain.com create drivefile mimetype gfolder drivefilename "~~Name~~ Digital Portfolio" parentid <TeamDriveID> csv addcsvdata primaryEmail "~primaryEmail"
gam redirect csv ./StudentFolders.csv multiprocess csv Students.csv gam user admin@domain.com create drivefile mimetype gfolder drivefilename "~~Name~~ Digital Portfolio" parentid <SharedDriveID> csv addcsvdata primaryEmail "~primaryEmail"
# Add ACLs granting the students write access to their folders; "~User" refers to admin@domain.com
gam csv StudentFolders.csv gam user "~User" add drivefileacl "~id" user "~primaryEmail" role fileorganizer
# Add a shortcut to the folder on the student's My Drive
@@ -389,7 +389,7 @@ User: user@domain.com, Drive Folder Path:, Create
Build in a Shared Drive Folder
```
gam user user@domain.com create drivefolderpath path "Top Folder/Middle Folder/Bottom Folder/Sub Folder" teamdriveparent "TS Shared Drive" teamdriveparentname "TS SD6 Folder"
gam user user@domain.com create drivefolderpath path "Top Folder/Middle Folder/Bottom Folder/Sub Folder" shareddriveparent "TS Shared Drive" shareddriveparentname "TS SD6 Folder"
Getting all Drive Files/Folders that match query (mimeType = 'application/vnd.google-apps.folder' and name = 'TS SD6 Folder' and trashed = false) for user@domain.com
Got 1 Drive File/Folder that matched query (mimeType = 'application/vnd.google-apps.folder' and name = 'TS SD6 Folder' and trashed = false) for user@domain.com...
User: user@domain.com, Drive Folder Path:, Create
@@ -495,10 +495,10 @@ You can change where the new file is to be located; this removes all other paren
* `parentid <DriveFolderID>` - Folder ID.
* `parentname <DriveFolderName>` - Folder name; the folder must be owned by `<UserTypeEntity>`.
* `anyownerparentname <DriveFolderName>` - Folder name; the folder can be owned by any user, `<UserTypeEntity>` must be able to write to the folder.
* `teamdriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `teamdriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `shareddriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `shareddriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
You can add/remove parent folders without affecting other parent folders.
* `addparents|removeparents <DriveFolderIDList>` - Specify the parent folders by ID.

View File

@@ -30,13 +30,13 @@
(parentid <DriveFolderID>)|
(parentname <DriveFolderName>)|
(anyownerparentname <DriveFolderName>)|
(teamdriveparentid <DriveFolderID>)|
(teamdriveparent <SharedDriveName>)|
(teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>)|
(teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>))|
(teamdriveparentid <DriveFolderID>)|(teamdriveparent <SharedDriveName>)|
(teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>)|
(teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>)
(shareddriveparentid <DriveFolderID>)|
(shareddriveparent <SharedDriveName>)|
(shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>)|
(shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>))|
(shareddriveparentid <DriveFolderID>)|(shareddriveparent <SharedDriveName>)|
(shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>)|
(shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>)
<DriveOrderByFieldName> ::=
createddate|createdtime|

View File

@@ -357,8 +357,8 @@ The `quotechar <Character>` option allows you to choose an alternate quote chara
For example, to get the ACLs for your Team Drives with the Team Drive name included in the output:
```
gam redirect csv ./TeamDrives.csv print teamdrives
gam redirect csv ./TeamDriveACLs.csv multiprocess csv ./TeamDrives.csv gam print drivefileacls teamdriveid "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted
gam redirect csv ./SharedDrives.csv print shareddrives
gam redirect csv ./SharedDriveACLs.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls shareddriveid "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted
```
## Delete all ACLs except owner from a file

View File

@@ -26,10 +26,10 @@
(parentid <DriveFolderID>)|
(parentname <DriveFolderName>)|
(anyownerparentname <DriveFolderName>)|
(teamdriveparentid <DriveFolderID>)|
(teamdriveparent <SharedDriveName>)|
(teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>)|
(teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>)
(shareddriveparentid <DriveFolderID>)|
(shareddriveparent <SharedDriveName>)|
(shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>)|
(shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>)
```
## Create shortcuts
@@ -48,10 +48,10 @@ There are two modes of operaton:
* `parentid <DriveFolderID>` - Folder ID.
* `parentname <DriveFolderName>` - Folder name; the folder must be owned by `<UserTypeEntity>`.
* `anyownerparentname <DriveFolderName>` - Folder name; the folder can be owned by any user, `<UserTypeEntity>` must be able to write to the folder.
* `teamdriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `teamdriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `teamdriveparentid <SharedDriveID> teamdriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `teamdriveparent <SharedDriveName> teamdriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `shareddriveparentid <DriveFolderID>` - Shared Drive folder ID; when used alone, this indicates a specfic Shared Drive folder.
* `shareddriveparent <SharedDriveName>` - Shared Drive name; when used alone, this indicates the root level of the Shared Drive.
* `shareddriveparentid <SharedDriveID> shareddriveparentname <DriveFolderName>` - A Shared Drive ID and a folder name on that Shared Drive.
* `shareddriveparent <SharedDriveName> shareddriveparentname <DriveFolderName>` - A Shared Drive name and a folder name on that Shared Drive.
* `convertparents` - Convert all but the last parent reference in `<DriveFileEntity>` to shortcuts. My testing shows that as parents are added to a file, they are added to the front of the parents list; thus, the last parent is the original parent.
If neither `<DriveFileParentAttribute>` nor `convertparents` are specified, the shortcut is placed in the root folder (My Drive).
@@ -142,6 +142,6 @@ gam csv Shortcuts.csv matchfield code 4 gam user "~owner" create drivefileshortc
## Check shortcut validity on Shared Drives
```
gam redirect csv ./TDShortcuts.csv user organizer@domain.com print filelist select teamdriveid <SharedDriveID> showmimetype gshortcut fields id
gam redirect csv ./TDShortcuts.csv user organizer@domain.com print filelist select shareddriveid <SharedDriveID> showmimetype gshortcut fields id
gam redirect csv ./Shortcuts.csv user organizer@domain.com check drivefileshortcut csvfile TDShortcuts.csv:id csv
```

View File

@@ -3,7 +3,8 @@
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Aliases](#aliases)
- [Delegation Notification](#delegation-notification)
- [Delegator Banner](#delegator-banner)
- [Delegate Notification](#delegate-notification)
- [Create Gmail delegates](#create-gmail-delegates)
- [Delete Gmail delegates](#delete-gmail-delegates)
- [Update Gmail delegates](#update-gmail-delegates)
@@ -57,7 +58,13 @@ The `convertalias` option causes GAM to make an extra API call per user in `<Use
to convert aliases to primary email addresses. If you know that all of the email addresses
in `<UserEntity>` are primary, you can omit `convertalias` and avoid the extra API calls.
## Delegation Notification
## Delegator Banner
When creating a delegate, the following banner is displayed in the delegator's Gmail inbox, it can not be suppressed.
```
<Delegate> now has delegated access to your account. This notice will end in 7 days.
```
## Delegate Notification
When creating a delegate, you can send a message to the delegate.
```
[notify [<Boolean>]

View File

@@ -404,7 +404,7 @@ Messages are archived to the group specified by `<GroupItem>`.
### Archive a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_archive` - Limit the number of messages that will be archived; use a value of 0 for no limit
* `max_to_archive <Number>` - Limit the number of messages that will be archived; use a value of 0 for no limit
* `doit` - No messages are archived unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
When `matchlabel <LabelName>` is specified, the following characters are replaced with a `-` in the generated query.
@@ -412,8 +412,8 @@ When `matchlabel <LabelName>` is specified, the following characters are replace
&()"|{}/
```
By default, Gam fetches all matching messages from Google and then processes only `max_to_archive` of them.
To speed up fetching, specify `quick` and only `max_to_archive` of the matching messages will be fetched.
By default, Gam fetches all matching messages from Google and then archives only `max_to_archive <Number>` of them.
To speed up fetching, specify `quick` and only `max_to_archive <Number>` of the matching messages will be fetched.
You must still specify `doit` to perform the operation.
By default, the command results are displayed as indented keys and values. Use the `csv` option
@@ -447,6 +447,9 @@ gam <UserTypeEntity> export thread|threads
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
```
By default, Gam fetches all matching messages from Google and then exports only `max_to_export <Number>` of them.
To speed up fetching, specify `quick` and only `max_to_export <Number>` of the matching messages will be fetched.
By default, when exporting a message, it is downloaded to the directory specified in `gam.cfg/drive_dir`.
* `targetfolder <FilePath>` - Specify an alternate location for the downloaded file.
@@ -477,6 +480,9 @@ gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
[subject <String>] [addorigfieldstosubject]
```
By default, Gam fetches all matching messages from Google and then forwards only `max_to_forward <Number>` of them.
To speed up fetching, specify `quick` and only `max_to_forwrd <Number>` of the matching messages will be fetched.
By default, the message subject has `Fwd: ` prepended; use `subject <String>` to specify a new subject.
All `Cc` addresses are removed from the forwarded message.
@@ -538,7 +544,7 @@ user@domain.com,18e9fc58c5491f4c,Deleted,
### Manage a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_xxx` - Limit the number of messages that will be processed; use a value of 0 for no limit
* `max_to_xxx <Number>` - Limit the number of messages that will be processed; use a value of 0 for no limit
* `doit` - No messages are processed unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
When `matchlabel <LabelName>` is specified, the following characters are replaced with a `-` in the generated query.
@@ -546,8 +552,8 @@ When `matchlabel <LabelName>` is specified, the following characters are replace
&()"|{}/
```
By default, Gam fetches all matching messages from Google and then processes only `max_to_process` of them.
To speed up fetching, specify `quick` and only `max_to_process` of the matching messages will be fetched.
By default, Gam fetches all matching messages from Google and then processes only `max_to_process <Number>` of them.
To speed up fetching, specify `quick` and only `max_to_process <Number>` of the matching messages will be fetched.
You must still specify `doit` to perform the operation.
## Delete messages by Message-Id
@@ -611,7 +617,7 @@ gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
```
## Display all messages
By default, Gam displays all messages.
* `max_to_xxx` - Limit the number of messages that will be displayed
* `max_to_print|max_to_show <Number>` - Limit the number of messages that will be displayed
* `includespamtrash` - Include messages in the Spam and Trash folders
By default, all messages in a thread are displayed with `print|show threads`.
@@ -627,7 +633,7 @@ gam user user@domain.com print|show threads maxmessagesperthread 1
## Display a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_xxx` - Limit the number of messages that will be displayed
* `max_to_print|max_to_show <Number>` - Limit the number of messages that will be displayed
* `includespamtrash` - Include messages in the Spam and Trash folders
* `labelmatchpattern <REMatchPattern>` - Only display messages with some label that matches `<REMatchPattern>`
* `labelmatchpattern xyz` - Label must start with xyz
@@ -641,8 +647,8 @@ When `matchlabel <LabelName>` is specified, the following characters are replace
&()"|{}/
```
By default, Gam fetches only `max_to_process` matching messages from Google and then displays them.
To see how many messages actually match, specify `notquick` and all matching messages will be fetched; only `max_to_process` of them will be displayed.
By default, Gam fetches only `max_to_process <Number>` matching messages from Google and then displays them.
To see how many messages actually match, specify `notquick` and all matching messages will be fetched; only `max_to_process <Number>` of them will be displayed.
### Difference between `From` and `Sender` headers
The `From` header specifies the author of the message, that is,

View File

@@ -116,7 +116,7 @@ gam <UserTypeEntity> show sendas [compact|format|html]
```
These are the output formatting options:
* `compact` - Escape carriage returns as \r and newlines as \n in original HTML; this format produces output that can be used as input to GAM
* `compact` - Escape carriage returns as \r and newlines as \n in original HTML
* `format` - Strip HTML keywords leaving basic printable information
* `html` - Show original HTML; this is the default option; the output is human readable but cannot be used as input to GAM
@@ -184,12 +184,13 @@ If you have a current default signature, the API will update that, but if you de
## Display signature
### Display the signature as an indented list of keys and values.
```
gam <UserTypeEntity> show signature|sig [compact|format|html]
gam <UserTypeEntity> show signature|sig [compact|format|html|template]
[primary|default] [verifyonly]
```
These are the output formatting options:
* `compact` - Escape carriage returns as \r and newlines as \n in original HTML; this format produces output that can be used as input to GAM
* `template` - Escape carriage returns as \r and newlines as \n in original HTML; this format produces output that can be used as input to GAM
* `compact` - Escape carriage returns as \r and newlines as \n in original HTML
* `format` - Strip HTML keywords leaving basic printable information
* `html` - Show original HTML; this is the default option; the output is human readable but cannot be used an input to GAM
@@ -295,19 +296,10 @@ Use text like `{FirstName}` and `{Email}` in the locations where the actual valu
Once you're created the template signature, do the following:
```
$ gam user testuser@domain.com show signature compact > SimpleSig.html
$ more SimpleSig.html
SendAs Address: <testuser@domain.com>
IsPrimary: True
Default: True
Signature: <div dir="ltr">--<div>Name: {FirstName} {LastName}<div>Phone: {Phone}</div><div>Email: {Email}</div></div><div><br></div><div>Company Name</div><div>Company Address</div><div><br></div></div>\n
```
Edit SimpleSig.html and delete all text from `SendAs ` through `Signature: `.
The result should be:
```
$ gam redirect stdout ./SigTemplate.html user testuser@domain.com show signature template
$ more SigTemplate.html
<div dir="ltr">--<div>Name: {FirstName} {LastName}<div>Phone: {Phone}</div><div>Email: {Email}</div></div><div><br></div><div>Company Name</div><div>Company Address</div><div><br></div></div>\n
```
This is a sample Users.csv file.
```
email,first,last,phone
@@ -317,5 +309,20 @@ mjones@domain.com,Mary,Jones,510-555-1212 x 456
This command will update the user's signatures.
```
gam csv Users.csv gam user "~email" signature htmlfile SimpleSig.html replace FirstName "~first" replace LastName "~last" replace Phone "~phone" replace Email "~email"
```
gam csv Users.csv gam user "~email" signature htmlfile SigTemplate.html replace FirstName "~first" replace LastName "~last" replace Phone "~phone" replace Email "~email"
```
You can also do the update with user attributes:
This is a sample Users.csv file.
```
email
bsmith@domain.com
mjones@domain.com
```
This command will update the user's signatures.
```
gam csv Users.csv gam user "~email" signature htmlfile SigTemplate.html replace FirstName field:name.givenname replace LastName field:name.familyname replace Phone field:phone.value.type.work replace Email field:email.primaryemail
```

View File

@@ -586,6 +586,9 @@ Getting all Groups for testuser1@domain.com (1/2)
Getting all Groups for testuser2@domain.com (2/2)
User,Groups,GroupsList
testuser2@domain.com,0,
# Get group membership for all users
$ gam config auto_batch_min 1 num_threads 10 redirect csv ./UsersGroups.csv multiprocess sortheaders User,Group redirect stderr - multiprocess all users print groups
```
### Display groups and their parents
Display a user's groups and their parents as an indented list.

View File

@@ -148,6 +148,8 @@
<CSVkmdSelector> |
<CSVDataSelector>
<QuerySharedDrive> ::= <String> See: https://developers.google.com/workspace/drive/api/guides/search-shareddrives
<SharedDriveACLRole> ::=
manager|organizer|owner|
contentmanager|fileorganizer|
@@ -159,8 +161,8 @@
<SharedDriveName> ::= <String>
<SharedDriveEntity> ::=
<SharedDriveID>|
(teamdriveid <SharedDriveID>)|(teamdriveid:<SharedDriveID>)|
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
(shareddriveid <SharedDriveID>)|(shareddriveid:<SharedDriveID>)|
(shareddrive <SharedDriveName>)|(shareddrive:<SharedDriveName>)
<SharedDriveFieldName> ::=
backgroundimagefile|
@@ -174,10 +176,10 @@
themeid
<SharedDriveFieldNameList> ::= "<SharedDriveFieldName>(,<SharedDriveFieldName>)*"
<SharedDriveIDEntity> ::= (teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveFileQueryEntity> ::= (teamdrivequery <QueryDriveFile>) | (teamdrivequery:<QueryDriveFile>)
<SharedDriveIDEntity> ::= (shareddriveid <DriveFileItem>) | (shareddriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (shareddrive <SharedDriveName>) | (shareddrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (shareddrivefilename <DriveFileName>) | (shareddrivefilename:<DriveFileName>)
<SharedDriveFileQueryEntity> ::= (shareddrivequery <QueryDriveFile>) | (shareddrivequery:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
@@ -291,11 +293,11 @@ When either of these options is chosen, no infomation about Shared Drive restric
To retrieve the Shared Drive ID with `returnidonly`:
```
Linux/MacOS
teamDriveId=$(gam user user@domain.com create shareddrive ... returnidonly)
shareddriveId=$(gam user user@domain.com create shareddrive ... returnidonly)
Windows PowerShell
$teamDriveId = & gam user user@domain.com create shareddrive ... returnidonly
$shareddriveId = & gam user user@domain.com create shareddrive ... returnidonly
Windows Command Prompt
for /f "delims=" %a in ('gam user user@domain.com create shareddrive ... returnidonly') do set teamDriveId=%a
for /f "delims=" %a in ('gam user user@domain.com create shareddrive ... returnidonly') do set shareddriveId=%a
```
## Bulk Create Shared Drives
@@ -417,12 +419,12 @@ The `quotechar <Character>` option allows you to choose an alternate quote chara
Display the number of Shared Drives.
```
gam <UserTypeEntity> show|print shareddrives
[teamdriveadminquery|query <QueryTeamDrive>]
[shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
showitemcountonly
```
By default, all Shared Drives are counted; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -466,7 +468,7 @@ Options `shareddriveadminquery|query` and `shareddrives|teamdrives` are mutually
Options `shareddriveadminquery|query` and `orgunit|org|ou` require `adminaccess|asadmin`.
By default, organizers for all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddrives|teamdrives <SharedDriveIDList>` - Select the Shared Drive IDs specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Select the Shared Drive IDs specified in `<FileSelector>|<CSVFileSelector>`
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
@@ -486,7 +488,7 @@ To select organizers from any domain, use: `domainlist ""`
For example, to get a single user organizer from your domain for all Shared Drives including no organizer drives:
```
gam redirect csv ./TeamDriveOrganizers.csv print shareddriveorganizers
gam redirect csv ./ShareddriveOrganizers.csv print shareddriveorganizers
```
## Manage Shared Drive access
@@ -596,14 +598,14 @@ The `quotechar <Character>` option allows you to choose an alternate quote chara
## Display Shared Drive access for selected Shared Drives
```
gam <UserTypeEntity> show shareddriveacls
adminaccess [teamdriveadminquery|query <QueryTeamDrive>]
adminaccess [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
[oneitemperrow] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> print shareddriveacls [todrive <ToDriveAttribute>*]
adminaccess [teamdriveadminquery|query <QueryTeamDrive>]
adminaccess [shareddriveadminquery|query <QuerySharedDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
@@ -615,7 +617,7 @@ Shared Drives in the workspace, `<UserTypeEntity>` should specify a super admin
option shoud be used.
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `shareddriveadminquery|query <QuerySharedDrive>` - Use a query to select Shared Drives
* `matchname <REMatchPattern>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
* `<PermissionMatch>* [<PermissionMatchAction>] pmselect` - Use permission matching to select Shared Drives

View File

@@ -1018,6 +1018,10 @@ These existing options enable the display of additional information.
* `(products|product <ProductIDList>)|(skus|sku <SKUIDList>)` - Display license information for a selected list of products/SKUs.
* `schemas|custom|customschemas <SchemaNameList>` - Display all fields or selected fields of the specified custom schemas
You can use `license_skus = <SKUIDList>` in `gam.cfg` to list all of the licensing SKUs
used in your workspace. Without this list or the `products|skus` options from above,
GAM has to make 70+ API calls to get the licenses for a user; this can cause quota limit errors.
By default, Gam displays fields that only an adminstrator can view.
* `userview` - Only display fields that other users in the domain can view.

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAM 7.31.06 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
macOS Tahoe 26.2 x86_64
@@ -15,7 +15,7 @@ Time: 2025-12-23T13:57:00-08:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.31.06 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
macOS Tahoe 26.2 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAM 7.31.06 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
macOS Tahoe 26.2 x86_64
@@ -35,7 +35,7 @@ Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2025-12-23T13:57:00-08:00
Your system time differs from admin.googleapis.com by less than 1 second
OpenSSL 3.5.3 16 Sep 2025
OpenSSL 3.6.1 27 Jan 2026
arrow 1.3.0
chardet 5.2.0
cryptography 46.0.1
@@ -68,7 +68,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7
Version Check:
Current: 5.35.08
Latest: 7.31.06
Latest: 7.34.00
echo $?
1
```
@@ -76,7 +76,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.31.06
7.34.00
```
In Linux/MacOS you can do:
```
@@ -86,7 +86,7 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.31.06 - https://github.com/GAM-team/GAM
GAM 7.34.00 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
macOS Tahoe 26.2 x86_64

View File

@@ -33,6 +33,7 @@ Notes and Information
* [Questions? Visit the GAM Discussion Forum](https://groups.google.com/forum/#!forum/google-apps-manager)
* [GAM Public Chat Room](GAM-Public-Chat-Room)
* [Scripts](Scripts)
* [Code Wiki](https://codewiki.google/github.com/gam-team/gam)
* [Other Resources](Other-Resources)
* [Drive REST API v3](Drive-REST-API-v3)
* [BNF Syntax](BNF-Syntax)
@@ -73,6 +74,7 @@ Client Access
* [Calendars](Calendars)
* [Calendars - Access](Calendars-Access)
* [Calendars - Events](Calendars-Events)
* [Calendars - Secondary Calendars with no Owner](No-Owner-Secondary-Calendars)
* [Chrome Auto Update Expiration Counts](Chrome-AUE-Counts)
* [Chrome Browser Cloud Management](Chrome-Browser-Cloud-Management)
* [Chrome Device Counts](Chrome-Device-Counts)

View File

@@ -232,6 +232,11 @@ csv_output_header_order
Any headers in the file but not in the list will appear after
the headers in the list
Default: ''
csv_output_header_required
A list of <Strings> used to specify column headers
for inclusion in the CSV file written by a gam print command
even if the API didn't return any data for those columns.
Default: ''
csv_output_line_terminator
Allowed values: cr, lf, crlf
Designates character(s) used to terminate the lines of a CSV file.
@@ -307,6 +312,21 @@ debug_level
debug_redaction
Enable/disable redaction of sensitive data from API debugging output
Default: True
developer_preview_apis
A comma separated list of APIs requiring a Developer Preview key.
Default: Blank
Valid values:
accesscontextmanager,admin,alertcenter,analyticsadmin,calendar-json,cbcm,chat,
chromemanagement,chromepolicy,classroom,cloudchannel,cloudidentity,
cloudresourcemanager,contactdelegation,contacts,datastudio,docs,drive,
driveactivity,drivelabels,email-audit,forms,gmail,groupsmigration,groupssettings,
iam,iamcredentials,keep,licensing,meet,mybusinessaccountmanagement,oauth2,
orgpolicy,people,pubsub,reseller,searchconsole,serviceaccountlookup,
servicemanagement,serviceusage,sheets,siteVerification,storage,tagmanager,tasks,
vault,versionhistory,youtube
developer_preview_api_key
A Developer Preview API key that is passed to all API calls for APIs in developer_preview_apis
Default: Blank
device_max_results
When retrieving lists of ChromeOS devices from API,
how many should be retrieved in each API call
@@ -325,13 +345,6 @@ drive_max_results
how many should be retrieved in each API call
Default: 1000
Range: 1 - 1000
drive_v3_beta
Enable/disable use of Drive API v3 beta for Limited Folder Access testing
Default: False
drive_v3_native_names
Enable/disable use of Drive API v3 native column names
in all gam print/show commands related to Google Drive
Default: True
email_batch_size
When archiving, printing, showing, trashing, untrashing, marking as spam Gmail messages.
how many should be processed in each batch
@@ -371,7 +384,7 @@ gmail_cse_inkey_dir
Default: Blank
input_dir
Input directory for files with non-absolute file names.
The default
The default is the current working directory.
Default: .
inter_batch_wait
When processing items in batches, how many seconds should GAM wait between batches
@@ -387,9 +400,6 @@ license_skus
Each item in the list can be a <SKUID> which will be validated or
a <ProductID>/<SKUID> which will not be validated.
Default: Blank
meet_v2_beta
Enable/disable use of Meet API v2 beta for additional Chat Space parameters.
Default: False
member_max_results
When retrieving lists of Google Group members from API,
how many should be retrieved in each API call
@@ -404,7 +414,7 @@ member_max_results_ci_basic
member_max_results_ci_full
When retrieving lists of Cloud Identity Group members from API
with either the basic or full options,
how many should be retrieved in each API call
how many should be retrieved in each API call
Default: 500
Range: 1 - 500
message_batch_size
@@ -463,6 +473,10 @@ oauth2_txt
Path to oauth2.txt
Default: GamConfigDir/oauth2.txt
Environment variable: OAUTHFILE
oauth2_txt_lock_mode
Allowed values: 644, 664, 666
File permissions for oauth2.txt.lock
Default: 644
oauth2service_json
Path to oauth2service.json
Default: GamConfigDir/oauth2service.json
@@ -573,7 +587,7 @@ timezone
to your local timezone. If you are running GAM on a remote computer or on a
cloud shell, "local" will mean the time at the remote/cloud shell computer,
not your location, Use "+|-hh:mm" to specify the timezone at your location.
Starting with version 7.21.00 you can use a timezone name; the names are case sensitive.
Starting with version 7.21.00 you can use a timezone name; the names are case sensitive.
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Default: utc
Range: utc|z|local|(+|-hh:mm)|<ValidTimezoneName>
@@ -721,6 +735,8 @@ Section: DEFAULT
csv_output_header_drop_filter = ''
csv_output_header_filter = ''
csv_output_header_force = ''
csv_output_header_order = ''
csv_output_header_required = ''
csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"'
@@ -933,7 +949,7 @@ Edit gam.cfg to set up additional clients; it should look like this when complet
activity_max_results = 100
admin_email = ''
api_calls_rate_check = false
api_calls_rate_limit = 1000
api_calls_rate_limit = 100
api_calls_tries_limit = 10
auto_batch_min = 0
bail_on_internal_error_tries = 2
@@ -943,55 +959,75 @@ cache_dir = /Users/admin/.gam/gamcache
cache_discovery_only = true
channel_customer_id = ''
charset = utf-8
cmdlog = ''
cmdlog_max_backups = 5
cmdlog_max_kilo_bytes = 1000
chat_max_results = 100
classroom_max_results = 0
client_secrets_json = client_secrets.json
clock_skew_in_seconds = 10
cmdlog = ''
cmdlog_max_backups = 5
cmdlog_max_kilo_bytes = 1000
config_dir = /Users/admin/.gam
contact_max_results = 100
csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"'
csv_input_row_drop_filter = ''
csv_input_row_drop_filter_mode = anymatch
csv_input_row_filter = ''
csv_input_row_filter_mode = allmatch
csv_input_row_limit = 0
csv_output_column_delimiter = ,
csv_output_convert_cr_nl = false
csv_output_field_delimiter = ' '
csv_output_header_drop_filter = ''
csv_output_header_filter = ''
csv_output_header_force = ''
csv_output_header_order = ''
csv_output_header_required = ''
csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"'
csv_output_row_drop_filter =
csv_output_row_drop_filter = ''
csv_output_row_drop_filter_mode = anymatch
csv_output_row_filter = ''
csv_output_row_filter_mode = allmatch
csv_output_row_limit = 0
csv_output_sort_headers = ''
csv_output_subfield_delimiter = '.'
csv_output_timestamp_column = ''
csv_output_users_audit = false
customer_id = my_customer
debug_level = 0
debug_redaction = true
developer_preview_api_key = ''
developer_preview_apis = ''
device_max_results = 200
domain =
domain = ''
drive_dir = /Users/admin/Downloads
drive_max_results = 1000
drive_v3_native_names = true
email_batch_size = 100
email_batch_size = 50
enable_dasa = false
enable_gcloud_reauth = false
enforce_expansive_access = true
event_max_results = 250
extra_args =
extra_args = ''
gmail_cse_incert_dir = ''
gmail_cse_inkey_dir = ''
input_dir = .
inter_batch_wait = 0
license_max_results = 100
license_sku = ''
license_skus = ''
member_max_results = 200
member_max_results_ci_basic = 1000
member_max_results_ci_full = 500
message_batch_size = 50
message_max_results = 1000
message_max_results = 500
mobile_max_results = 100
multiprocess_pool_limit = 0
never_time = Never
no_browser = false
no_cache = false
no_short_urls = true
no_update_check = true
no_verify_ssl = false
num_tbatch_threads = 2
@@ -1005,9 +1041,10 @@ print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = False
quick_info_user = False
quick_cros_move = false
quick_info_user = false
reseller_id = ''
retry_api_service_not_available = false
section =
show_api_calls_retry_data = false
show_commands = false
@@ -1022,26 +1059,28 @@ smtp_password = ''
smtp_username = ''
timezone = utc
tls_max_version = ''
tls_min_version = 'TLSv1_2'
tls_min_version = 'TLSv1_3'
todrive_clearfilter = false
todrive_clientaccess = false
todrive_conversion = true
todrive_localcopy = false
todrive_locale = ''
todrive_no_escape_char = true
todrive_nobrowser = false
todrive_noemail = true
todrive_no_escape_char = true
todrive_parent = root
todrive_sheet_timeformat = ''
todrive_sheet_timestamp = false
todrive_timeformat = ''
todrive_timestamp = false
todrive_timezone = ''
todrive_upload_nodata = true
todrive_user = ''
truncate_client_id = false
update_cros_ou_with_id = false
use_chat_admin_access = false
use_course_owner_access = false
use_projectid_as_name = false
user_max_results = 500
user_service_account_access_only = false