Compare commits

...

64 Commits

Author SHA1 Message Date
Ross Scroggs
c3e23fabf1 Update pyproject.toml 2026-02-24 17:22:59 -08:00
Ross Scroggs
95eb36c5c2 Update to avoid requests error 2026-02-24 15:56:30 -08:00
Ross Scroggs
17105d51f1 Initial guest user support 2026-02-24 15:45:47 -08:00
Ross Scroggs
8dbc455407 Initial guest user support 2026-02-24 14:45:03 -08:00
Ross Scroggs
7e7b8416a4 Define guest user fields 2026-02-24 14:10:49 -08:00
Ross Scroggs
ed81501bf2 Define guest user fields
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-vs2026) (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-24 14:10:13 -08:00
Ross Scroggs
428f8f5987 Added option copyfolderpermissions [<Boolean>] to gam <UserTypeEntity> copy|move drivefile
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-vs2026) (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-02-20 13:54:34 -08:00
Ross Scroggs
b9a489251b Added option copyfolderpermissions [<Boolean>] to gam <UserTypeEntity> copy|move drivefile 2026-02-20 13:54:14 -08:00
Ross Scroggs
3b9a9ba224 Update Users-Drive-Files-Display.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-vs2026) (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-20 08:34:59 -08:00
Ross Scroggs
0d63a85a45 Update Users-Gmail-Messages-Threads.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-vs2026) (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-18 09:49:00 -08:00
Ross Scroggs
a8ea30e19e Sort all events in gam report <ActivityApplictionName> 2026-02-18 09:08:56 -08:00
Ross Scroggs
660e9deb70 Sort all events in gam report <ActivityApplictionName> 2026-02-18 09:08:34 -08:00
Ross Scroggs
ad5ba656ee Improved create drivefileacl error handling
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-vs2026) (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-02-17 16:15:39 -08:00
Ross Scroggs
991b1aa33b Improved create drivefileacl error handling 2026-02-17 16:15:22 -08:00
Ross Scroggs
51fafdb735 Update Reports.md 2026-02-17 14:37:42 -08:00
Ross Scroggs
52f1e998fd Update Reports.md 2026-02-17 14:04:50 -08:00
Ross Scroggs
0f144b24d0 Update Reports.md 2026-02-17 13:54:08 -08:00
Ross Scroggs
52d0b0a84b Update course add external teacher|student error message
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-vs2026) (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-16 10:12:53 -08:00
Ross Scroggs
28224045b2 Update course add external teacher|student error message
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-vs2026) (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-16 10:12:28 -08:00
Jay Lee
3fbb261821 actions: rebuild to get Python 3.14.3
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-vs2026) (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-02-13 18:59:29 -05:00
Jay Lee
0b4a4a270e bump cryptography for security 2026-02-13 18:44:37 -05:00
Jay Lee
177f5f0792 Update build.yml 2026-02-13 18:35:48 -05:00
Ross Scroggs
57e0cc80af Mre fix typos 2026-02-13 15:33:14 -08:00
Ross Scroggs
1e67310f3d Fix typos 2026-02-13 15:31:36 -08:00
Jay Lee
e661641544 Update build.yml 2026-02-13 17:11:53 -05:00
Ross Scroggs
81aa9c6e16 Merge branch 'main' of https://github.com/GAM-team/GAM 2026-02-13 14:03:58 -08:00
Ross Scroggs
8c3b49a967 Update Users-Drive-Permissions.md 2026-02-13 14:03:54 -08:00
Jay Lee
13c6893b67 Update build.yml 2026-02-13 17:02:46 -05:00
Jay Lee
6702e4db30 [actions]: custom cryptography wheel for win arm64 2026-02-13 16:48:41 -05:00
Jay Lee
2ed23c8f55 Update build.yml 2026-02-13 16:30:11 -05:00
Jay Lee
24a58c8edc [actions] use VS Code 2026 on Win x64 2026-02-13 14:18:03 -05:00
Jay Lee
0112264291 [actions] update env variables for apply notary 2026-02-13 12:59:04 -05:00
Jay Lee
fa5af0ed1f [actions] switch Apple notary auth to using a key instead of ASP. 2026-02-13 12:46:15 -05:00
Ross Scroggs
15e3f50a3c Updated GAM to prevent unable to find the server errors 2026-02-13 09:17:34 -08:00
Ross Scroggs
24b7c65754 Updated GAM to prevent unable to find the server errors 2026-02-13 08:04:14 -08:00
Ross Scroggs
2429e99e18 Updated GAM to prevent unable to find the server errors
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-13 08:03:48 -08:00
Ross Scroggs
ff41390c85 Updated gam create|update adminrole
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-02-12 09:53:54 -08:00
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
40 changed files with 1409 additions and 547 deletions

View File

@@ -91,7 +91,7 @@ jobs:
freethreaded: false
goal: build
name: Build Arm MacOS 26
- os: windows-2025
- os: windows-2025-vs2026
jid: 12
freethreaded: false
goal: build
@@ -153,7 +153,7 @@ jobs:
with:
path: |
cache.tar.xz
key: gam-${{ matrix.jid }}-20260129
key: gam-${{ matrix.jid }}-20260224
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -507,6 +507,8 @@ jobs:
"$PYTHON" -m pip list
- name: Install pip requirements
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "before anything..."
"$PYTHON" -m pip list
@@ -517,6 +519,12 @@ jobs:
echo "--pip debug verbose--"
"$PYTHON" -m pip debug --verbose
echo "--------"
if ([ "$RUNNER_OS" == "Windows" ] && [ "$RUNNER_ARCH" == "ARM64" ]); then
# custom cryptography wheel for win arm64 since the project doesn't provide one:
# https://github.com/pyca/cryptography/issues/14293
gh release download --repo "jay0lee/cryptography-wheels" --pattern "*win_arm64.whl" --clobber
"$PYTHON" -m pip install cryptography-*.whl
fi
"$PYTHON" -m pip install -vvv --upgrade ..[yubikey]
echo "after everything..."
"$PYTHON" -m pip list
@@ -625,13 +633,19 @@ jobs:
- name: MacOS send GAM binary for Apple notarization
if: runner.os == 'macOS'
env:
ASP_NOTARIZE: ${{ secrets.ASP_NOTARIZE }}
APPLE_KEY: ${{ secrets.APPLE_KEY }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
run: |
# Apple wants some kind of "package" submitted so just add gam to a .zip
# name it something we can track and link in Apple's notarize process
zipfilename="./gam-${RUNNER_ARCH}-${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}.zip"
zip -r "$zipfilename" "$gampath"
xcrun notarytool submit --apple-id "jay0lee@gmail.com" --password "$ASP_NOTARIZE" --team-id GZ85H2DRLM "$zipfilename"
export KEY_FILE="$(mktemp).p8"
trap 'rm -f "$KEY_FILE"' EXIT
echo "$APPLE_KEY" > "$KEY_FILE"
xcrun notarytool submit "$zipfilename" --key "$KEY_FILE" --key-id "$APPLE_KEY_ID" --issuer "$APPLE_ISSUER_ID"
rm -v "$KEY_FILE"
rm -v "$zipfilename"
- name: Basic Tests all jobs
@@ -669,10 +683,9 @@ jobs:
if: runner.os == 'Windows'
shell: pwsh
run: |
#$url = "https://files.certum.eu/software/SimplySignDesktop/Windows/9.3.2.67/SimplySignDesktop-9.3.2.67-64-bit-en.msi"
#$file = "SimplySignDesktop-9.3.2.67-64-bit-en.msi"
$url = "https://files.certum.eu/software/SimplySignDesktop/Windows/9.3.4.72/SimplySignDesktop-9.3.4.72-64-bit-en.msi"
$file = "SimplySignDesktop-9.3.4.72-64-bit-en.msi"
#$url = "https://files.certum.eu/software/SimplySignDesktop/Windows/9.3.4.72/SimplySignDesktop-9.3.4.72-64-bit-en.msi"
$url = "https://www.files.certum.eu/software/SimplySignDesktop/Windows/9.4.0.84/SimplySignDesktop-9.4.0.84-64-bit-en.msi"
$file = "SimplySignDesktop.msi"
Invoke-WebRequest $url -OutFile $file
$log = "install.log"
$procMain = Start-Process "msiexec" "/i `"$file`" /qn /l*! `"$log`"" -NoNewWindow -PassThru

View File

@@ -11,8 +11,8 @@ authors = [
#significant compile dependencies.
dependencies = [
"arrow>=1.3.0",
"chardet>=5.2.0",
"cryptography==46.0.3",
"chardet==5.2.0",
"cryptography>=46.0.5",
"distro; sys_platform=='linux'",
"filelock>=3.18.0",
"google-api-python-client>=2.167.0",

View File

@@ -2789,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> ::=
@@ -4660,6 +4662,7 @@ gam report <ActivityApplicationName> [todrive <ToDriveAttribute>*]
[event|events <EventNameList>] [ip <String>]
[gmaileventtypes <NumberRangeList>]
[groupidfilter <String>] [resourcedetailsfilter <String>]
[notimesort]
[maxactivities <Number>] [maxevents <Number>] [maxresults <Number>]
[countsonly [bydate|summary] [eventrowfilter]]
(addcsvdata <FieldName> <String>)* [shownoactivities]
@@ -5690,6 +5693,7 @@ gam download storagefile <StorageBucketObjectName>
fullname|
gender|
givenname|firstname|
guestaccountinfo|
id|
ims|im|
includeinglobaladdresslist|gal|
@@ -5697,6 +5701,7 @@ gam download storagefile <StorageBucketObjectName>
isdelegatedadmin|admin|isadmin|
isenforcedin2sv|is2svenforced|
isenrolledin2sv|is2svenrolled|
isguestuser|
ismailboxsetup|
keyword|keywords|
language|languages|
@@ -6166,6 +6171,7 @@ Display a users calendar settings
defaulteventlength|
format24hourtime|
hideinvitations|
hideinvitationssetting|
hideweekends|
locale|
remindonrespondedeventsonly|
@@ -6903,6 +6909,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
[copyfilepermissions [<Boolean>]]
[copyfileinheritedpermissions [<Boolean>]
[copyfilenoninheritedpermissions [<Boolean>]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]]
@@ -6932,6 +6939,7 @@ gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileNam
[createshortcutsfornonmovablefiles [<Boolean>]]
[duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
[duplicatefolders merge|duplicatename|uniquename|skip]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]]
@@ -6974,6 +6982,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>)]
@@ -7457,6 +7466,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>)]
@@ -7570,6 +7580,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>]

View File

@@ -1,7 +1,162 @@
7.34.07
Added the following command to create a guest user.
* See: https://support.google.com/a/answer/16558545?hl=en
```
gam create guestuser <EmailAddress>
```
Added the following items to `<UserFieldName>`:
* `guestaccountinfo` - Additional guest-related metadata fields
* `isguestuser` - Indicates if the inserted user is a guest
7.34.06
Added option `copyfolderpermissions [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`.
When `copyfolderpermissions false` is specified, no folder permissions are copied; this simplifies
disabling all folder permission copying.
When not specified or `copyfolderpermissions [true]` is specified, folder permissions are copied based on the following options:
```
copymergewithparentfolderpermissions [<Boolean>]
copymergedtopfolderpermissions [<Boolean>]
copytopfolderpermissions [<Boolean>]
copytopfolderiheritedpermissions [<Boolean>]
copytopfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
copymergedsubfolderpermissions [<Boolean>]
copysubfolderpermissions [<Boolean>]
copysubfolderinheritedpermissions [<Boolean>]
copysubfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
```
7.34.05
Updated `gam report <ActivityApplictionName>` to perform a reverse chronological sort
on all rows across multiple users and/or event names; this is consistent with the behavior
in the Admin console. Use option `notimesort` to suppress this sort.
7.34.04
Updated `gam <UserTypeEntity> create drivefileacl <DriveFileEntity> user <UserItem> role owner` to better
handle the case where the current owner of a file is suspended. Previously, the command was displayed as an error
even though the ownership was changed.
```
gam user currentowner@domain.com add drivefileacl <DriveFileID> user newowner@domain.com role owner
User: currentowner@domain.com, Add 1 Drive File/Folder ACL
User: currentowner@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: newowner@domain.com, Add Failed: Sorry, the items were successfully shared but emails could not be sent to newowner@domain.com.
```
Now the command is displayed as a success with a note indicating that the ownership change email was not sent.
```
gam user currentowner@domain.com add drivefileacl <DriveFileID> user newowner@domain.com role owner
User: currentowner@domain.com, Add 1 Drive File/Folder ACL
User: currentowner@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: newowner@domain.com, Added: Sorry, the items were successfully shared but emails could not be sent to newowner@domain.com.
New Owner
id: 10834698115409747890
type: user
emailAddress: newowner@domain.com
domain: domain.com
role: owner
permissionDetails:
role: writer
type: file
inherited: True
inheritedFrom: Unknown
role: owner
type: file
inherited: False
deleted: False
pendingOwner: False
```
7.34.03
Updated to Python 3.14.3
Updated Cryptography to 46.0.5
Updated `gam course <CourseID> create student|teacher <EmailAddress>` error message when
`<EmailAddress>` is not in a trusted domain to remove suggestion about creating an invitation.
7.34.02
Updated GAM to prevent errors like the following:
```
ERROR: Unable to find the server at oauth2.googleapis.com
ERROR: Unable to find the server at gmail.googleapis.com
```
If you experience any unexpected errors, post a message to:
* The GAM Discussion Forum (google-apps-manager@googlegroups.com)
* The GAM Public Chat Room (https://chat.google.com/app/chat/AAAA4BULhWo)
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
of files whose `modifiedTime` meets specified requirements.
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

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.32.06'
__version__ = '7.34.08'
__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]
@@ -4820,11 +4840,12 @@ def getService(api, httpObj):
triesLimit = 3
for n in range(1, triesLimit+1):
try:
if api not in {API.CHAT} 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, {})
@@ -5692,7 +5713,9 @@ def chooseSaAPI(api1, api2):
def buildGAPIServiceObject(api, user, i=0, count=0, displayError=True):
userEmail = getSaUser(user)
httpObj = getHttpObj(cache=GM.Globals[GM.CACHE_DIR])
if GM.Globals[GM.HTTP_OBJECT] is None:
GM.Globals[GM.HTTP_OBJECT] = getHttpObj(cache=GM.Globals[GM.CACHE_DIR])
httpObj = GM.Globals[GM.HTTP_OBJECT]
service = getService(api, httpObj)
credentials = getSvcAcctCredentials(api, userEmail)
request = transportCreateRequest(httpObj)
@@ -6066,7 +6089,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 +6102,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 +7339,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 +7360,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 +7384,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 +7396,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 +7927,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 +8644,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 +9090,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 +9109,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 +9929,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 +9954,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 +10179,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],
@@ -13786,7 +13829,9 @@ REPORT_ACTIVITIES_TIME_OBJECTS = {'time'}
# yesterday|today|thismonth|(previousmonths <Integer>)]
# [filter <String> (filtertime<String> <Time>)*]
# [event|events <EventNameList>] [ip <String>]
# [groupidfilter <String>]
# [gmaileventtypes <NumberRangeList>]
# [groupidfilter <String>] [resourcedetailsfilter <String>]
# [notimesort]
# [maxactivities <Number>] [maxevents <Number>] [maxresults <Number>]
# [countsonly [bydate|summary] [eventrowfilter]]
# (addcsvdata <FieldName> <String>)* [shownoactivities]
@@ -14101,6 +14146,7 @@ def doReport():
maxResults = 1000
aggregateByDate = aggregateByUser = convertMbToGb = countsOnly = countsByDate = countsSummary = \
eventRowFilter = exitUserLoop = noAuthorizedApps = normalizeUsers = select = userCustomerRange = False
sortAllTimes = True
limitDateChanges = -1
allVerifyUser = userKey = 'all'
cd = orgUnit = orgUnitId = None
@@ -14198,6 +14244,8 @@ def doReport():
eventNames.append(event)
elif activityReports and myarg == 'ip':
actorIpAddress = getString(Cmd.OB_STRING)
elif activityReports and myarg == 'notimesort':
sortAllTimes = False
elif activityReports and myarg == 'countsonly':
countsOnly = True
elif activityReports and myarg == 'bydate':
@@ -14663,6 +14711,8 @@ def doReport():
if addCSVData:
row.update(addCSVData)
csvPF.WriteRowTitles(row)
elif sortAllTimes:
csvPF.SortRows('id.time', True)
else:
if eventRowFilter:
csvPF.SetRowFilter([], GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE])
@@ -16951,12 +17001,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 +17025,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))
@@ -27063,6 +27114,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):
@@ -27093,6 +27146,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]
@@ -27127,6 +27182,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)
@@ -27181,6 +27238,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>]
@@ -27252,6 +27311,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)
@@ -30067,7 +30128,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):
@@ -30138,25 +30199,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)
@@ -30168,6 +30258,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':
@@ -30191,6 +30283,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)
@@ -30280,7 +30374,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 = {
@@ -34783,13 +34878,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 = {
@@ -37735,7 +37831,7 @@ def doCreateUpdateCIPolicy():
updateCmd = Act.Get() == Act.UPDATE
groupEmail = orgUnit = None
checkArgumentPresent('json', True)
jsonData = getJSON(['type'])
jsonData = getJSON(['customer', 'type'])
if updateCmd:
pname = jsonData.pop('name', None)
else:
@@ -45915,7 +46011,10 @@ def doCreateGuestUser():
result = callGAPI(cd.users(), 'createGuest',
throwReasons=[GAPI.FAILED_PRECONDITION],
body=body)
entityActionPerformed([Ent.GUEST_USER, result['primaryGuestEmail']])
entityActionPerformed([Ent.GUEST_USER, body['primaryGuestEmail']])
Ind.Increment()
showJSON(None, result)
Ind.Decrement()
except (GAPI.failedPrecondition) as e:
entityActionFailedExit([Ent.GUEST_USER, body['primaryGuestEmail']], str(e))
@@ -46528,8 +46627,9 @@ USER_FIELDS_CHOICE_MAP = {
'firstname': 'name.givenName',
'fullname': 'name.fullName',
'gal': 'includeInGlobalAddressList',
'givenname': 'name.givenName',
'gender': ['gender.type', 'gender.customGender', 'gender.addressMeAs'],
'givenname': 'name.givenName',
'guestaccountinfo': 'guestAccountInfo',
'id': 'id',
'im': 'ims',
'ims': 'ims',
@@ -46539,6 +46639,7 @@ USER_FIELDS_CHOICE_MAP = {
'isdelegatedadmin': ['isAdmin', 'isDelegatedAdmin'],
'isenforcedin2sv': 'isEnforcedIn2Sv',
'isenrolledin2sv': 'isEnrolledIn2Sv',
'isguestuser': 'isGuestUser',
'is2svenforced': 'isEnforcedIn2Sv',
'is2svenrolled': 'isEnrolledIn2Sv',
'ismailboxsetup': 'isMailboxSetup',
@@ -51302,8 +51403,6 @@ def _batchAddItemsToCourse(croom, courseId, i, count, addItems, addType):
errMsg = getPhraseDNEorSNA(riItem)
else:
errMsg = getHTTPError(_ADD_PART_REASON_TO_MESSAGE_MAP, http_status, reason, message)
if (reason == GAPI.PERMISSION_DENIED) and (addType in {Ent.STUDENT, Ent.TEACHER}) and ('CannotDirectAddUser' in errMsg):
errMsg += f' Add external user with: gam user {riItem} create classroominvitation courses {ri[RI_ENTITY]} addType {Ent.Singular(addType)}'
entityActionFailedWarning([Ent.COURSE, ri[RI_ENTITY], addType, riItem], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT]))
return
waitOnFailure(1, 10, reason, message)
@@ -54125,6 +54224,7 @@ USER_CALENDAR_SETTINGS_FIELDS_CHOICE_MAP = {
'defaulteventlength': 'defaultEventLength',
'format24hourtime': 'format24HourTime',
'hideinvitations': 'hideInvitations',
'hideinvitationssetting': 'hideInvitationsSetting',
'hideweekends': 'hideWeekends',
'locale': 'locale',
'remindonrespondedeventsonly': 'remindOnRespondedEventsOnly',
@@ -57294,6 +57394,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:
@@ -57320,7 +57445,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):
@@ -57354,9 +57480,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':
@@ -57416,6 +57542,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>
@@ -57425,6 +57552,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):
@@ -57487,7 +57615,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:
@@ -57526,12 +57655,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')
@@ -58859,6 +58990,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]
@@ -59039,7 +59171,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']
@@ -59056,8 +59189,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)
@@ -59279,7 +59416,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():
@@ -59352,7 +59490,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:
@@ -59383,7 +59522,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)
@@ -59415,8 +59554,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:
@@ -59427,6 +59567,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
@@ -61927,6 +62070,7 @@ def initCopyMoveOptions(copyCmd):
'copyFilePermissions': False,
'copyFileInheritedPermissions': True,
'copyFileNonInheritedPermissions': COPY_NONINHERITED_PERMISSIONS_ALWAYS,
'copyFolderPermissions': True,
'copyMergeWithParentFolderPermissions': False,
'copyMergedTopFolderPermissions': copyCmd,
'copyMergedSubFolderPermissions': copyCmd,
@@ -62004,6 +62148,8 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
copyMoveOptions['duplicateFiles'] = getChoice(DUPLICATE_FILE_CHOICES, mapChoice=True)
elif myarg == 'duplicatefolders':
copyMoveOptions['duplicateFolders'] = getChoice(DUPLICATE_FOLDER_CHOICES, mapChoice=True)
elif myarg == 'copyfolderpermissions':
copyMoveOptions['copyFolderPermissions'] = getBoolean()
elif myarg == 'copymergewithparentfolderpermissions':
copyMoveOptions['copyMergeWithParentFolderPermissions'] = getBoolean()
elif myarg == 'copymergedtopfolderpermissions':
@@ -62682,6 +62828,7 @@ copyReturnItemMap = {
# [copyfilepermissions [<Boolean>]]
# [copyfileinheritedpermissions [<Boolean>]
# [copyfilenoninheritedpermissions [<Boolean>]
# [copyfolderpermissions [<Boolean>]]
# [copymergewithparentfolderpermissions [<Boolean>]]
# [copymergedtopfolderpermissions [<Boolean>]]
# [copytopfolderpermissions [<Boolean>]]
@@ -62729,7 +62876,8 @@ def copyDriveFile(users):
_writeCSVData(user, folderName, folderId, newParentName, newParentId, MIMETYPE_GA_FOLDER)
Act.Set(action)
_incrStatistic(statistics, STAT_FOLDER_MERGED)
if (copyMoveOptions['copyMergeWithParentFolderPermissions'] and
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions['copyMergeWithParentFolderPermissions'] and
copyMoveOptions['destParentType'] != DEST_PARENT_MYDRIVE_ROOT):
copyFolderNonInheritedPermissions =\
_getCopyFolderNonInheritedPermissions(copyMoveOptions,
@@ -62759,7 +62907,8 @@ def copyDriveFile(users):
_writeCSVData(user, folderName, folderId, newFolderName, newFolderId, MIMETYPE_GA_FOLDER)
Act.Set(action)
_incrStatistic(statistics, STAT_FOLDER_MERGED)
if (copyMoveOptions[['copyMergedSubFolderPermissions', 'copyMergedTopFolderPermissions'][atTop]] and
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions[['copyMergedSubFolderPermissions', 'copyMergedTopFolderPermissions'][atTop]] and
(not atTop or copyMoveOptions['destParentType'] != DEST_PARENT_MYDRIVE_ROOT)):
copyFolderNonInheritedPermissions =\
_getCopyFolderNonInheritedPermissions(copyMoveOptions,
@@ -62811,7 +62960,8 @@ def copyDriveFile(users):
else:
_writeCSVData(user, folderName, folderId, newFolderName, newFolderId, body['mimeType'])
_incrStatistic(statistics, STAT_FOLDER_COPIED_MOVED)
if copyMoveOptions[['copySubFolderPermissions', 'copyTopFolderPermissions'][atTop]]:
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions[['copySubFolderPermissions', 'copyTopFolderPermissions'][atTop]]):
_copyPermissions(drive, user, i, count, j, jcount,
Ent.DRIVE_FOLDER, folderId, folderName, newFolderId, newFolderName,
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
@@ -63566,6 +63716,7 @@ def _recursiveUpdateMovePermissions(drive, user, i, count,
# [createshortcutsfornonmovablefiles [<Boolean>]]
# [duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
# [duplicatefolders merge|duplicatename|uniquename|skip]
# [copyfolderpermissions [<Boolean>]]
# [copymergewithparentfolderpermissions [<Boolean>]]
# [copymergedtopfolderpermissions [<Boolean>]]
# [copytopfolderpermissions [<Boolean>]]
@@ -63602,7 +63753,8 @@ def moveDriveFile(users):
entityPerformActionModifierItemValueList(kvList, Act.MODIFIER_CONTENTS_WITH, [Ent.DRIVE_FOLDER, newParentNameId], j, jcount)
Act.Set(action)
_incrStatistic(statistics, STAT_FOLDER_MERGED)
if (copyMoveOptions['copyMergeWithParentFolderPermissions'] and
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions['copyMergeWithParentFolderPermissions'] and
copyMoveOptions['destParentType'] != DEST_PARENT_MYDRIVE_ROOT):
copyFolderNonInheritedPermissions =\
_getCopyFolderNonInheritedPermissions(copyMoveOptions,
@@ -63632,7 +63784,8 @@ def moveDriveFile(users):
entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_CONTENTS_WITH, [Ent.DRIVE_FOLDER, f'{newFolderName}({newFolderId})'], j, jcount)
Act.Set(action)
_incrStatistic(statistics, STAT_FOLDER_MERGED)
if (copyMoveOptions[['copyMergedSubFolderPermissions', 'copyMergedTopFolderPermissions'][atTop]] and
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions[['copyMergedSubFolderPermissions', 'copyMergedTopFolderPermissions'][atTop]] and
(not atTop or copyMoveOptions['destParentType'] != DEST_PARENT_MYDRIVE_ROOT)):
copyFolderNonInheritedPermissions =\
_getCopyFolderNonInheritedPermissions(copyMoveOptions,
@@ -63726,7 +63879,8 @@ def moveDriveFile(users):
j, jcount)
Act.Set(action)
_incrStatistic(statistics, STAT_FOLDER_COPIED_MOVED)
if copyMoveOptions[['copySubFolderPermissions', 'copyTopFolderPermissions'][atTop]]:
if (copyMoveOptions['copyFolderPermissions'] and
copyMoveOptions[['copySubFolderPermissions', 'copyTopFolderPermissions'][atTop]]):
_copyPermissions(drive, user, i, count, j, jcount,
Ent.DRIVE_FOLDER, folderId, folderName, newFolderId, newFolderName,
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
@@ -66650,6 +66804,29 @@ def _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess):
# [sendemail|sendnotification] [emailmessage <String>]
# [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
def createDriveFileACL(users, useDomainAdminAccess=False):
def _showResult(permission, showAction):
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, True, permission)
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
else:
if showAction:
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
if showDetails:
_showDriveFilePermission(permission, printKeys, timeObjects)
moveToNewOwnersRoot = False
sendNotificationEmail = showTitles = _transferOwnership = updateSheetProtectedRanges = False
roleLocation = withLinkLocation = expirationLocation = None
@@ -66759,35 +66936,30 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
_, sheet = buildGAPIServiceObject(API.SHEETS, user, i, count)
if not sheet:
break
permission = callGAPI(drive.permissions(), 'create',
bailOnInternalError=True,
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
moveToNewOwnersRoot=moveToNewOwnersRoot,
useDomainAdminAccess=useDomainAdminAccess,
fileId=fileId, sendNotificationEmail=sendNotificationEmail, emailMessage=emailMessage,
transferOwnership=_transferOwnership, body=body, fields='*', supportsAllDrives=True)
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, True, permission)
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
else:
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
if showDetails:
_showDriveFilePermission(permission, printKeys, timeObjects)
try:
permission = callGAPI(drive.permissions(), 'create',
bailOnInternalError=True,
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
moveToNewOwnersRoot=moveToNewOwnersRoot,
useDomainAdminAccess=useDomainAdminAccess,
fileId=fileId, sendNotificationEmail=sendNotificationEmail, emailMessage=emailMessage,
transferOwnership=_transferOwnership, body=body, fields='*', supportsAllDrives=True)
_showResult(permission, True)
except GAPI.invalidSharingRequest as e:
errMsg = str(e)
if ('successfully shared but emails could not be sent' not in errMsg) or ('emailAddress' not in body):
entityActionFailedWarning([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], errMsg, j, jcount)
else:
if not csvPF:
entityActionPerformedMessage([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], errMsg, j, jcount)
tempPermId = getPermissionIdForEmail(user, i, count, body['emailAddress'])
permission = callGAPI(drive.permissions(), 'get',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.PERMISSION_NOT_FOUND, GAPI.INSUFFICIENT_ADMINISTRATOR_PRIVILEGES],
useDomainAdminAccess=useDomainAdminAccess,
fileId=fileId, permissionId=tempPermId, fields='*', supportsAllDrives=True)
_showResult(permission, False)
except (GAPI.badRequest, GAPI.invalid, GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError,
GAPI.cannotSetExpiration, GAPI.cannotSetExpirationOnAnyoneOrDomain,
GAPI.permissionNotFound, GAPI.cannotSetExpiration, GAPI.cannotSetExpirationOnAnyoneOrDomain,
GAPI.expirationDateNotAllowedForSharedDriveMembers, GAPI.expirationDatesMustBeInTheFuture,
GAPI.insufficientFilePermissions, GAPI.unknownError, GAPI.ownershipChangeAcrossDomainNotPermitted,
GAPI.teamDriveDomainUsersOnlyRestriction, GAPI.teamDriveTeamMembersOnlyRestriction,
@@ -66801,7 +66973,7 @@ def createDriveFileACL(users, useDomainAdminAccess=False):
GAPI.fileOrganizerOnNonTeamDriveNotSupported,
GAPI.cannotModifyInheritedPermission,
GAPI.teamDrivesFolderSharingNotSupported, GAPI.invalidLinkVisibility,
GAPI.invalidSharingRequest, GAPI.fileNeverWritable, GAPI.abusiveContentRestriction) as e:
GAPI.fileNeverWritable, GAPI.abusiveContentRestriction) as e:
entityActionFailedWarning([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], str(e), j, jcount)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.USER, user, Ent.SHAREDDRIVE, fileName], str(e), j, jcount)
@@ -66820,6 +66992,29 @@ def doCreateDriveFileACL():
# [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
# [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
def updateDriveFileACLs(users, useDomainAdminAccess=False):
def _showResult(permission, showAction):
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, True, permission)
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
else:
if showAction:
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
if showDetails:
_showDriveFilePermission(permission, printKeys, timeObjects)
fileIdEntity = getDriveFileEntity()
isEmail, permissionId = getPermissionId()
enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
@@ -66899,26 +67094,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
useDomainAdminAccess=useDomainAdminAccess, enforceExpansiveAccess=enforceExpansiveAccess,
fileId=fileId, permissionId=permissionId, removeExpiration=removeExpiration,
transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True)
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, True, permission)
if csvPF:
baserow = {'Owner': user, 'id': fileId}
if showTitles:
baserow['name'] = fileName
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
else:
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
if showDetails:
_showDriveFilePermission(permission, printKeys, timeObjects)
_showResult(permission, True)
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.cannotSetExpiration, GAPI.cannotSetExpirationOnAnyoneOrDomain,
GAPI.expirationDateNotAllowedForSharedDriveMembers, GAPI.expirationDatesMustBeInTheFuture,
@@ -67410,8 +67586,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])
@@ -67466,7 +67640,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()
@@ -67501,13 +67675,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)

View File

@@ -649,6 +649,16 @@ _SVCACCT_SCOPES = [
'api': CLOUDIDENTITY_DEVICES,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity.devices'},
# {'name': 'Cloud Identity API - Policy',
# 'api': CLOUDIDENTITY_POLICY,
# 'subscopes': READONLY,
# 'roByDefault': True,
# 'scope': 'https://www.googleapis.com/auth/cloud-identity.policies'},
# {'name': 'Cloud Identity API - Policy Beta',
# 'api': CLOUDIDENTITY_POLICY_BETA,
# 'subscopes': [],
# 'offByDefault': True,
# 'scope': 'https://www.googleapis.com/auth/cloud-identity.policies'},
# {'name': 'Cloud Identity User Invitations API',
# 'api': CLOUDIDENTITY_USERINVITATIONS,
# 'subscopes': READONLY,
@@ -812,6 +822,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

@@ -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
@@ -327,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}
@@ -371,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: '',
@@ -385,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: '',
@@ -484,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'
@@ -541,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},
@@ -557,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)},

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'
@@ -125,6 +129,8 @@ GAM_CFG_SECTION_NAME = 'gcsn'
GAM_PATH = 'gpth'
# Python source, PyInstaller or StaticX?
GAM_TYPE = 'gtyp'
# Shared Service Account HTTP Object
HTTP_OBJECT = 'http'
# Length of last Got message
LAST_GOT_MSG_LEN = 'lgml'
# License SKUs
@@ -246,6 +252,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 +274,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: [],
@@ -276,6 +284,7 @@ Globals = {
GAM_CFG_SECTION_NAME: '',
GAM_PATH: '.',
GAM_TYPE: '',
HTTP_OBJECT: None,
LAST_GOT_MSG_LEN: 0,
LICENSE_SKUS: [],
MAKE_BUILDING_ID_NAME_MAP: True,

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

@@ -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

@@ -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

@@ -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)
- [Display external users in groups with allowExternalMembers False](#display-external-users-in-groups-with-allowexternalmembers-false)
- [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)
@@ -534,6 +534,40 @@ 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
```
## Display external users in groups with allowExternalMembers False
When printing group membership, the option `verifyallowexternal` causes
GAM to only display external users in groups with `allowExternalMembers=False`.
## 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

@@ -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>
@@ -327,7 +327,7 @@ Use these options to select users for GAM commands.
* `ou_arch` - Archived users
* `ou_ns` - Non-suspended users
* `ou_susp` - Suspended users
* `ou_na_ns` - Non-archived and nn-suspended users
* `ou_na_ns` - Non-archived and non-suspended users
## Users in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units
* `ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>`
@@ -336,7 +336,7 @@ Use these options to select users for GAM commands.
* `ou_and_children_arch` - Archived users
* `ou_and_children_ns` - Non-suspended users
* `ou_and_children_susp` - Suspended users
* `ou_and_children_na_ns` - Non-archived and nn-suspended users
* `ou_and_children_na_ns` - Non-archived and non-suspended users
## Users directly in the Organization Units `<OrgUnitList>`
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
@@ -345,7 +345,7 @@ Use these options to select users for GAM commands.
* `ous_arch` - Archived users
* `ous_ns` - Non-suspended users
* `ous_susp` - Suspended users
* `ous_na_ns` - Non-archived and nn-suspended users
* `ous_na_ns` - Non-archived and non-suspended users
`<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.

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,169 @@ 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.07
Added the following command to create a guest user.
* See: https://support.google.com/a/answer/16558545
```
gam create guestuser <EmailAddress>
```
Added the following items to `<UserFieldName>`:
* `guestaccountinfo` - Additional guest-related metadata fields
* `isguestuser` - Indicates if the inserted user is a guest
### 7.34.06
Added option `copyfolderpermissions [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`.
When `copyfolderpermissions false` is specified, no folder permissions are copied; this simplifies
disabling all folder permission copying.
When not specified or `copyfolderpermissions [true]` is specified, folder permissions are copied based on the following options:
```
copymergewithparentfolderpermissions [<Boolean>]
copymergedtopfolderpermissions [<Boolean>]
copytopfolderpermissions [<Boolean>]
copytopfolderiheritedpermissions [<Boolean>]
copytopfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
copymergedsubfolderpermissions [<Boolean>]
copysubfolderpermissions [<Boolean>]
copysubfolderinheritedpermissions [<Boolean>]
copysubfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
```
### 7.34.05
Updated `gam report <ActivityApplictionName>` to perform a reverse chronological sort
on all rows across multiple users and/or event names; this is consistent with the behavior
in the Admin console. Use option `notimesort` to suppress this sort.
### 7.34.04
Updated `gam <UserTypeEntity> create drivefileacl <DriveFileEntity> user <UserItem> role owner` to better
handle the case where the current owner of a file is suspended. Previously, the command was displayed as an error
even though the ownership was changed.
```
gam user currentowner@domain.com add drivefileacl <DriveFileID> user newowner@domain.com role owner
User: currentowner@domain.com, Add 1 Drive File/Folder ACL
User: currentowner@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: newowner@domain.com, Add Failed: Sorry, the items were successfully shared but emails could not be sent to newowner@domain.com.
```
Now the command is displayed as a success with a note indicating that the ownership change email was not sent.
```
gam user currentowner@domain.com add drivefileacl <DriveFileID> user newowner@domain.com role owner
User: currentowner@domain.com, Add 1 Drive File/Folder ACL
User: currentowner@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: newowner@domain.com, Added: Sorry, the items were successfully shared but emails could not be sent to newowner@domain.com.
New Owner
id: 10834698115409747890
type: user
emailAddress: newowner@domain.com
domain: domain.com
role: owner
permissionDetails:
role: writer
type: file
inherited: True
inheritedFrom: Unknown
role: owner
type: file
inherited: False
deleted: False
pendingOwner: False
```
### 7.34.03
Updated to Python 3.14.3
Updated Cryptography to 46.0.5
Updated `gam course <CourseID> create student|teacher <EmailAddress>` error message when
`<EmailAddress>` is not in a trusted domain to remove suggestion about creating an invitation.
### 7.34.02
Updated GAM to prevent errors like the following:
```
ERROR: Unable to find the server at oauth2.googleapis.com
ERROR: Unable to find the server at gmail.googleapis.com
```
If you experience any unexpected errors, post a message to:
* The GAM Discussion Forum (google-apps-manager@googlegroups.com)
* The GAM Public Chat Room (https://chat.google.com/app/chat/AAAA4BULhWo)
### 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

View File

@@ -9,30 +9,30 @@ and all necessary authentications.
## Linux and MacOS and Google Cloud Shell
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
In these examples, your Google Super admin is shown as gamteam@domain.com; replace with the
actual email adddress.
In these examples, the user home folder is shown as /Users/admin; adjust according to your
In these examples, the user home folder is shown as /Users/gamteam; adjust according to your
specific situation; e.g., /home/administrator.
This example assumes that GAM7 has been installed in /Users/admin/bin/gam7.
This example assumes that GAM7 has been installed in /Users/gamteam/bin/gam7.
If you've installed GAM7 in another directory, substitute that value in the directions.
### Set a configuration directory
The default GAM configuration directory is /Users/admin/.gam; for more flexibility you
The default GAM configuration directory is /Users/gamteam/.gam; for more flexibility you
probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
configuration directory will be /Users/gamteam/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
Make the directory:
```
admin@server:/Users/admin$ mkdir -p /Users/admin/GAMConfig
gamteam@server:/Users/gamteam$ mkdir -p /Users/gamteam/GAMConfig
```
Add the following line:
```
export GAMCFGDIR="/Users/admin/GAMConfig"
export GAMCFGDIR="/Users/gamteam/GAMConfig"
```
to one of these files based on your shell:
```
@@ -44,34 +44,34 @@ to one of these files based on your shell:
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
admin@server:/Users/admin$ source <Filename>
gamteam@server:/Users/gamteam$ source <Filename>
```
You need to make sure the GAM configuration directory actually exists. Test that like this:
```
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
```
### Set a working directory
You should establish a GAM working directory; you will store your GAM related
data in this folder and execute GAM commands from this folder. You should not use
/Users/admin/bin/gam7 or /Users/admin/GAMConfig for this purpose.
This example assumes that the GAM working directory will be /Users/admin/GAMWork; If you've chosen
/Users/gamteam/bin/gam7 or /Users/gamteam/GAMConfig for this purpose.
This example assumes that the GAM working directory will be /Users/gamteam/GAMWork; If you've chosen
another directory, substitute that value in the directions.
Make the directory:
```
admin@server:/Users/admin$ mkdir -p /Users/admin/GAMWork
gamteam@server:/Users/gamteam$ mkdir -p /Users/gamteam/GAMWork
```
### Set an alias
You should set an alias to point to /Users/admin/bin/gam7/gam so you can operate from the /Users/admin/GAMWork directory.
You should set an alias to point to /Users/gamteam/bin/gam7/gam so you can operate from the /Users/gamteam/GAMWork directory.
Aliases aren't available in scripts, so you may want to set a symlink instead, see below.
Add the following line:
```
alias gam="/Users/admin/bin/gam7/gam"
alias gam="/Users/gamteam/bin/gam7/gam"
```
to one of these files based on your shell:
```
@@ -84,48 +84,48 @@ to one of these files based on your shell:
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
admin@server:/Users/admin$ source <Filename>
gamteam@server:/Users/gamteam$ source <Filename>
```
### Set a symlink
Set a symlink in `/usr/local/bin` (or some other location on $PATH) to point to GAM.
```
admin@server:/Users/admin$ ln -s "/Users/admin/bin/gam7/gam" /usr/local/bin/gam
gamteam@server:/Users/gamteam$ ln -s "/Users/gamteam/bin/gam7/gam" /usr/local/bin/gam
```
### Initialize GAM7; this should be the first GAM7 command executed.
```
admin@server:/Users/admin$ gam config drive_dir /Users/admin/GAMWork verify
Created: /Users/admin/GAMConfig
Created: /Users/admin/GAMConfig/gamcache
Config File: /Users/admin/GAMConfig/gam.cfg, Initialized
gamteam@server:/Users/gamteam$ gam config drive_dir /Users/gamteam/GAMWork verify
Created: /Users/gamteam/GAMConfig
Created: /Users/gamteam/GAMConfig/gamcache
Config File: /Users/gamteam/GAMConfig/gam.cfg, Initialized
Section: DEFAULT
...
cache_dir = /Users/admin/GAMConfig/gamcache
cache_dir = /Users/gamteam/GAMConfig/gamcache
...
config_dir = /Users/admin/GAMConfig
config_dir = /Users/gamteam/GAMConfig
...
drive_dir = /Users/admin/GAMWork
drive_dir = /Users/gamteam/GAMWork
...
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Verify initialization, this was a successful installation.
```
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
total 48
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
-rw-rw-rw-+ 1 admin staff 0 Mar 3 09:23 oauth2.txt.lock
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Create your project with local browser
```
admin@server:/Users/admin$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
gamteam@server:/Users/gamteam$ gam create project
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/gamteam/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/gamteam/GAMConfig/oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gamteam@domain.com
Your browser has been opened to visit:
@@ -167,7 +167,7 @@ Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-p
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: /Users/admin/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Service Account OAuth2 File: /Users/gamteam/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
@@ -185,16 +185,16 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Create your project without local browser (Google Cloud Shell for instance)
```
admin@server:/Users/admin$ gam config no_browser true save
admin@server:/Users/admin$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
gamteam@server:/Users/gamteam$ gam config no_browser true save
gamteam@server:/Users/gamteam$ gam create project
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/gamteam/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/gamteam/GAMConfig/oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gamteam@domain.com
Go to the following link in a browser on other computer:
@@ -235,7 +235,7 @@ Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-p
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: /Users/admin/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Service Account OAuth2 File: /Users/gamteam/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
@@ -253,7 +253,7 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Enable GAM7 client access
@@ -261,7 +261,7 @@ You select a list of scopes, GAM uses a browser to get final authorization from
writes the credentials into the file oauth2.txt.
```
admin@server:/Users/admin$ gam oauth create
gamteam@server:/Users/gamteam$ gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -328,7 +328,7 @@ Continue to authorization by entering a 'c'
Please enter 0-50[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Enter your Google Workspace admin email address? gamteam@domain.com
Go to the following link in a browser on this computer or on another computer:
@@ -340,16 +340,16 @@ click the Allow button, paste "Unable to connect" URL from other computer (only
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
Client OAuth2 File: /Users/gamteam/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
If clicking on the link in the instructions does not work (i.e. you get a 404 or 400 error message, instead of something about 'unable to connect') the URL in the link is too long. Most likely, you have selected all scopes. Try again with fewer scopes until it works. (there is no harm in repeatedly trying)
### Enable GAM7 service account access.
```
admin@server:/Users/admin$ gam user admin@domain.com update serviceaccount
gamteam@server:/Users/gamteam$ gam user gamteam@domain.com update serviceaccount
[*] 0) AlertCenter API
[*] 1) Analytics API - read only
[*] 2) Analytics Admin API - read only
@@ -413,7 +413,7 @@ Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ FAIL (1/38)
https://sites.google.com/feeds FAIL (2/38)
https://www.googleapis.com/auth/analytics.readonly FAIL (3/38)
@@ -464,7 +464,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -474,14 +474,14 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
gamteam@server:/Users/gamteam$ gam user gamteam@domain.com check serviceaccount
System time status
Your system time differs from admin.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds PASS (2/38)
https://www.googleapis.com/auth/analytics.readonly PASS (3/38)
@@ -524,14 +524,14 @@ All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
admin@server:/Users/admin$ gam info domain
gamteam@server:/Users/gamteam$ gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -539,8 +539,8 @@ Primary Domain Verified: True
Default Language: en
...
admin@server:/Users/admin$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/admin/GAMConfig/gam.cfg, Saved
gamteam@server:/Users/gamteam$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/gamteam/GAMConfig/gam.cfg, Saved
Section: DEFAULT
...
customer_id = C01234567
@@ -550,12 +550,12 @@ Section: DEFAULT
timezone = local
...
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
## Windows
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
In these examples, your Google Super admin is shown as gamteam@domain.com; replace with the
actual email adddress.
This example assumes that GAM7 has been installed in C:\GAM7; if you've installed
@@ -645,7 +645,7 @@ C:\>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gamteam@domain.com
Your browser has been opened to visit:
@@ -714,7 +714,7 @@ C:\>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gamteam@domain.com
Go to the following link in a browser on other computer:
@@ -848,7 +848,7 @@ Continue to authorization by entering a 'c'
Please enter 0-50[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Enter your Google Workspace admin email address? gamteam@domain.com
Go to the following link in a browser on this computer or on another computer:
@@ -866,7 +866,7 @@ C:\>
```
### Enable GAM7 service account access.
```
C:\>gam user admin@domain.com update serviceaccount
C:\>gam user gamteam@domain.com update serviceaccount
[*] 0) AlertCenter API
[*] 1) Analytics API - read only
[*] 2) Analytics Admin API - read only
@@ -930,7 +930,7 @@ Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ FAIL (1/38)
https://sites.google.com/feeds FAIL (2/38)
https://www.googleapis.com/auth/analytics.readonly FAIL (3/38)
@@ -991,14 +991,14 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\>gam user admin@domain.com check serviceaccount
C:\>gam user gamteam@domain.com check serviceaccount
System time status
Your system time differs from admin.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds PASS (2/38)
https://www.googleapis.com/auth/analytics.readonly PASS (3/38)

View File

@@ -10,30 +10,30 @@ and all necessary authentications.
## Linux and MacOS and Google Cloud Shell
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
In these examples, your Google Super admin is shown as gamteam@domain.com; replace with the
actual email adddress.
In these examples, the user home folder is shown as /Users/admin; adjust according to your
In these examples, the user home folder is shown as /Users/gamteam; adjust according to your
specific situation; e.g., /home/administrator.
This example assumes that GAM7 has been installed in /Users/admin/bin/gam7.
This example assumes that GAM7 has been installed in /Users/gamteam/bin/gam7.
If you've installed GAM7 in another directory, substitute that value in the directions.
### Set a configuration directory
The default GAM configuration directory is /Users/admin/.gam; for more flexibility you
The default GAM configuration directory is /Users/gamteam/.gam; for more flexibility you
probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
configuration directory will be /Users/gamteam/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
Make the directory:
```
admin@server:/Users/admin$ mkdir -p /Users/admin/GAMConfig
gamteam@server:/Users/gamteam$ mkdir -p /Users/gamteam/GAMConfig
```
Add the following line:
```
export GAMCFGDIR="/Users/admin/GAMConfig"
export GAMCFGDIR="/Users/gamteam/GAMConfig"
```
to one of these files based on your shell:
```
@@ -45,34 +45,34 @@ to one of these files based on your shell:
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
admin@server:/Users/admin$ source <Filename>
gamteam@server:/Users/gamteam$ source <Filename>
```
You need to make sure the GAM configuration directory actually exists. Test that like this:
```
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
```
### Set a working directory
You should establish a GAM working directory; you will store your GAM related
data in this folder and execute GAM commands from this folder. You should not use
/Users/admin/bin/gam7 or /Users/admin/GAMConfig for this purpose.
This example assumes that the GAM working directory will be /Users/admin/GAMWork; If you've chosen
/Users/gamteam/bin/gam7 or /Users/gamteam/GAMConfig for this purpose.
This example assumes that the GAM working directory will be /Users/gamteam/GAMWork; If you've chosen
another directory, substitute that value in the directions.
Make the directory:
```
admin@server:/Users/admin$ mkdir -p /Users/admin/GAMWork
gamteam@server:/Users/gamteam$ mkdir -p /Users/gamteam/GAMWork
```
### Set an alias
You should set an alias to point to /Users/admin/bin/gam7/gam so you can operate from the /Users/admin/GAMWork directory.
You should set an alias to point to /Users/gamteam/bin/gam7/gam so you can operate from the /Users/gamteam/GAMWork directory.
Aliases aren't available in scripts, so you may want to set a symlink instead, see below.
Add the following line:
```
alias gam="/Users/admin/bin/gam7/gam"
alias gam="/Users/gamteam/bin/gam7/gam"
```
to one of these files based on your shell:
```
@@ -85,62 +85,62 @@ to one of these files based on your shell:
If you already have an alias for legacy GAM but are no longer going to run it, delete these lines:
```
function gam() { "/Users/admin/bin/gam/gam" "$@" ; }"
alias gam="/Users/admin/bin/gam/gam"
function gam() { "/Users/gamteam/bin/gam/gam" "$@" ; }"
alias gam="/Users/gamteam/bin/gam/gam"
```
If you already have an alias for legacy GAM and want to run it and GAM7, give your old alias a different name:
```
function gamstd() { "/Users/admin/bin/gam/gam" "$@" ; }"
alias gamstd="/Users/admin/bin/gam/gam"
function gamstd() { "/Users/gamteam/bin/gam/gam" "$@" ; }"
alias gamstd="/Users/gamteam/bin/gam/gam"
```
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
admin@server:/Users/admin$ source <Filename>
gamteam@server:/Users/gamteam$ source <Filename>
```
### Set a symlink
Set a symlink in `/usr/local/bin` (or some other location on $PATH) to point to GAM.
```
admin@server:/Users/admin$ ln -s "/Users/admin/bin/gam7/gam" /usr/local/bin/gam
gamteam@server:/Users/gamteam$ ln -s "/Users/gamteam/bin/gam7/gam" /usr/local/bin/gam
```
Set environment variable OLDGAMPATH to point to the existing Gam directory; /Users/admin/bin/gam will be used in this example.
Set environment variable OLDGAMPATH to point to the existing Gam directory; /Users/gamteam/bin/gam will be used in this example.
If your existing Gam is in another directory, substitute that value in the directions.
```
admin@server:/Users/admin$ export OLDGAMPATH=/Users/admin/bin/gam
gamteam@server:/Users/gamteam$ export OLDGAMPATH=/Users/gamteam/bin/gam
```
Verify that OLDGAMPATH points to the correct location.
```
admin@server:/Users/admin$ ls -l $OLDGAMPATH/*.json
-rw-r-----@ 1 admin staff 553 Feb 26 10:39 /Users/admin/bin/gam/client_secrets.json
-rw-r-----@ 1 admin staff 2377 Feb 26 10:39 /Users/admin/bin/gam/oauth2service.json
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$ ls -l $OLDGAMPATH/*.json
-rw-r-----@ 1 admin staff 553 Feb 26 10:39 /Users/gamteam/bin/gam/client_secrets.json
-rw-r-----@ 1 admin staff 2377 Feb 26 10:39 /Users/gamteam/bin/gam/oauth2service.json
gamteam@server:/Users/gamteam$
```
### Initialize GAM7; this should be the first GAM7 command executed.
```
admin@server:/Users/admin$ gam config drive_dir /Users/admin/GAMWork verify
Created: /Users/admin/GAMConfig
Created: /Users/admin/GAMConfig/gamcache
Copied: /Users/admin/bin/gam/oauth2service.json, To: /Users/admin/GAMConfig/oauth2service.json
Copied: /Users/admin/bin/gam/oauth2.txt, To: /Users/admin/GAMConfig/oauth2.txt
Copied: /Users/admin/bin/gam/client_secrets.json, To: /Users/admin/GAMConfig/client_secrets.json
Config File: /Users/admin/GAMConfig/gam.cfg, Initialized
gamteam@server:/Users/gamteam$ gam config drive_dir /Users/gamteam/GAMWork verify
Created: /Users/gamteam/GAMConfig
Created: /Users/gamteam/GAMConfig/gamcache
Copied: /Users/gamteam/bin/gam/oauth2service.json, To: /Users/gamteam/GAMConfig/oauth2service.json
Copied: /Users/gamteam/bin/gam/oauth2.txt, To: /Users/gamteam/GAMConfig/oauth2.txt
Copied: /Users/gamteam/bin/gam/client_secrets.json, To: /Users/gamteam/GAMConfig/client_secrets.json
Config File: /Users/gamteam/GAMConfig/gam.cfg, Initialized
Section: DEFAULT
...
cache_dir = /Users/admin/GAMConfig/gamcache
cache_dir = /Users/gamteam/GAMConfig/gamcache
...
config_dir = /Users/admin/GAMConfig
config_dir = /Users/gamteam/GAMConfig
...
drive_dir = /Users/admin/GAMWork
drive_dir = /Users/gamteam/GAMWork
...
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Verify initialization, this was a successful installation.
```
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
total 48
-rw-r-----+ 1 admin staff 553 Mar 3 09:23 client_secrets.json
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
@@ -149,21 +149,21 @@ drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
-rw-r-----+ 1 admin staff 5104 Mar 3 09:23 oauth2.txt
-rw-rw-rw-+ 1 admin staff 0 Mar 3 09:23 oauth2.txt.lock
-rw-r-----+ 1 admin staff 2377 Mar 3 09:23 oauth2service.json
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
If the verification looks like this, then you'll have to copy client_secrets.json and oauth2service.json manually.
```
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
total 40
-rw-r-----+ 1 admin admin 1427 Nov 1 11:38 gam.cfg
drwxr-x---+ 16 admin admin 544 Nov 2 07:25 gamcache
-rw-r--r--+ 1 admin admin 10 Nov 2 15:31 lastupdatecheck.txt
-rw-rw-rw-+ 1 admin admin 0 Sep 19 17:28 oauth2.txt.lock
admin@server:/Users/admin$ cp -p $OLDGAMPATH/client_secrets.json $GAMCFGDIR/
admin@server:/Users/admin$ cp -p $OLDGAMPATH/oauth2service.json $GAMCFGDIR/
admin@server:/Users/admin$ cp -p $OLDGAMPATH/oauth2.txt $GAMCFGDIR/
admin@server:/Users/admin$ ls -l $GAMCFGDIR
gamteam@server:/Users/gamteam$ cp -p $OLDGAMPATH/client_secrets.json $GAMCFGDIR/
gamteam@server:/Users/gamteam$ cp -p $OLDGAMPATH/oauth2service.json $GAMCFGDIR/
gamteam@server:/Users/gamteam$ cp -p $OLDGAMPATH/oauth2.txt $GAMCFGDIR/
gamteam@server:/Users/gamteam$ ls -l $GAMCFGDIR
total 40
-rw-r-----+ 1 admin staff 553 Mar 3 09:23 client_secrets.json
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
@@ -175,9 +175,9 @@ drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
```
### Update your project with local browser to include the additional APIs that GAM7 uses.
```
admin@server:/Users/admin$ gam update project
gamteam@server:/Users/gamteam$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? gamteam@domain.com
Your browser has been opened to visit:
@@ -205,14 +205,14 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Update your project without local browser (Google Cloud Shell for instance) to include the additional APIs that GAM7 uses
```
admin@server:/Users/admin$ gam config no_browser true save
admin@server:/Users/admin$ gam update project
gamteam@server:/Users/gamteam$ gam config no_browser true save
gamteam@server:/Users/gamteam$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? gamteam@domain.com
Go to the following link in a browser on other computer:
@@ -239,7 +239,7 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Enable GAM7 client access
@@ -249,17 +249,17 @@ You select a list of scopes, GAM uses a browser to get final authorization from
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.32.05 - https://github.com/GAM-team/GAM - pyinstaller
gamteam@server:/Users/gamteam$ rm -f /Users/gamteam/GAMConfig/oauth2.txt
gamteam@server:/Users/gamteam$ gam version
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/gamteam/GAMConfig/oauth2.txt, Not Found
GAM 7.34.07 - 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
Path: /Users/admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64
Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
admin@server:/Users/admin$ gam oauth create
gamteam@server:/Users/gamteam$ gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -326,7 +326,7 @@ Continue to authorization by entering a 'c'
Please enter 0-50[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Enter your Google Workspace admin email address? gamteam@domain.com
Go to the following link in a browser on this computer or on another computer:
@@ -338,13 +338,13 @@ click the Allow button, paste "Unable to connect" URL from other computer (only
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
Client OAuth2 File: /Users/gamteam/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Enable GAM7 service account access.
```
admin@server:/Users/admin$ gam user admin@domain.com update serviceaccount
gamteam@server:/Users/gamteam$ gam user gamteam@domain.com update serviceaccount
[*] 0) AlertCenter API
[*] 1) Analytics API - read only
[*] 2) Analytics Admin API - read only
@@ -408,7 +408,7 @@ Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds FAIL (2/38)
https://www.googleapis.com/auth/analytics.readonly FAIL (3/38)
@@ -459,7 +459,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -469,7 +469,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
gamteam@server:/Users/gamteam$ gam user gamteam@domain.com check serviceaccount
System time status
Your system time differs from admin.googleapis.com by less than 1 second PASS
@@ -477,7 +477,7 @@ Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds PASS (2/38)
https://www.googleapis.com/auth/analytics.readonly PASS (3/38)
@@ -519,14 +519,14 @@ Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
admin@server:/Users/admin$ gam info domain
gamteam@server:/Users/gamteam$ gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -534,8 +534,8 @@ Primary Domain Verified: True
Default Language: en
...
admin@server:/Users/admin$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/admin/GAMConfig/gam.cfg, Saved
gamteam@server:/Users/gamteam$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/gamteam/GAMConfig/gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
admin_email = ''
@@ -546,19 +546,21 @@ Section: DEFAULT
bail_on_internal_error_tries = 2
batch_size = 50
cacerts_pem = ''
cache_dir = /Users/admin/GAMConfig/gamcache
cache_dir = /Users/gamteam/GAMConfig/gamcache
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
client_secrets_json = client_secrets.json ; /Users/gamteam/GAMConfig/client_secrets.json
clock_skew_in_seconds = 10
cmdlog = ''
cmdlog_max_backups = 5
cmdlog_max_kilo_bytes = 1000
config_dir = /Users/admin/GAMConfig
config_dir = /Users/gamteam/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_dir = /Users/gamteam/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
@@ -604,15 +622,17 @@ Section: DEFAULT
no_verify_ssl = false
num_tbatch_threads = 2
num_threads = 5
oauth2_txt = oauth2.txt ; /Users/admin/GAMConfig/oauth2.txt
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
oauth2_txt = oauth2.txt ; /Users/gamteam/GAMConfig/oauth2.txt
oauth2service_json = oauth2service.json ; /Users/gamteam/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,16 +668,18 @@ 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
admin@server:/Users/admin$
gamteam@server:/Users/gamteam$
```
## Windows
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
In these examples, your Google Super admin is shown as gamteam@domain.com; replace with the
actual email adddress.
This example assumes that GAM7 has been installed in C:\GAM7; if you've installed
@@ -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
@@ -919,7 +965,7 @@ C:\>dir %GAMCFGDIR%
```
C:\>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? gamteam@domain.com
Your browser has been opened to visit:
@@ -951,7 +997,7 @@ C:\>
C:\>gam config no_browser true save
C:\>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? gamteam@domain.com
Go to the following link in a browser on other computer:
@@ -990,9 +1036,9 @@ 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.32.05 - https://github.com/GAM-team/GAM - pythonsource
GAM 7.34.07 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.2 64-bit final
Python 3.14.3 64-bit final
Windows 11 10.0.26200 AMD64
Path: C:\GAM7
Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
@@ -1064,7 +1110,7 @@ Continue to authorization by entering a 'c'
Please enter 0-50[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Enter your Google Workspace admin email address? gamteam@domain.com
Go to the following link in a browser on this computer or on another computer:
@@ -1083,7 +1129,7 @@ C:\>
### Enable GAM7 service account access.
```
C:\>gam user admin@domain.com update serviceaccount
C:\>gam user gamteam@domain.com update serviceaccount
[*] 0) AlertCenter API
[*] 1) Analytics API - read only
[*] 2) Analytics Admin API - read only
@@ -1147,7 +1193,7 @@ Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds FAIL (2/38)
https://www.googleapis.com/auth/analytics.readonly FAIL (3/38)
@@ -1208,14 +1254,14 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\>gam user admin@domain.com check serviceaccount
C:\>gam user gamteam@domain.com check serviceaccount
System time status
Your system time differs from admin.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 1 day WARN
Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 38
Domain-wide Delegation authentication:, User: gamteam@domain.com, Scopes: 38
https://mail.google.com/ PASS (1/38)
https://sites.google.com/feeds PASS (2/38)
https://www.googleapis.com/auth/analytics.readonly PASS (3/38)
@@ -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

@@ -14,17 +14,17 @@
## API documentation
* [Activity Data Sources](https://support.google.com/a/answer/11482175)
Changes starting 2025-10-29.
* [Reports API - Admin log event changes](https://support.google.com/a/answer/16601511)
Changes starting 2025-12-20
* [Reports API - Admin log enhancements](https://workspaceupdates.googleblog.com/2025/12/google-workspace-audit-log-api.html)
These pages show event/parameter names; scroll down in the left column to: Reports.
Changes starting 2026-02-17.
* [Reports API - Admin log event changes](https://support.google.com/a/answer/16601511)
* [Reports API - Activities](https://developers.google.com/admin-sdk/reports/v1/reference/activities)
* [Reports API - Customer Usage](https://developers.google.com/admin-sdk/reports/v1/reference/customerUsageReports)
* [Reports API - User Usage](https://developers.google.com/admin-sdk/reports/v1/reference/userUsageReport)
These pages show event/parameter names:
* [Reports API - Admin Activities](https://developers.google.com/workspace/admin/reports/v1/appendix/activity/admin-event-names)
* [Reports API - Activities](https://developers.google.com/workspace/admin/reports/v1/appendix/activity/access-transparency)
* [Reports API - Customer Usage](https://developers.google.com/workspace/admin/reports/v1/appendix/usage/customer)
* [Reports API - User Usage](https://developers.google.com/workspace/admin/reports/v1/appendix/usage/user)
## Definitions
```
@@ -99,6 +99,7 @@ gam report <ActivityApplicationName> [todrive <ToDriveAttribute>*]
[event|events <EventNameList>] [ip <String>]
[gmaileventtypes <NumberRangeList>]
[groupidfilter <String>] [resourcedetailsfilter <String>]
[notimesort]
[maxactivities <Number>] [maxevents <Number>] [maxresults <Number>]
[countsonly [bydate|summary] [eventrowfilter]]
(addcsvdata <FieldName> <String>)* [shownoactivities]
@@ -176,6 +177,9 @@ show the most recent activity/event; this can be useful when reporting drive act
Add additional columns of data from the command line to the output.
* `addcsvdata <FieldName> <String>`
By default, a reverse chronological sort is performed on all rows across multiple users and/or event names;
this is consistent with the behavior in the Admin console. Use option `notimesort` to suppress this sort.
Display a row with a key value of `NoActivities` when there are no activities to report.
* `shownoactivities`

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

@@ -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; you must have a `developer_preview_api_key` in `gam.cfg` to use these commands.
`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`.
```

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

@@ -68,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)|
@@ -111,6 +111,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
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]
@@ -119,6 +120,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
[copyfilepermissions [<Boolean>]]
[copyfileinheritedpermissions [<Boolean>]
[copyfilenoninheritedpermissions [<Boolean>]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]]
@@ -182,16 +184,18 @@ 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.
* `filenamematchpattern <REMatchPattern>` - Only files whose name matches `<REMatchPattern>` are copied
@@ -207,6 +211,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>`
@@ -224,10 +232,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
@@ -287,6 +295,8 @@ When a folder is copied, its permissions are not copied; these options control c
of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
When copied, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions.
* `copyfolderpermissions false` - The permissions of the source folders are not copied to the target folder.
* `copyfolderpermissions true` - The permissions of the source folders are copied to the target folder based on the following options; this is the default action.
When `mergewithparent` is `true`:
* `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
@@ -407,15 +417,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
@@ -431,7 +441,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
@@ -451,7 +461,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
@@ -471,7 +481,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
@@ -481,31 +491,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
@@ -564,6 +574,7 @@ gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileNam
[createshortcutsfornonmovablefiles [<Boolean>]]
[duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
[duplicatefolders merge|duplicatename|uniquename|skip]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]]
@@ -607,10 +618,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
@@ -653,6 +664,8 @@ When a folder is moved by recreating it, its permissions are not copied by the D
For options of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
When recreated, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions;
* `copyfolderpermissions false` - The permissions of the source folders are not copied to the target folder.
* `copyfolderpermissions true` - The permissions of the source folders are copied to the target folder based on the following options; this is the default action.
When `mergewithparent` is `true`:
* `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
@@ -754,14 +767,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
@@ -771,7 +784,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"
@@ -787,13 +800,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]
@@ -617,8 +619,10 @@ This option is not available for `print|show filetree`.
```
((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*
```
GAM initializes the query to `'me' in owners`.
* `query "xxx"` - ` and xxx` is appended to the current query; you can repeat the query argument to build up a longer query.
* `fullquery "xxx"` - The query is set to `xxx` eliminating the initial `'me' in owners`.
* `fullquery "xxx"` - The query is set to `xxx` eliminating the initial `'me' in owners`. You must also use `showownedby any|others` as desired.
* `<DriveFileQueryShortcut>` - Predefined queries
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryDriveFile>` option.
@@ -1102,6 +1106,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

@@ -15,6 +15,7 @@
- [Remove domainCanFind-domainWithLink ACLs for internal domain](#remove-domaincanfind-domainwithlink-acls-for-internal-domain)
- [Remove My Drive ACLs for external domains](#remove-my-drive-acls-for-external-domains)
- [Remove anyoneCanFind-anyoneWithLink ACLs](#remove-anyonecanfind-anyonewithlink-acls)
- [Target Audiences](#target-audiences)
## API documentation
* [Drive API - Permissions](https://developers.google.com/drive/api/v3/reference/permissions)
@@ -143,6 +144,7 @@ specify `basicpermissions` and additional permission fields, e.g., `permissions.
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
```
## GUI API permission name mapping
| GUI setting | API setting |
@@ -357,8 +359,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
@@ -616,3 +618,51 @@ Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
## Target Audiences
* See: https://support.google.com/a/answer/9934697
You can manage target audiences in the admin console at Directory/Target audiences.
If you click on a target audience the URL will look like this: `https://admin.google.com/ac/targetaudiences/02xcytpi0xrdqxi`
You can add this target audience to a file with:
```
gam user user@domain.com create drivefileacl <DriveFileID> domain 02xcytpi0xrdqxi.audience.googledomains.com role reader
User: user@domain.com, Add 1 Drive File/Folder ACL
User: user@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: 02xcytpi0xrdqxi.audience.googledomains.com, Added
Test Audience
id: 02897912034288871303
type: domain
domain: 02xcytpi0xrdqxi.audience.googledomains.com
role: reader
permissionDetails:
role: reader
type: file
inherited: False
allowFileDiscovery: False
```
You can update the target audience role with:
```
gam user user@domain.com update drivefileacl <DriveFileID> id:02897912034288871303 role writer
User: user@domain.com, Update 1 Drive File/Folder ACL
User: user@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: 02897912034288871303, Updated
Test Audience
id: 02897912034288871303
type: domain
domain: 02xcytpi0xrdqxi.audience.googledomains.com
role: writer
permissionDetails:
role: writer
type: file
inherited: False
allowFileDiscovery: False
```
You can delete the target audience from a file with:
```
gam user user@domain.com delete drivefileacl <DriveFileID> id:02897912034288871303
User: user@domain.com, Delete 1 Drive File/Folder ACL
User: user@domain.com, Drive File/Folder ID: <DriveFileID>, Permission ID: 02897912034288871303, Deleted
```

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
@@ -430,8 +430,6 @@ user@domain.com,18e9fc6581b9acab,Archived,
user@domain.com,18e9fc58c5491f4c,Archived,
```
See below for message selection.
## Export messages/threads
Export messages in EML format.
```
@@ -447,6 +445,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.
@@ -461,7 +462,18 @@ By default, when exporting a message, an existing local file will not be overwri
* `overwrite true` - Overwite an existing file
* `overwrite false` - Do not overwite an existing file; add a numeric prefix and create a new file
See below for message selection.
### Export a specific set of messages
* `ids <MessageIDEntity>` - A list of message ids
### Export 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_export <Number>` - Limit the number of messages that will be exported; use a value of 0 for no limit
When `matchlabel <LabelName>` is specified, the following characters are replaced with a `-` in the generated query.
```
&()"|{}/
```
## Forward messages/threads
```
@@ -477,6 +489,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.
@@ -486,7 +501,19 @@ If `addorigfieldstosubject` is specified, GAM appends the original `from`, `to`
Fwd: Ross to TestUser (Original From: Ross Scroggs <ross.scroggs@gmail.com> To: testuser@domain.com Date: Thu, 23 Nov 2023 07:01:59 -0800)
```
See below for message selection.
### Forward a specific set of messages
* `ids <MessageIDEntity>` - A list of message ids
### Forward 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_forward <Number>` - Limit the number of messages that will be forwarded; 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.
```
&()"|{}/
```
## Manage messages/threads
```
@@ -538,7 +565,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 +573,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 +638,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 +654,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 +668,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

@@ -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

@@ -40,6 +40,7 @@
- [Print user list](#print-user-list)
- [Display user counts](#display-user-counts)
- [Verify domain membership](#verify-domain-membership)
- [Guest Users](#guest-users)
## API documentation
* [Directory API - Users](https://developers.google.com/admin-sdk/directory/reference/rest/v1/users)
@@ -169,6 +170,7 @@ queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Stude
fullname|
gender|
givenname|firstname|
guestaccountinfo|
id|
ims|im|
includeinglobaladdresslist|gal|
@@ -176,6 +178,7 @@ queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Stude
isdelegatedadmin|admin|isadmin|
isenforcedin2sv|is2svenforced|
isenrolledin2sv|is2svenrolled|
isguestuser|
ismailboxsetup|
keyword|keywords|
language|languages|
@@ -1384,3 +1387,9 @@ testuser1@domain.com,118080758787650801331,True,Test User 1
testuserxxx@domain.com,,False,Test User XXX
testuser2@domain.com,107344800159717682514,True,Test User 2
```
## Guest Users
* See: https://support.google.com/a/answer/16558545
```
gam create guestuser <EmailAddress>
```

View File

@@ -3,23 +3,23 @@
Print the current version of Gam with details
```
gam version
GAM 7.32.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.07 - 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
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
Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64
Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00
```
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.32.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.07 - 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
Path: /Users/Admin/bin/gam7
Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64
Path: /Users/gamteam/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Your system time differs from www.googleapis.com by less than 1 second
```
@@ -27,29 +27,29 @@ 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.32.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.34.07 - 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
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
Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64
Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00
Your system time differs from admin.googleapis.com by less than 1 second
OpenSSL 3.5.3 16 Sep 2025
arrow 1.3.0
OpenSSL 3.6.1 27 Jan 2026
arrow 1.4.0
chardet 5.2.0
cryptography 46.0.1
filelock 3.19.1
google-api-python-client 2.182.0
google-auth-httplib2 0.2.0
google-auth-oauthlib 1.2.2
google-auth 2.40.3
lxml 6.0.1
httplib2 0.31.0
cryptography 46.0.5
filelock 3.21.2
google-api-python-client 2.190.0
google-auth-httplib2 0.3.0
google-auth-oauthlib 1.2.4
google-auth 2.48.0
lxml 6.0.2
httplib2 0.31.2
passlib 1.7.4
pathvalidate 3.3.1
pyscard 2.3.0
yubikey-manager 5.8.0
pyscard 2.3.1
yubikey-manager 5.9.0
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
```
@@ -65,10 +65,10 @@ google-api-python-client 2.77.0
httplib2 0.16.0
oauth2client 4.1.3
MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7
Path: /Users/gamteam/bin/gam7
Version Check:
Current: 5.35.08
Latest: 7.32.05
Latest: 7.34.07
echo $?
1
```
@@ -76,7 +76,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.32.05
7.34.07
```
In Linux/MacOS you can do:
```
@@ -86,13 +86,13 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.32.05 - https://github.com/GAM-team/GAM
GAM 7.34.07 - 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
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
Help: Syntax in file /Users/Admin/bin/gam7/GamCommands.txt
Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64
Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00
Help: Syntax in file /Users/gamteam/bin/gam7/GamCommands.txt
Help: Documentation is at https://github.com/GAM-team/GAM/wiki
```

View File

@@ -74,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
@@ -577,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>
@@ -725,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 = '"'
@@ -937,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
@@ -947,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
@@ -1009,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
@@ -1026,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