Compare commits

...

2906 Commits

Author SHA1 Message Date
Ross Scroggs
367c23a13c Updated gam create project to retry the following unexpected error:
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
ERROR: 400 - invalidArgument - Service account gam-project-a1b2c@gam-project-a1b2c.iam.gserviceaccount.com does not exist.
2025-01-27 08:16:37 -08:00
Ross Scroggs
82e8977003 Updated gam create|use project to discontinue use of the Identity-Aware Proxy (IAP) OAuth Admin APIs
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-26 15:30:45 -08:00
Ross Scroggs
54eb666bc5 Merge branch 'main' of https://github.com/GAM-team/GAM
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-23 15:26:09 -08:00
Ross Scroggs
f6ea570888 Two updates
Updated `gam report <ActivityApplicationName>` to display `id:<actor.profileId>` in the `emailAddress` column
when `actor.email` is empty. This typically occurs when the actor is not in your workspace.

Updated `gam <UserTypeEntity> copy drivefile` to ignore ACLs referencing deleted user/groups.
2025-01-23 15:26:01 -08:00
Jay Lee
5d3fbed497 actions: scratch to test win signing 2025-01-23 11:19:10 -05:00
Ross Scroggs
e7b3b1453a Added option bydate to gam report <ActivityApplicationName> ... countsonly #1740
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-01-22 16:16:15 -08:00
Jay Lee
c31beeddfa actions: use ubuntu-24.04 instead of ubuntu-latest
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-20 17:01:45 -05:00
Ross Scroggs
bad376ea82 Add resource options to event commands
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-18 10:52:21 -08:00
Jay Lee
6af38e24af actions: disable python 3.9 testing
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
We currently only have 13 JID accounts available for testing but after Linux arm64 changes needed 14 runners.

I'm disabling Python 3.9 tests for now since it's the oldest and due for deprecation in October.

If there's any concerns we can re-enable and disable something else or else Jay can rebuild the auth files to add a 14th JID Google account and credentials (not hard but cumbersome and time consuming).
2025-01-16 14:35:46 -05:00
Jay Lee
a4eff89658 actions: install scons for staticx (needed for arm64) 2025-01-16 13:46:27 -05:00
Jay Lee
91db5e5c45 actions: apt install on GH hosted arm builds also 2025-01-16 12:27:28 -05:00
Jay Lee
67390a9863 actions: GH hosted arm runners, rebuild cache 2025-01-16 12:22:17 -05:00
Jay Lee
6c24636833 actions: scratch again 2025-01-16 09:47:26 -05:00
Jay Lee
776bc969de actions: scratch to kick off a build
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-14 16:45:32 -05:00
Ross Scroggs
7008d8c311 Fixed bug in gam print|show chromepolicies that caused a trap
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-01-13 11:54:17 -08:00
Ross Scroggs
a54870f91d Updated gam delete|update chromepolicy
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-06 16:45:00 -08:00
Ross Scroggs
782d57b02e Added option <JSONData> to gam <UserTypeEntity> create|update form
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-01-04 10:30:52 -08:00
Ross Scroggs
0c6825fa12 Updated gam [<UserTypeEntity>] show shareddriveacls ... formatjson
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-27 19:27:04 -08:00
Ross Scroggs
6a82343668 Update gam-install.sh
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-27 12:21:43 -08:00
Ross Scroggs
47ec93140e Updated code to eliminate trap caused by bug introduced in 7.02.00
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-26 08:36:25 -08:00
Ross Scroggs
d0d5ac74da Fix issue #1732
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-23 12:24:30 -08:00
Ross Scroggs
a9e28e966a Added option archive to gam <UserTypeEntity> update license <NewSKUID> from <OldSKUID>
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-18 08:24:15 -08:00
Ross Scroggs
89970bbf0d Updated gam <UserTypeEntity> archive messages <GroupItem>
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-17 09:04:59 -08:00
Ross Scroggs
0b16bded50 Add support for locking/unlocking cigroups #1728
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-13 19:48:39 -08:00
Jay Lee
2ea6f773cd catch non-success HTTP codes on GitHub URL retrieval
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-12 12:52:02 -08:00
Jay Lee
bb922dcff6 gam-install.sh full rollback
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-11 15:31:57 -08:00
Jay Lee
b38bf3e9bb undo shell install changes that MacOS doesn't like 2024-12-11 15:27:10 -08:00
Jay Lee
39e5a45d72 gam-install.sh: check curl response code 2024-12-11 15:23:25 -08:00
Ross Scroggs
d0b7ac80da Improved the error message displayed for user service account access commands
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
#1720, #1721, #1722
2024-12-06 15:03:28 -08:00
Jay Lee
320827b76e Update get-cacerts.yml
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-05 14:49:30 -05:00
Ross Scroggs
65c2a7f3b8 Fix error handling bug
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-04 12:23:33 -08:00
Ross Scroggs
74b18457d4 Expand the options for viewing group members
Update gamlib/files
2024-12-04 10:17:11 -08:00
Ross Scroggs
82ac454080 Expand the options for viewing group members 2024-12-04 10:09:23 -08:00
Jay Lee
111471a5ad update notes 2024-12-04 16:46:40 +00:00
Jay Lee
2bc1429ee2 revert to previous project length limits
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-12-04 13:07:35 +00:00
Ross Scroggs
25fdd76af0 Update projectId processing
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
With `PROJECTID_PATTERN = re.compile(r'^[a-z][a-z0-9-]{4,99}[a-z0-9]$')`, the max projectid length is 101

Delete debugging prints
2024-12-03 20:12:27 -08:00
Jay Lee
ff3f31cf9e GAM 7.01.04 2024-12-04 03:16:04 +00:00
Jay Lee
0b303ffc30 suppress warning on private key create. Fixes #1725 2024-12-04 03:00:09 +00:00
Jay Lee
4c78c5fe9f no warning on service account email lookup. Starts #1725 2024-12-04 02:32:25 +00:00
Jay Lee
17b97d2fb1 Remove redundant discovery JSON files. Continues #1724 2024-12-04 01:41:19 +00:00
Jay Lee
2193d34f76 remove local admin v1beta discovery. Starts #1724 2024-12-04 01:36:32 +00:00
Jay Lee
b1c212e9f6 actions: rebuild to get Python 3.13.1 2024-12-03 19:34:54 -05:00
Jay Lee
da58ae62a8 actions: increment scratch to rebuild Linux arm64
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-12-02 20:24:01 -05:00
Ross Scroggs
84d04141b3 Issue #1722
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-26 20:36:18 -08:00
Ross Scroggs
f29c697455 Updated code that uses the Domain Shared Contacts API with an HTTPS proxy to avoid a trap:
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-26 13:43:55 -08:00
Ross Scroggs
a1238c6397 Added option positivecountsonly to gam <UserTypeEntity> print|show filecomments 2024-11-26 13:09:44 -08:00
Ross Scroggs
4dfdc3a717 Fixes #1719
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-23 15:32:33 -08:00
Jay Lee
7e97f68013 fix version parsing for Windows
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-22 12:06:34 -05:00
Ross Scroggs
48ef2450fd Added support for managing/displaying Chrome profiles. 2024-11-22 08:32:11 -08:00
Jay Lee
ec769703d6 Fix scope defs for #1718
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-21 18:41:14 +00:00
Jay Lee
e2984ca10b basic print chromeprofiles output. #1718 2024-11-21 18:32:59 +00:00
Jay Lee
7400bfab70 Initial wiring for Chrome Profiles. Starts #1718
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-21 16:58:08 +00:00
Ross Scroggs
1870b25b0b Updated gam <UserTypeEntity> update serviceaccount
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
to properly set the readonly scope
for `[R] 35)  Meet API (supports readonly)` as it is a special case.
2024-11-20 14:10:41 -08:00
Jay Lee
8f7eeae4a7 fix re
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-18 15:40:14 -05:00
Jay Lee
f2e16c52cb pyinstaller: include version info 2024-11-18 15:36:35 -05:00
Jay Lee
759f0cfb69 Create version_info.txt.in 2024-11-18 15:28:17 -05:00
Jay Lee
e1941cb220 pyinstaller: use Windows manifest 2024-11-18 15:23:12 -05:00
Jay Lee
1af1f10974 Create gam.exe.manifest for PyInstaller 2024-11-18 15:15:48 -05:00
Jay Lee
0e3d82b718 Update gam-install.sh 2024-11-18 12:53:00 -05:00
Jay Lee
74417bbe24 Throw proper error if MacOS is outdated. 2024-11-18 12:51:41 -05:00
Jay Lee
3ed60c95c2 Fix code scanning alert no. 13: Default version of SSL/TLS may be insecure
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-11-18 12:00:13 -05:00
Jay Lee
f859d5eb26 remove extra debug line
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-18 07:36:42 -05:00
Jay Lee
f9848c78dc fix macos version extract 2024-11-18 07:34:49 -05:00
Ross Scroggs
60a4014d09 Docs moved to Wiki
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-16 10:37:56 -08:00
Ross Scroggs
2884904d19 Doc update, minor code updates
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-15 19:19:42 -08:00
Jay Lee
6fe196bd97 GAM 7.00.39
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-15 19:18:09 +00:00
Jay Lee
e2bbb95591 Install script handling of MacOS versions 2024-11-15 19:15:01 +00:00
Jay Lee
8568b24db2 restore overwritten install script upgrade
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-14 15:08:51 -05:00
Jay Lee
d8f10dc72a actions: include MacOS version in package file, rebuild for MacOS 15
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-11-14 08:04:30 -05:00
Ross Scroggs
98ef879a34 Fixed logic flaw in gam print|show policies where non-matching policies were displayed.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-10 18:57:22 -08:00
Ross Scroggs
95b3a97925 Added group/ou filtering to print|show policies
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
Updated `gam get|update|delete contactphotos` to use the People API
2024-11-10 08:18:43 -08:00
Ross Scroggs
f24629602c Updated gam print chromeapps to correct a trap caused by an API change.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-05 12:34:20 -08:00
Ross Scroggs
e5125b6853 Update Users-Classification-Labels.md
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-02 15:03:40 -07:00
Ross Scroggs
31e8ac11a2 Classification labels are now available for Gmail in addition to Drive. 2024-11-02 12:41:22 -07:00
Ross Scroggs
a9c4c006b2 Fixed bug introduced in 7.00.33 in gam print group-members that caused a trap.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-31 11:27:56 -07:00
Ross Scroggs
378c763aa3 Fixed bug in gam print group-members ... cachememberinfo that caused a trap.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-30 16:11:24 -07:00
Jay Lee
e46c837416 actions: not dasa
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-28 14:48:36 +00:00
Jay Lee
a478d45258 actions: call policies API 2024-10-28 14:40:42 +00:00
Jay Lee
5476c4d14f actions: remove extra matter delete 2024-10-28 10:19:38 -04:00
Jay Lee
2759d59cbf actions: vault matter close improvements 2024-10-28 10:14:43 -04:00
Jay Lee
d2213709f0 actions: no error on empty vault matter results
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-28 09:52:37 -04:00
Jay Lee
d2840b95d5 not gam 2024-10-28 09:42:28 -04:00
Jay Lee
49cdad014b close and delete matters 2024-10-28 09:35:18 -04:00
Jay Lee
532271130c actions: try refreshing creds again 2024-10-28 09:17:30 -04:00
Jay Lee
628ef4aeff actions: update creds 2024-10-28 08:59:58 -04:00
Ross Scroggs
34b344baf9 Update GamUpdates.md
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-27 19:07:27 -07:00
Jay Lee
b2daeffa36 actions: fi!
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-27 16:27:33 -04:00
Jay Lee
3440fa7415 actions: quotes 2024-10-27 16:23:08 -04:00
Jay Lee
77bf001195 actions: gtar on MacOS 2024-10-27 16:20:41 -04:00
Jay Lee
5d0003ce93 actions: try, try again. 2024-10-27 16:10:55 -04:00
Jay Lee
a0c4be1d5c actions: tell tar the file is a tar.xz 2024-10-27 15:56:21 -04:00
Jay Lee
95be4e2d53 actions: try to update creds again. ugh. 2024-10-27 15:52:11 -04:00
Jay Lee
5f8705fc09 actions: update creds to add policy scope 2024-10-27 15:44:06 -04:00
Jay Lee
975833bf87 actions: add policy scope for testing 2024-10-27 15:39:07 -04:00
Ross Scroggs
b4e3f25c1e Updated gam info policies to accept different policy specifications 2024-10-27 09:36:13 -07:00
Ross Scroggs
bb198c8c1a Updated gam info|print|show policies to make additional API calls for settings/workspace_marketplace.apps_allowlist
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-26 19:20:29 -07:00
Ross Scroggs
40899de989 Added command to display selected Cloud Identity policies.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-25 16:01:15 -07:00
Jay Lee
01a6781454 actions: wait longer for mailbox setup 2024-10-25 17:04:16 -04:00
Ross Scroggs
f448a75da4 Added option name <CIPolicyName> to gam print|show policies
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-24 14:52:20 -07:00
Jay Lee
8e5f5c9a6b siteverification off by default, roByDefault for policy 2024-10-24 16:21:30 -04:00
Ross Scroggs
04156061c4 Wiki updates
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-23 11:58:03 -07:00
Jay Lee
36f96f75c7 v7.00.28, policies group fix
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-23 10:23:42 +00:00
Ross Scroggs
197bcb3599 Added commands to display Cloud Identity policies. 2024-10-22 22:21:16 -07:00
Jay Lee
1474335a79 Merge branch 'main' of https://github.com/gam-team/gam
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-22 20:32:54 -04:00
Jay Lee
0f8c361dcd Initial support for Policy API 2024-10-22 20:32:12 -04:00
Ross Scroggs
beb75dbc20 Updated drive_dir in gam.cfg to allow the value . 2024-10-22 17:17:13 -07:00
Jay Lee
cbb95a47f8 actions: rebuild for OpenSSL 3.4.0
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-22 09:22:56 -04:00
Ross Scroggs
d7e36bc5eb Updated authentication process for gam print|show projects.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-21 10:17:34 -07:00
Ross Scroggs
ef14359d9b Updated gam print|show projects ... showiampolicies 0|1|3 to use non-service account authentication.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-20 11:14:50 -07:00
Ross Scroggs
b1444d7c04 Updated gam <UserTypeEntity> create|delete chatmember to accept external (non-domain) email addresses.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-18 20:09:58 -07:00
Ross Scroggs
c3c7d629f7 Fixed bug in gam create vaultmatter ... showdetails that caused a trap.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-18 14:35:56 -07:00
Ross Scroggs
eb33b6521b Added csv_output_header_order variable to gam.cfg
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-18 09:51:57 -07:00
Jay Lee
932fe5db02 v7.00.21
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-16 15:55:43 -07:00
Jay Lee
6885bcae92 Enable new gam-install.sh with glibc version autodetect 2024-10-16 15:54:13 -07:00
Jay Lee
d35e9fcae4 uprev version to start confirming MSI fix works. Related to #1714 2024-10-16 14:45:44 -07:00
Jay Lee
861279e614 actions: revert filename generated by heat.exe (MSI) 2024-10-16 16:30:36 -04:00
Jay Lee
b80dd15f4b actions: $PYTHON not $python 2024-10-16 15:51:17 -04:00
Jay Lee
ae95c8fdea generate stable Guids for files in lib.wxs to fix MSI issues 2024-10-16 12:44:51 -07:00
Jay Lee
090b5937ab actions: set Wix GUID to * so Wix (hopefully) uses it's own stable Guid. 2024-10-16 11:33:54 -07:00
Ross Scroggs
2323e130b1 Two minor fixes
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-14 14:46:29 -07:00
Jay Lee
6ef127f283 actions: re-order
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-14 10:22:17 -04:00
Jay Lee
266f00d3a8 actions: rebuild with sqlite3 libraries 2024-10-14 10:17:23 -04:00
Jay Lee
5c61867e1f actions: add 24.04 Ubuntu build. Fixes #1712
thanks to Ross for suggesting.
2024-10-14 09:03:52 -04:00
Jay Lee
0bbe1cc958 actions: scratch build to see if Windows signing still works
Some checks failed
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-12 10:02:08 -04:00
Ross Scroggs
d1e02e4695 Updated gam create project to use a default project name of gam-project-a1b2c
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-11 12:04:35 -07:00
Ross Scroggs
f707c83e1a Update all user calendar commands to disable falling back to client access if service account authorization has never been performed.
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-10 20:21:28 -07:00
Ross Scroggs
ae67319975 Two updates
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
Updated `gam <UserTypeEntity> claim|transfer ownership` to show `Got N Drive Files/Folders that matched query` messages
as files/folders are being identified for processing.

Added option `<JSONData>` to `gam create|update caalevel`.
2024-10-09 20:34:51 -07:00
Ross Scroggs
dffdd2e190 Added options timestamp [<Boolean>] and timeformat <String> to gam <UserTypeEntity> create|update drivefile
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-08 20:13:51 -07:00
Jay Lee
e3ba323764 Fix issues with PyInstaller 6.10+
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-08 09:16:33 -04:00
Jay Lee
2d7153e151 [no ci] actions: re-order test jobs, test on 3.12 2024-10-08 07:13:08 -04:00
Jay Lee
333ad533c1 actions: Py3.13 requires PyInstaller 6.10+, see if we can get it working
we may need to revert to 3.12 / 6.9 if this proves problematic
2024-10-08 07:07:21 -04:00
Jay Lee
f91ebfabcb actions: rebuild to pickup Python 3.13.0 2024-10-08 06:48:51 -04:00
Ross Scroggs
cae58ffb96 Retry the following unexpected errors in gam print users.
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
ERROR: 400: failedPrecondition - Precondition check failed.
ERROR: 500: unknownError - Unknown Error.
2024-10-07 19:54:34 -07:00
Ross Scroggs
caddda2b1c Integrate Wikis - Step 1
Some checks failed
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-06 09:02:31 -07:00
Jay Lee
f63a04a123 actions: scratch an itch and do a build.
Some checks failed
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-10-05 09:55:01 -04:00
Ross Scroggs
fe13508f95 Revert := ro :-
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-04 15:11:50 -07:00
Ross Scroggs
53e2b5b563 Fix new install scriot, update Wiki
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-04 09:10:57 -07:00
Jay Lee
af42342e08 install script, both linux archs are on 2.35 now 2024-10-04 11:11:52 -04:00
Jay Lee
1da63a6be0 Start testing a new GAM install script
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-03 16:56:47 +00:00
Jay Lee
0448bfef28 7.00.13
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-03 09:29:35 +00:00
Ross Scroggs
6fc4726e34 Update gam-install.sh
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-02 18:16:24 -07:00
Ross Scroggs
a0363357ef Update gam-install.sh 2024-10-02 18:09:19 -07:00
Ross Scroggs
134a7d3d83 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-10-02 15:37:18 -07:00
Jay Lee
79f83f34fd actions: disable create contact command that may be actual issue 2024-10-02 17:02:49 -04:00
Jay Lee
a34b6610d2 actions: just send email to someone else (grr) 2024-10-02 16:50:04 -04:00
Jay Lee
24f2efb833 actions: assign new user license sooner to avoid Gmail send error 2024-10-02 16:36:32 -04:00
Jay Lee
d77d873a42 actions: remove duplicate sendemail command that was throwing errors 2024-10-02 16:14:12 -04:00
Ross Scroggs
707d938656 Updated option showlastmodification to gam <UserTypeEntity> print|show filecounts 2024-10-02 12:17:32 -07:00
Jay Lee
ccaa76026c actions: fix MSI location, remove dupe upload for signing
Some checks are pending
Build and test GAM / build (Win64, build, 7, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-24.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-02 11:33:50 -04:00
Jay Lee
ac540b75a7 actions: upgrade test runners to 24.04, fix signed MSI download 2024-10-02 09:31:06 -04:00
Jay Lee
be573c8ae4 actions: No more Ubuntu 20.04, recount jobs, rebuild to align cache 2024-10-02 07:56:47 -04:00
Ross Scroggs
6076111d83 Bump version, new Python
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-10-01 17:31:38 -07:00
Jay Lee
7c1ee239c7 actions: rebuild to get Python 3.12.7 2024-10-01 17:24:50 -04:00
Jay Lee
d3a02f9d25 actions: fix missing include -b for light.exe 2024-10-01 17:10:38 -04:00
Jay Lee
b8501195ad show lib.wxs output 2024-10-01 19:53:38 +00:00
Jay Lee
49192cb604 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-10-01 19:34:40 +00:00
Jay Lee
5e8bbd4ce4 actions: fix wix source dir 2024-10-01 19:34:33 +00:00
Jay Lee
5a85572a9c actions: print some dirs 2024-10-01 14:35:03 -04:00
Jay Lee
d2d48f772b actions: try windows path fix again 2024-10-01 14:20:09 -04:00
Jay Lee
25e7196a37 actions: more cd changes on win 2024-10-01 14:07:40 -04:00
Jay Lee
8a4fabb4c9 actions: move up one more directory for Wix 2024-10-01 13:56:29 -04:00
Jay Lee
7825a66768 Windows onedir in 3...2...1...<crash> 2024-10-01 17:39:23 +00:00
Ross Scroggs
2b6891c12d Handle ERROR: 412: conditionNotMet - User creation is not complete.
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-30 19:44:10 -07:00
Ross Scroggs
70fb68d81b Handle ERROR: 412: conditionNotMet - User creation is not complete.
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-30 16:28:56 -07:00
Ross Scroggs
6b15628d81 Handle ERROR: 412: conditionNotMet - User creation is not complete. 2024-09-30 16:00:15 -07:00
Ross Scroggs
7c88793e8f Handle ERROR: 412: conditionNotMet - User creation is not complete. 2024-09-30 15:54:36 -07:00
Ross Scroggs
896f7f5d37 Initial limited access, api_call_tries_limit new max
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-29 21:05:40 -07:00
Ross Scroggs
46d05e37d0 Fix bugs with groups and DASA
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-09-26 20:16:33 -07:00
Ross Scroggs
9dc87a060d Fixed bug in gam <UserTypeEntity> delete groups 2024-09-26 20:04:06 -07:00
Ross Scroggs
3e638dd35e Updated <PeopleContactAttribute> fields address,email,phone,url to allow an empty type field.
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-26 11:17:23 -07:00
Jay Lee
e4ad4fb26c actions: also cleanup signed MSI drive folder
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-09-24 21:19:30 -04:00
Jay Lee
cc63aee62c actions: cleanup Windows sign folders 2024-09-24 20:40:27 -04:00
Jay Lee
31806438a9 GAM 7.00.06
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-24 20:23:59 +00:00
Jay Lee
74ac351aa4 actions: don't exclude json files from our package archives 2024-09-24 16:01:05 -04:00
Jay Lee
7e157dab42 actions: enable logging to see why json files are excluded on onedir 2024-09-24 15:43:55 -04:00
Jay Lee
8b2586ead2 actions: save signed MSI to workspace 2024-09-24 14:54:07 -04:00
Jay Lee
ebcfd18457 actions: tell gam to save signed MSI to . 2024-09-24 14:29:32 -04:00
Jay Lee
cbb496e491 actions: don't save signed MSI to gampath 2024-09-24 14:10:38 -04:00
Jay Lee
1ff93b1051 actions: also sign MSI 2024-09-24 13:34:22 -04:00
Jay Lee
2fdb6156e7 actions: disable signtool verify for now 2024-09-24 12:42:19 -04:00
Jay Lee
f7c13a3063 actions: signtool /pa to trust broader set of CAs 2024-09-24 11:29:48 -04:00
Jay Lee
c0470c35a9 actions: finally found signtool.exe (thanks for nothing MS) 2024-09-24 11:11:50 -04:00
Jay Lee
304a897290 actions: shuffle gam.exe after we download signed. 2024-09-24 10:44:23 -04:00
Jay Lee
af2499a0ea actions: rm needs unix style path 2024-09-24 10:32:38 -04:00
Jay Lee
52ccd735ca actions: search for right path to signtool.exe to verify signed gam.exe 2024-09-24 10:22:51 -04:00
Jay Lee
ffcb1c4ddf actions: targetname not targetfile 2024-09-24 09:48:20 -04:00
Jay Lee
0dd74e226c actions: fix wait for signed gam.exe 2024-09-24 09:40:47 -04:00
Jay Lee
bd5149d3f8 actions: id doesn't belong in query
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-24 09:00:17 -04:00
Jay Lee
7c6649b24f [no ci] actions: attest after signing 2024-09-24 08:58:26 -04:00
Jay Lee
cfd9447f39 actions: actually download signed gam.exe 2024-09-24 08:52:42 -04:00
Jay Lee
820698d9d4 actions: missing }
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-23 21:15:35 -04:00
Jay Lee
7645edee6b actions: Windows back to onefile 2024-09-23 21:08:09 -04:00
Jay Lee
7e6f7b8bab actions: fix path 2024-09-23 20:55:53 -04:00
Jay Lee
ee77ae8319 actions: missing } 2024-09-23 20:46:16 -04:00
Jay Lee
0f2eba580d actions: move oauth2.txt setup sooner 2024-09-23 20:40:38 -04:00
Jay Lee
1cdf160b35 actions: submit gam.exe and MSI for signing 2024-09-23 20:33:59 -04:00
Ross Scroggs
7e68c108c1 Updated gam <UserTypeEntity> create|update chatspace to support the new permissions settings 2024-09-23 17:18:17 -07:00
Ross Scroggs
8ecbe67054 Updated gam <UserTypeEntity> create|update chatspace to support the new permissions settings 2024-09-23 17:11:48 -07:00
Jay Lee
a6016825ff actions: re-enable old MSI builds for now
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-23 10:55:44 -04:00
Jay Lee
15221a1a20 actions: restore wxs to previous values 2024-09-23 10:54:08 -04:00
Ross Scroggs
6718938c1a Fixed bug that caused an error when creating a calendar birthday event.
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-09-20 07:38:44 -07:00
Jay Lee
acd1a9ad91 actions: restore accidentally deleted MacOS package name 2024-09-20 07:40:45 -04:00
Jay Lee
cce2894dac actions: store packages in working directory
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-20 07:12:16 -04:00
Jay Lee
877ea0cc19 actions: archive and attest package files sooner so they're available for debugging 2024-09-20 06:44:09 -04:00
Jay Lee
cd4c1fc7ac actions: disable MSI generation while we re-evaluate options... 2024-09-20 06:15:19 -04:00
Jay Lee
09292fd28b actions: need to move up one more folder for ONEDIR
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-20 01:27:22 +00:00
Jay Lee
ccef86d2a0 actions: fix tool path 2024-09-20 01:20:15 +00:00
Jay Lee
ba34ef4494 actions: fee FI foo fum 2024-09-20 01:13:53 +00:00
Jay Lee
26eca09bb9 ONEDIR for Windows and anything that's not StaticX 2024-09-20 01:11:21 +00:00
Jay Lee
64d4cc00e4 fix call 2024-09-20 01:01:20 +00:00
Jay Lee
33b4de86a9 dynamic gam.wx2 generation based on compiled files in dist/gam 2024-09-20 00:56:15 +00:00
Ross Scroggs
f33da85518 Improve gat report users, add birthday events 2024-09-19 16:44:08 -07:00
Jay Lee
93ecbf479e [no ci] update maintainer names (yes, it's James for legal purposes, sigh) 2024-09-19 08:35:49 -04:00
Jay Lee
ca2d6541ce [no ci] Only enforce min version of MacOS and allow diff values for each arch. 2024-09-18 21:59:37 -04:00
Ross Scroggs
db7154dca9 Fix old guy typo 2024-09-18 14:55:54 -07:00
Ross Scroggs
72bba3d948 MacOS 15 - Sequoia out today 2024-09-18 14:49:26 -07:00
Jay Lee
07bbf4d4ea tell MSI build where to find gam7 2024-09-18 16:10:56 -04:00
Jay Lee
7aafbbe58e Merge branch 'main' of https://github.com/gam-team/gam 2024-09-18 16:04:32 -04:00
Jay Lee
c2058211fe [no ci] bump checkconn timeout to 30s to attempt fix for annoying Github Actions failures 2024-09-18 16:04:25 -04:00
Jay Lee
08a6cbb270 actions: try fixing windows package 2024-09-18 15:56:49 -04:00
Jay Lee
c5da8963d4 actions: fix packaging legacy staticx build 2024-09-18 15:53:57 -04:00
Jay Lee
89b854ea57 actions: try to simplify gam/gampath logic 2024-09-18 15:47:31 -04:00
Jay Lee
42fd8cd1e8 actions: fix $gam value on non-onedir 2024-09-18 15:37:09 -04:00
Jay Lee
0e0f49c540 actions: more attempts to fix staticx 2024-09-18 15:22:46 -04:00
Jay Lee
f0b1b62e79 [no ci] comment out pyinstaller spec debug output for now 2024-09-18 15:22:15 -04:00
Jay Lee
7606a40a58 actions: reduce debug on PyInstaller, fix $gam 2024-09-18 15:11:52 -04:00
Jay Lee
ac5098522b actions: keep one file for staticx builds 2024-09-18 15:04:37 -04:00
Jay Lee
d84ff8d392 actions: fix mac/linux packaging. 2024-09-18 14:59:08 -04:00
Jay Lee
4a0687cfe9 actions: actually enable one dir on Linux 2024-09-18 14:55:40 -04:00
Jay Lee
19e386ed21 actions: fix non-onedir distpath 2024-09-18 14:43:32 -04:00
Jay Lee
8165c72606 actions: gam7 in packages. 2024-09-18 14:39:45 -04:00
Ross Scroggs
5267992e31 Revert "Revert setting target_gam"
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
This reverts commit 38375b1710.
2024-09-18 11:35:38 -07:00
Ross Scroggs
1949b3346c Merge branch 'main' of https://github.com/GAM-team/GAM 2024-09-18 11:28:13 -07:00
Ross Scroggs
38375b1710 Revert setting target_gam 2024-09-18 11:28:11 -07:00
Jay Lee
281e790260 actions: fix gam/gam7 path 2024-09-18 13:04:45 -04:00
Jay Lee
2b8b2521d1 actions: hack to make gam7 the folder for mac/linux packages 2024-09-18 12:57:42 -04:00
Jay Lee
52601edb35 [no ci] remove 3.8 testing. Fixes #1702 2024-09-18 11:46:43 -04:00
Ross Scroggs
5475f281eb Merge branch 'main' of https://github.com/GAM-team/GAM 2024-09-18 08:42:45 -07:00
Ross Scroggs
b1f8893783 Use gam7 target directory on Linux/MacOS 2024-09-18 08:42:41 -07:00
Jay Lee
640cb322d7 [no ci] remove 3.8 from setup.cfg 2024-09-18 11:41:36 -04:00
Jay Lee
c4f15cbf3a actions: give up on PyInstaller 6.10 again. Urgh. 2024-09-18 11:24:00 -04:00
Ross Scroggs
bef392cf7a Merge branch 'main' of https://github.com/GAM-team/GAM 2024-09-18 07:15:07 -07:00
Ross Scroggs
abb49ed336 Updated gam delete ou and gam print admins to handle the following error:
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2024-09-18 07:14:53 -07:00
Jay Lee
fe5bc5569d actions: kill cache for a rebuild on MacOS 13, also see if PyInstaller 6.10 will work now. 2024-09-18 10:12:03 -04:00
Jay Lee
18615f246d actions: MacOS 12 is deprecated, move to 13 for x86_64 2024-09-18 10:05:23 -04:00
Jay Lee
7958632046 Merge branch 'main' of https://github.com/gam-team/gam 2024-09-18 09:32:50 -04:00
Jay Lee
3e8bff23c4 GAM 7.00.03 pre-release 2024-09-18 09:31:30 -04:00
Jay Lee
0221781a05 [no ci] remove add_lib.py hack file 2024-09-18 08:19:08 -04:00
Jay Lee
e6ced7fff6 actions: remove add_lib hack and use contents_directory PyInstaller feature instead 2024-09-18 08:18:27 -04:00
Jay Lee
484238ece2 try to cleanup and correct some logic. Might have made things worse... 2024-09-18 08:01:46 -04:00
Jay Lee
ee32bb87f0 actions: one directory for MacOS 2024-09-18 07:43:06 -04:00
Jay Lee
73803acb89 actions: zip whole gam path, cleanup the .zip 2024-09-18 07:15:12 -04:00
Jay Lee
a40df40f9b [no ci] comment on what add_lib.py does 2024-09-17 22:01:36 -04:00
Jay Lee
a33b89788c actually set our codesign ID 2024-09-17 21:50:04 -04:00
Jay Lee
54f815e503 only use add_lib.py on onedir 2024-09-17 21:45:10 -04:00
Jay Lee
e54d3d274a Have PyInstaller sign MacOS binaries 2024-09-17 21:35:47 -04:00
Jay Lee
b7a20ceb4f actions: fix typo in create printer 2024-09-17 19:15:08 -04:00
Jay Lee
bbc965d38f [no ci] fix build status badge 2024-09-17 19:11:50 -04:00
Jay Lee
8935cf7041 actions: give zip file for notarization a name we can track
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-17 13:05:44 -04:00
Jay Lee
4583f6d996 actions: need team-id to notarize 2024-09-17 12:36:23 -04:00
Jay Lee
92282fb493 actions: use newer tool for notarization 2024-09-17 12:30:39 -04:00
Jay Lee
65ea328f2a actions: attempt to notarize macos binaries 2024-09-17 12:15:13 -04:00
Jay Lee
2da4833a0d actions: file is a .plist, not .xml 2024-09-17 11:55:22 -04:00
Jay Lee
631ce68126 actions: actually try to sign gam binary for MacOS 2024-09-17 11:52:34 -04:00
Jay Lee
480aca680d actions: create entitlements.plist file for MacOS signing 2024-09-17 11:45:45 -04:00
Jay Lee
6e3ab6700d actions: actually comment out create admin line 2024-09-17 11:41:26 -04:00
Jay Lee
61319fa08e actions: just create at root and don't make delegated admin 2024-09-17 11:36:39 -04:00
Jay Lee
673e9f88ad actions: sleep 5 min each 2024-09-17 11:18:45 -04:00
Jay Lee
f2b8200a3b actions: sleep 3m (bleh) 2024-09-17 11:11:21 -04:00
Jay Lee
0383624c72 actions: sleep before and after user creation (create admin was also failing) 2024-09-17 11:01:50 -04:00
Jay Lee
cb03b8d9d4 [no ci] actions: print that we're intentionally sleeping 2024-09-17 10:56:46 -04:00
Jay Lee
e7e821ca3d actions: sleep 5 min to wait for OU creation to work for user creation (yuck) 2024-09-17 10:47:36 -04:00
Jay Lee
6b21fdbcc6 actions: early work to add MacOS code signing 2024-09-17 07:47:28 -04:00
Ross Scroggs
ee326c6fe3 Updated print filecounts and update filerevisions
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-16 15:20:04 -07:00
Ross Scroggs
8945fd163c Updated print filecounts and update filerevisions 2024-09-16 14:12:43 -07:00
Jay Lee
4dab0bd4bb actions: re-arrange job order
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-16 12:07:08 -04:00
Jay Lee
49ec0c6df4 actions: rebuild to get Python 3.12.6
Some checks failed
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-16 03:29:37 -04:00
Ross Scroggs
f3d29c47e2 Added option shownames to gam <UserTypeEntity> print|show sheet
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
Added build for ubuntu-22.04, it is my most common Linux download
2024-09-14 20:01:04 -07:00
Jay Lee
41b4577665 actions: disable busted universal2 build
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-14 16:51:42 -04:00
Ross Scroggs
2ca813f209 Update Mac OS install
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-13 13:47:47 -07:00
Ross Scroggs
66734f07fa Updated gam update group postmaster@domain.com to handle the error that is generated. 2024-09-13 11:11:33 -07:00
Ross Scroggs
90844effa7 Update Shared-Drives.md 2024-09-13 09:25:22 -07:00
Ross Scroggs
4765c6e186 Fixed bug in gam <UserTypeEntity> create meetspace
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-13 07:11:20 -07:00
Ross Scroggs
d2f52fd7bf Update Chrome-Policies.md
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-12 17:53:18 -07:00
Ross Scroggs
85c55c5aa8 Chrome policies/Meet/Courses
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-12 13:57:09 -07:00
Ross Scroggs
6043411825 Updated gam <UserTypeEntity> archive messages to handle the followong error:
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
googleapiclient.errors.MediaUploadSizeError: Media larger than: 26214400
2024-09-09 08:38:04 -07:00
Ross Scroggs
72ca010a5f Updated gam report usage user and gam report users to handle the followong error:
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2024-09-08 20:54:49 -07:00
Ross Scroggs
e34f7164d8 investigate create inboundssoprofile
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-09-06 07:02:14 -07:00
Ross Scroggs
ef975437a6 Update build.yml
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-05 19:59:52 -07:00
Ross Scroggs
68863cd44b Updated gam create inboundssoprofile ... returnnameonly to return inProgress if the API does not return a complete result.
Some checks are pending
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-05 19:19:45 -07:00
Ross Scroggs
737deb8e39 Fixed bug in gam create inboundssoprofile that caused a trap. 2024-09-05 16:57:09 -07:00
Jay Lee
67048fce86 Update build.yml
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-09-03 16:54:57 -04:00
Jay Lee
97adde0f5e Update build.yml 2024-09-03 16:49:21 -04:00
Jay Lee
998bdfd40d more logging to figure out why we're picking up old OpenSSL 2024-09-03 15:36:52 -04:00
Jay Lee
05a04a0d23 log more info on collected files for PyInstaller 2024-09-03 15:09:38 -04:00
Jay Lee
6651ad20ef [no ci] remove redundant OpenSSL 2024-09-03 14:25:03 -04:00
Jay Lee
75cd22d645 [no ci] show all OpenSSL version info 2024-09-03 14:13:59 -04:00
Jay Lee
00d0708d2d show OpenSSL version Python picked up 2024-09-03 14:04:18 -04:00
Jay Lee
2d5550e09e rebuild to catch OpenSSL 3.3.2
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-03 10:46:26 -04:00
Ross Scroggs
11969364d3 Updated gam print|show admins
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-29 13:53:45 -07:00
Ross Scroggs
b7c0a86b1f Back to PyInstaller 6.9.0 2024-08-29 12:31:47 -07:00
Ross Scroggs
1eb1942085 Update build.yml 2024-08-29 11:45:47 -07:00
Ross Scroggs
7073d8b6b4 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-08-29 11:30:23 -07:00
Ross Scroggs
0e90d10f17 Python/PyInstaller build cleanup 2024-08-29 11:30:13 -07:00
Jay Lee
e989167267 Not sure we even need LDFLAGS on Windows and it's breaking PyInstaller atm 2024-08-29 14:26:17 -04:00
Ross Scroggs
49128d5559 Reset cache, check Windows pyinstaller install
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-28 19:18:20 -07:00
Ross Scroggs
d3c7af784f Updated gam <UserTypeEntity> modify messages to improve error handling. 2024-08-28 17:53:51 -07:00
Ross Scroggs
41dd34ec9e Fixed bug in gam print vaultcounts that caused a trap.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-27 07:02:45 -07:00
Ross Scroggs
c565f9aa0f Fixed bug in gam <UserTypeEntity> print filelist ... countsrowfilter
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-26 18:36:50 -07:00
Ross Scroggs
f40f631810 Updated gam <UserTypeEntity> print messages|threads
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-25 08:01:48 -07:00
Ross Scroggs
130ee7b371 Added my_publishable_items to <DriveFileQueryShortcut>
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-24 09:44:40 -07:00
Ross Scroggs
4bbb97b749 Updated gam print vaultcounts to correctly display accounts with errors.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-23 12:32:39 -07:00
Ross Scroggs
3fb96aaab6 Updated gam <UserTypeEntity> delete|purge|trash|untrash <DriveFileEntity> shortcutandtarget
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-20 09:04:15 -07:00
Ross Scroggs
7d64ca2057 Added shortcut target processing
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-19 21:14:53 -07:00
Ross Scroggs
37f6a9694a Added options allschemas|(schemas|custom|customschemas <SchemaNameList>) to gam print group-members
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-19 14:12:46 -07:00
Ross Scroggs
77df7c5fea Updated gam print|show oushareddrives
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-18 15:41:17 -07:00
Ross Scroggs
4fc08c78d3 Merge branch 'main' of https://github.com/GAM-team/GAM
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-15 18:37:28 -07:00
Ross Scroggs
c31461b9e7 Updated dateheaderformat iso in gam <UserTypeEntity> info|print|show messages 2024-08-15 18:37:16 -07:00
Jay Lee
1875eadbfe fix "print chromehistory releases"
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-15 18:43:56 +00:00
Ross Scroggs
50ac49c713 Fix f-string typo 2024-08-15 10:36:47 -07:00
Ross Scroggs
def079d944 Added option tdreturnidonly [<Boolean>] to <ToDriveAttribute> 2024-08-15 09:49:09 -07:00
Ross Scroggs
bc5c468581 Improved individual student options gam create|update course ... copyfrom
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-14 21:58:47 -07:00
Ross Scroggs
020ddee777 Fix typo 2024-08-14 17:35:04 -07:00
Ross Scroggs
3e7124946e Cleaned up progress messages in gam create|update course ... copyfrom. 2024-08-14 17:04:49 -07:00
Ross Scroggs
395916bc86 Added option stripcrsfromname to gam <UserTypeEntity> print driveactivity
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-14 10:36:19 -07:00
Ross Scroggs
e80ed0e700 print filecounts addcsvdata; course copyfrom updates
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-13 19:54:49 -07:00
Ross Scroggs
8db7e32bd2 Course-work and vacation updates
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-12 20:32:47 -07:00
Ross Scroggs
d263327997 Upgraded to Python 3.12.5 where possible.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
Check for Google Root CA Updates / check-apis (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-11 20:49:52 -07:00
Ross Scroggs
93a6e4d835 Fixed bug in gam <UserTypeEntity> print users ... license ... formatjson that caused a trap. 2024-08-11 20:19:59 -07:00
Ross Scroggs
9dab94bd7b Fixed bug in gam user admin@domain.com print chatspaces asadmin
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-09 08:17:08 -07:00
Ross Scroggs
d3a108ae9c Fixed bug in gam <UserItem> print|show chatmembers where the filter <String> was not applied.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-08 08:19:19 -07:00
Ross Scroggs
3b39f90a0e Updated commands to handle a trap that occurs when oauth2service.json specifies a YubiKey but the YubiKey is not insertd.
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-07 13:27:44 -07:00
Jay Lee
e994c769a6 Allow drive.file clientaccess scope
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
todrive actions for reports often only need to create drive files, not read
other files. drive.file scope limits GAM to being able to create files and
read just those files.
2024-08-07 15:10:59 +00:00
Ross Scroggs
bbc974fb69 Added option addcsvdata <FieldName> <String> to gam <UserTypeEntity> print teamdriveacls
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-08-06 17:46:00 -07:00
Ross Scroggs
71bf658e17 Clarified action to perform messages when creating/deleting/updating licenses.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-08-05 10:14:29 -07:00
Ross Scroggs
8211d5df8c Updated gam <UserTypeEntity> print|show groups` to show totals
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-07-31 16:37:28 -07:00
Ross Scroggs
10e54e49a5 Fixed bug in gam calendars <CalendarEntity> update event ... removeattendee <EmailAddress>
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-07-30 11:51:12 -07:00
Ross Scroggs
6b9ac2700e Updated gam <UserTypeEntity> empty drivetrash <SharedDriveEntity>
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (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-apis (push) Has been cancelled
2024-07-26 17:09:27 -07:00
Ross Scroggs
012616a285 Fix bug in check ou 2024-07-25 19:16:01 -07:00
Ross Scroggs
2669b1bff6 Added options filename <FileName> and movetoou <OrgUnitItem> to gam check ou <OrgUnitItem> 2024-07-25 18:28:28 -07:00
Ross Scroggs
2aeebd17a4 Added column|field assignedToUnknown to gam print|show admins 2024-07-24 08:49:09 -07:00
Ross Scroggs
e43802e197 Updated gam print admins to handle the following error
ERROR: 404: notFound - Requested entity was not found.
2024-07-23 16:00:36 -07:00
Ross Scroggs
16b3d2b006 Allow <RoleItem> in any case 2024-07-22 20:47:05 -07:00
Ross Scroggs
f777ec177c Updated code to work around a Cryptography library change 2024-07-22 08:37:33 -07:00
Ross Scroggs
19304f95e8 Added command to check if an OU contains items 2024-07-21 13:14:15 -07:00
Ross Scroggs
5b49b8c957 Added option showitemcountonly to gam print domainaliasess 2024-07-19 16:11:57 -07:00
Ross Scroggs
f1e599d535 Added option showitemcountonly to gam print domains 2024-07-18 13:19:41 -07:00
Ross Scroggs
752b502399 Fixed bug in gam <UserTypeEntity> print filelist that caused a trap. 2024-07-18 07:07:54 -07:00
Ross Scroggs
8e3d562830 Revert to setuptools 70.3.0 2024-07-17 19:05:54 -07:00
Ross Scroggs
5b6c7a30d7 Updated gam calendars <CalendarEntity> import event icaluid <iCalUID> json <JSONdata> 2024-07-17 16:50:04 -07:00
Ross Scroggs
5b7e8b6e01 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-07-17 14:13:28 -07:00
Ross Scroggs
8bd30af109 Fixed bug in gam calendars <CalendarEntity> import event icaluid <iCalUID> json <JSONdata> 2024-07-17 14:13:25 -07:00
Jay Lee
828b196414 allow browsers to be added to groups with ci commands 2024-07-17 20:39:09 +00:00
Ross Scroggs
83117a1eca Updated gam <UserTypeEntity> print|show filecounts 2024-07-15 11:35:02 -07:00
Ross Scroggs
bb65265930 Fixed bug in gam <UserTypeEntity> print chatspaces todrive 2024-07-12 07:15:32 -07:00
Ross Scroggs
14ea845aa3 Added option convertmbtogb to gam report 2024-07-10 17:11:06 -07:00
Ross Scroggs
c1bb4bf7fa Fixed bug in gam <UserTypeEntity> get profilephoto 2024-07-08 17:21:05 -07:00
Ross Scroggs
38dcdea6d5 Added option usertokencounts to gam <UserTypeEntity> print|show tokens 2024-07-08 13:04:18 -07:00
Ross Scroggs
bc222d2a91 Fix delete/sync chatmember group bugs 2024-07-07 21:01:35 -07:00
Ross Scroggs
c421904b78 Fixed bug in gam <UserTypeEntity> create chatmember <ChatSpace> ... group <GroupItem> that caused an error. 2024-07-07 14:56:45 -07:00
Ross Scroggs
f6d0f14b49 Updated gam update ou <OrgUnitItem> ... parent <OrgUnitItem> 2024-07-06 17:00:38 -07:00
Ross Scroggs
f4c6c7d6d8 Update Users-Drive-Files-Manage.md 2024-07-05 16:50:54 -07:00
Ross Scroggs
cad4e7b59e Wiki updates 2024-07-05 16:21:13 -07:00
Ross Scroggs
e05dad2717 Documentation cleanup 2024-07-03 12:43:09 -07:00
Ross Scroggs
74bc4596ed Added option onlyusers <UserTypeEntity> to gam <UserTypeEntity> claim ownership <DriveFileEntity>` 2024-07-03 11:26:15 -07:00
Ross Scroggs
cc3d79b3b9 Fixed bug in gam report users ... range <Date> <Date> 2024-07-01 15:30:44 -07:00
Ross Scroggs
4e0ae154a5 Quote tildes in gam csv command lines 2024-06-28 16:55:10 -07:00
Ross Scroggs
435388aa0b gam report updates 2024-06-27 10:11:06 -07:00
Ross Scroggs
e66ff54c3c Cleanup 2024-06-26 10:13:00 -07:00
Ross Scroggs
a7da52a485 Fix RE for sa emails in print admins 2024-06-26 07:38:16 -07:00
Ross Scroggs
ab65890455 sa email address cleanup 2024-06-26 07:07:11 -07:00
Jay Lee
f8dafa294d New Colab SKUs 2024-06-25 17:03:54 +00:00
Jay Lee
19ea4bbb9c JSON file needs to be in both places. Weird. 2024-06-25 16:33:44 +00:00
Jay Lee
53f40eb9eb Lookup service account emails by ID 2024-06-25 16:25:10 +00:00
Ross Scroggs
793f230c30 Cleaned up problems with some of the new Chat API asadmin commands. 2024-06-22 10:20:44 -07:00
Ross Scroggs
6964f10aa3 Cleanup 2024-06-21 20:48:36 -07:00
Ross Scroggs
3f6f6a191d Merge branch 'main' of https://github.com/GAM-team/GAM 2024-06-21 19:18:43 -07:00
Ross Scroggs
9388b8497c Update Chat dicumentation 2024-06-21 19:18:39 -07:00
Jay Lee
28ca319632 print backupcodes countsonly 2024-06-21 21:24:37 +00:00
Jay Lee
d5ad1cb2fb add nokey to create project 2024-06-21 16:19:39 +00:00
Ross Scroggs
c12ee6438c Added use_chat_admin_access Boolean variable to gam.cfg. 2024-06-20 17:06:53 -07:00
Jay Lee
e18eb0931e actions: just don't set arch on x86_64 and arm64 CFLAGS 2024-06-20 15:23:36 -04:00
Jay Lee
2c0295d674 actions: only set CFLAGS on universal2 for now 2024-06-20 15:21:30 -04:00
Jay Lee
ced1e84567 actions: exit 0 even on config failure so we get logs 2024-06-20 14:52:01 -04:00
Jay Lee
5adc996f3e actions: try dumping config.log 2024-06-20 14:44:39 -04:00
Ross Scroggs
a3b3353e71 OpenSSL 3.3.1 on Mac x64 seems to work now 2024-06-20 11:19:37 -07:00
Ross Scroggs
f084096658 Multiple updates
Course copyfrom update

Python 3.12.4

Chat API DPP
2024-06-20 07:33:03 -07:00
Jay Lee
d9188da059 update Chat discovery 2024-06-19 14:43:53 +00:00
Ross Scroggs
12c150f64d Fixed bug in `gam <UserTypeEntity> print|show filesharecounts 2024-06-12 20:57:36 -07:00
Jay Lee
6d25ada6a4 actions: re-enable build job tests 2024-06-12 14:00:41 -04:00
Jay Lee
c0cd121a91 actions: disable ssl also 2024-06-11 13:16:59 -04:00
Jay Lee
e8e508eb18 actions: disable version check temporarily 2024-06-11 12:44:45 -04:00
Jay Lee
deda162375 actions: fix arch variables 2024-06-11 12:20:27 -04:00
Jay Lee
b69601c5c2 actions: try something else for macos x86 2024-06-11 12:03:41 -04:00
Jay Lee
87f9aa37b5 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-06-10 16:26:41 +00:00
Jay Lee
b74e2e1fd2 retry group update on create on invalid argument
should address frequenty GROUP_METADATA_DOES_NOT_EXIST error in github actions
2024-06-10 16:25:32 +00:00
Jay Lee
e40cbc32a6 Update build.yml 2024-06-10 11:37:21 -04:00
Jay Lee
636a49b1a6 Try rebuilding openssl macos x86 on 3.3 branch 2024-06-10 11:07:19 -04:00
Jay Lee
7239f252da actions: put x86 mac back on 3.3.0 for now 2024-06-07 22:58:17 -04:00
Jay Lee
5d85ea63b0 actions: temp test x86 MacOS 14 2024-06-07 22:44:39 -04:00
Jay Lee
cf50fcc78f Update build.yml 2024-06-07 22:19:03 -04:00
Jay Lee
eead1bd8b9 USee if MacOS 13 will make a difference 2024-06-07 20:10:05 -04:00
Jay Lee
206a09aad3 Add scratch counter, variable we can iterate to force a new action run 2024-06-07 15:48:55 -04:00
Jay Lee
eb365a3eb5 [no ci] Set MACOSX_DEPLOYMENT_TARGET to our actual MacOS major version 2024-06-07 14:53:07 -04:00
Jay Lee
1690daccb5 Investigate issues with OpenSSL 3.3.1 2024-06-07 14:32:22 -04:00
Ross Scroggs
233eeb0744 Added Gemini License for Education SKUs 2024-06-07 07:29:45 -07:00
Ross Scroggs
3f17525169 Handle MacOS x86_64 SSL problem 2024-06-06 07:04:05 -07:00
Ross Scroggs
100df45d46 Retry errors when getting file labels 2024-06-05 12:22:48 -07:00
Ross Scroggs
cb00e6de9f Chat admin cleanup 2024-06-04 18:04:15 -07:00
Jay Lee
82585dc28a Merge branch 'main' of https://github.com/GAM-team/GAM 2024-06-04 17:50:47 +00:00
Jay Lee
cb16747125 Chat Admin APIs DevPreview 2024-06-04 17:50:30 +00:00
Jay Lee
8632c98556 actions: rebuild to get OpenSSL 3.3.1 2024-06-04 11:03:06 -04:00
Ross Scroggs
6c3a805a4d Fixed bug in gam <UserTypeEntity> print|show chatspaces 2024-06-03 07:36:20 -07:00
Ross Scroggs
f6b949e4c1 Updated gam <UserTypeEntity> print filelist ... showshareddrivepermissions 2024-05-31 20:47:00 -07:00
Jay Lee
1f9624ad5c add 2 Gemini SKUs 2024-05-31 19:36:56 +00:00
Jay Lee
9c9ddff973 gam report vault 2024-05-31 19:36:12 +00:00
Ross Scroggs
f1636c7768 Added fromgmail to <EventType> 2024-05-31 12:26:06 -07:00
Ross Scroggs
0ebefda760 Updated gam update|delete|info adminrole to handle the following error:
ERROR: 400: failedPrecondition - Precondition check failed.
2024-05-29 19:13:46 -07:00
Ross Scroggs
5a335fb57b Updated <SchemaNameList> to allow schema fields 2024-05-29 10:49:31 -07:00
Ross Scroggs
db95cbcfa4 Fixed control-C bug 2024-05-28 13:06:19 -07:00
Ross Scroggs
33d9949283 MacOS swig: it's here/it's not 2024-05-26 17:35:09 -07:00
Ross Scroggs
41078d5ff6 Fix Windows build, cleanup 2024-05-26 16:21:06 -07:00
Ross Scroggs
52316774ad Disable Chat Admin APIs 2024-05-25 09:36:34 -07:00
Ross Scroggs
ce545ad062 Chat Admin APIs default to off 2024-05-25 09:02:10 -07:00
Ross Scroggs
2e5df12df1 Update print messages and print drivesettings 2024-05-25 08:35:11 -07:00
Jay Lee
46b9de642d actions: remove fullGamTest logic
Ensure live Google API tests run on test runners so we are exercising our code against Python versions other than the version used by GAM binaries.

These runners generally finish fastest anyway since they never need to compile OpenSSL, Python or PyInstaller.
2024-05-22 21:29:04 -04:00
Jay Lee
a9d600234c [no ci] actions: macOS runner now ships with rust, gnupg and swig 2024-05-22 21:15:33 -04:00
Jay Lee
5c8b69e8b7 actions: move PyInstaller back to latest to see what happens 2024-05-22 21:08:58 -04:00
Ross Scroggs
29792677d7 Added option showusagebytes to gam <UserTypeEntity> print|show drivesettings 2024-05-22 13:18:02 -07:00
Ross Scroggs
7de9e986e0 Updated transfer calendars to manipulate calendar lists 2024-05-19 09:49:06 -07:00
Ross Scroggs
2b711be6a4 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-05-17 11:05:06 -07:00
Ross Scroggs
16ef9e60d5 Add new fields to CrOSFieldName 2024-05-17 11:05:03 -07:00
Jay Lee
4d1a31c6bf [actions] else not lse 2024-05-17 13:16:07 -04:00
Ross Scroggs
5a5b98cccb Added option folderpathonly [<Boolean>] to commands that display paths 2024-05-17 07:42:32 -07:00
Ross Scroggs
f94afedfa8 Fix typo 2024-05-16 16:18:03 -07:00
Ross Scroggs
c9996f4942 MacOS 14.5 curl doesn't like empty arguments 2024-05-16 09:59:16 -07:00
Ross Scroggs
d32942a1d7 Updated gam update group to handle the following error:
ERROR: 400: invalidArgument - Failed request validation in update settings: WHO_CAN_VIEW_MEMBERSHIP_CANNOT_BE_BROADER_THAN_WHO_CAN_SEE_GROUP
2024-05-14 11:34:59 -07:00
Ross Scroggs
95d1e4ab7c Updated gam update group to handle the following error:
ERROR: 400: invalidArgument - Failed request validation in update settings: WHO_CAN_VIEW_MEMBERSHIP_CANNOT_BE_BROADER_THAN_WHO_CAN_SEE_GROUP
2024-05-14 11:30:22 -07:00
Ross Scroggs
dd4fb084e6 Update docs; improve error message on missing SA scope 2024-05-14 08:10:42 -07:00
Ross Scroggs
2c039c3730 Fix missing scope issue; other minor fixs 2024-05-13 20:17:22 -07:00
Jay Lee
0cef0aecb5 retain None type for user, not empty string 2024-05-13 16:53:43 +00:00
Ross Scroggs
4ed9d7ac1f Fixed bug in gam create vaulthold ... corpus calendar that caused a trap. 2024-05-09 10:10:29 -07:00
Ross Scroggs
21b2093b55 Updated versions of gam create|use project 2024-05-07 20:00:23 -07:00
Jay Lee
d4ea2ec978 Update build.yml 2024-05-06 10:57:55 -04:00
Jay Lee
8cffa6e394 Update build.yml 2024-05-06 10:47:12 -04:00
Jay Lee
58337e0722 actions: fix gam location with realpath 2024-05-06 10:31:28 -04:00
Jay Lee
cedbae36b7 actions: missing export 2024-05-06 10:13:17 -04:00
Jay Lee
d5e9df41fb actions: fix Windows gam.exe location 2024-05-06 09:53:18 -04:00
Jay Lee
e7323f0b74 actions: archives are in src/ 2024-05-06 09:43:10 -04:00
Jay Lee
00d3600881 actions: GH Attestation for GAM executables and packages
https://github.blog/changelog/2024-05-02-artifact-attestations-public-beta/

attest that GAM was built on GitHub actions to help end users validate they're running a legit GAM binary.
2024-05-06 09:35:49 -04:00
Ross Scroggs
4c799aaf10 Added option csv [todrive <ToDriveAttribute>*] to message processing commands 2024-05-04 18:39:09 -07:00
Ross Scroggs
a8938f84f0 print user counts by ou, upload message attachments 2024-05-03 17:52:54 -07:00
Ross Scroggs
ab5aa02bf8 Fixed bug in gam batch|tbatch 2024-05-02 15:14:11 -07:00
Ross Scroggs
42d33786a1 Updated gam report <ActivityApplictionName> to retry/handle the following error:
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2024-05-01 13:33:13 -07:00
Ross Scroggs
683435cfb8 Added option admin <EmailAddress> to gam upload sakey. 2024-04-26 09:16:22 -07:00
Ross Scroggs
6b8170dd2f Improved code in gam upload sakey. 2024-04-26 08:33:50 -07:00
Ross Scroggs
941fe97785 Updated gam create project
to simplify handling the situation when your workspace is configured to disable service account private key uploads.
2024-04-25 22:23:16 -07:00
Ross Scroggs
f87e013ec4 Fixed bug in gam <UserTypeEntity> print shareddrives ... formatjson that caused a trap. 2024-04-25 08:46:14 -07:00
Ross Scroggs
fc792bf454 Updated gam create|update drivefileacl <DriveFileEntity> ... expiration <Time> to handle the following
ERROR: 403: expirationDateNotAllowedForSharedDriveMembers - Expiration dates are not allowed for shared drive members.
2024-04-23 15:18:37 -07:00
Ross Scroggs
b4b9bd2436 Added truncate_client_id Boolean variable to gam.cfg doc cleanup 2024-04-22 18:31:06 -07:00
Ross Scroggs
0e455a2e40 Added truncate_client_id Boolean variable to gam.cfg 2024-04-22 18:26:24 -07:00
Ross Scroggs
b384bdb503 Do not truncate client_id by default 2024-04-22 17:17:47 -07:00
jeffssh
10a6348ddd fixed minor typo not -> no (#1685) 2024-04-19 15:41:30 -04:00
Ross Scroggs
74be07a9ef The Google Chat API has been updated so that chat members can now have their role set to manager. 2024-04-19 10:05:35 -07:00
Ross Scroggs
5607d659fb Updated emailaddressList <EmailAddressList> and domainlist|notdomainlist <DomainNameList> in <PermissionMatch> to perform case-insensitive matches 2024-04-18 15:03:14 -07:00
Ross Scroggs
da1ef497a1 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-04-18 13:03:00 -07:00
Ross Scroggs
ac4fef0e4b Updated all commands that display tasks to display the due date in GMT 2024-04-18 12:43:39 -07:00
Jay Lee
0bc44582af BCE > CEP to match admin console product name change 2024-04-17 14:13:51 -04:00
Ross Scroggs
baf0c7863f Upgraded to Python 3.12.3 where possible. 2024-04-16 19:52:03 -07:00
Ross Scroggs
b00077151b Added the following option to <EventMatchProperty>
```
matchfield attendeesonlydomainlist <DomainNameList>
```
2024-04-16 18:34:13 -07:00
Ross Scroggs
842e46d060 Added the following options to <EventMatchProperty>
```
matchfield attendeesdomainlist <DomainNameList>
matchfield attendeesnotdomainlist <DomainNameList>
```
2024-04-16 15:32:25 -07:00
Ross Scroggs
bad4866bf7 Added option oneitemperrow to 'gam print vaultholds` 2024-04-15 15:59:57 -07:00
Ross Scroggs
3f5d96e13b Added timeofdayrange=<HH:MM>/<HH:MM> and timeofdayrange!=<HH:MM>/<HH:MM> to <RowValueFilter> 2024-04-12 11:55:50 -07:00
Ross Scroggs
a0dc04e7b0 Updated countsonly option of gam <UserTypeEntity> print|show notes to additionally display the total number of notes. 2024-04-04 17:57:55 -07:00
Ross Scroggs
23b0b0f203 Added option countsonly to gam <UserTypeEntity> print|show notes 2024-04-04 11:37:41 -07:00
Ross Scroggs
83d464d167 Updated commands that send emails to not downshift 'First Last<firstlast@domain.com>' 2024-04-02 10:38:35 -07:00
Ross Scroggs
1ba9f73fbd Update sendemail and notify email address lists 2024-04-01 19:36:12 -07:00
Ross Scroggs
0a21f2c959 Cleaned up code for all commands that display Chat objects. 2024-03-30 09:37:43 -07:00
Ross Scroggs
62b7b5d84b Added commands to display Chat events. 2024-03-29 20:06:07 -07:00
Ross Scroggs
7e12a8f0a7 Fixed bug in gam <UserTypeEntity> create chatspace that caused a trap. 2024-03-28 08:00:58 -07:00
Ross Scroggs
d347c65fcb Updated gam delete admin <RoleAssignmentId> 2024-03-25 20:01:38 -07:00
Ross Scroggs
51f109ffa7 Improved commands to display drive file comments. 2024-03-24 08:44:22 -07:00
Ross Scroggs
a5e7d6ff6c Added commands to display drive file comments 2024-03-22 15:52:44 -07:00
Ross Scroggs
2260e7df50 Updated <CrOSFieldName> to include cpuinfo and backlightinfo. 2024-03-21 11:42:12 -07:00
Ross Scroggs
08fc3bdb6f Added depth column to output of gam <UserTypeEntity> print diskusage <DriveFileEntity> 2024-03-17 18:39:39 -07:00
Ross Scroggs
0754a9b176 Updated gam <UserTypeEntity> create|update sendas <EmailAddress> ... replyto <EmailAddress>
to allow uppercase letters in `sendas <EmailAddress>` and `replyto <EmailAddress>`.
2024-03-17 12:05:27 -07:00
Ross Scroggs
448d58f9ba Updated gam create project to handle the following error:
ERROR: 403: permissionDenied - Authentication error: 7; Error Details: User not allowed to access GCP services.
2024-03-13 15:13:46 -07:00
Ross Scroggs
bdc330405e Show new label name on update 2024-03-11 17:04:05 -07:00
Ross Scroggs
abe1d5381d Added a command to update a Gmail label's settings by specifying it's ID rather than it's name. 2024-03-11 16:41:47 -07:00
Ross Scroggs
be0eff7e14 Updated <UserMultiAttribute>.location.buildingid <String> to allow non-validated building IDs 2024-03-09 07:06:45 -08:00
Ross Scroggs
f88a125966 Update WIX toolset version 2024-03-06 18:35:45 -08:00
Ross Scroggs
623ff1fae9 Added option showmimetype category <MimeTypeNameList> to gam <UserTypeEntity> print|show filecounts|filelist|filetree 2024-03-06 17:13:01 -08:00
Ross Scroggs
63d7b5568b Added option addcsvdata <FieldName> <String> to gam print cros 2024-03-05 16:14:18 -08:00
Ross Scroggs
7c8a87673a Reverted change made in 6.71.09 to gam <UserTypeEntity> print filelist 2024-03-04 10:41:43 -08:00
Ross Scroggs
a3b814f758 Improved the performance of gam <UserTypeEntity> print filelist when showmimetype and filepath|fullpath are both specified. 2024-03-03 14:18:17 -08:00
Ross Scroggs
1989d72f4f Added option oneitemperrow to 'gam print admins|adminroles` 2024-03-01 15:10:42 -08:00
Ross Scroggs
63b1ca7e30 Added command to upload changes to Google Docs. 2024-02-29 22:08:17 -08:00
Ross Scroggs
a328ac8ea9 Add licenses, thanks to Jay 2024-02-29 14:15:11 -08:00
Ross Scroggs
2188bfa704 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-02-29 14:03:36 -08:00
Ross Scroggs
0f5adbe211 Added additional error handling to Gmail Client Side Encryption commands. 2024-02-29 14:03:29 -08:00
Jay Lee
d0251182de Education Endpoint SKU 2024-02-29 19:42:30 +00:00
Ross Scroggs
a04345fb10 Include missing gamlib updates 2024-02-29 11:09:35 -08:00
Ross Scroggs
80440255ab Many updates/fixes
Gmail CSE updates

Added todrive options: tdalert, tdfrom, tdsubject

Added CSV output row sorting

Fixed audit monitor create
2024-02-29 10:58:46 -08:00
Ross Scroggs
7b3cc6d819 Update documentation YouTube API off by default 2024-02-26 11:30:12 -08:00
Ross Scroggs
76d3ead61b Updated gam oauth create and gam <UserTypeEntity> update serviceaccount 2024-02-26 10:58:25 -08:00
Ross Scroggs
21ca008a47 Updated gam info users <UserTypeEntity> to not include group tree infornation unless option grouptree is specified. 2024-02-25 10:24:06 -08:00
Ross Scroggs
96aa4f3bd2 Added commands to create|delete|display Drive Label permissions. 2024-02-24 16:56:16 -08:00
Ross Scroggs
883979f5f5 Added options showvalidcolumn and addcsvdata to `gam print use 2024-02-23 14:41:45 -08:00
Ross Scroggs
b03a43777d Update DuetAI licenses to Gemini 2024-02-22 08:33:53 -08:00
Ross Scroggs
a0e4be4b50 Use gam.cfg/use_course_owner_access in course copyfrom. 2024-02-21 14:20:40 -08:00
Ross Scroggs
115caf2486 Added support for Gmail Client Side Encryption 2024-02-21 11:32:00 -08:00
Ross Scroggs
d5255615fd Added use_classroom_owner_access Boolean variable to gam.cfg 2024-02-18 20:59:58 -08:00
Ross Scroggs
d949ca2cad permissionDetails improvements 2024-02-15 18:24:47 -08:00
Ross Scroggs
4b0533ff0e Merge branch 'main' of https://github.com/GAM-team/GAM 2024-02-14 08:34:53 -08:00
Ross Scroggs
d1e87df2df Updated gam info user ... locations formatjson to include the buildingName field in the locations entries. 2024-02-14 08:34:39 -08:00
Jay Lee
dc8f6c3b5e actions: upgrade various action versions 2024-02-13 19:12:46 -05:00
Ross Scroggs
70640c1ddb Bug fix/enhancement copy|more drive file 2024-02-13 13:08:20 -08:00
Ross Scroggs
a72b81f99e Limit testing so jobs complete 2024-02-12 19:58:32 -08:00
Ross Scroggs
89a7c86840 Try multi artifact build - 2 2024-02-12 18:08:19 -08:00
Ross Scroggs
a086c1c2a8 Try multi artifact build 2024-02-12 18:02:57 -08:00
Ross Scroggs
be3c6f10c7 Updated gam print groups ... ciallfields|(cifields <CIGroupFieldNameList>) to account for an API shortcoming that failed to get all of the Cloud Identity fields. 2024-02-12 11:28:09 -08:00
Ross Scroggs
1c9f65f7ca Fix for delete artifacts failing? Try 2 2024-02-11 15:20:46 -08:00
Ross Scroggs
b023ecf8ce Fix for delete artifacts failing? 2024-02-11 15:16:48 -08:00
Ross Scroggs
0a0cb2a18b Back to macos-14 for universal2 build 2024-02-10 19:56:54 -08:00
Ross Scroggs
a02afe76fc Add missing lines
Build universal2 with macos-12, doesn't run with macos-14
2024-02-10 19:27:05 -08:00
Ross Scroggs
0b24beca30 Make artifact names unique with jid 2024-02-10 18:16:39 -08:00
Ross Scroggs
7dfa236bc1 Use v4 actions 2024-02-10 15:29:36 -08:00
Ross Scroggs
b7400b9010 run format cleanup, fix typo line 594 2024-02-09 16:03:11 -08:00
Jay Lee
50c5986c3e actions: fix Windows cache 2024-02-09 15:08:16 -05:00
Ross Scroggs
fff892300b Update glmsgs.py 2024-02-09 10:29:32 -08:00
Ross Scroggs
adbee45073 Added option skiprows <Integer> to gam csv|loop 2024-02-09 10:00:33 -08:00
Ross Scroggs
2d091c8ca0 Fixed bug in gam <UserTypeEntity> create drivefileacl that caused a trap. 2024-02-09 07:26:39 -08:00
Jay Lee
933fc19379 actions: reduce cache sizes by only caching necessary path for OS 2024-02-09 06:23:20 -05:00
Jay Lee
2bb2684165 actions: fix jid numbering 2024-02-08 14:29:33 -05:00
Jay Lee
868e5e1ab6 actions: expire cache to ensure all builds are correct 2024-02-08 14:25:55 -05:00
Jay Lee
d537067908 [no ci] actions: build arm64 and universal2 on github hosted runner 2024-02-08 14:23:17 -05:00
Jay Lee
a9b8a14d8e actions: cleanup brew installs for macOS 2024-02-08 14:18:24 -05:00
Ross Scroggs
f3d654fc76 Upgraded to Python 3.12.2 where possible. 2024-02-08 10:27:41 -08:00
Ross Scroggs
62a01bbcfd Added options restricted|(audience <String>) to gam <UserTypeEntity> create|update chatspace 2024-02-08 10:15:29 -08:00
Jay Lee
e60e1e939b [actions] github hosted Apple silicon (sweet) 2024-02-08 10:55:44 -05:00
Jay Lee
5305f1bda0 actions: rebuild for Python 3.12.2 2024-02-08 08:47:24 -05:00
Ross Scroggs
6126e6ac67 Fixed <PermissionMatch> bug for real. 2024-02-07 12:18:08 -08:00
Ross Scroggs
58e2f74700 Fixed <PermissionMatch> bug introduced in 6.67.35 2024-02-07 09:04:47 -08:00
Ross Scroggs
dcaf892e95 Added option wait <Integer> <Integer> to gam create datatransfer 2024-02-06 18:20:54 -08:00
Ross Scroggs
e8b2dee02d Added option tdnotify [<Boolean>] to <ToDriveAttribute> 2024-02-06 13:46:53 -08:00
Ross Scroggs
267d63fcd6 Fixed bug in gam <UserTypeEntity> show messages ... showattachments to avoid a trap when text/plain attachments in character sets other than UTF-8 are displayed. 2024-02-03 21:14:16 -08:00
Ross Scroggs
566a0c0345 Added sleep <Integer> to batch commands 2024-02-03 17:33:36 -08:00
Ross Scroggs
6ed3f8ebfc Added the following options to <PermissionMatch> that allow more powerful matching.
Added the following options to `<PermissionMatch>` that allow more powerful matching.
```
nottype	<DriveFileACLType>
typelist <DriveFileACLTypeList>
nottypelist <DriveFileACLTypeList>
rolelist <DriveFileACLRoleList>
notrolelist <DriveFileACLRoleList>
```
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Permission-Matches#define-a-match
2024-02-03 12:09:09 -08:00
Ross Scroggs
51c7a542e3 Shared Drive fixes/updates 2024-02-02 16:00:43 -08:00
Ross Scroggs
ee68669652 Fixed bug in gam <UserTypeEntity> print shareddrives where role was improperly displayed as unknown 2024-02-01 15:40:18 -08:00
Ross Scroggs
e7e653d395 Updated <ToDriveAttribute> to allow multiple tdshare <EmailAddress> commenter|reader|writer options. 2024-02-01 13:28:43 -08:00
Ross Scroggs
e6a4eb7fd9 Merge branch 'main' of https://github.com/GAM-team/GAM 2024-01-31 10:41:39 -08:00
Ross Scroggs
25cdf2e544 Multiple updates 2024-01-31 10:41:36 -08:00
Jay Lee
5e1702018c [actions] bump actions for OpenSSL 3.2.1 2024-01-30 13:04:12 -05:00
Ross Scroggs
a404af0582 Fixed bug that caused HTML password notification email messages to be displayed in raw form. 2024-01-22 09:52:26 -08:00
Ross Scroggs
741b69ff2d Update __init__.py 2024-01-20 10:23:17 -08:00
Ross Scroggs
da1f808c06 Use local copy of googleapiclient to remove static discovery documents to improve performance. 2024-01-20 10:01:04 -08:00
Ross Scroggs
39a8bf9485 Two updates
Added `permissionidlist <PermissionIDList>` to `<PermissionMatch>`

Added option `exportlinkeddrivefiles <Boolean>` to `gam create vaultexport`
2024-01-19 14:31:47 -08:00
Ross Scroggs
53d1ce5ddb Updated gam remove aliases <EmailAddress> user|group <EmailAddressEntity> 2024-01-19 08:12:27 -08:00
Ross Scroggs
432ef09129 Added option onelicenseperrow|onelicenceperrow to gam print users ... licenses 2024-01-17 20:14:18 -08:00
Ross Scroggs
647da9f980 Password notification fix
Updated `gam create|update user ... notify` to encode the characters `<>&` in the password
so that they display correctly when the notify message content is HTML.
2024-01-15 09:31:05 -08:00
Ross Scroggs
cc50ae28cd Cleaned up Getting/Got messages for gam print courses|course-participants. 2024-01-13 17:18:45 -08:00
Ross Scroggs
64ed92692a Added option showitemcountonly to various commands 2024-01-12 21:53:12 -08:00
Ross Scroggs
2dd810ba69 Correct editing error 2024-01-12 11:40:25 -08:00
Ross Scroggs
5922d939e2 Improve gam print group-members 2024-01-12 11:23:41 -08:00
Ross Scroggs
14eaa9f32f Updated reseller commands to handle the following error:
ERROR: 400: invalid - Customer domain [domain.com] is linked to one or more email verified customers, please provide a customer id.
2024-01-10 16:46:04 -08:00
Ross Scroggs
f935a6bdfc Updated gam create domain <DomainName> to handle the following error:
ERROR: 409: conflict - Domain in request is in use by an email verified customer.
2024-01-10 14:42:25 -08:00
Ross Scroggs
29ceda7f43 Added option addcsvdata <FieldName> <String> to gam print datatransfers 2024-01-10 11:38:19 -08:00
Ross Scroggs
f950c863f4 Gmail permissions update
Updated various Gmail related commands to handle this error:
```
ERROR: 403: permissionDenied - Insufficient Permission
```
2024-01-10 08:52:57 -08:00
Ross Scroggs
90f9931dca Fixed bug that caused a trap when optional argument charset <Charset> was used with emlfile <FileName> 2024-01-09 15:21:06 -08:00
Ross Scroggs
4c357d5281 Added option maxevents <Number> to gam report <ActivityApplictionName> 2024-01-08 12:08:50 -08:00
Ross Scroggs
0abf2ceeca Added optional argument charset <Charset> to emlfile <FileName> 2024-01-07 21:38:02 -08:00
Ross Scroggs
3088570449 Handle gam <UserTypeEntity> delete message permission error 2024-01-07 10:29:15 -08:00
Ross Scroggs
800943c401 Updated commands that create ACLs to handle the following error:
ERROR: 400: abusiveContentRestriction - Bad Request. User message: "You cannot share this item because it has been flagged as inappropriate."
2024-01-04 15:04:24 -08:00
Ross Scroggs
3bedb57443 Handle Gmail sharing settings permission errors 2024-01-03 09:31:44 -08:00
Ross Scroggs
668ded91e2 Updated user attribute replace <Tag> <UserReplacement> to allow field:photourl 2024-01-02 21:08:35 -08:00
Ross Scroggs
293e1c1d9a Fixed bug introduced in 6.67.02 in gam <UserTypeEntity> claim ownership that caused a trap. 2024-01-02 12:32:13 -08:00
Ross Scroggs
7596215bbe Added option skipids <DriveFileEntity> to gam <UserTypeEntity> copy drivefile 2023-12-30 08:57:54 -08:00
Ross Scroggs
7c6bbaf107 Revert "Sdd skids to more command, handle Shared Drive limitations"
This reverts commit 5271368776.
2023-12-30 07:47:06 -08:00
Ross Scroggs
5271368776 Sdd skids to more command, handle Shared Drive limitations 2023-12-29 21:01:59 -08:00
Ross Scroggs
430a30e2d2 Fix vault corpus bug 2023-12-23 08:20:29 -08:00
Ross Scroggs
b0eae53f80 Improve print vaultcounts error message 2023-12-23 07:58:16 -08:00
Ross Scroggs
dd03bafaec Fixed bug in gam print vaultcounts that caused a trap. 2023-12-23 07:42:24 -08:00
Ross Scroggs
ded3ea104b Document sitesurl in vault 2023-12-22 19:55:50 -08:00
Ross Scroggs
0d9c6a77b6 Updates for API changes
Updated `gam <CrOSTypeEntity> update action <CrOSAction>` to use the new API function `batchChangeStatus`

Updated `gam create vaultexport matter <MatterItem>` to support `corpus calendar`.
2023-12-22 19:38:06 -08:00
Ross Scroggs
ae46ae8738 Added option convertcrnl to gam update chromepolicy 2023-12-20 19:59:18 -08:00
Ross Scroggs
06a4c7a8c9 Added option copysubfilesownedby any|me|others to `gam <UserTypeEntity> copy drivefile 2023-12-20 12:32:10 -08:00
Ross Scroggs
f89f730957 Handle issues in update alias/message 2023-12-19 20:04:06 -08:00
Ross Scroggs
80fc40a9c7 Updated functionality of option preservefiletimes in gam <UserTypeEntity> update drivefile <DriveFileEntity>. 2023-12-14 10:06:46 -08:00
Ross Scroggs
2bb0088ade Updated all drive commands to handle the following error:
```
ERROR: 401: Active session is invalid. Error code: 4 - authError
```
2023-12-12 10:25:59 -08:00
Jay Lee
d113b3ec8e flush cache to pickup Python 3.12.1 2023-12-12 06:57:08 -05:00
Ross Scroggs
97e13b92be Fixed/improved handling of shortcuts in gam <UserTypeEntity> transfer drive. 2023-12-11 15:56:00 -08:00
Ross Scroggs
dc832b8c7f Updated gam create datatransfer to handle the following error:
ERROR: 401: Active session is invalid. Error code: 4 - authError
2023-12-09 10:16:40 -08:00
Ross Scroggs
56c33fec87 Fixed bug in gam <UserTypeEntity> print filelist ... allfields that caused a trap 2023-12-07 18:26:59 -08:00
Ross Scroggs
48862997b0 Added additional columns isBase and baseId' to gam <UserTypeEntity> print fileparenttree` 2023-12-07 08:29:11 -08:00
Ross Scroggs
59dd01f1e8 Update and fix
Fixed bug in `gam <UserTypeEntity> print diskusage` that caused a trap.

Added a command the print the parent tree of file/folder.
2023-12-06 14:18:33 -08:00
Ross Scroggs
d639e8e728 Two small updates 2023-12-04 11:57:56 -08:00
Ross Scroggs
1c0e6ebf9c Fixed bug in gam <UserTypeEntity> print filelist select <DriveFileEntity> where stripcrsfromname was not being applied to files below the selected folder. 2023-12-02 09:09:40 -08:00
Ross Scroggs
c289fb08f1 Update library files 2023-12-01 18:42:42 -08:00
Ross Scroggs
a64d6f1215 Updated device commmands, Update use of \ in CSV files 2023-12-01 18:04:18 -08:00
Ross Scroggs
b0f05c2dea Added support for Focus Time and Out of Office status events in user's primary calendars.
Updated `gam <UserTypeEntity> print|show messages` to allow option `show_size` to be used with option `countsonly`
to display the cumulative size of the messages selected.

Chat prerelease updates
2023-11-29 16:23:45 -08:00
Ross Scroggs
46d4e78b79 Multiple updates/fixes 2023-11-25 09:18:06 -08:00
Ross Scroggs
0562639715 Added additional options to gam <UserTypeEntity> print|show youtubechannels. 2023-11-22 20:36:43 -08:00
Ross Scroggs
51de288f27 Added option sizefield quotabytesused|size to file display commands
Fixed bug in gam <UserTypeEntity> copy|move drivefile` that caused a trap.
2023-11-22 08:56:30 -08:00
Ross Scroggs
7cfb16c1f5 dditional updates on MacOS when a gam csv command is interrupted with a contol-C. 2023-11-18 14:22:38 -08:00
Ross Scroggs
f0cddbe7c2 Fixed bug in `gam print|show crostelemetry
Updated multiprocessing to handle the following error that occurs on MacOS when a `gam csv` command
is interrupted with a contol-C.

It's a pyinstaller issue, revert to 5.13.2 for Mac OS
2023-11-18 08:49:28 -08:00
Ross Scroggs
06840c2608 Two fixes
Updated multiprocessing to handle the following error that occurs on MacOS when a `gam csv` command
is interrupted with a contol-C.
```
multiprocessing/resource_tracker.py:224: UserWarning: resource_tracker: There appear to be N leaked semaphore objects to clean up at shutdown
```

Fixed bug in `gam print crostelemetry` that caused a trap: `KeyError: 'reportTime'`.
2023-11-17 11:12:29 -08:00
Ross Scroggs
87db64897d Ignore github/Google time offset errors 2023-11-16 08:01:31 -08:00
Ross Scroggs
683d47175b Added option noduplicate to gam <UserTypeEntity> create drivefile 2023-11-15 18:27:12 -08:00
Ross Scroggs
fac8c11798 Updated gam <UserTypeEntity> get drivefile <DriveFileEntity>
to handle the following error
that seems to occur when multiple tabs from a Google sheet are being downloaded in parallel.
```
Download Failed: HTTP Error: 429
```
2023-11-13 16:59:11 -08:00
Ross Scroggs
b5f5291e14 Added options to gam report <ActivityApplicationName>
`addcsvdata <FieldName> <String>`
`shownoactivities`
2023-11-11 17:11:18 -08:00
Ross Scroggs
194b93a7ee Updated gam delete building to handle the following error:
ERROR: 412: conditionNotMet - Cannot delete building because there are Calendar resources associated with it.
2023-11-07 19:17:00 -08:00
Ross Scroggs
55099e6835 Improved error message when trying to add external students/teachers to a course. 2023-11-03 14:40:56 -07:00
Ross Scroggs
4a199c7b6f Multiple updates 2023-11-03 08:52:05 -07:00
Ross Scroggs
3facd05a94 SKU fix and update 2023-10-25 13:11:17 -07:00
Ross Scroggs
bb443be367 Fixed bug in commands that display calendar events where event start and end times were not properly displayed 2023-10-24 21:21:21 -07:00
GitHub Action
1952aa2026 [ci skip] Updated cacerts.pem 2023-10-23 23:24:19 +00:00
Ross Scroggs
d206ac4518 Handle service not available when listing cros 2023-10-21 06:46:14 -07:00
Ross Scroggs
6b19ba1933 Updated gam print|show browsers to handle the following error:
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2023-10-20 19:32:36 -07:00
Ross Scroggs
bcf9c051f0 Try to fix build errors 2023-10-20 16:42:06 -07:00
Ross Scroggs
4934809b88 Add showmimetypesize to print filelist/filecounts 2023-10-20 14:35:45 -07:00
Ross Scroggs
55298f0134 Two updates
Fixed bug in `gam <UserTypeEntity> create contact <JSONData>` that caused a trap when
contacts were being copied from one user to another.

Updated the commands to allow specification of a task list by its title.
2023-10-19 08:14:03 -07:00
Ross Scroggs
7e9207ae3c Fixed bug in gam <UserTypeEntity> create task <TasklistIDEntity> 2023-10-17 20:25:24 -07:00
Ross Scroggs
7915f97bd5 Updated lookerstudioassets|lookerstudiopermissions commands to handle the following error:
ERROR: 500: internalError - Internal error encountered.
2023-10-13 11:36:44 -07:00
Ross Scroggs
1231627412 More info chromeapp cleanup 2023-10-12 12:33:14 -07:00
Ross Scroggs
40977cedc7 Cleaned up and renamed gam info appdetails to gam info chromeapp. 2023-10-12 12:14:14 -07:00
Ross Scroggs
d500196dee Added command to get customer app details. 2023-10-12 09:03:03 -07:00
Jay Lee
994d489226 actions: remove errant ) 2023-10-11 13:25:51 -04:00
Jay Lee
602c47a900 actions: pin win to python 3.11.6 2023-10-11 13:10:29 -04:00
Jay Lee
de4315b4b7 actions: revert pyinstaller on Win 2023-10-11 12:20:43 -04:00
Ross Scroggs
9bbdae6986 Added support for Google Workspace Labs license (for real) 2023-10-11 07:55:11 -07:00
Ross Scroggs
c7899ba401 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-10-11 07:28:36 -07:00
Ross Scroggs
4b9a8cc235 Added support for Google Workspace Labs license. 2023-10-11 07:22:46 -07:00
Jay Lee
4ae5cdee83 actions: forward slashes 2023-10-11 09:40:49 -04:00
Jay Lee
1393ed3ca6 actions: attempt windows fix 2023-10-11 09:38:20 -04:00
Jay Lee
6ec24c87cd Create openssl.props 2023-10-11 08:43:00 -04:00
Jay Lee
a404311097 [no ci] actions: revert openssl.props copy 2023-10-11 08:41:38 -04:00
Jay Lee
a7d8260de5 [no ci] actions: test python 3.11 2023-10-10 16:41:19 -04:00
Jay Lee
63fe8b53f9 Delete src/tools/openssl.props 2023-10-10 16:28:18 -04:00
Jay Lee
4ad4711b84 [no ci] actions: pyinstaller 5.3.2 for staticx, no openssl.props needed 2023-10-10 16:06:33 -04:00
Ross Scroggs
f13625719b Merge branch 'main' of https://github.com/GAM-team/GAM 2023-10-10 11:26:24 -07:00
Ross Scroggs
5ae29742ce Fixed bug introduced in 6.64.09 that caused a trap when gam redirect csv <FileName> multiprocess was used. 2023-10-10 11:25:57 -07:00
Jay Lee
ec6f36cf82 actions: disable sso assignment for now 2023-10-10 13:58:54 -04:00
Ross Scroggs
c18cf75b4f Cleaned up print filelist when there are no rows to print 2023-10-10 07:21:38 -07:00
Ross Scroggs
7b6673b43b Fixed bug in redirect csv - todrive tdtitle "File Title" tdsheettitle "Sheet Title" where "Sheet Title" was not assigned to the new sheet. 2023-10-06 10:42:17 -07:00
Ross Scroggs
d1dea2593f Updated gam <UserTypeEntity> move drivefile to handle the following error:
ERROR: 403: targetUserRoleLimitedByLicenseRestriction - Cannot set the requested role for that user as they lack the necessary license
2023-10-04 09:36:28 -07:00
Ross Scroggs
aebec7fa94 Added fields devicelicensetype and osupdatestatus to <CrOSFieldName>. 2023-10-03 13:43:01 -07:00
Ross Scroggs
7f79bf0e87 Added matchfield organizerself <Boolean> to <EventMatchProperty> 2023-10-03 08:34:37 -07:00
Ross Scroggs
0e0d45322e Updated gam calendars <CalendarEntity> move events
to handle the following error:
```
ERROR: 400: badRequest - Bad Request
2023-10-01 11:47:41 -07:00
Ross Scroggs
b7f572149f Updated gam <UserTypeEntity> get drivefile to allow downloading Jamboard files 2023-09-28 13:00:57 -07:00
Ross Scroggs
b07bd82f60 Updated gam <UserTypeEntity> print|show youtubechannels to handle the following error:
ERROR: 403: unsupportedSupervisedAccount - Access Forbidden. The authenticated user cannot access this service.
2023-09-27 16:48:31 -07:00
Ross Scroggs
086c7469c5 Added support for displaying users YouTube channels.
Pyinstaller 6.0.0 causes errors. You can tweak build.yml to revert to 5.13.2
2023-09-26 21:10:52 -07:00
Ross Scroggs
37a968a142 Fix typo 2023-09-25 09:48:04 -07:00
Ross Scroggs
dab05fb5c5 Fixed bug in gam print vacation where endDate value was not converted to yyyy-mm-dd format. 2023-09-22 07:14:57 -07:00
Ross Scroggs
115dde8c2f Updated gam print|show ownership to show the correct file owner when the most recent event is change_owner. 2023-09-20 15:24:20 -07:00
Ross Scroggs
38c78228aa Multiple changes
Added support for Duet AI license.

Added `api_call_tries_limit` variable to `gam.cfg` that limits the number of tries
for Google API calls that return an error that indicates a retry should be performed. The default value is 10 and the range of allowable values is 3-10.

Code cleanup for retry loops

Initial (not announced, in preview mode) code for Chat API support of group members and role management

Allow spaces/xxx and space/xxx when specifying chat spaces
2023-09-20 11:26:16 -07:00
Ross Scroggs
9999abe462 Update OU inheritance options 2023-09-17 16:46:31 -07:00
Ross Scroggs
d16ce28ee5 Multiple updates 2023-09-15 19:44:26 -07:00
Ross Scroggs
effa972a40 Updated print aliases|groups|group-members|users
Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`
2023-09-13 13:45:10 -07:00
Jay Lee
e998bcfde6 Python 3.12 fix for six no longer needed 2023-09-12 10:11:25 -04:00
Ross Scroggs
c9023d4792 Show actual Shared Drive names for drives in other domains 2023-09-07 21:15:08 -07:00
Ross Scroggs
c30931545f Added option showdeleted [<Boolean>]' to gam <UserTypeEntity> print|show chatmessages`.
Updated commands that call the Reports API (including `gam info domain`) to handle a change
in the Reports API that generated the following warning:
```
WARNING: End date greater than LastReportedDate.
2023-09-07 09:03:00 -07:00
Ross Scroggs
ed62abe464 Added option ou_and_children <OrgUnitItem> to gam print|show crostelemetry 2023-09-04 20:04:41 -07:00
Ross Scroggs
34e42a1076 Added option addcsvdata <FieldName> <String> to commands that print calendar acsl 2023-09-03 19:16:56 -07:00
Jay Lee
451d945095 temp show body on sso assignment for debugging purposes 2023-09-01 14:35:10 +00:00
Ross Scroggs
cfb44548ab Added commands to show the number of CrOS devices or Users in an entity.
Updated `gam create project` to prompt user to mark `GAM Project Creation` as a trusted app.
2023-08-31 13:27:49 -07:00
Ross Scroggs
c6de3de370 Updated gam create teamdrive to handle the following error:
ERROR: 403: userCannotCreateTeamDrives - The authenticated user cannot create new shared drives.
2023-08-30 08:04:01 -07:00
Ross Scroggs
59b653f92a 6.63.08 updates 2023-08-29 16:20:21 -07:00
Ross Scroggs
b509e35cd1 Updated cigroup commands to handle the following error:
ERROR: 400: invalidArgument - Request contains an invalid argument.
2023-08-29 16:19:16 -07:00
Ross Scroggs
079553e8bb Update Users-Drive-Files-Manage.md 2023-08-28 19:17:33 -07:00
Ross Scroggs
220cbbac80 Fixed bug in gam <UserTypeEntity> append sheetrange that caused a trap 2023-08-26 07:56:59 -07:00
Ross Scroggs
6993137430 Fixed bug in gam <UserTypeEntity> append sheetrange that caused a trap
Upgraded to Python 3.11.5 where possible.
2023-08-25 21:18:15 -07:00
Jay Lee
d0a378413f actions: rebuild for Python 3.11.5 2023-08-25 13:28:58 -04:00
Ross Scroggs
c314637847 Updated cigroup commands to handle the following error:
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2023-08-24 09:55:19 -07:00
Ross Scroggs
219e9ee8da Updated inboundsso commands to handle the following error:
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
2023-08-23 22:10:54 -07:00
Ross Scroggs
d47268f45c Revert "Made serviceNotAvailable retryable"
This reverts commit d5eef1faf5.
2023-08-23 21:39:23 -07:00
Ross Scroggs
d5eef1faf5 Made serviceNotAvailable retryable 2023-08-23 20:46:05 -07:00
Ross Scroggs
a7097a7310 Added option ignorerole to gam update groups|cigroups <GroupEntity> sync [<GroupRole>|ignorerole] ... <UserTypeEntity> 2023-08-23 15:43:43 -07:00
Ross Scroggs
0335ea7056 Documentation updates 2023-08-23 08:25:05 -07:00
Ross Scroggs
71777652cf Documentation updates 2023-08-22 09:55:20 -07:00
Ross Scroggs
7a91faab2b indentation cleanup 2023-08-21 16:38:40 -07:00
Ross Scroggs
ed073877a6 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-21 16:10:25 -07:00
Ross Scroggs
8a46365f51 Allow external members in chat spaces 2023-08-21 16:10:21 -07:00
Jay Lee
04fded6d94 remove failing tests 2023-08-21 18:35:35 +00:00
Jay Lee
15670fc7c4 backout urllib3 shim changes until google-auth supports urllib3 2.0+ 2023-08-21 15:02:27 +00:00
Jay Lee
cf27d4d9cc Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-21 14:22:15 +00:00
Jay Lee
48c30dc266 switch to modern urllib3 via a shim 2023-08-21 14:21:59 +00:00
Ross Scroggs
d2430323b2 Fixed bug in gam <UserTypeEntity> collect orphans where shortcuts were being created unnecessarily 2023-08-20 13:57:18 -07:00
Ross Scroggs
2a38699595 Fix bug/typo 2023-08-19 08:26:32 -07:00
Ross Scroggs
e76b71e245 Added process_wait_limit variable to gam.cfg 2023-08-18 15:40:00 -07:00
Jay Lee
92174438f6 TLS 1.2 on IAM credentials api call also 2023-08-18 19:16:33 +00:00
Jay Lee
0c85abf074 actions: allow TLS 1.2 to see if it fixes Python 3.12 2023-08-18 15:00:41 -04:00
Jay Lee
e9ea536aaf debug stepping to figure out where we die... 2023-08-18 18:49:38 +00:00
Jay Lee
d2bbbb3b73 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-18 18:44:05 +00:00
Jay Lee
6735c361a4 use TLS 1.2 with WIF and Github Actions 2023-08-18 18:43:48 +00:00
Ross Scroggs
1243ece157 Use writeStdout so redirect stdout catches data; update documentation 2023-08-18 11:37:55 -07:00
Ross Scroggs
7573013da4 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-18 10:43:16 -07:00
Ross Scroggs
b79c48718e pylint cleanup; fix broken links 2023-08-18 10:43:13 -07:00
Jay Lee
8354c63a62 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-18 17:38:04 +00:00
Jay Lee
c163d9ac46 output signjwt data for troubleshooting 2023-08-18 17:37:48 +00:00
Jay Lee
dcf63e203a actions: expect no tests to run (exit code 5) 2023-08-18 11:22:17 -04:00
Jay Lee
8fb01205ea gdata: cleanup some regex 2023-08-18 15:14:28 +00:00
Jay Lee
3e85b268a0 actions: get create contact command right (maybe) 2023-08-18 14:30:17 +00:00
Jay Lee
78d93428f2 actions: fix contacts filter 2023-08-18 14:20:25 +00:00
Jay Lee
4454e55b1e GData reduction, security recs for regex 2023-08-18 14:12:00 +00:00
Jay Lee
f1229fe8ce Set flag to honor admin console conflict account resolution setting by default 2023-08-17 12:24:40 +00:00
Ross Scroggs
09581ae654 Added support for calendar working location events. 2023-08-16 19:26:03 -07:00
Jay Lee
03fd8c296d actions: upgrade google-auth libraries to ToT for Python 3.12 2023-08-16 21:30:37 -04:00
Ross Scroggs
155c29cc55 Fix typo 2023-08-16 07:26:08 -07:00
Ross Scroggs
a017621a3d Added support for alternative output when creating contacts 2023-08-15 07:58:23 -07:00
Jay Lee
bea1c1c22d actions: reenable Python 3.12 2023-08-13 11:31:40 -04:00
Ross Scroggs
02c7628840 Wiki cleanup 2023-08-11 16:28:30 -07:00
Ross Scroggs
b5a9f302df Added output Item cap to gam <UserTypeEntity> print filecounts select select <SharedDriveEntity> 2023-08-11 13:26:50 -07:00
Jay Lee
7b62c14ce5 actions: fix rm folder 2023-08-10 19:53:10 -04:00
Ross Scroggs
c668eb5db8 Suppress browser startup on todrive 2023-08-10 16:35:22 -07:00
Jay Lee
2d53459291 actions: set explicit vault download directory and clean it up 2023-08-10 16:43:13 -04:00
Ross Scroggs
b25ca66cc6 Update Authorization.md 2023-08-10 13:26:16 -07:00
Ross Scroggs
ae4578758a Added command gam <UserTypeEntity> print diskusage to display disk usage by folder. 2023-08-10 11:06:40 -07:00
Ross Scroggs
790d38b646 Handled Google Directory API bug in gam print groups that caused a trap. 2023-08-09 15:17:55 -07:00
Ross Scroggs
cccc51283a Fixed bug introduced in 6.62.01 that caused a trap that broke redirect csv ... multiprocess. 2023-08-08 16:20:12 -07:00
Ross Scroggs
da43e5fc5b Handle csv_output_timestamp_column and output_timeformat 2023-08-07 18:51:41 -07:00
Ross Scroggs
97defccf9e Working location update (not public) 2023-08-07 14:10:29 -07:00
Ross Scroggs
2fd5d33094 Added output_dateformat and output_timeformat variables to gam.cfg 2023-08-07 12:35:36 -07:00
Ross Scroggs
c9cda88f7f Added output_dateformat and output_timeformat variables to gam.cfg 2023-08-07 12:19:10 -07:00
Ross Scroggs
5cb7299b64 Add entity items for working locations 2023-08-05 09:27:04 -07:00
Ross Scroggs
7e99c0d0a5 Use new Drive API v3 for emptying Shared Drive trash 2023-08-05 08:56:28 -07:00
Ross Scroggs
a2e5452255 Use allIncludingParent 2023-08-03 21:07:37 -07:00
Ross Scroggs
21d5dbe6e3 workingLocation cleanup (not public) 2023-08-02 16:07:59 -07:00
Ross Scroggs
e648a01d95 Appease the pylint gods 2023-08-02 14:32:08 -07:00
Jay Lee
a526d519bd catch no rapt token from gcloud. 2023-08-02 18:22:39 +00:00
Ross Scroggs
78fc9b0478 Inform user of gcloud reauth 2023-08-02 10:06:53 -07:00
Jay Lee
cd9f5b927e [no ci] actions: no need for single delete, multi-delete will cleanup $newuser 2023-08-01 18:23:16 -04:00
Jay Lee
4faf940689 actions: catch a couple common timing errors and continue 2023-08-01 17:16:29 -04:00
Jay Lee
6c956f472a catch error if gcloud is installed but not authenticated as GAM admin 2023-08-01 19:37:35 +00:00
Jay Lee
5060e05c21 actions: create shared drive early to give it time to cook 2023-08-01 12:40:08 -04:00
Ross Scroggs
128cb39d4b Merge branch 'main' of https://github.com/GAM-team/GAM 2023-08-01 07:52:57 -07:00
Ross Scroggs
0773bea679 Remove audit.googleapis.com from the list of project APIs. 2023-08-01 07:52:54 -07:00
Jay Lee
effbae9289 actions: invert gpg macos check 2023-08-01 10:32:52 -04:00
Jay Lee
f04dd95c38 actions: bump cache ver to rebuild with OpenSSL 3.1.2 2023-08-01 10:21:32 -04:00
Jay Lee
b5c400044a Update gam-install.sh 2023-08-01 09:13:14 -04:00
Ross Scroggs
3a9f294bd0 VAR_SFFT only required if Standard GAM had a signal file
enabledasa.txt for example
2023-07-31 14:34:14 -07:00
Jay Lee
1707eff9a6 handle platforms that don't support termios (#1652) 2023-07-31 17:18:45 -04:00
Jay Lee
5bc294f62e only install gpg on hosted macs 2023-07-31 17:13:37 -04:00
Jay Lee
0b927d5390 Merge 1a39e03b33 into 2705508c4d 2023-07-31 16:18:58 -04:00
Jay Lee
1a39e03b33 Merge branch 'main' into gcloud_reauth 2023-07-31 16:18:56 -04:00
Jay Lee
ffa5fd5b36 gam.cfg changes for gcloud reauth 2023-07-31 20:16:28 +00:00
Ross Scroggs
2705508c4d Make default value for enable_gcloud_reauth False 2023-07-31 12:46:49 -07:00
Ross Scroggs
748f2a9417 Add enable_gcloud_reauth to gam.cfg 2023-07-31 12:37:36 -07:00
Jay Lee
739ec52243 Merge 53866cdcbd into 750397e213 2023-07-31 18:15:51 +00:00
Jay Lee
53866cdcbd experimental gcloud reauth. Fixes #1649 2023-07-31 18:14:01 +00:00
Ross Scroggs
750397e213 Two small updates
* - Trap targetUserRoleLimitedByLicenseRestriction
* - Update print|show chatmembers, avoid GAMADV-XTD3 bug
2023-07-31 07:53:42 -07:00
Ross Scroggs
438656a549 Improved create shareddrive retries 2023-07-29 09:17:12 -07:00
Ross Scroggs
fa70d9cbed Couple of small updates 2023-07-28 15:29:19 -07:00
Jay Lee
b5f9b85324 pyinstaller spec: use $arch to determine if we need universal2 2023-07-28 09:57:12 -04:00
Jay Lee
8d5acc195c actions: goal not gaol 2023-07-28 09:17:41 -04:00
Jay Lee
cf78f4b397 actions: oh bash... 2023-07-28 09:14:51 -04:00
Jay Lee
a2cdc7ce31 actions: fix bash condition
That died quicker than I thought it would, man Bash is picky...
2023-07-28 08:44:34 -04:00
Jay Lee
c4cca8cf42 actions: self hosted arm64 runner, take 1
This will probably blow up, but the flames should look cool :-)
2023-07-28 08:39:44 -04:00
Ross Scroggs
5d03661357 Hold off on gam config 2023-07-27 14:59:09 -07:00
Ross Scroggs
fa9d167025 Added the following license SKUs.
+```
1010060005 - Google Workspace Essentials Plus
1010020031 - Google Workspace Frontline Standard
1010340005 - Google Workspace Business Starter - Archived User
1010340006 - Google Workspace Business Standard - Archived User
```
2023-07-27 14:08:23 -07:00
Ross Scroggs
01aaff9b83 Added option contentrestrictions ownerrestricted [<Boolean>] to <DriveFileAttribute>. 2023-07-27 10:00:54 -07:00
Ross Scroggs
e26cda1d6b Added option contentrestrictions ownerrestricted [<Boolean>] to <DriveFileAttribute>. 2023-07-27 09:49:30 -07:00
Jay Lee
7f9b31bcc2 actions: rename get-roots.yml to get-cacerts.yml 2023-07-26 16:37:27 -04:00
Jay Lee
08800e8152 [no ci] delete roots.pem 2023-07-26 16:05:30 -04:00
Jay Lee
6f7a93c517 [no ci] actions: cacerts.pem in releasess, not roots.pem 2023-07-26 16:04:30 -04:00
Jay Lee
9f0c288374 [no ci] actions: roots check should use cacert.pem filename 2023-07-26 16:03:16 -04:00
Jay Lee
0a49ab8474 wix: fix path for MSI source files 2023-07-26 14:48:10 -04:00
Jay Lee
40b8f02a2e [no ci] actions: spacing fix 2023-07-26 14:47:02 -04:00
Ross Scroggs
7d686b9d91 Update Reports.md 2023-07-26 08:04:47 -07:00
Jay Lee
75ebe459be actions: handle 55 return code on hold cleanup 2023-07-26 10:21:19 -04:00
Jay Lee
02c6665051 Home.md > README.md 2023-07-25 23:43:51 +00:00
Jay Lee
7a3b19b64b docs: initial commit 2023-07-25 23:38:58 +00:00
Jay Lee
7d186f2281 actions: handle 55 return code on list user holds 2023-07-25 19:17:10 -04:00
Ross Scroggs
1aa4d85161 Added aggregatebyuser [Boolean] option to gam report user to allow data aggregation for users across multiple dates. 2023-07-25 16:10:34 -07:00
Jay Lee
93ad0e7251 actions: declare some common env vars earlier 2023-07-25 15:21:14 -04:00
Jay Lee
1590b7e927 actions: use cygpath to fix GAMCFGDIR on Windows 2023-07-25 14:58:16 -04:00
Jay Lee
f9b90b4ce6 actions: remove errant quote 2023-07-25 12:13:11 -04:00
Jay Lee
9c92aa5972 update decrypt.sh to receive output folder 2023-07-25 16:08:25 +00:00
Jay Lee
d3c0da36aa actions: use GAMCFGDIR instead of ~/.gam 2023-07-25 12:02:22 -04:00
Jay Lee
374530df4e actions: actually save GAMCFGDIR 2023-07-25 11:57:23 -04:00
Jay Lee
a3adde2661 actions: disable 3.12, set GAMCFGDIR 2023-07-25 11:47:53 -04:00
Jay Lee
bf9940516d Merge branch 'main' of https://github.com/GAM-team/GAM 2023-07-25 15:46:08 +00:00
Jay Lee
09a1e09c30 [no ci] handle matters with no holds 2023-07-25 15:45:55 +00:00
Ross Scroggs
3955f0d7ae Added commands to display Analytic UA properties. 2023-07-25 08:40:06 -07:00
Jay Lee
1483559254 actions: google-auth ToT to solve Python 3.12 issues with deprecated six library 2023-07-25 11:24:02 -04:00
Ross Scroggs
f09441ac28 Simplify three gam test commands 2023-07-24 16:52:15 -07:00
Ross Scroggs
90cff02b26 Updated gam print|show vaultexports|vaultholds|vaultqueries to handle the case
where a vault matter changes state from `OPEN` to `CLOSED|DELETED` while the command is being processed.
2023-07-24 15:44:27 -07:00
Ross Scroggs
cb2228b823 Handle matters with unknown state 2023-07-24 13:56:22 -07:00
Jay Lee
e5bd3e6bc0 actions: force dasa off to start, parse created printer id 2023-07-24 16:52:52 -04:00
Jay Lee
223e017b9e actions: returnidonly belongs outside the quotes, duh 2023-07-24 16:16:52 -04:00
Jay Lee
9535d05584 actions: returnidonly on shared drive creation 2023-07-24 16:00:13 -04:00
Jay Lee
f01f050ffd actions: report users with fields seems to never find an old date that works. 2023-07-24 15:11:52 -04:00
Jay Lee
f48f486f64 actions: catch 60 return codes on message deletes 2023-07-24 14:26:25 -04:00
Jay Lee
31fa445733 actions: handle 20 return code from whatis 2023-07-24 13:59:12 -04:00
Ross Scroggs
3eea0cea08 Added option returnidonly to gam create vaultexport|vaulthold|vaultmatter 2023-07-24 08:14:35 -07:00
Jay Lee
ff6364c77b actions: noinfo on whatis command to avoid DASA license errors 2023-07-24 10:33:49 -04:00
Jay Lee
893b63c5d5 actions: capture Vault matterId output 2023-07-24 10:16:30 -04:00
Jay Lee
b1ec0b9b83 macos script: 6.48 is universal2 only 2023-07-23 21:27:43 +00:00
Jay Lee
5db66a2fb3 linux script: GAM 6.58 glibc version correction 2023-07-23 21:24:36 +00:00
Jay Lee
e233b88969 actions: DASA disabled for Vault commands 2023-07-23 14:26:33 +00:00
Jay Lee
eca4377c5a actions: add calendar domain/default ACLs instead of updating 2023-07-23 14:12:15 +00:00
Jay Lee
3c706aed5e actions: disable calendar acl deletion for now 2023-07-23 01:11:57 +00:00
Jay Lee
450bcf4e66 create a folder before listing them 2023-07-22 23:16:51 +00:00
Jay Lee
ff4568235a Python 3.12 needs lxml>4.9.2 2023-07-22 22:57:49 +00:00
Jay Lee
6f598f9e72 actions: move check serviceaccount up higher 2023-07-22 22:51:03 +00:00
Jay Lee
68d4337b15 actions: change column name in csv input also 2023-07-22 22:43:40 +00:00
Jay Lee
34b061b11c update csv filters for new syntax 2023-07-22 22:36:34 +00:00
Jay Lee
f943890cfb update creds again 2023-07-22 21:59:44 +00:00
Jay Lee
f75994f735 make decrypt.sh more verbose 2023-07-22 21:49:21 +00:00
Jay Lee
2c83b13192 use xz with creds file 2023-07-22 00:03:57 +00:00
Jay Lee
08bcd64289 try gpg again 2023-07-21 23:57:59 +00:00
Jay Lee
e81cfe9990 Merge branch 'main' of https://github.com/GAM-team/GAM 2023-07-21 23:53:52 +00:00
Jay Lee
5bc80eba6a update credentials with GAM7 format 2023-07-21 23:53:31 +00:00
Ross Scroggs
727a100f81 Fix bug in gam oauth create 2023-07-21 13:51:19 -07:00
Ross Scroggs
23204e545b Merge branch 'main' of https://github.com/GAM-team/GAM 2023-07-21 12:50:50 -07:00
Ross Scroggs
639a9152c2 6.61.08 and 6.61.09 changes 2023-07-21 12:50:30 -07:00
Jay Lee
ffbe879062 change order of oauth commands 2023-07-21 19:48:14 +00:00
Jay Lee
f233b13e51 more build fixes 2023-07-21 19:44:55 +00:00
Jay Lee
dbe2e22511 1st attempt fix live tests 2023-07-21 19:39:41 +00:00
Jay Lee
b998ef860b Update build.yml 2023-07-21 15:24:51 -04:00
Jay Lee
e29327a0d9 Update decrypt.sh 2023-07-21 15:13:08 -04:00
Jay Lee
c94cf22fcc Merge branch 'main' of https://github.com/GAM-team/GAM 2023-07-21 18:52:45 +00:00
Jay Lee
07ad008f3d spec fixes for the big merge 2023-07-21 18:52:32 +00:00
Jay Lee
9fa282d18e install libxslt package on Linux 2023-07-21 14:34:06 -04:00
Jay Lee
84ec84f4ac roots.pem > cacerts.pem for actions 2023-07-21 14:30:25 -04:00
GitHub Action
1475fd50ba [ci skip] Updated roots.pem 2023-07-21 18:28:12 +00:00
Jay Lee
03917fb70b GAM version merge (kaa-boom) 2023-07-21 18:24:45 +00:00
Ross Scroggs
3046cbf3b9 Support singleEvents in calendar printevents (#1639) 2023-07-05 10:23:10 -04:00
Jay Lee
74fc224a84 Update build.yml 2023-06-09 21:35:14 -04:00
Jay Lee
0ea88630e2 undo collect_all for cryptography, did not solve win32 2023-06-08 16:52:23 -04:00
Jay Lee
f1f351a8c0 Update gam.spec 2023-06-08 15:58:02 -04:00
Jay Lee
5f85bec1ec Update gam.spec 2023-06-08 15:49:11 -04:00
Jay Lee
c498067e75 Update gam.spec 2023-06-08 15:46:56 -04:00
Jay Lee
25c4bba3fa Update gam.spec 2023-06-08 14:28:49 -04:00
Jay Lee
034e8faaf4 collect everything for cryptography 2023-06-08 14:26:01 -04:00
Jay Lee
9db0bdedb1 [skip ci] undo collect-all, remove gcp 2023-06-08 14:20:06 -04:00
Jay Lee
48117a6894 Update build.yml 2023-06-08 14:14:42 -04:00
Jay Lee
3cd890a1f5 [skip ci] PyInstaller cherry pick no longer after 5.12.0 release 2023-06-08 08:17:14 -04:00
Jay Lee
dddbb0ed8f Cherry pick pyinstaller fix for Python 3.11.4 2023-06-08 07:42:30 -04:00
Jay Lee
5d4f672411 [skip ci] 3.12 beta 2023-06-07 18:15:25 -04:00
Jay Lee
9c3a0964b6 test pin to python 3.11.3 2023-06-07 17:51:21 -04:00
Jay Lee
5f0774a84f [skip ci] undo ipaddress hidden import 2023-06-07 17:49:49 -04:00
Jay Lee
e560b80611 Update gam.spec 2023-06-07 16:57:32 -04:00
Jay Lee
4da6fad049 rebuild for Python 3.11.4 2023-06-07 15:55:10 -04:00
Ross Scroggs
8f76d94b86 Correct namespace capitalization (#1631) 2023-06-07 07:31:22 -04:00
Jay Lee
a28bce71df Rebuild for OpenSSL 3.1.1 2023-05-30 09:34:36 -04:00
Jay Lee
eed55490ef re-add ACM API 2023-05-19 09:38:32 -04:00
Jay Lee
b1c7685afe remove accesscontextmanager API for time being... 2023-05-19 07:40:49 -04:00
Jay Lee
4d79e9de4f 6.58, workaround for #1625 2023-04-26 12:42:13 +00:00
Jay Lee
1ae54db7de fix pageSize 2023-04-19 14:42:00 +00:00
Jay Lee
6d63df24a3 revert 1hr workaround. Fixes #1534 2023-04-19 14:39:59 +00:00
Jay Lee
85dd32e0ce Update build.yml 2023-04-17 08:17:43 -04:00
Jay Lee
28e418ff23 Update build.yml 2023-04-16 09:05:31 -04:00
Jay Lee
4eb89b187f Update build.yml 2023-04-14 19:43:41 -04:00
Jay Lee
c5734beef6 Update var.py 2023-04-14 18:53:52 -04:00
Jay Lee
f4735ebd80 Update build.yml 2023-04-14 16:07:45 -04:00
Jay Lee
43ae6a4a37 Update build.yml 2023-04-14 15:55:36 -04:00
Jay Lee
f362f58f95 fi 2023-04-14 18:42:59 +00:00
Jay Lee
6d211264fc Support delegated admin role assignments to groups 2023-04-14 18:35:44 +00:00
Jay Lee
3d919f5df6 fix legacy linux package name 2023-04-14 18:09:04 +00:00
Jay Lee
f9d5f9852a Update gam.spec 2023-04-12 16:49:14 -04:00
Jay Lee
0e79035765 Update build.yml 2023-04-12 16:38:59 -04:00
Jay Lee
d5cf38eaca single static list of libs 2023-04-12 14:56:31 +00:00
Jay Lee
1cfa14d8d2 only copy metadata for imports that exist 2023-04-12 14:38:24 +00:00
Jay Lee
bf5a50eb2a copy_metadata for all reqs. Fixes "gam version extended" dep outputs 2023-04-12 14:23:31 +00:00
Jay Lee
f296579aad Update transport.py 2023-04-11 10:43:21 -04:00
Jay Lee
16bb53d0e4 Update var.py 2023-04-11 09:54:43 -04:00
Jay Lee
b6e2549436 Update build.yml 2023-04-11 09:11:53 -04:00
Jay Lee
0814173210 [no ci] use default Vault export format 2023-04-11 08:18:33 -04:00
Jay Lee
375ffada5c Update build.yml 2023-04-11 08:02:52 -04:00
Jay Lee
ae37de0dd2 Update build.yml 2023-04-10 16:22:59 -04:00
Jay Lee
ce4b4771db Update build.yml 2023-04-10 15:10:20 -04:00
Jay Lee
56c61ac723 Update build.yml 2023-04-10 13:32:21 -04:00
Jay Lee
9900dd64b8 prepare 6.55 2023-04-10 17:14:36 +00:00
Jay Lee
53400b6322 Update __init__.py 2023-04-10 12:20:22 -04:00
Jay Lee
47537ab30a Update signjwt.py 2023-04-10 12:18:56 -04:00
Jay Lee
6a3692d7f4 catch signjwt refresh error on create 2023-04-10 10:21:59 -04:00
Jay Lee
eef2b95948 Only run publish on new tag starting with v 2023-04-07 09:49:02 -04:00
Jay Lee
7012bef28d package and test staticx builds as part of normal flow 2023-04-06 13:27:51 -04:00
Jay Lee
b3b44d144e GAM 6.54 2023-04-06 12:44:30 -04:00
Jay Lee
841eba79a3 Update build.yml 2023-04-06 11:02:55 -04:00
Jay Lee
77234f9e3d Update build.yml 2023-04-06 09:59:53 -04:00
Jay Lee
14478d7831 Update build.yml 2023-04-06 09:07:32 -04:00
Jay Lee
50aa7d937e Update build.yml 2023-04-06 08:07:05 -04:00
Jay Lee
2c7e01e003 Update build.yml 2023-04-06 07:01:35 -04:00
Jay Lee
a6ce5f04aa Update build.yml 2023-04-06 05:37:24 -04:00
Jay Lee
8bc6814b42 Use TLS 1.2 for SignJWT 2023-04-06 09:36:23 +00:00
Jay Lee
024177b0c7 Update __main__.py 2023-04-06 05:18:05 -04:00
Jay Lee
b7faa0acae Update build.yml 2023-04-06 05:15:35 -04:00
Ross Scroggs
0dbdbc7a13 Two updates (#1618)
* Update documentation: gam delete inboundssoassignment <SSOAssignmentSelector>

* tsv is a valid Google Doc extension
2023-04-06 05:13:50 -04:00
Jay Lee
08271e60bf Update __init__.py 2023-04-06 05:05:08 -04:00
Jay Lee
ec74698001 Update build.yml 2023-04-06 04:23:28 -04:00
Jay Lee
6cecacd334 Update __init__.py 2023-04-05 20:27:35 -04:00
Jay Lee
c3d27900e1 Update __main__.py 2023-04-05 20:16:10 -04:00
Jay Lee
f10df3607f Update __init__.py 2023-04-05 20:01:49 -04:00
Jay Lee
416be24722 Update build.yml 2023-04-05 14:55:21 -04:00
Jay Lee
e53b4a2285 backout retries 2023-04-05 18:51:03 +00:00
Jay Lee
a88320b1b2 backout sign change 2023-04-05 18:48:47 +00:00
Jay Lee
76f9a144ac debug network issues 2023-04-05 18:41:20 +00:00
Jay Lee
a673772cc1 add request to createsignjwtserviceaccount 2023-04-05 18:36:17 +00:00
Jay Lee
9e6d8195eb scope is a list, not str 2023-04-05 18:26:04 +00:00
Jay Lee
91d97c4a2c Merge branch 'main' of https://github.com/GAM-team/GAM 2023-04-05 17:18:22 +00:00
Jay Lee
5e1df9263b use transport and bump retries 2023-04-05 17:18:10 +00:00
Jay Lee
e54921ad71 rebuild for Python 3.11.3 2023-04-05 10:49:09 -04:00
Jay Lee
1b8d0877f3 retire soon-to-be EoL Python 3.7. Hello walrus operator... 2023-04-05 14:33:17 +00:00
Jay Lee
a4e962560c Update build.yml 2023-04-05 08:48:29 -04:00
Jay Lee
be7d3ceb15 [no ci] make cigroup a security group 2023-04-05 08:36:55 -04:00
Jay Lee
1e652d5725 Update build.yml 2023-04-05 08:28:50 -04:00
Jay Lee
1e7e5422be sso v1 and delete assignments 2023-04-05 12:27:28 +00:00
Jay Lee
723e9e2bb1 Update build.yml 2023-04-04 14:20:05 -04:00
Jay Lee
1f572cc95b Update build.yml 2023-04-04 14:13:19 -04:00
Jay Lee
fb63eea4a0 Update build.yml 2023-04-04 12:50:18 -04:00
Jay Lee
7efb37010d Update build.yml 2023-04-04 12:47:46 -04:00
Jay Lee
6372af8d8a Update build.yml 2023-04-04 12:18:35 -04:00
Jay Lee
0b823ea43e Update build.yml 2023-04-04 12:15:24 -04:00
Jay Lee
cebb92199f Update build.yml 2023-04-04 12:12:42 -04:00
Jay Lee
6deabf8a66 Update build.yml 2023-04-04 12:10:55 -04:00
Jay Lee
5de74a51e0 Update build.yml 2023-04-04 12:02:11 -04:00
Jay Lee
85d6305874 Update build.yml 2023-04-04 11:57:30 -04:00
Jay Lee
30d685a6f7 Update build.yml 2023-04-04 11:54:42 -04:00
Jay Lee
fcc8a58839 Update build.yml 2023-04-04 11:26:26 -04:00
Jay Lee
5a608a9b62 Update build.yml 2023-04-04 11:19:04 -04:00
Jay Lee
eb9c127a10 Update build.yml 2023-04-03 12:46:49 -04:00
Jay Lee
ed55690ff3 Update build.yml 2023-04-03 12:30:45 -04:00
Jay Lee
502afa5213 Update __init__.py 2023-04-03 12:13:34 -04:00
Jay Lee
24185d66ce Update cbcm-v1.1beta1.json 2023-04-03 11:55:41 -04:00
Jay Lee
181ba65c63 Update build.yml 2023-04-03 11:13:01 -04:00
Jay Lee
702f36a529 Update build.yml 2023-04-03 11:06:52 -04:00
Jay Lee
e2f73bf858 Update build.yml 2023-04-03 09:37:47 -04:00
Jay Lee
7265e8c6f4 Update build.yml 2023-04-03 09:26:12 -04:00
Jay Lee
b8b9808e94 Update build.yml 2023-04-03 09:02:34 -04:00
Jay Lee
7639773c40 Update build.yml 2023-04-03 08:52:54 -04:00
Jay Lee
6ab7370149 Update build.yml 2023-04-03 08:47:58 -04:00
Jay Lee
73994fe603 Update build.yml 2023-04-03 08:39:56 -04:00
Jay Lee
3fa646723d Update build.yml 2023-04-03 08:31:36 -04:00
Jay Lee
eb08b1fbdc Update build.yml 2023-04-03 08:11:44 -04:00
Jay Lee
93ac820005 Update build.yml 2023-04-03 08:03:49 -04:00
Jay Lee
c100e25ab9 Update build.yml 2023-04-03 08:01:09 -04:00
Jay Lee
716489ceed key_type is a GAMism, use type to identify SA file. 2023-04-03 08:00:12 -04:00
Jay Lee
07d5f5e52c Update build.yml 2023-04-02 17:00:18 -04:00
Jay Lee
b889debd5e Update build.yml 2023-04-02 16:57:04 -04:00
Jay Lee
b273fe1f68 Update build.yml 2023-04-02 16:54:56 -04:00
Jay Lee
376cd6e83f Update signjwt.py 2023-04-02 15:58:04 -04:00
Jay Lee
e8cb1a7b9f Update __init__.py 2023-04-02 15:53:17 -04:00
Jay Lee
9f0c5beae7 Update __init__.py 2023-04-02 15:49:02 -04:00
Jay Lee
0ea2f16322 Update build.yml 2023-04-02 15:08:49 -04:00
Jay Lee
13ca2e8d93 Update build.yml 2023-04-02 15:03:27 -04:00
Jay Lee
3833256c8c Update build.yml 2023-04-02 14:40:50 -04:00
Jay Lee
30521612b2 fix permissions 2023-04-02 14:34:56 -04:00
Jay Lee
d069cfc309 Use WIF for service account credentials 2023-04-02 14:33:15 -04:00
Jay Lee
27461b067a Update var.py 2023-03-31 09:17:10 -04:00
Jay Lee
017712742b Merge branch 'main' of https://github.com/GAM-team/GAM 2023-03-30 17:37:23 +00:00
Jay Lee
afce21a1bd Add steps to trust GAM client_ID 2023-03-30 17:34:59 +00:00
Jay Lee
030e2e270f Another attempt at fixing cryptography 2023-03-30 10:14:24 -04:00
Jay Lee
c69a86b535 use constraints.txt to prevent any downgrades during pip install 2023-03-28 08:49:03 -04:00
Jay Lee
b64e4cf3dc [no ci] that didn't work, we'll try rolling forward... 2023-03-28 08:43:57 -04:00
Jay Lee
a2e06adbbe pin cryptography to 39.0.2 for time being 2023-03-28 08:21:46 -04:00
Jay Lee
43b3397541 Rebuild for cryptography 2023-03-25 10:00:29 -04:00
Jay Lee
bd0bb1542c AppSheet licenses 2023-03-22 12:54:27 +00:00
Jay Lee
a92a07f9c0 Update var.py 2023-03-16 12:35:11 -04:00
Ross Scroggs
42ed5509ee Updates/cleanup (#1614)
* Handle socks error when checking local time offset

* Keep pylint happy

* Avoid trap when authentication flow blows up

* Fix bug that causes trap on create project
2023-03-16 12:31:20 -04:00
Jay Lee
a6582503f2 Update var.py 2023-03-15 18:31:35 -04:00
Jay Lee
7aecb889d2 Allow setting sakey validity_hours 2023-03-15 20:41:25 +00:00
Jay Lee
c273f87cc7 clear cache to pickup OpenSSL 3.1.0 2023-03-14 10:08:02 -04:00
Jay Lee
76d00c993a Update build.yml 2023-03-06 10:13:17 -05:00
Jay Lee
013b47e6e7 Update build.yml 2023-03-06 09:43:50 -05:00
Jay Lee
9f1e9934ff Update build.yml 2023-03-06 09:29:08 -05:00
Jay Lee
48b218bd9c Update build.yml 2023-03-06 08:40:59 -05:00
Jay Lee
af5baa4f3a Update build.yml 2023-03-06 08:37:37 -05:00
Jay Lee
a2cf38d904 Update build.yml 2023-03-06 07:40:01 -05:00
Jay Lee
185522d943 Update build.yml 2023-03-05 15:29:27 -05:00
Jay Lee
a42e4dd080 openssl security level 2 2023-03-05 15:28:02 -05:00
Ross Scroggs
3a5486889f Update chromepolicy.py (#1610)
split of an empty string returns [''], the API wants []
2023-03-04 11:33:22 -05:00
Jay Lee
1a1f100902 completely disalbe TLS 1.0/1.1 2023-03-03 07:09:46 -05:00
Ross Scroggs
c67b214298 Allow user to optionally specify serial number on resetpiv (#1607) 2023-02-27 11:17:20 -05:00
Ross Scroggs
3ad1d5c661 Give error on invalid subargument; handle no YubiKeys in resetpiv (#1606) 2023-02-27 10:37:22 -05:00
Jay Lee
13400d9bde Update build.yml 2023-02-24 14:20:37 -05:00
Ross Scroggs
048e8dfef5 Add gam version checkrc (#1605)
* Add gam version checkrc

* Fix code

* gam version checkrc cleanup
2023-02-24 10:58:23 -05:00
Ross Scroggs
aaf7a89192 Fix documenataion error (#1604) 2023-02-24 09:45:22 -05:00
Jay Lee
e3ee9135ff Update build.yml 2023-02-23 16:30:23 -05:00
Ross Scroggs
a774fc0beb GCP cleanup (#1602) 2023-02-23 11:44:52 -05:00
Jay Lee
f3429bd537 Update build.yml 2023-02-23 08:50:03 -05:00
Jay Lee
37876acfda Update var.py 2023-02-23 08:17:22 -05:00
Jay Lee
2a6dd0d1a2 fix building iamcredentials 2023-02-22 17:30:10 +00:00
Jay Lee
b0626dd37a improve on gam enable apis 2023-02-17 22:07:36 +00:00
Jay Lee
ed0ed8d7fc fix Id 2023-02-17 20:33:47 +00:00
Jay Lee
d67d999930 enable APIs command for signjwt 2023-02-17 20:32:29 +00:00
Jay Lee
ac79cff6b9 create signjwtserviceaccount 2023-02-17 19:39:02 +00:00
Jay Lee
50aadc6ea7 allow forcing OAuth for service account 2023-02-17 15:40:36 +00:00
Jay Lee
9036d114ed signjwt key_type for key-less service account auth 2023-02-17 15:17:01 +00:00
Jay Lee
75c19104ae fix ipv6 with checkconn 2023-02-15 17:22:34 +00:00
Jay Lee
d9b7f88287 6.42 - build shared drive restrictions dynamically 2023-02-13 21:51:41 +00:00
Jay Lee
ae28c09560 6.41 - fixes #1600 2023-02-11 13:40:59 +00:00
Jay Lee
6ffc738a51 Update gam-install.sh 2023-02-11 08:12:35 -05:00
Jay Lee
82dcc4de6a rebuild to get Python 3.11.2 2023-02-08 10:35:58 -05:00
Jay Lee
f7a426f65a rebuild for OpenSSL 3.0.8 2023-02-07 12:25:31 -05:00
Jay Lee
a94ef78066 fix Vault download filenames 2023-02-06 21:43:33 +00:00
Ross Scroggs
62d738f5c2 copy storagebucket/vault cleanup (#1599) 2023-02-06 15:50:39 -05:00
Jay Lee
1c56a0a608 Update var.py 2023-02-06 09:57:47 -05:00
Jay Lee
dc3976bdda gam copy vaultexport/storagebucket commands 2023-02-06 13:33:26 +00:00
Ross Scroggs
454778b190 print chromeaues/chromeversions cleanup, add print chromeneedsattn (#1598)
* print chromeaues/chromeversions cleanup, add print chromeneedsattn

* Fix typo

* Define new ChromeOS fields
2023-02-03 14:10:35 -05:00
Ross Scroggs
5e78c93b71 Added gam print chromeaues (#1597) 2023-01-30 19:42:28 -05:00
Jay Lee
3aefe21f16 Update build.yml 2023-01-13 11:54:03 -05:00
Jay Lee
0fc7958ccc Update build.yml 2023-01-13 11:14:35 -05:00
Jay Lee
13dc4e74c9 Update build.yml 2023-01-12 11:11:07 -05:00
Jay Lee
a17fa16841 Update var.py 2022-12-28 19:08:01 -05:00
Jay Lee
b13757f5d3 Update var.py 2022-12-28 18:49:37 -05:00
Jay Lee
b9df6f4762 Assured controls SKU 2022-12-28 18:44:20 -05:00
Jay Lee
b7d1c62486 [no ci] let other jobs keep building 2022-12-24 14:29:36 -05:00
Jay Lee
90e5f1b665 use search endpoint when cigroup query is specified 2022-12-18 17:19:39 +00:00
Jay Lee
3132fd7783 another fix for show holds 2022-12-17 23:10:58 +00:00
Jay Lee
87808902e6 cat and allow closed matters on show holds 2022-12-17 22:56:12 +00:00
Jay Lee
fb33d8186e fix Win64 PyInstaller 2022-12-17 18:10:53 +00:00
Jay Lee
8bd2e7f879 Upgrade yubkey for 5.0 release. Fixes #1587 2022-12-17 16:28:41 +00:00
Jay Lee
e66744e3f1 Update build.yml 2022-12-07 10:24:14 -05:00
Ross Scroggs
85f2979313 Fix Chrome schema enum processing (#1582)
Prefix should not include anything after ENUM_
```
        name: RollbackToTargetVersionEnum
          value:
            name: ROLLBACK_TO_TARGET_VERSION_ENUM_ROLLBACK_DISABLED
              number: 1
            name: ROLLBACK_TO_TARGET_VERSION_ENUM_ROLLBACK_AND_RESTORE_IF_POSSIBLE
              number: 3
```
2022-12-02 21:51:39 -05:00
Jay Lee
a85ee9b108 Update build.yml 2022-12-02 12:20:18 -05:00
Jay Lee
9ab2f38436 Update build.yml 2022-12-02 09:57:21 -05:00
Jay Lee
5bcdca4fcc Update build.yml 2022-12-02 09:48:53 -05:00
Jay Lee
729edb65be Ubuntu 20.04 so less users need legacy build 2022-12-01 16:25:38 -05:00
Jay Lee
db8afb769b Update build.yml 2022-12-01 14:09:56 -05:00
Jay Lee
7dfc93892c Update build.yml 2022-12-01 13:47:09 -05:00
Jay Lee
d278cb6939 Update build.yml 2022-12-01 13:14:59 -05:00
Jay Lee
bced5172d2 single spec for one file/folder 2022-12-01 18:05:55 +00:00
Jay Lee
bb5beb66a7 Update build.yml 2022-12-01 12:09:56 -05:00
Jay Lee
f849b6ddb7 --noconfirm to overwrite existing gam folder 2022-11-30 21:12:41 +00:00
Jay Lee
d2733a53a2 fix gampath 2022-11-30 21:04:36 +00:00
Jay Lee
1b1ae44f5d Merge branch 'main' of github.com:GAM-team/GAM 2022-11-30 20:51:53 +00:00
Jay Lee
8515dc2616 Switch to PyInstaller onedir for better performance 2022-11-30 20:51:31 +00:00
Jay Lee
ba7a8d8937 Update build.yml 2022-11-30 09:51:49 -05:00
Jay Lee
d543fb9917 Update build.yml 2022-11-30 09:16:22 -05:00
Ross Scroggs
f4d390b77b Use returnnameonly, it's like returnidonly in create drivefile (#1579)
* Document nameonly in create/update inboundssoprofile

* Use returnnameonly, it's like returnidonly in create drivefile
2022-11-30 09:15:36 -05:00
Jay Lee
ffbce1fd25 no ~~ 2022-11-29 15:01:55 +00:00
Jay Lee
2d78ec6edd merge 2022-11-29 14:48:07 +00:00
Jay Lee
9cacdd166f name_only argument for ssoprofile 2022-11-29 14:43:25 +00:00
Ross Scroggs
9af0a5d843 Code fix, consistency preference (#1578)
* Code fix, consistency preference

* Code cleanup

* Code cleanup for sso assignments

* Fix typo

* Shorten lines
2022-11-22 07:08:15 -05:00
Jay Lee
3313295532 Test with user displayname 2022-11-21 23:50:30 +00:00
Jay Lee
fdf6c147dc fix temperature in chrome telemetry 2022-11-21 23:30:21 +00:00
Jay Lee
323dbd5ca9 Allow setting displayName for users 2022-11-21 23:21:45 +00:00
Jay Lee
d01fd74fa3 merge 2022-11-18 16:08:13 +00:00
Jay Lee
8c33b88e3e Inbound SSO improvements 2022-11-18 16:06:14 +00:00
Jay Lee
5d11397fca Update build.yml 2022-11-16 16:05:11 -05:00
Jay Lee
995321978f Update build.yml 2022-11-16 15:58:56 -05:00
Jay Lee
448789dad0 Update build.yml 2022-11-16 15:39:41 -05:00
Jay Lee
e9ba6819ba Update vault.py 2022-11-16 15:31:07 -05:00
Jay Lee
3056c7b803 Update vault.py 2022-11-16 15:23:53 -05:00
Jay Lee
f2c28fd1f7 Update vault.py 2022-11-16 15:20:49 -05:00
Jay Lee
11e4ff1eb5 Update __init__.py 2022-11-16 15:03:23 -05:00
Jay Lee
81cd74c244 Update build.yml 2022-11-16 13:08:44 -05:00
Jay Lee
faade7c057 Update build.yml 2022-11-16 12:47:49 -05:00
Jay Lee
0032066e1d Update build.yml 2022-11-16 12:33:17 -05:00
Jay Lee
dd938baced Update build.yml 2022-11-16 12:12:01 -05:00
Jay Lee
b835b6ee36 Update build.yml 2022-11-16 11:04:06 -05:00
Jay Lee
3660d65df6 Update build.yml 2022-11-16 10:52:19 -05:00
Ross Scroggs
3e0b4125e0 Code fixup (#1577) 2022-11-16 09:30:17 -05:00
Ross Scroggs
9820a3d81e Inbound SSO documentation; org is synonym for ou and orgunit (#1576)
Are `gam info inboundssoassignment` and `gam delete inboundssoassignment` coming?

Is `gam info inboundssocredentials` coming?
2022-11-15 07:07:04 -05:00
Jay Lee
b670a4cee6 Update build.yml 2022-11-14 21:40:53 -05:00
Jay Lee
a5dd5275c8 Update build.yml 2022-11-14 20:57:35 -05:00
Jay Lee
9b6ad2fa60 prepare 6.31 2022-11-15 01:32:22 +00:00
Jay Lee
1d80028c93 Update build.yml 2022-11-14 20:21:38 -05:00
Jay Lee
a013e95fcf Windows actions doesn\'t like an argument that has / as first char 2022-11-15 00:40:43 +00:00
Jay Lee
eb4d6ece3f Update build.yml 2022-11-14 18:53:37 -05:00
Jay Lee
a50d1ef456 new credentials with inbound sso scope 2022-11-14 17:50:38 -05:00
Jay Lee
c179ed732c login and logout, not signin signout 2022-11-14 21:21:32 +00:00
Jay Lee
a85a313ebb Merge branch 'main' of github.com:GAM-team/GAM 2022-11-14 21:10:11 +00:00
Jay Lee
534ccd275d remove / that seems to break Github Actions 2022-11-14 21:09:59 +00:00
Ross Scroggs
3c3d043276 Sort fields in info group, allow gal as an alias for includeinglobaladdresslist (#1575) 2022-11-14 16:09:28 -05:00
Jay Lee
786adb7c44 remove debug 2022-11-14 21:03:00 +00:00
Jay Lee
bb6c8dc225 more debug for orgunits on windows 2022-11-14 20:49:30 +00:00
Jay Lee
a7cd88b2be Merge branch 'main' of github.com:GAM-team/GAM 2022-11-14 20:32:01 +00:00
Jay Lee
a9fad337e2 debug ou create body 2022-11-14 20:31:48 +00:00
Jay Lee
d4dc1b1589 Update build.yml 2022-11-14 15:19:36 -05:00
Jay Lee
ad94adbb53 more actions 2022-11-14 20:12:21 +00:00
Jay Lee
b692799dcb bash quote fixes 2022-11-14 19:54:31 +00:00
Jay Lee
04dcf47746 rollback shelve (leave lowmem framework) 2022-11-14 19:40:36 +00:00
Jay Lee
aebb3c44fe quick fixes 2022-11-14 19:31:16 +00:00
Jay Lee
8cf345196a Inbound SSO API first take 2022-11-14 19:23:37 +00:00
Jay Lee
173fdb2297 Merge branch 'main' of github.com:GAM-team/GAM 2022-11-02 12:26:57 +00:00
Jay Lee
120db6e7d8 Updated Actions creds 2022-11-02 12:23:01 +00:00
Jay Lee
55555506be Update decrypt.sh 2022-11-01 16:32:15 -04:00
Jay Lee
41965e962d rebuild to pickup OpenSSL 3.0.7 2022-11-01 14:39:36 -04:00
Jay Lee
30fdd00d65 GAM 6.30
To be released soon after OpenSSL 3.0.7...
2022-11-01 07:54:38 -04:00
Ross Scroggs
37e3fd904d Rework getting local-Google time offset (#1572) 2022-10-30 08:22:58 -04:00
Jay Lee
dc22b024b8 Try disabling check hostname on time checks 2022-10-29 11:21:00 -04:00
Jay Lee
f412d5ad4c Update build.yml 2022-10-29 10:12:33 -04:00
Jay Lee
24cfe807e6 Update build.yml 2022-10-28 09:35:42 -04:00
Jay Lee
6a721ac2c1 [no ci] 2022-10-28 09:25:08 -04:00
Jay Lee
4a4b22dfba Update build.yml 2022-10-28 08:30:26 -04:00
Ross Scroggs
6d4524c153 Update var.py (#1571) 2022-10-26 17:36:53 -04:00
Jay Lee
d7b2f82a4a Update build.yml 2022-10-26 11:39:32 -04:00
Jay Lee
844a2fe1e8 Update build.yml 2022-10-26 10:03:44 -04:00
Jay Lee
baf822c685 Update build.yml 2022-10-26 09:59:32 -04:00
Jay Lee
f3169a631c Update build.yml 2022-10-26 08:44:31 -04:00
Jay Lee
d171db36bc Update build.yml 2022-10-26 08:40:01 -04:00
Jay Lee
34c7576cd5 Update build.yml 2022-10-26 08:01:21 -04:00
Jay Lee
f859d0678b Update build.yml 2022-10-25 20:19:09 -04:00
Jay Lee
0986cb3fd9 Update build.yml 2022-10-25 19:17:16 -04:00
Jay Lee
645fd9a135 Update build.yml 2022-10-25 10:15:20 -04:00
Jay Lee
9582e6840a Update build.yml 2022-10-24 18:07:32 -04:00
Jay Lee
a8a9cfb2ab Update build.yml 2022-10-24 18:03:11 -04:00
Jay Lee
5519b33a08 Update build.yml 2022-10-24 17:54:55 -04:00
Jay Lee
976ef0252e Update build.yml 2022-10-24 17:52:13 -04:00
Jay Lee
e6829d0804 Update build.yml 2022-10-24 16:51:58 -04:00
Jay Lee
9f985a7b26 Update build.yml 2022-10-17 15:30:26 -04:00
Jay Lee
a628aeb1a8 Update build.yml 2022-10-17 14:54:35 -04:00
Jay Lee
d81c80b150 Update build.yml 2022-10-17 13:56:42 -04:00
Jay Lee
63ee016691 Update build.yml 2022-10-17 13:51:45 -04:00
Ross Scroggs
4935385572 Pass lock (l) not one (1) to initargs (#1567) 2022-10-17 09:08:42 -04:00
Jay Lee
30069d3039 Update build.yml 2022-10-12 12:00:07 -04:00
Jay Lee
3ef8a5a762 Update var.py 2022-10-12 08:10:38 -04:00
Jay Lee
b12fda5007 Update build.yml 2022-10-11 17:15:03 -04:00
Jay Lee
26925c30c1 Update build.yml 2022-10-07 11:40:59 -04:00
Jay Lee
4085816fa3 Update build.yml 2022-10-07 10:52:12 -04:00
Jay Lee
7e36e5abe6 Update build.yml 2022-10-07 10:23:26 -04:00
Jay Lee
2037189148 Update build.yml 2022-10-07 08:13:43 -04:00
Jay Lee
c7781e66e1 Update build.yml 2022-10-06 22:18:30 -04:00
Jay Lee
8843675ad4 leave Homebrew in place 2022-10-06 22:47:35 +00:00
Jay Lee
c05a1ea6b4 Honor nobrowser.txt on auth 2022-10-06 22:36:25 +00:00
Jay Lee
d9a5ac849b try again with new creds 2022-10-06 17:45:05 +00:00
Jay Lee
51d4c29dd5 update creds 2022-10-06 17:38:01 +00:00
Jay Lee
c2bb9cbdaf Catch revoke and throw nicer error 2022-10-05 17:09:39 +00:00
Lewis Lebentz
d185765831 Add Frontline Worker alias (#1566) 2022-10-05 12:40:53 -04:00
Jay Lee
f57f311f16 Update build.yml 2022-09-27 07:07:21 -04:00
Jay Lee
4c81849c60 Update build.yml 2022-09-26 16:28:42 -04:00
Jay Lee
156c8319d9 Update build.yml 2022-09-26 14:20:54 -04:00
Jay Lee
b8de3310d0 Update build.yml 2022-09-26 13:53:29 -04:00
Jay Lee
f28cf664cb Update build.yml 2022-09-26 13:46:14 -04:00
Jay Lee
02b876155a Allow 'info domain' for delegate admins 2022-09-15 20:03:03 +00:00
Jay Lee
97bd1f71c3 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-09-15 14:46:53 +00:00
Jay Lee
8be4445f0d Fix crm org retrieval 2022-09-15 14:45:02 +00:00
Jay Lee
550cf47db4 Update reports.py 2022-09-15 10:22:29 -04:00
Jay Lee
05d32eec08 Update __init__.py 2022-09-14 19:17:04 -04:00
Jay Lee
59c181eeda Update __init__.py 2022-09-14 19:07:58 -04:00
Jay Lee
dd5fd2a2c3 Update __init__.py 2022-09-14 18:02:59 -04:00
Jay Lee
6ab8fbf538 test with lowmemory.txt 2022-09-14 17:49:40 -04:00
Jay Lee
509919da84 Reduce memory with shelve. Fixes #1560 2022-09-14 18:55:17 +00:00
Jay Lee
04bd5f36a0 Update build.yml 2022-09-07 10:17:17 -04:00
Jay Lee
801f5b7861 Update build.yml 2022-09-06 16:50:18 -04:00
Jay Lee
09d86e1220 Update build.yml 2022-09-02 17:13:40 -04:00
Jay Lee
6110aa1d32 Update build.yml 2022-09-02 16:41:25 -04:00
Jay Lee
11e6c80dbf Update build.yml 2022-09-02 16:31:42 -04:00
Jay Lee
1f32536ff7 Update build.yml 2022-09-02 12:15:07 -04:00
Jay Lee
7979206f21 Update build.yml 2022-09-02 09:45:10 -04:00
Jay Lee
f7901790ad Update build.yml 2022-09-02 09:44:16 -04:00
Jay Lee
7fae16f962 Update build.yml 2022-09-01 14:56:23 -04:00
Jay Lee
1dd76012f8 Update __init__.py 2022-09-01 14:34:55 -04:00
Jay Lee
8fd3f4ee7d Update setup.cfg 2022-08-31 16:27:21 -04:00
Jay Lee
e30b8ed53e Update setup.cfg 2022-08-31 16:26:06 -04:00
Jay Lee
e0960d9113 Update setup.cfg 2022-08-31 16:16:55 -04:00
Jay Lee
35dda1cd34 Update setup.cfg 2022-08-31 15:56:59 -04:00
Jay Lee
ef2253fe58 Update setup.cfg 2022-08-31 15:52:57 -04:00
Jay Lee
ecea3aed7e [no ci] 6.25 2022-08-31 15:52:22 -04:00
Jay Lee
2e81cae271 add roots.pem to MSI 2022-08-31 15:44:06 -04:00
Jay Lee
080eede356 Update devices.py 2022-08-31 14:10:22 -04:00
Jay Lee
fe37c687e4 Update build.yml 2022-08-31 11:59:10 -04:00
Jay Lee
27efef1d9b Update build.yml 2022-08-31 08:41:52 -04:00
Jay Lee
52aa1ac0da Update build.yml 2022-08-31 08:39:18 -04:00
Jay Lee
b5c23fdb83 Update gam.spec 2022-08-31 08:30:53 -04:00
Jay Lee
0b16c9aef4 Default to Google's roots.pem CA file 2022-08-31 08:29:34 -04:00
Jay Lee
3be97acd9c Update build.yml 2022-08-31 08:27:11 -04:00
GitHub Action
8df8e6797f [ci skip] Updated roots.pem 2022-08-31 12:19:58 +00:00
Jay Lee
156ba44656 Update get-roots.yml 2022-08-31 08:19:42 -04:00
Jay Lee
1b3663d60c Update get-roots.yml 2022-08-31 08:15:38 -04:00
Jay Lee
8f0ea2f6a5 Rename get-roots.yaml to get-roots.yml 2022-08-31 08:13:59 -04:00
Jay Lee
5e34b12e5c Update get-roots.yaml 2022-08-31 08:13:11 -04:00
Jay Lee
d124575a91 Update get-roots.yaml 2022-08-31 08:11:35 -04:00
Jay Lee
f5364ab4d0 Download Google roots.pem 2022-08-31 08:10:19 -04:00
Jay Lee
b5580c5649 Update var.py 2022-08-29 17:07:31 -04:00
Jay Lee
e9200ea8fb Update var.py 2022-08-29 17:03:00 -04:00
Jay Lee
2e0c280ea6 Update oauth.py 2022-08-29 17:02:41 -04:00
Ross Scroggs
3948a414b5 Back to client access for user invitations (#1553) 2022-08-24 15:24:38 -04:00
Jay Lee
2c83068605 enable user invite scope by default 2022-08-24 17:53:57 +00:00
Jay Lee
6f6ccad00b further refine gam checkconn 2022-08-22 15:16:40 +00:00
Ross Scroggs
bd18f14137 checkconnection cleanup (#1552) 2022-08-22 09:19:39 -04:00
Jay Lee
d54ca7ee43 Update build.yml 2022-08-20 09:31:46 -04:00
Jay Lee
19452c2461 Fix info customer 2022-08-20 13:10:23 +00:00
Jay Lee
4e2e96a6dd Update build.yml 2022-08-20 08:54:15 -04:00
Jay Lee
7957d131c0 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-08-19 20:37:32 +00:00
Jay Lee
ca9dfaff1d gam checkconn first shot 2022-08-19 20:33:19 +00:00
Ross Scroggs
7e9475791b Handle Reports API bug (#1550)
* Handle Reports API bug

* Handle Reports API bug
2022-08-18 19:07:17 -04:00
Jay Lee
c8fb44a7c4 Update build.yml 2022-08-10 19:42:57 -04:00
Jay Lee
bb70183bc7 Update build.yml 2022-08-10 09:11:14 -04:00
Jay Lee
ff80ba1814 Update build.yml 2022-08-09 10:52:51 -04:00
Jay Lee
5d292dcaf7 Update var.py 2022-08-04 14:34:49 -04:00
Jay Lee
bcc5c4520f Update build.yml 2022-08-04 13:44:48 -04:00
Jay Lee
aa7ea59b5e Update oauth.py 2022-08-04 09:33:13 -04:00
Jay Lee
16e85d6d5c pass CA file to fetch_token so it's used by requests 2022-08-03 11:26:36 -04:00
Ross Scroggs
453e65ec53 Clean up calendar ACL documentation (#1545) 2022-08-02 10:05:03 -04:00
Jay Lee
4cbcb9418c Update build.yml 2022-08-02 07:11:48 -04:00
Jay Lee
f2120229e2 Update userinvitations.py 2022-07-20 18:52:32 -04:00
Ross Scroggs
4d2db30000 Update course field names (#1542) 2022-07-18 17:17:11 -04:00
Ross Scroggs
ca575b267b Bound sleep time in create project (#1541) 2022-07-15 13:35:53 -04:00
Jay Lee
3216666a94 retry project creation status check 10 times instead of 5 2022-07-15 11:08:36 -04:00
Ross Scroggs
4ef5606f05 Add cros_ou and cros_ou_and_children to <CrOSTypeEntity> (#1538)
* Add cros_ou and cros_ou_and_children to <CrOSTypeEntity>

Most useful here:
`gam update org|ou <OrgUnitPath> add|move <CrOSTypeEntity>`

* Update GamCommands.txt

* Code cleanup/appease pylint
2022-07-14 13:48:02 -04:00
Ross Scroggs
6122dc3353 Allow print of cros OU and children (#1537) 2022-07-14 09:53:43 -04:00
Jay Lee
14ae792091 Update build.yml 2022-07-13 14:17:14 -04:00
Ross Scroggs
9da5065700 Two updates (#1536)
New CRoS actions

Allow child privileges in create|update adminrole
2022-07-12 14:07:04 -04:00
Jay Lee
22e155998d Update gam-install.sh 2022-06-30 14:56:51 -04:00
Jay Lee
939a1afbbf fix device user printing 2022-06-30 14:48:44 +00:00
Jay Lee
ecda9fe232 fix deviceuser list pageSize 2022-06-30 00:28:10 +00:00
Jay Lee
76eb79eb2d Merge branch 'main' of https://github.com/GAM-team/GAM 2022-06-30 00:12:51 +00:00
Jay Lee
325e597772 Workaround for #1534 2022-06-30 00:12:45 +00:00
Ross Scroggs
c6334d2bcd Allow super admin to delete any shared drive (#1533) 2022-06-27 14:50:17 -04:00
Jay Lee
72ff9ff7e9 rebuild to start using OpenSSL 3.0.4 2022-06-21 12:53:10 -04:00
Jay Lee
b45ad5dcaf Update build.yml 2022-06-17 08:23:29 -04:00
Ross Scroggs
3d14964365 Add address fields to buildings (#1529) 2022-06-10 11:16:15 -04:00
Jay Lee
d15bab5a29 Update build.yml 2022-06-06 13:43:57 -04:00
Jay Lee
c4deb29b21 Update build.yml 2022-05-31 12:20:50 -04:00
Jay Lee
0eafee3105 [no ci] upgrade test runs to Ubuntu 22.04 2022-05-31 11:54:13 -04:00
Ross Scroggs
4d116e81c8 Eliminate orgUnitPath encoding (#1527) 2022-05-31 11:24:37 -04:00
Ross Scroggs
3a41b31e19 Use i, not 6 (#1526) 2022-05-27 16:44:43 -04:00
Jay Lee
f9786468db Merge branch 'main' of https://github.com/GAM-team/GAM 2022-05-27 15:03:47 +00:00
Jay Lee
a49124d1d0 fix org_unit admin role assignment 2022-05-27 14:59:17 +00:00
Ross Scroggs
3087b4b776 Update pip version (#1525) 2022-05-26 09:58:22 -04:00
Jay Lee
aa595fe623 Update var.py 2022-05-26 08:54:27 -04:00
Jay Lee
30a571f56c Update build.yml 2022-05-25 21:39:15 -04:00
Jay Lee
7b0a8dce1e Update build.yml 2022-05-25 20:32:17 -04:00
Jay Lee
6fce941640 Update build.yml 2022-05-25 19:51:13 -04:00
Jay Lee
dbfbf61ddc Update build.yml 2022-05-25 19:18:51 -04:00
Jay Lee
5d618de296 Update build.yml 2022-05-25 17:01:00 -04:00
Ross Scroggs
3e556425ec New Oauth2 error message (#1524) 2022-05-25 16:29:18 -04:00
Jay Lee
370db726a4 Update build.yml 2022-05-21 16:46:28 -04:00
Jay Lee
12d6c8c3f5 Update build.yml 2022-05-21 16:10:52 -04:00
Jay Lee
0fdb6544cc Update build.yml 2022-05-21 16:04:52 -04:00
Jay Lee
ca52845c65 Update build.yml 2022-05-21 15:28:43 -04:00
Jay Lee
fac32f95d8 Update build.yml 2022-05-21 14:40:46 -04:00
Jay Lee
f27b37d21a Update build.yml 2022-05-21 09:09:21 -04:00
Jay Lee
e066fcc172 Make all step if conditions OS generic 2022-05-21 08:39:58 -04:00
Jay Lee
14535e814f [no ci] replace some OS context with generic OS 2022-05-21 08:14:56 -04:00
Jay Lee
1cfb873122 [no ci] undo commented out lines while troubleshooting 2022-05-21 07:47:22 -04:00
Jay Lee
de16285bf2 Update build.yml 2022-05-21 07:21:36 -04:00
Jay Lee
d01f3f31ff Update build.yml 2022-05-21 07:19:12 -04:00
Jay Lee
edec98579d Update build.yml 2022-05-20 22:10:00 -04:00
Jay Lee
ea583e98b2 Update build.yml 2022-05-20 21:39:04 -04:00
Jay Lee
c4a080e081 [no ci] document setuptools_scm issue 2022-05-20 21:31:32 -04:00
Jay Lee
4e35845ecf Update build.yml 2022-05-20 21:05:18 -04:00
Jay Lee
9d76fcbcf1 Update requirements.txt 2022-05-20 09:42:32 -04:00
Jay Lee
60290473e1 Update build.yml 2022-05-20 09:14:17 -04:00
Jay Lee
f94456ce7f Update setup.cfg 2022-05-19 19:16:53 -04:00
Jay Lee
65cda68f40 Update requirements.txt 2022-05-18 03:25:47 -04:00
Jay Lee
576731c386 Update build.yml 2022-05-17 21:22:29 -04:00
Jay Lee
0b56af76b7 Update build.yml 2022-05-17 20:46:23 -04:00
Ross Scroggs
10e6cbabcf Support displaying Chromebook OU ID (#1523) 2022-05-10 14:10:59 -04:00
Jay Lee
f33529a1d4 Update build.yml 2022-05-10 14:10:31 -04:00
Jay Lee
7a5a6a8db2 Update build.yml 2022-05-10 09:50:31 -04:00
Jay Lee
c43c4a8b07 Update build.yml 2022-05-10 08:08:13 -04:00
Jay Lee
0e0e1332c7 Update build.yml 2022-05-10 08:00:33 -04:00
Ross Scroggs
ee19c5e25f Multivalued schema files default to type work; update URLs (#1522)
* multivalued schema field defaults to type work;

* Update URLs

* Add new Product/SKU

* Revert to https://jaylee.us/gam
2022-05-08 19:42:39 -04:00
Ross Scroggs
c0c1355216 Handle missing type field in multivalued schema valus (#1520) 2022-05-04 12:41:35 -04:00
Jay Lee
da3394f3fd Update build.yml 2022-05-03 21:37:27 -04:00
Jay Lee
c856723945 Update var.py 2022-04-29 06:12:36 -04:00
Jay Lee
5e10ccdbdd Update __main__.py 2022-04-29 06:12:00 -04:00
Jay Lee
a49f645647 Update za-bug-report.md 2022-04-29 06:10:51 -04:00
Jay Lee
cf8d714ba7 Update ISSUE_TEMPLATE.txt 2022-04-29 06:10:13 -04:00
Jay Lee
17bb625d0d goodbye git.io :-/ 2022-04-29 06:08:51 -04:00
Ross Scroggs
5e7a858d55 Document delete teamdrive allowitemdeletion (#1517) 2022-04-24 08:00:06 -04:00
Jay Lee
8276474314 GAM 6.21 2022-04-22 18:16:17 -04:00
Jay Lee
d108261654 [test] force shared drive deletion 2022-04-22 19:15:20 +00:00
Jay Lee
aa98be443c create drive file on shared drive 2022-04-22 18:53:02 +00:00
Jay Lee
eecb583f10 Option to force shared drive deletion 2022-04-22 18:48:21 +00:00
Ross Scroggs
809aae27b1 Add option to update cigroup to allow updating a dynamic group to a security group (#1515) 2022-04-17 19:51:15 -04:00
Jay Lee
028ca15498 Create codeql-analysis.yml 2022-04-11 21:45:44 -04:00
Jay Lee
be4403331f Update var.py 2022-04-11 08:44:08 -04:00
Ross Scroggs
b84025debf Use new CI orgUnits.memberships/move (#1514)
Old method never seemed to work; commented code can probably be dropped
2022-04-11 02:33:45 -04:00
Jay Lee
4685f29aba Handle Cloud identity OrgUnits update 500 errors 2022-04-10 19:50:06 -04:00
Ross Scroggs
a832698366 Update CAA documentation (#1513) 2022-04-10 10:41:23 -04:00
Ross Scroggs
cf894fd0bd Code cleanup (#1512)
* Code cleanup

* Two fixes
2022-04-10 08:16:10 -04:00
Ross Scroggs
fd6c04bd94 Fix indentaton (#1511) 2022-04-09 14:20:22 -04:00
Ross Scroggs
49a2352d6d Standardize getting Shared Drive ID or Name (#1510) 2022-04-09 07:26:46 -04:00
Ross Scroggs
291871ec45 Update CAA osType in documentation (#1509) 2022-04-08 22:45:19 -04:00
Jay Lee
73c21a1156 Update caa.py 2022-04-08 19:42:20 -04:00
Ross Scroggs
27eed06617 Document CAA, minimumVersion is optional in constraint (#1508) 2022-04-08 19:39:29 -04:00
Ross Scroggs
a440cbbbdc Make print|show oushareddrives consistent with other commands (#1507) 2022-04-08 15:13:04 -04:00
Jay Lee
eb9ca5eb1d Update build.yml 2022-04-08 15:11:15 -04:00
Ross Scroggs
5eb1277691 Do print|show for caalevels and oushareddrives (#1506) 2022-04-08 12:28:11 -04:00
Ross Scroggs
6de424b185 Two updates (#1504) 2022-04-08 10:43:47 -04:00
Jay Lee
f89491d801 Update build.yml 2022-04-08 10:18:36 -04:00
Jay Lee
154de4818e Update build.yml 2022-04-08 09:57:02 -04:00
Jay Lee
c5895a3082 Update build.yml 2022-04-08 09:40:58 -04:00
Jay Lee
e085257a51 Update var.py 2022-04-08 09:37:22 -04:00
Ross Scroggs
d8e84cf045 Delete extraneous code, custom <String> is operative (#1503) 2022-04-07 21:12:37 -04:00
Jay Lee
a5eb61421d Update build.yml 2022-04-07 20:23:22 -04:00
Jay Lee
cddbea2718 don't use dasa for printer cmds 2022-04-08 00:10:38 +00:00
Jay Lee
c9bf5158e4 capture shared drive id 2022-04-07 23:58:32 +00:00
Jay Lee
7822b36f97 enable commands now that scopes should be present 2022-04-07 23:31:41 +00:00
Jay Lee
20d541ca8e juggle command order to give time for propogation 2022-04-07 23:26:50 +00:00
Jay Lee
72af9fb4a9 Update creds.tar.gpg 2022-04-07 23:17:24 +00:00
Jay Lee
a2972a3329 disable shared drive OU update for now, need to Actions 2022-04-07 20:31:22 +00:00
Jay Lee
97b74c0c8f fix shareddrive name 2022-04-07 20:20:02 +00:00
Jay Lee
332519e5d4 fix gam_user 2022-04-07 20:06:54 +00:00
Jay Lee
881641e2b4 gapi_drive 2022-04-07 19:53:11 +00:00
Jay Lee
82bfe74175 orgunits.py 2022-04-07 19:51:15 +00:00
Jay Lee
bac3451c21 OrgUnit Support for Shared Drives 2022-04-07 19:48:23 +00:00
Ross Scroggs
c97495ab05 Fix bug (#1502) 2022-04-07 15:36:56 -04:00
Jay Lee
aa3dad1e07 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-04-07 17:00:05 +00:00
Jay Lee
2d4e15504c GAM 6.19 2022-04-07 16:59:58 +00:00
Jay Lee
3cd41e3d0f Update build.yml 2022-04-07 11:10:03 -04:00
Jay Lee
a94518c48d Update build.yml 2022-04-07 09:39:18 -04:00
Jay Lee
2837671ed7 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-04-07 12:52:34 +00:00
Jay Lee
e49eed2a24 Improve error instructions for CAA 2022-04-07 12:52:21 +00:00
Jay Lee
edfc27c960 Update project-apis.txt 2022-04-07 08:29:25 -04:00
Jay Lee
41a10932cb handle >1 access policies in org, action tests 2022-04-07 01:21:15 +00:00
Jay Lee
119538c10c Support for CAA levels 2022-04-07 00:48:40 +00:00
Ross Scroggs
0a03fbb82e Fix add license message (#1497) 2022-03-31 13:38:18 -04:00
Ross Scroggs
b838054e2f Update pip install version (#1496) 2022-03-30 11:59:23 -04:00
Jay Lee
45ac118381 GAM 6.18 2022-03-30 08:16:20 -04:00
Jay Lee
e1600eadbc remove noupx and onefile args that already exist in spec file 2022-03-30 07:29:11 -04:00
Jay Lee
cc23f98078 [no cd] strip non-Win builds 2022-03-30 07:27:31 -04:00
Jay Lee
b68cc671eb Update build.yml 2022-03-29 20:10:44 -04:00
Jay Lee
8c215a0a0b Update build.yml 2022-03-29 20:10:21 -04:00
Jay Lee
374c6a9367 Update gam-install.sh 2022-03-29 19:53:04 -04:00
Jay Lee
5d93d9893e Update build.yml 2022-03-29 16:04:23 -04:00
Jay Lee
010c26ea89 Update build.yml 2022-03-29 14:23:28 -04:00
Jay Lee
5da90f7585 Update build.yml 2022-03-29 14:22:43 -04:00
Jay Lee
5356591d9c Update build.yml 2022-03-28 20:18:01 -04:00
Jay Lee
8df5d22805 Update build.yml 2022-03-28 19:39:17 -04:00
Jay Lee
5684ab3c05 Update build.yml 2022-03-28 18:33:38 -04:00
Jay Lee
d7b8f4c228 Update build.yml 2022-03-28 18:29:41 -04:00
Jay Lee
66fe03bbcd Update build.yml 2022-03-28 16:09:11 -04:00
Ross Scroggs
e7496dc9cb Fix bug in print vaultcounts ... account emailaddress (#1493) 2022-03-26 16:42:19 -04:00
Jay Lee
3b52af0b8a Update build.yml 2022-03-25 19:57:09 -04:00
Jay Lee
4ffe709ab9 Update build.yml 2022-03-16 12:28:35 -04:00
Jay Lee
c0c15a3ee5 Update build.yml 2022-03-16 08:33:51 -04:00
Jay Lee
b724330cb1 Update var.py 2022-03-14 15:49:11 -04:00
Jay Lee
8b9ce17959 Update gam-install.sh 2022-03-08 14:26:59 -05:00
Jay Lee
26116474c5 Update build.yml 2022-03-08 07:54:50 -05:00
Jay Lee
3411fd8557 Update build.yml 2022-03-08 07:22:01 -05:00
Jay Lee
0bee3e38a0 Update build.yml 2022-03-07 16:00:58 -05:00
Jay Lee
dcc2224657 Update build.yml 2022-03-07 15:24:07 -05:00
Jay Lee
1bf1c43f23 GAM 6.17 2022-03-07 20:11:56 +00:00
Jay Lee
53b336aee9 Try universal ToS. Fixes #1489 2022-03-07 19:51:43 +00:00
Jay Lee
94b5407cb4 Update build.yml 2022-03-04 14:52:59 -05:00
Jay Lee
e7357e69fb Update build.yml 2022-03-04 10:05:51 -05:00
Jay Lee
d5a036dfc6 Update build.yml 2022-03-04 08:23:32 -05:00
Jay Lee
e256de06d9 Update build.yml 2022-03-04 06:05:03 -05:00
Jay Lee
59beba616c Update build.yml 2022-03-03 21:53:50 -05:00
Jay Lee
735747e0d4 Update build.yml 2022-03-03 21:02:10 -05:00
Jay Lee
ab167d8c4c Update build.yml 2022-03-03 20:59:58 -05:00
Jay Lee
944f010a8c Update build.yml 2022-03-03 20:00:40 -05:00
Jay Lee
dd064a3843 Update build.yml 2022-03-03 18:14:20 -05:00
Jay Lee
244b20e1f0 Update build.yml 2022-03-03 18:12:40 -05:00
Jay Lee
88308a352b Update build.yml 2022-03-03 18:07:40 -05:00
Jay Lee
c63df9d245 Update build.yml 2022-03-03 17:20:11 -05:00
Jay Lee
2780ad2edc Update build.yml 2022-03-03 17:15:20 -05:00
Jay Lee
00b3122c2c Update build.yml 2022-03-03 14:13:05 -05:00
Jay Lee
18221be556 Update build.yml 2022-03-03 13:14:04 -05:00
Jay Lee
80abd9284f Update build.yml 2022-03-03 12:10:27 -05:00
Jay Lee
87b6cb073f Update build.yml 2022-03-03 12:03:55 -05:00
Jay Lee
e2cbbb2c93 Update build.yml 2022-03-03 09:30:08 -05:00
Jay Lee
c771b84463 Update build.yml 2022-03-02 20:40:31 -05:00
Jay Lee
2460e6957f Update build.yml 2022-03-02 18:35:55 -05:00
Jay Lee
0ec42eb796 Update build.yml 2022-03-02 10:40:37 -05:00
Jay Lee
b78b5ea9e1 Update build.yml 2022-03-02 10:31:27 -05:00
Jay Lee
d26bfc9aab Update build.yml 2022-03-02 09:21:52 -05:00
Jay Lee
c64730e07b Update build.yml 2022-03-02 09:19:45 -05:00
Jay Lee
f8b00b92b4 Update build.yml 2022-03-02 08:21:24 -05:00
Jay Lee
3c9ec2578e Update build.yml 2022-03-01 21:44:43 -05:00
Jay Lee
5f79f46e30 Update build.yml 2022-03-01 20:41:32 -05:00
Jay Lee
30c250c314 Update build.yml 2022-03-01 20:29:44 -05:00
Jay Lee
69f504d91c Update build.yml 2022-03-01 20:02:45 -05:00
Jay Lee
c505dd9c2b Update build.yml 2022-03-01 19:59:53 -05:00
Jay Lee
a7638dee0a Update build.yml 2022-03-01 17:14:31 -05:00
Jay Lee
b8e5ad5107 Update build.yml 2022-03-01 14:09:39 -05:00
Jay Lee
0b2d04bc6f Update build.yml 2022-03-01 13:22:39 -05:00
Jay Lee
803025b8c5 Update build.yml 2022-03-01 13:17:42 -05:00
Jay Lee
a7154da0b6 Update build.yml 2022-03-01 13:15:19 -05:00
Jay Lee
d04b33d1d9 [no ci] don't install Linux packages on cached runs 2022-03-01 12:26:22 -05:00
Jay Lee
614edc22ca Update gam.spec 2022-03-01 12:20:32 -05:00
Jay Lee
eeb760260a Update build.yml 2022-03-01 11:32:32 -05:00
Jay Lee
eb5d876487 Update build.yml 2022-03-01 10:45:50 -05:00
Jay Lee
3bf2c5c8b6 Update build.yml 2022-03-01 10:07:26 -05:00
Jay Lee
3c24049d66 Update build.yml 2022-03-01 09:27:42 -05:00
Jay Lee
1f1b6d45e3 Update build.yml 2022-03-01 09:00:00 -05:00
Jay Lee
7b8a17a544 Update build.yml 2022-03-01 08:35:41 -05:00
Jay Lee
95d1b1295e Update build.yml 2022-03-01 08:20:09 -05:00
Jay Lee
4abd0407c8 Update build.yml 2022-03-01 08:13:59 -05:00
Jay Lee
65f229875d Update build.yml 2022-03-01 08:11:53 -05:00
Jay Lee
9be84501ec Update build.yml 2022-03-01 07:20:23 -05:00
Jay Lee
6e400cabd0 Update build.yml 2022-02-28 22:11:00 -05:00
Jay Lee
1f00614551 Update build.yml 2022-02-28 21:45:59 -05:00
Jay Lee
1da61d076e Update build.yml 2022-02-28 21:26:08 -05:00
Jay Lee
2ce04b4dd2 Update build.yml 2022-02-28 21:10:38 -05:00
Jay Lee
94a52c80cd Update build.yml 2022-02-28 20:49:17 -05:00
Jay Lee
af71cf9a82 Update build.yml 2022-02-28 20:41:50 -05:00
Jay Lee
594c7d6d29 Update build.yml 2022-02-28 20:30:54 -05:00
Jay Lee
4575c3576f Update build.yml 2022-02-28 20:26:22 -05:00
Jay Lee
243a6d20cc Update build.yml 2022-02-28 20:19:57 -05:00
Jay Lee
9f27cc155a Update build.yml 2022-02-28 20:16:54 -05:00
Jay Lee
64bfa122bd Update build.yml 2022-02-28 20:04:31 -05:00
Jay Lee
5be9a3f219 Update build.yml 2022-02-28 20:01:50 -05:00
Jay Lee
b0a478c156 Update build.yml 2022-02-28 19:58:23 -05:00
Jay Lee
96b6a0bc2c Update build.yml 2022-02-28 19:44:01 -05:00
Jay Lee
c3b79c5330 Update build.yml 2022-02-28 16:43:32 -05:00
Jay Lee
da54738902 Update build.yml 2022-02-28 16:40:02 -05:00
Jay Lee
ced508443a Update build.yml 2022-02-28 16:38:20 -05:00
Jay Lee
22d0446da4 Update build.yml 2022-02-28 16:34:01 -05:00
Jay Lee
8c7b3455c9 Update build.yml 2022-02-28 16:30:58 -05:00
Jay Lee
eac145f010 Update build.yml 2022-02-28 16:20:30 -05:00
Jay Lee
8765d06c2f Update build.yml 2022-02-28 16:17:54 -05:00
Jay Lee
7d19450da7 Update build.yml 2022-02-28 16:14:26 -05:00
Jay Lee
4edaeee883 Update build.yml 2022-02-28 16:12:51 -05:00
Jay Lee
e44ea5dbed Apple M1 support part 1 2022-02-28 16:07:17 -05:00
Jay Lee
7ae61b0c6d Update build.yml 2022-02-28 14:30:45 -05:00
Jay Lee
f0ffdc371f Update build.yml 2022-02-28 14:29:02 -05:00
Jay Lee
50f2040eb2 disable user undelete for now 2022-02-27 19:05:28 +00:00
Jay Lee
b76a8f7d76 only look for open matters 2022-02-27 18:58:29 +00:00
Jay Lee
9b0ab6b1c1 support new remove_reset_lock device wipe capability 2022-02-27 18:41:53 +00:00
Jay Lee
bf899f5044 support new export method for Vault 2022-02-27 18:31:56 +00:00
Jay Lee
75a20b66d3 Explain URL copy to users 2022-02-27 17:11:49 +00:00
Ross Scroggs
018862d012 Allow user copy/paste retries in gam oauth create (#1488) 2022-02-27 11:46:41 -05:00
Ross Scroggs
87d3714ed0 Cleanup (#1486)
* Cleanup

* Update oauth.py
2022-02-26 16:12:19 -05:00
Jay Lee
f8f5ee7f25 Update build.yml 2022-02-23 12:28:19 -05:00
Jay Lee
45e772acde Update oauth_test.py 2022-02-18 17:59:52 -05:00
Jay Lee
0b7a79bce0 rough draft work to move GAM off oob auth #1483 2022-02-18 16:06:40 -05:00
ejochman
4a9d571cb1 Update LICENSE file contents and location (#1482)
Move LICENSE to root and remove non-applicable "server subcomponents"
section.
2022-02-15 10:44:19 -05:00
Ross Scroggs
1d5a8ec81b Add verifytarget to update alias to address Issue #1479 (#1481)
* Add verifytarget to update alias to address Issue #1479

* Make default behavior in update alias to be verify; provide opt-out

* Update __init__.py

* Remove verifynotinvitable check on update alias
2022-02-12 10:59:27 -05:00
Ross Scroggs
f6c4e26b3b Document create admin condition (#1476)
* Document create admin condition

* Print condition  in original form
2022-02-11 20:43:50 -05:00
Jay Lee
536fded762 Update gam-install.sh 2022-02-06 08:54:23 -05:00
Jay Lee
4a79b3f42c Update var.py 2022-02-04 09:52:38 -05:00
Jay Lee
6e5052f6ab Update build.yml 2022-02-04 09:21:21 -05:00
Jay Lee
fddaeca050 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-02-03 19:13:06 +00:00
Jay Lee
5b53ba33ab add build_beta 2022-02-03 19:12:29 +00:00
Jay Lee
583fb8d6d2 Update build.yml 2022-02-03 14:10:13 -05:00
Jay Lee
9fa51836c7 remove print debug statement 2022-02-03 19:03:50 +00:00
Jay Lee
6432dd1fef Update build.yml 2022-02-03 13:57:51 -05:00
Jay Lee
341d61444c Allow conditions for admin role assignments 2022-02-03 18:45:35 +00:00
Ross Scroggs
40f71cc703 Update setup.cfg (#1474) 2022-02-02 15:02:38 -05:00
Jay Lee
a8155b9a39 Update gam-install.sh 2022-02-02 14:22:45 -05:00
Jay Lee
f5e9aea2ac [no ci] remove old file 2022-02-02 10:39:10 -05:00
Jay Lee
be41f0ba11 [no ci] remove old file 2022-02-02 10:39:02 -05:00
Jay Lee
f92ca02907 [no ci] remove old file 2022-02-02 10:38:54 -05:00
Jay Lee
7ccddd3d33 [no ci] remove old file 2022-02-02 10:38:41 -05:00
Jay Lee
545c4ec30f [no ci] remove old file 2022-02-02 10:38:32 -05:00
Jay Lee
7aa58c8287 [no ci] update wheel 2022-02-02 10:38:07 -05:00
Jay Lee
32bd11dccc Update build.yml 2022-02-02 10:04:31 -05:00
Jay Lee
1c6488312e [no ci] 7z.exe verbose output 2022-02-02 10:00:32 -05:00
Jay Lee
d767e33da5 [no ci] list installed pip packages and versions 2022-02-02 09:52:01 -05:00
Jay Lee
cee82e7408 [no ci] remove debug lines 2022-02-02 09:33:19 -05:00
Jay Lee
8361a47259 rollback cache since setuptools was issue 2022-02-02 09:15:49 -05:00
Jay Lee
1032421fdd Update build.yml 2022-02-02 08:41:41 -05:00
Jay Lee
17e52e2598 Update build.yml 2022-02-02 08:16:12 -05:00
Jay Lee
4265f86c48 Update resource.py 2022-02-02 07:40:22 -05:00
Jay Lee
f82535c497 Update build.yml 2022-02-01 13:43:43 -05:00
Jay Lee
d25b80ee9c Update build.yml 2022-02-01 13:39:25 -05:00
Jay Lee
0c019d07a2 Update build.yml 2022-02-01 13:08:51 -05:00
Jay Lee
dcaa9c56c0 Update build.yml 2022-02-01 13:02:32 -05:00
Jay Lee
87d45840d9 Update build.yml 2022-02-01 12:57:42 -05:00
Jay Lee
8174aae392 Create package_exclusions.txt 2022-02-01 12:49:20 -05:00
Jay Lee
2a916d1d45 Update build.yml 2022-02-01 09:11:34 -05:00
Jay Lee
b628c34b20 Update build.yml 2022-02-01 09:08:07 -05:00
Jay Lee
f161b165b2 Update build.yml 2022-02-01 09:02:32 -05:00
Jay Lee
316ee693e3 Update build.yml 2022-02-01 08:47:12 -05:00
Jay Lee
82bfb99548 Update build.yml 2022-01-31 10:13:10 -05:00
Jay Lee
ed5ccf1faa Update build.yml 2022-01-31 10:08:54 -05:00
Jay Lee
fd3bec8371 Delete windows-install.sh 2022-01-31 10:05:53 -05:00
Jay Lee
9e2bf9cbbe Update build.yml 2022-01-31 08:08:22 -05:00
Jay Lee
ec198e818a Update build.yml 2022-01-26 21:45:59 -05:00
Jay Lee
aeeba5c668 Update build.yml 2022-01-26 20:28:52 -05:00
Jay Lee
0ca5c74ce7 Update build.yml 2022-01-26 20:28:21 -05:00
Jay Lee
b6c1ad5ce7 Update build.yml 2022-01-26 18:51:07 -05:00
Jay Lee
4c64671cb8 Update build.yml 2022-01-26 17:55:56 -05:00
Jay Lee
7773c49112 Update build.yml 2022-01-26 17:08:49 -05:00
Jay Lee
5e451e4fe3 Update build.yml 2022-01-26 16:21:06 -05:00
Jay Lee
0801ef66a0 Update build.yml 2022-01-26 15:07:33 -05:00
Jay Lee
31f0064e53 Update build.yml 2022-01-26 14:24:01 -05:00
Jay Lee
142191caeb Update build.yml 2022-01-26 14:21:23 -05:00
Jay Lee
d5ee92f12a Update build.yml 2022-01-26 13:46:16 -05:00
Jay Lee
2cd36e6244 Update build.yml 2022-01-26 13:38:52 -05:00
Jay Lee
7b4b637ec3 Update build.yml 2022-01-26 13:29:00 -05:00
Jay Lee
ca931d1caa Update build.yml 2022-01-26 13:18:41 -05:00
Jay Lee
e6773a09c0 Update build.yml 2022-01-26 12:34:18 -05:00
Jay Lee
006b0f1c9d Update build.yml 2022-01-25 21:31:38 -05:00
Jay Lee
14c87f427e Update build.yml 2022-01-25 20:11:50 -05:00
Jay Lee
310cc87a5e Update build.yml 2022-01-25 19:25:15 -05:00
Jay Lee
7533eb0540 Update build.yml 2022-01-25 18:45:27 -05:00
Jay Lee
e5d9a84fc8 Update build.yml 2022-01-25 18:23:05 -05:00
Jay Lee
fb2bb0cb09 Update build.yml 2022-01-25 18:00:01 -05:00
Jay Lee
4a7ce7ebfb Update build.yml 2022-01-25 17:16:52 -05:00
Jay Lee
8eaaabe5da Update build.yml 2022-01-25 16:59:13 -05:00
Jay Lee
f78bdf834d [no ci] verbose cp 2022-01-25 16:40:02 -05:00
Jay Lee
86cc187eed [no ci] verbose mkdir 2022-01-25 16:37:52 -05:00
Jay Lee
9ae4ee1430 Update build.yml 2022-01-25 16:35:02 -05:00
Jay Lee
2a71a0f0be Update build.yml 2022-01-25 15:55:28 -05:00
Jay Lee
b3cf0c1bde Update build.yml 2022-01-25 14:46:33 -05:00
Jay Lee
b4e01737c7 Update build.yml 2022-01-25 14:25:54 -05:00
Jay Lee
8243fe8846 Update build.yml 2022-01-25 14:04:24 -05:00
Jay Lee
44b9a3ca8a Update build.yml 2022-01-25 13:31:08 -05:00
Jay Lee
52becd0255 Update build.yml 2022-01-25 13:29:07 -05:00
Jay Lee
4774227a76 Update build.yml 2022-01-25 13:27:41 -05:00
Jay Lee
faaeeb5f72 Update build.yml 2022-01-25 13:23:35 -05:00
Jay Lee
499eb45064 Update build.yml 2022-01-25 12:50:46 -05:00
Jay Lee
86d2dc725b Update build.yml 2022-01-25 12:47:25 -05:00
Jay Lee
39104183e9 Update build.yml 2022-01-25 12:45:33 -05:00
Jay Lee
ce41283a71 Update build.yml 2022-01-25 12:02:54 -05:00
Jay Lee
ad8aaa1738 Create openssl.props 2022-01-25 12:02:15 -05:00
Jay Lee
7ff381cacf Update build.yml 2022-01-25 11:15:52 -05:00
Jay Lee
e522f76db6 Update build.yml 2022-01-25 11:08:35 -05:00
Jay Lee
106e3544a8 Update build.yml 2022-01-25 10:55:42 -05:00
Jay Lee
704fd3bea8 Update build.yml 2022-01-25 10:52:58 -05:00
Jay Lee
c8f13eedbc Update build.yml 2022-01-25 10:46:59 -05:00
Jay Lee
959cf3d483 Update build.yml 2022-01-25 10:30:00 -05:00
Jay Lee
7d59ceb9d1 Update build.yml 2022-01-25 10:21:40 -05:00
Jay Lee
cdcb071826 Update build.yml 2022-01-25 10:17:17 -05:00
Jay Lee
2829c4c26a Update build.yml 2022-01-25 10:13:45 -05:00
Jay Lee
c810874014 Update build.yml 2022-01-25 10:09:54 -05:00
Jay Lee
e1d9aef2d7 Update gam-install.sh 2022-01-24 10:17:37 -05:00
Jay Lee
71e526370c Delete versionhistory-v1.json 2022-01-23 11:12:03 -05:00
Jay Lee
3c7df4974c [no ci] vh discovery doc is now public, remove local 2022-01-23 11:11:44 -05:00
Janosh Riebesell
f5c95d2ba0 Flynt + shellcheck (#1473)
* quote variables in src/gam-install.sh + fix typos

* flynt src (auto f-string conversion)

* quote all shell variables
2022-01-23 11:08:23 -05:00
Jay Lee
a4f09c02e8 Update gam-install.sh 2022-01-21 14:37:08 -05:00
Jay Lee
be8363786c Update build.yml 2022-01-17 16:34:08 -05:00
Janosh Riebesell
7710711def Pre-commit (#1467)
* pre-commit run trailing-whitespace -a

* pre-commit run end-of-file-fixer -a

* pre-commit run double-quote-string-fixer -a

* pre-commit run requirements-txt-fixer -a

* add pyupgrade hook

* remove pre-commit default_language_version 3.7 (since no upwards incompatible hooks)
2022-01-16 14:23:27 -05:00
Jay Lee
7320136079 Update build.yml 2022-01-15 16:19:00 -05:00
Jay Lee
eaced6942a Update var.py 2022-01-15 14:18:04 -05:00
Ross Scroggs
5411724696 Improve gam user show vaultholds (#1472)
* Improve gam user show vaultholds

* Handle user in /

* Handle user in / more efficiently

* Display total holds, don't set rc, allow uid
2022-01-15 12:24:08 -05:00
Jay Lee
ef3c282bfa Update linux-before-install.sh 2022-01-15 12:23:56 -05:00
Jay Lee
1a1cd223d3 Update linux-before-install.sh 2022-01-15 11:54:18 -05:00
Jay Lee
3d55591436 Update linux-before-install.sh 2022-01-15 11:42:52 -05:00
Jay Lee
b5b9cfe2aa Update build.yml 2022-01-15 11:22:31 -05:00
Ross Scroggs
39db76f189 Four changes (#1471)
* Three changes

Document:
gam <UserTypeEntity> show vaultholds|holds
hidden <Boolean> for update teamsrive

Fix showHoldsForUsers

* Standardize update teamdrive input of orgUnitId

* One too many =
2022-01-15 04:01:09 -05:00
Jay Lee
303e32fe5d Update build.yml 2022-01-14 20:18:50 -05:00
Jay Lee
dd4841c82c Update build.yml 2022-01-14 19:58:28 -05:00
Jay Lee
add970c0ae Update var.py 2022-01-14 15:33:43 -05:00
Jay Lee
7df3e70722 Update README.md 2022-01-14 15:32:25 -05:00
Jay Lee
ea4459b89e Update gam-install.sh 2022-01-14 15:31:06 -05:00
Jay Lee
259c952636 Better error on user delete pre-condition. 2022-01-14 13:50:10 -05:00
Jay Lee
15b1ce370c Show holds for users, hide shared drives 2022-01-14 13:35:06 -05:00
Ross Scroggs
f7ab4aef4e Handle missing descriptions in Chrome polilcies (#1468)
Document Chrome Browser field
2022-01-12 18:00:01 -05:00
Jay Lee
a1e6459dc1 GAM 6.13 2022-01-12 09:23:04 -05:00
Jay Lee
31a3dcd2f7 Update gam.spec 2022-01-12 08:50:29 -05:00
Jay Lee
f0120fef63 Update build.yml 2022-01-11 14:54:03 -05:00
Jay Lee
5095e6af14 Update build.yml 2022-01-11 13:25:35 -05:00
Janosh Riebesell
19f21a9453 pyupgrade --py37-plus **/*.py (#1445) 2022-01-11 11:05:02 -05:00
Jay Lee
676908daca Update build.yml 2022-01-11 09:03:43 -05:00
Jay Lee
66a5d0472d Update build.yml 2022-01-11 08:58:29 -05:00
Jay Lee
cc30e307e9 Update build.yml 2022-01-11 08:47:21 -05:00
Jay Lee
57e3eb5c8e Update macos-before-install.sh 2022-01-11 08:45:07 -05:00
Jay Lee
b855f6876c Update build.yml 2022-01-11 08:41:00 -05:00
Jay Lee
8edc06ba41 Update build.yml 2022-01-11 08:33:42 -05:00
Jay Lee
69aa31566b Update build.yml 2022-01-11 08:23:10 -05:00
Jay Lee
19d3483209 Update build.yml 2022-01-10 12:58:46 -05:00
Jay Lee
c1c7e65a3c Update build.yml 2022-01-10 10:19:39 -05:00
Jay Lee
2d0044de95 Update build.yml 2022-01-10 10:13:54 -05:00
Jay Lee
418e3af903 Update build.yml 2022-01-10 07:05:20 -05:00
Jay Lee
c3ddeae3f3 Make TLS 1.3 the default minimum.
Admins can still downgrade to 1.2 if they need to. Most should not need to.
2022-01-02 14:38:27 -05:00
Jay Lee
a9f0e5ba16 Python 3.6 is EOL, require 3.7 2022-01-02 14:33:04 -05:00
Ross Scroggs
8bf8d45ebe Make gam info crostelemetry <SerialNumber> (#1464)
* Make gam info crostelemetry <SerialNumber>

* Handle missing <SerialNumber> for gam info crostelemetry
2021-12-29 14:48:57 -05:00
Ross Scroggs
1777c762b3 Make print crostelemetry consistent print cros (#1463)
* Make print crostelemetry consistent print cros

Strip newline from cpuStatusReport.cpuTemperature.label
Replace list of label/temperatureCelsius pairs with
cpuStatusReport.cpuTemperature.label = temperaureCelsius

* Document print crostelemetry

* Update GamCommands.txt

* More work on print crostelemetry
2021-12-29 12:23:52 -05:00
Jay Lee
0b1337070e Update gam-install.sh 2021-12-28 12:45:37 -05:00
Jay Lee
b158496bea Update build.yml 2021-12-28 11:16:23 -05:00
Jay Lee
a79b23e090 Update build.yml 2021-12-28 10:55:38 -05:00
Jay Lee
bdb56240f0 Update build.yml 2021-12-28 10:20:45 -05:00
Jay Lee
6dddf3eb30 Update build.yml 2021-12-28 10:20:25 -05:00
Jay Lee
7bd8569151 Update build.yml 2021-12-28 09:57:14 -05:00
Jay Lee
b03c9f1e35 Update build.yml 2021-12-28 09:47:54 -05:00
Jay Lee
057b5ff760 Update build.yml 2021-12-23 13:44:04 -05:00
Jay Lee
ba512b4159 Update build.yml 2021-12-23 13:39:00 -05:00
Jay Lee
a298aea2fe Update build.yml 2021-12-23 13:32:42 -05:00
Jay Lee
f433463074 Update build.yml 2021-12-23 13:24:01 -05:00
Jay Lee
afae08d6fe Update build.yml 2021-12-23 13:16:25 -05:00
Jay Lee
7cf2a08aff Update build.yml 2021-12-23 13:04:22 -05:00
Jay Lee
7df6781985 Update build.yml 2021-12-23 12:39:57 -05:00
Jay Lee
ae0f5e62e3 Update build.yml 2021-12-23 12:36:43 -05:00
Jay Lee
14c8356c6b Update build.yml 2021-12-23 12:23:37 -05:00
Jay Lee
45ffd4a793 Update build.yml 2021-12-23 12:16:37 -05:00
Jay Lee
eb8d39025e Update build.yml 2021-12-23 12:11:36 -05:00
Jay Lee
1f739e1c63 Update build.yml 2021-12-23 09:11:12 -05:00
Jay Lee
82111236fb Update build.yml 2021-12-23 08:32:32 -05:00
Jay Lee
813a94f8d6 Update build.yml 2021-12-23 08:28:15 -05:00
Jay Lee
e83b75e2c3 Update build.yml 2021-12-23 08:24:08 -05:00
Jay Lee
ce1e880ed0 Update build.yml 2021-12-23 08:19:11 -05:00
Jay Lee
427672065e Update build.yml 2021-12-23 07:24:25 -05:00
Jay Lee
055c5d5e54 Update build.yml 2021-12-22 20:22:05 -05:00
Jay Lee
4de7794e04 Update build.yml 2021-12-22 20:18:46 -05:00
Jay Lee
79686fd8ce Update build.yml 2021-12-22 20:06:18 -05:00
Jay Lee
cc5df0198b Update build.yml 2021-12-22 19:43:50 -05:00
Jay Lee
abc6e55ba7 Update build.yml 2021-12-22 19:31:03 -05:00
Jay Lee
0c8afb7fd6 Update build.yml 2021-12-22 19:26:36 -05:00
Jay Lee
c0c2cca44e Update build.yml 2021-12-22 19:01:16 -05:00
Jay Lee
faa645cb97 Update build.yml 2021-12-22 18:59:29 -05:00
Jay Lee
725c19aafc Update build.yml 2021-12-22 18:49:19 -05:00
Jay Lee
cc3b4c974d Update build.yml 2021-12-22 18:45:23 -05:00
Jay Lee
6ce64fad72 Update build.yml 2021-12-22 18:39:01 -05:00
Jay Lee
c1af67d4a3 Update build.yml 2021-12-22 18:35:59 -05:00
Jay Lee
802cb15007 Update requirements.txt 2021-12-22 16:46:04 -05:00
Jay Lee
b34bf3e56a Update linux-before-install.sh 2021-12-22 15:58:08 -05:00
Jay Lee
bf37700088 Update build.yml 2021-12-22 15:55:47 -05:00
Jay Lee
4a43ddfc25 Update build.yml 2021-12-22 15:51:03 -05:00
Jay Lee
650a1f5154 Update build.yml 2021-12-22 15:43:24 -05:00
Jay Lee
5eda7e30b0 Update build.yml 2021-12-22 13:10:09 -05:00
Jay Lee
8a26f547e5 Update build.yml 2021-12-22 10:25:41 -05:00
Jay Lee
343088913f Update build.yml 2021-12-22 09:56:08 -05:00
Jay Lee
5a0272fd5b Merge branch 'main' of github.com:jay0lee/GAM 2021-12-22 09:54:29 -05:00
Jay Lee
dc93503625 CrOS Telemetry API 2021-12-22 09:52:48 -05:00
Ross Scroggs
6ea6c0889b Fix show filelist query issue; add driveId to drive file fields (#1461)
* Fix show filelist query issue

If the user says: query "A or B" this becomes "'me' in owners and A or B" which is the same as "('me' in owners and A) or B" which gives incorrect results. The fix makes "'me' in owners and (A or B)"

* Add driveId to list of drive file fields
2021-12-17 11:51:32 -05:00
Jay Lee
99ab72df3f GAM 6.12 2021-12-16 07:41:30 -05:00
Ross Scroggs
99bda1385e languages update; fields for gam info user; cloud identity groups update to v1 (#1459)
* languages update

The API doesn't return languages unless you specifically mention in in fields list

* languages cleanup in print users

* Add fields to gam info user

* No up for languages

* Use v1 for Cloud Identity groups; fix bug in print cigroups member

* It's an error to set preference on custom language
2021-12-16 07:40:08 -05:00
Jay Lee
7ce3b4a8c0 Update build.yml 2021-12-15 12:06:46 -05:00
Jay Lee
495722d0d6 Update build.yml 2021-12-14 20:20:09 -05:00
Jay Lee
aca31be5d7 Update build.yml 2021-12-14 19:53:11 -05:00
Jay Lee
b9b7ae8d99 Merge branch 'main' of github.com:jay0lee/GAM 2021-12-09 15:27:38 -05:00
Jay Lee
0d46c1d13a Set user preferred language 2021-12-09 15:07:57 -05:00
Ross Scroggs
6b63ecdc19 Add limittoou <OrgUnitPath> to print users to allow selection of OU w/o children (#1455) 2021-12-09 10:35:47 -05:00
Jay Lee
f9ca0323a1 Update build.yml 2021-12-07 08:18:03 -05:00
Jay Lee
c50aa4d2e8 Update build.yml 2021-12-06 16:27:53 -05:00
Jay Lee
a72ded9079 wipe cache 2021-11-24 11:17:41 -05:00
Jay Lee
cbabbee075 wipe cache 2021-11-24 11:15:24 -05:00
Jay Lee
f55a344b7a Update build.yml 2021-11-23 10:48:03 -05:00
Jay Lee
d84f8418ff Update build.yml 2021-11-23 10:39:56 -05:00
Jay Lee
30c5e92de6 Update build.yml 2021-11-23 10:15:54 -05:00
Jay Lee
5f618a7f65 Update build.yml 2021-11-23 08:41:50 -05:00
Jay Lee
3e833419db Update README.md 2021-11-23 08:33:53 -05:00
Jay Lee
0d94bae0b5 Update README.md 2021-11-23 08:33:40 -05:00
Jay Lee
f5dec96ffb Update README.md 2021-11-23 08:31:32 -05:00
Jay Lee
e91d12caaf Update macos-install.sh 2021-11-23 08:26:12 -05:00
Jay Lee
fd5a1faa58 Update gam.spec 2021-11-22 16:31:44 -05:00
Jay Lee
90a9212793 Update build.yml 2021-11-22 16:28:10 -05:00
Jay Lee
7e582ac1fc Update build.yml 2021-11-22 16:19:34 -05:00
Jay Lee
65a740569c Update build.yml 2021-11-22 16:16:28 -05:00
Jay Lee
a47ef0e1f5 Update build.yml 2021-11-22 15:41:05 -05:00
Jay Lee
b75ad006f1 Update build.yml 2021-11-22 08:26:33 -05:00
Jay Lee
dbc3f0cd83 Update var.py 2021-11-22 08:16:32 -05:00
Jay Lee
ea2750f970 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-11-22 08:08:33 -05:00
Jay Lee
a2eb5a2483 Correct certificate not before value to UTC-1h. Fixes #1453 2021-11-22 08:08:20 -05:00
Ross Scroggs
54178543d6 Fix Row Filtering Part 3 (#1450)
Graak! Why I can't get my code translated into yours is beyond me; this time for sure.
2021-11-21 20:25:09 -05:00
Jay Lee
5436f21bc0 Use OpenSSL 3.0.0 in builds 2021-10-29 18:12:30 -04:00
Ross Scroggs
839768a2a5 Fix error handling (#1447) 2021-10-29 13:04:59 -04:00
Jay Lee
2e195d5aa1 Update build.yml 2021-10-29 11:05:57 -04:00
Ross Scroggs
66811f8eb5 Fix Row Filtering Part 2 (#1446)
```
Row Filtering
There can be multiple filters, a filter can match multiple columns (wildcard).
The semantics should be:
For row keep filters, if all filters match, the row is kept.
For row drop filters, if any filter matches, the row is dropped.

For an individual filter that specifies multiple columns, there is a match if any column matches.

Prior to PR 1433, the semantics for keep/drop were reversed; the semantics for multiple columns was correct.

PR 1433 corrected the semantics for keep/drop but broke the semantics for multiple columns.

This PR corrects the semantics for multiple columns.
```
2021-10-29 10:24:12 -04:00
Jay Lee
a92326790d Update build.yml 2021-10-29 10:19:09 -04:00
Ross Scroggs
d405767fb0 Update requirements.txt to get latest library versions (#1444)
* Update requirements.txt

* Revert "Update requirements.txt"

This reverts commit f89f66d44c.

* Update to fixed google oauth library
2021-10-26 14:45:34 -04:00
Ross Scroggs
8d7c6d3835 MacOS codesign fix no longer needed; MacOS 12 = Monterey (#1441)
* Updated 3.9 to 3.10, is this still needed?

* Fix no longer required

* MacOS 12 is Monterey
2021-10-26 12:56:47 -04:00
Jay Lee
e362591b7a pin google-auth to 2.0.2
Need https://github.com/googleapis/google-auth-library-python/issues/889 fixed.
2021-10-21 19:32:39 -04:00
Jay Lee
ee5f4b73e8 Update var.py 2021-10-21 18:43:34 -04:00
Jay Lee
0d15eb2898 Workaround Python 3.10.0 CSV escape issue. Fixes #1437 2021-10-21 10:41:20 -04:00
Jay Lee
4af50206ad need lists to repro 2021-10-21 08:19:32 -04:00
Jay Lee
c596937006 Update build.yml 2021-10-21 08:13:17 -04:00
Jay Lee
17eb61e1eb Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-10-21 08:06:39 -04:00
Jay Lee
a333185e84 repro issue #1438 2021-10-21 08:06:26 -04:00
Jay Lee
f6863ae2d6 Update var.py 2021-10-20 13:57:11 -04:00
Ross Scroggs
36830250b5 Handle spurious Google error when enabling project APIs (#1436) 2021-10-20 13:48:41 -04:00
Jay Lee
4ca1c3537b Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-10-18 08:50:25 -04:00
Jay Lee
eeab09eacb fix deprecated package in a_atleast_b.py 2021-10-18 08:50:13 -04:00
Ross Scroggs
af16967257 Fix Row Filtering (#1433)
When multiple filter expressions are defined:
GAM_CSV_ROW_FILTER - should match only if all expressions match
GAM_CSV_ROW_DROP_FILTER - should match if any expression matches

Currently, the opposite is true
2021-10-14 20:12:51 -04:00
Jay Lee
75e2bf5a9a Update build.yml 2021-10-14 19:22:57 -04:00
Ross Scroggs
4db3bc409b Document member restrictions; fix print users (#1430)
* Document member restrictions

* Fix gam print users allfields custom all to include primaryEmail

If you really want everything say: gam print users full
2021-10-06 14:22:27 -04:00
Jay Lee
32ccf414ea Update gam-install.sh 2021-10-06 08:01:29 -04:00
Jay Lee
615e48fffc Update gam-install.sh 2021-10-05 20:18:07 -04:00
Jay Lee
93bf3fce29 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-10-05 18:05:52 -04:00
Jay Lee
899601569a Group member restrictions 2021-10-05 18:05:28 -04:00
Jay Lee
b1805b64a2 Update build.yml 2021-10-05 17:58:20 -04:00
Jay Lee
58190343b1 Update linux-install.sh 2021-10-05 16:49:53 -04:00
Jay Lee
99d48b1939 Update linux-before-install.sh 2021-10-05 16:49:36 -04:00
Jay Lee
82b66d53cb Update linux-install.sh 2021-10-05 09:08:55 -04:00
Ross Scroggs
3200de56cc Several fixes/updates (#1426)
* agreedToTerms is now read-only

* Fix sync devices

* assetTag if specified is part of sync device key

* Handle missing assetTags

* Leave agreedtoterms as an undocumented option

* More assetTag processing, the field is not returned from the API if it's empty

* Fix DriveFileAttribute formatting

* memberKey has been replaced by preferredMemberKey

* Correct license name

* If notdemail.txt is present, write_csv_file will not send an email
2021-10-05 08:37:09 -04:00
Jay Lee
0a627d5c79 Update build.yml 2021-10-05 08:29:19 -04:00
Jay Lee
22399deb79 Update build.yml 2021-10-05 08:22:59 -04:00
Jay Lee
6a77617e3b Update build.yml 2021-10-04 18:22:32 -04:00
Jay Lee
2868ef99ae Update build.yml 2021-10-04 18:11:54 -04:00
Jay Lee
21557f9892 Update linux-install.sh 2021-09-30 18:54:46 -04:00
Jay Lee
d2385ae62d Update linux-before-install.sh 2021-09-30 18:54:19 -04:00
Jay Lee
a84efef389 Update build.yml 2021-09-30 18:51:55 -04:00
Jay Lee
310bcd1585 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-09-27 08:21:54 -04:00
Jay Lee
753f44deb2 Fix some missing types in cbcm JSON, formatting 2021-09-27 08:21:08 -04:00
Jay Lee
df1f0f8f09 Update build.yml 2021-09-16 08:15:21 -04:00
Jay Lee
45e1b50674 Update build.yml 2021-09-10 14:41:08 -04:00
Jay Lee
0a2b048fb1 Update build.yml 2021-09-10 14:40:21 -04:00
Ross Scroggs
e3c5dca09d Three updates (#1421)
* Initialize pageToken for each namespace

* Update group sync to do removes before adds

This gets around problem when  a group contains a primary address and a sync is performed with an alias. With adds first you get a duplicate error; with removes first the primary address in the group is replaced with the alias.

* Add defaultsender to group settings
2021-09-09 13:06:50 -04:00
Jay Lee
88339b7214 Update build.yml 2021-08-31 13:59:04 -04:00
Jay Lee
1f2bb18bc1 GAM 6.08 2021-08-31 13:58:04 -04:00
Jay Lee
74977a6154 Update build.yml 2021-08-31 10:49:42 -04:00
Jay Lee
00413fe7a4 Update build.yml 2021-08-31 10:46:03 -04:00
Jay Lee
9bb9d331ad Update build.yml 2021-08-31 09:58:07 -04:00
Jay Lee
f022ffdff4 Update build.yml 2021-08-31 09:25:13 -04:00
Jay Lee
28dade2a34 Update build.yml 2021-08-31 09:18:23 -04:00
Jay Lee
7378b9d843 Update build.yml 2021-08-31 09:10:22 -04:00
Jay Lee
71075e95bf Update build.yml 2021-08-31 08:58:45 -04:00
Janosh Riebesell
108990cf06 Fix pip license error + add pip install command to readme (#1419)
* fix pip license error, add pip install to readme

* fix warning: the 'license_file' option is deprecated, use 'license_files' instead
2021-08-31 08:51:51 -04:00
Jay Lee
ebfdf4b052 Update build.yml 2021-08-31 08:49:55 -04:00
Jay Lee
dbf4073216 fix gam.py also 2021-08-27 12:10:54 -04:00
Jay Lee
83214eaaf8 attempt fixes for pip installable 2021-08-27 12:10:15 -04:00
Janosh Riebesell
1100fdd456 Make GAM pip-installable (#1417)
* wip: make pip-installable

* resolve @jay0lee's comments
2021-08-27 11:24:02 -04:00
Jay Lee
481bfa5440 Update build.yml 2021-08-27 10:16:34 -04:00
Jay Lee
30282c7fbb OpenSSL 1.1.1l not "i" 2021-08-27 09:44:01 -04:00
Jay Lee
382bc71b21 Update build.yml 2021-08-24 14:58:58 -04:00
Ross Scroggs
f3fba97652 Add shortcutDetails to drive file fields (#1413) 2021-08-23 16:05:15 -04:00
Yaroslav Nakonechnikov
7f51e35bd4 Pathvalidate (#1408)
* Update requirements.txt

Adding `pathvalidate` to requrements

* Update __init__.py

Adding `pathvalidate` to make  correct filename on other then ascii encodings.

* Updating with sanitize_filename

* Removing unused variable.
2021-08-23 16:04:11 -04:00
Ross Scroggs
95beb8e62a Update getting MacOS version (#1409) 2021-08-14 16:59:07 -04:00
Ross Scroggs
1a9de867f9 Work around API restriction that roleId and userKey are mutually exclusive (#1406) 2021-08-10 06:30:52 -04:00
Jay Lee
b42946bbe1 Update build.yml 2021-08-04 17:02:24 -04:00
Jay Lee
40b2fd09ff small service account improvements 2021-08-04 16:58:07 -04:00
Jay Lee
a3d560a8a2 YubiKey improvements and PIV reset 2021-07-27 09:24:34 -04:00
Jay Lee
ed20fe252e Use with conn so Yubikey connections close sooner 2021-07-26 14:46:58 -04:00
Jay Lee
375e36ff96 State what we don't like about invalid JSON 2021-07-26 14:45:26 -04:00
Jay Lee
e7108b108e Update build.yml 2021-07-23 13:31:06 -04:00
Jay Lee
6d59daad19 Update build.yml 2021-07-23 13:27:53 -04:00
Jay Lee
21c693921b Update build.yml 2021-07-23 13:13:34 -04:00
Jay Lee
7bcd5fbed7 Update build.yml 2021-07-23 13:06:22 -04:00
Jay Lee
7104970e17 Update build.yml 2021-07-23 13:01:20 -04:00
Jay Lee
1a2950b580 Update build.yml 2021-07-23 12:59:34 -04:00
Jay Lee
085b24e1c5 Update build.yml 2021-07-23 12:55:39 -04:00
Jay Lee
8688ce6328 Update build.yml 2021-07-23 12:52:35 -04:00
Jay Lee
fbdfed81e7 Update build.yml 2021-07-23 12:49:21 -04:00
Ross Scroggs
94fe20607e Updates for CRM v3 changes (#1401) 2021-07-22 19:19:10 -04:00
Ross Scroggs
6c62483e8e Updates for CRM v3 changes (#1400) 2021-07-21 17:27:46 -04:00
Ross Scroggs
54689129c6 Update gam print|show|update chromepolicy to handle the following special case policies: (#1399)
```
chrome.users.AutoUpdateCheckPeriodNew autoupdatecheckperiodminutesnew
chrome.users.BrowserSwitcherDelayDuration browserswitcherdelayduration
chrome.users.FetchKeepaliveDurationSecondsOnShutdown fetchkeepalivedurationsecondsonshutdown
chrome.users.MaxInvalidationFetchDelay maxinvalidationfetchdelay
chrome.users.PrintingMaxSheetsAllowed printingmaxsheetsallowednullable
chrome.users.PrintJobHistoryExpirationPeriodNew printjobhistoryexpirationperioddaysnew
chrome.users.SecurityTokenSessionSettings securitytokensessionnotificationseconds
chrome.users.SessionLength sessiondurationlimit
chrome.users.UpdatesSuppressed updatessuppresseddurationmin
chrome.users.UpdatesSuppressed updatessuppressedstarttime
```
2021-07-20 17:25:17 -04:00
Ross Scroggs
e9e8dd5a82 Fix call to be compatible with CRM v3 (#1398) 2021-07-19 19:31:08 -04:00
Jay Lee
00e764b118 Migrate to Resource Manager API v3 2021-07-16 10:14:58 -04:00
Jay Lee
cee7eb970a Merge branch 'main' of https://github.com/jay0lee/GAM 2021-07-13 10:45:21 -04:00
Jay Lee
daed17fac8 exclude null character, max out passwd length on random 2021-07-13 10:44:58 -04:00
Ross Scroggs
8708f4f93f Fix page_args_in_body, update namespace handling in show chromepolicies (#1393)
When page_args_in_body is true you have to add body to kwargs to ensure a place for pageToken

Allow setting a list of namespaces that override the defaults for printerid (not likely) and appid.
2021-07-08 08:55:18 -04:00
Jay Lee
c7c1bfbeba retry wait for mailbox if user doesn't exist 2021-07-07 11:03:04 -04:00
Jay Lee
0418438b6f increase rounds to Google max 2021-07-07 10:53:34 -04:00
Jay Lee
a2ea4d036e improve random password generator 2021-07-07 10:47:34 -04:00
Jay Lee
dc7a29908f updates to allow listing/setting extension policy 2021-07-02 13:36:21 -04:00
Jay Lee
794db5d2a4 More APIs now work with discovery v2 URL 2021-07-01 14:47:40 -04:00
Jay Lee
e5f9db129b Improve printing of app/extension/printer policy 2021-06-30 11:18:29 -04:00
Jay Lee
a6aecf4e9d undo version in exe 2021-06-29 11:22:33 -04:00
Jay Lee
b59bc4ec90 Merge branch 'main' of https://github.com/jay0lee/GAM 2021-06-29 11:04:17 -04:00
Jay Lee
41920f7865 add version info to Windows exe 2021-06-29 11:02:44 -04:00
Jay Lee
4630bf5681 Update var.py 2021-06-29 08:13:59 -04:00
Ross Scroggs
1c78ebd20e Add groupidfllert <String> to gam report <ActivityApplicationName> (#1390) 2021-06-28 21:34:50 -04:00
Jay Lee
80d17cfda3 Update windows-install.sh 2021-06-28 17:28:10 -04:00
Jay Lee
a154007927 Update windows-install.sh 2021-06-28 17:22:57 -04:00
Jay Lee
bd8274cc27 Update windows-install.sh 2021-06-28 17:13:42 -04:00
Jay Lee
fb08991c05 Update windows-before-install.sh 2021-06-28 17:06:47 -04:00
Jay Lee
7c1f06fdf7 Update build.yml 2021-06-28 16:57:11 -04:00
Jay Lee
93b38b9f95 Update build.yml 2021-06-28 16:44:40 -04:00
Jay Lee
7ffc97d301 Update build.yml 2021-06-28 16:40:43 -04:00
Jay Lee
280301f258 Update build.yml 2021-06-28 16:36:04 -04:00
Jay Lee
40daf38f80 Update build.yml 2021-06-28 16:32:41 -04:00
Jay Lee
d24925cd5f Update build.yml 2021-06-28 16:30:55 -04:00
Ross Scroggs
cd42d54b43 Fix typo, document new drive fields (#1389)
* Fix typo, document new drive fields

* Document new drive attribute
2021-06-28 15:40:22 -04:00
Jay Lee
53d8ecb6bc Update build.yml 2021-06-28 15:39:47 -04:00
Jay Lee
98e87d0297 Update build.yml 2021-06-28 15:38:04 -04:00
Jay Lee
400b4af769 Update macos-before-install.sh 2021-06-28 15:35:40 -04:00
Jay Lee
368701afb1 Update build.yml 2021-06-28 15:33:58 -04:00
Jay Lee
a501b89ecd resource key support 2021-06-25 16:52:14 -04:00
Jay Lee
91cddd72e5 Update build.yml 2021-06-17 14:54:09 -04:00
Jay Lee
8a1f0c9dbf GAM 6.06 2021-06-17 14:47:47 -04:00
Jay Lee
e3e5318b4f Update build.yml 2021-06-17 14:33:08 -04:00
Jay Lee
b060664c9f Update build.yml 2021-06-17 14:29:38 -04:00
Jay Lee
83fbf0e8ac Update build.yml 2021-06-17 14:23:13 -04:00
Jay Lee
537a926618 Update build.yml 2021-06-11 09:49:39 -04:00
Jay Lee
f791a59b1d GAM 6.05 2021-06-11 09:30:42 -04:00
Jay Lee
0b8e41f993 cleanup 2021-06-11 09:29:32 -04:00
Ross Scroggs
f540fa2a38 Unescape \r and \n in chatmessage text so multiline messages can be created from command line (#1387)
* Unescape \r and \n in chatmessage text so multiline messages can be created

* Bring gam report activity list up to date
2021-06-10 09:33:51 -04:00
Ross Scroggs
2d7bc2f34a Check that required arguments are present (#1386)
* Check that required arguments are present

* Correct chat message documentation
2021-06-07 15:56:09 -04:00
Jay Lee
c2dea0a4d7 add a few new user attribute types 2021-06-04 15:55:50 -04:00
Jay Lee
42cbfbf8ed Update macos-install.sh 2021-06-02 14:02:37 -04:00
Jay Lee
137e79b012 Update macos-install.sh 2021-06-02 13:49:34 -04:00
Jay Lee
5849ed3ecc Update build.yml 2021-06-02 10:04:30 -04:00
Ross Scroggs
d3dc1e1197 Add chat commands (#1384) 2021-05-27 21:07:55 -04:00
Jay Lee
c20f0bef44 GAM 6.04 2021-05-26 13:12:28 -04:00
Jay Lee
c572b6b182 fix win zip and MSI 2021-05-26 11:59:57 -04:00
Jay Lee
a1392dbf86 fix archive path 2021-05-26 10:53:06 -04:00
Jay Lee
4e719bab5e few build / install cleanups 2021-05-25 12:59:57 -04:00
Jay Lee
34b51ea64a GAM 6.03 2021-05-25 12:49:10 -04:00
Jay Lee
5a2a72f530 fix importlib_metadata on Python < 3.8 2021-05-25 12:27:52 -04:00
Jay Lee
2ea80c41ab retry a few more key operations 2021-05-25 11:49:44 -04:00
Jay Lee
6f987958e8 Print versions for more libraries 2021-05-25 10:39:14 -04:00
Jay Lee
ae4007aad5 re-enable legacy linux build 2021-05-25 10:09:47 -04:00
Jay Lee
c4401f8bd4 refine Chat calls 2021-05-25 09:32:02 -04:00
Jay Lee
0e7472de50 Initial Support for Google Chat API 2021-05-24 16:37:39 -04:00
Jay Lee
e998c78609 name artificat zip 2021-05-24 12:30:18 -04:00
Jay Lee
c30b92cd38 fix msi build 2021-05-24 11:23:45 -04:00
Jay Lee
2bf2d2aef7 try src/ 2021-05-24 11:07:39 -04:00
Jay Lee
cdc04b0803 fix gampath on win/mac 2021-05-24 10:48:42 -04:00
Jay Lee
5f5875acc1 fix distpath linux 2021-05-24 10:11:40 -04:00
Jay Lee
d306c5e0a3 try with extensions 2021-05-24 10:04:52 -04:00
Jay Lee
19a815cffe One file 2021-05-24 09:54:57 -04:00
Jay Lee
da0c559293 artifact wildcard attempt #3 2021-05-24 09:33:42 -04:00
Jay Lee
a2c91ef7b3 artifact wildcard attempt #2 2021-05-24 09:24:51 -04:00
Jay Lee
722b94ca32 no --universal2 argument yet 2021-05-24 09:00:18 -04:00
Jay Lee
299742fe03 reverting Actions changes for universal2 attempt 2021-05-24 08:56:25 -04:00
Ross Scroggs
3964cbf911 Add dynamic option to update cigroup (#1381)
Update print|show teamdrive documentation
2021-05-17 17:09:34 -04:00
Jay Lee
63e4947ad5 fix version 2021-05-12 08:36:10 -04:00
Jay Lee
e3cb13a414 youtoo 2021-05-11 14:46:24 -04:00
Jay Lee
01fec79d78 --universal2 2021-05-11 14:39:25 -04:00
Jay Lee
a7043a1359 disable rebuild of bootloader 2021-05-11 14:00:06 -04:00
Jay Lee
91a93ecd62 only set target arch on 32-bit Win 2021-05-11 13:20:40 -04:00
Jay Lee
c52fdf6395 preserve gam builds as Action artifact 2021-05-11 12:56:22 -04:00
Jay Lee
1d1dad4b30 switch to PyInstaller branch for Apple M1 support 2021-05-11 12:53:14 -04:00
Jay Lee
f07a57e478 no strip 2021-05-11 10:28:13 -04:00
Jay Lee
ebacd9b4b4 standardize pyinstaller arguments 2021-05-11 10:22:29 -04:00
Jay Lee
f010e59597 remove -F on Windows 2021-05-11 10:15:10 -04:00
Jay Lee
a184d7a8e0 list gampath 2021-05-11 09:15:16 -04:00
Jay Lee
807f54c549 wheel 2021-05-11 09:02:50 -04:00
Jay Lee
24684abc1d wheel 2021-05-11 08:56:17 -04:00
Jay Lee
1f1a49976c upgrade PyInstaller 2021-05-11 08:52:08 -04:00
Jay Lee
562fda3079 disable staticx for now 2021-05-10 09:30:53 -04:00
Jay Lee
05642f3c14 try w/o readlink 2021-05-10 09:06:53 -04:00
Jay Lee
251e2774aa no mkdir 2021-05-10 08:59:30 -04:00
Jay Lee
2089589d34 fix distpath 2021-05-10 08:53:19 -04:00
Jay Lee
c48b135c43 more debug decrypt 2021-05-10 08:44:45 -04:00
Jay Lee
70121a6ebf more output 2021-05-07 11:14:03 -04:00
Jay Lee
c23e53585a fix gam binary paths 2021-05-07 10:59:05 -04:00
Jay Lee
89e964163e fix dist paths 2021-05-07 10:55:42 -04:00
Jay Lee
0357774ba6 Test moving back to one-dir instead of one-file for PyInstaller 2021-05-07 10:48:36 -04:00
Ross Scroggs
93cf750249 Code cleanup; display role for group members (#1379)
* Code cleanup; display role for group members

* Standardize member and membertree output

Should dates be added to membergtree output?

* Use member_id to get subgroup, avoid call to convert email to id

* Only show role on top-level members

* Use v1beta1 for info user grouptree

* Update groups.py
2021-05-07 09:07:44 -04:00
Ross Scroggs
b712f7a344 Cloud Identity v1 only uses preferredMemberKey (#1378)
* Cloud Identity v1 only uses preferredMemberKey

* Document print labels

* Cleanup/bug fix info user grouptree; fix todrive for print labels

* Standardize write_csv_file call in print labels

* Use cloudidentity_beta for calls that process memberKey

* Code cleanup
2021-05-06 08:10:36 -04:00
Jay Lee
4159a5cbb8 test on Python 3.10-beta 2021-05-04 12:27:52 -04:00
Jay Lee
2e78a291d4 test on Python 3.10 2021-05-04 12:22:22 -04:00
Jay Lee
3f1705c2a5 test on Python 3.10 2021-05-04 12:20:45 -04:00
Jay Lee
bb1f5f7059 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-05-04 11:57:33 -04:00
Jay Lee
75b7d0c419 Mmebership oops 2021-05-04 11:57:19 -04:00
Ross Scroggs
41a6c11c55 Handle TYPE_MESSAGE fields with durations or counts as a special case (#1375)
* Handle TYPE_MESSAGE fields with durations or counts as a special case

* Allow schema TYPE_ENUM field values with/without common prefix
2021-05-04 10:15:36 -04:00
Jay Lee
57d908e369 disable grouptree for now 2021-05-04 09:59:21 -04:00
Jay Lee
64274fdb33 more test fixes 2021-05-04 09:19:59 -04:00
Jay Lee
da919fd189 add few tests and fix one 2021-05-04 09:17:14 -04:00
Jay Lee
cfa25f12d3 6.02, admin.googleapis.com as test, MacOS universal2 build 2021-05-04 09:12:45 -04:00
Jay Lee
05bc1c1263 just stick with staic python versions 2021-05-04 08:38:56 -04:00
Jay Lee
939c79c37f use env variable 2021-05-04 08:32:06 -04:00
Jay Lee
d352ddeea1 use env variable 2021-05-04 08:30:56 -04:00
Jay Lee
72a683f2b1 Merge branches (#1377)
* Fix tests with apiclient >= 2.1

* disable MacOS 11 job

* info user grouptree and info cigroup membertree

* build updates
2021-05-04 08:12:35 -04:00
Ross Scroggs
784399f345 Handle TYPE_MESSAGE fields with durations or counts as a special case (#1374) 2021-05-02 08:22:29 -04:00
Ross Scroggs
710be4371b Fix typo (#1373) 2021-04-30 21:00:51 -04:00
Jay Lee
eece358aec Googleapiclient test fix (#1372)
* Fix tests with apiclient >= 2.1

* disable MacOS 11 job
2021-04-26 07:35:07 -04:00
Ross Scroggs
b43ada4f83 Add Cloud Search product name (#1370) 2021-04-23 09:02:15 -04:00
Jay Lee
9030af4faf Cloud Search SKU 2021-04-21 09:46:11 -04:00
Ross Scroggs
38b424b62e Add convertalias to delegate commands to convert aliases to primary (#1368)
* Add convertalias to delegate commands to convert aliases to primary

* New PyInstaller, won't build ARM without it
2021-04-21 09:38:07 -04:00
Jay Lee
1d9bf0b1aa Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-20 15:57:06 -04:00
Jay Lee
d3b7700c07 re-enable MacOS universal2 build 2021-04-20 15:56:27 -04:00
Ross Scroggs
d9513e159f Added support for localfile - in gam <UserTypeEntity> create|update drivefile (#1366)
This allows commands/programs to output data to stdout which can then be uploaded to a Google Drive file.
```
generatedata | gam user user@domain.com create drivefile drivefilename test.csv localfile - mimetype gsheet
```
2021-04-20 15:43:09 -04:00
Jay Lee
6ddfdf2514 print labels with counts 2021-04-20 15:37:21 -04:00
Jay Lee
478804bd5c Show/print full teamdrives info 2021-04-15 12:25:04 -04:00
Jay Lee
b61165a753 make sure we are using primary addresses for delegation 2021-04-10 21:28:19 -04:00
Ross Scroggs
b3814ae7be Document new Google Workspave Frontline license (#1363) 2021-04-08 16:42:07 -04:00
Jay Lee
019c363a74 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-08 13:10:46 -04:00
Jay Lee
da5f80e704 Workspace Frontline SKU 2021-04-08 13:10:33 -04:00
Ross Scroggs
b37b10e669 Restandardize chromehistory columns; fix chromepolicy (#1362)
* Restandardize chromehistory columns; fix chromepolicy

* Update chromehistory.py
2021-04-08 11:27:30 -04:00
Jay Lee
8ca92eda39 G Suite > Workspace in few more spots 2021-04-08 09:38:37 -04:00
Jay Lee
81dbbc36db build channel and platform maps dynamically to reduce future maintenance 2021-04-08 09:08:04 -04:00
Jay Lee
7065101b87 further refine chromehistory output 2021-04-08 08:14:00 -04:00
Jay Lee
00c302e545 further refine chromehistory output 2021-04-08 08:12:15 -04:00
Ross Scroggs
703530ce7f Standardize chrome history column order; update data transfer apps (#1361) 2021-04-08 07:50:52 -04:00
Jay Lee
7ac15042d8 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-07 15:27:32 -04:00
Jay Lee
a80ec52027 add more useful columns to chromehistory 2021-04-07 15:27:28 -04:00
Ross Scroggs
4da4132220 Validate chrome.users.chromebrowserupdates targetVersionPrefixSetting channel-offset (#1359)
* Validate chrome.users.chromebrowserupdates targetVersionPrefixSetting channel-offset

* Fix typo, add extended channel

Pass extended on to maintainer of :
https://developer.chrome.com/docs/versionhistory/reference/#channel-identifiers
2021-04-07 15:09:45 -04:00
Jay Lee
8682e66eb0 Update build.yml 2021-04-07 13:01:27 -04:00
Ross Scroggs
34bf205d37 Fix indentation (#1357) 2021-04-07 12:34:31 -04:00
Jay Lee
d6c2c6a2c3 Lazy load yubikey module to avoid lib errors when not in use 2021-04-07 09:27:13 -04:00
Jay Lee
f45639e6e2 switch User Invitations to DwD for now 2021-04-06 17:42:39 -04:00
Jay Lee
82968e29bf fix tests 2021-04-06 16:44:07 -04:00
Jay Lee
5d3d571545 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-06 16:35:49 -04:00
Jay Lee
6999c13877 allow Chrome pinning to relative version like 'stable-1' 2021-04-06 16:35:34 -04:00
Ross Scroggs
82a551e88f Have whatis check for unmanaged accounts (#1355)
* Have whatis check for unmanaged accounts

* Handle addition error in whatis
2021-04-06 16:29:08 -04:00
Ross Scroggs
1b1a0c876c Implement Chrome version history (#1354)
* Implement Chrome version history

* Update GamCommands.txt

* Use httpObj
2021-04-06 14:08:27 -04:00
Ross Scroggs
b262c4a898 Implement Issue #1345 (#1352)
* Implement Issue #1345

* Clean up verifynotinvitable
2021-04-06 13:26:19 -04:00
Jay Lee
22d1055d82 allow i 2021-04-06 12:37:48 -04:00
Jay Lee
fe38565a9a 3.9.4 2021-04-06 12:06:57 -04:00
Jay Lee
a25d14e83f pin to google api client 2.0.2 for now 2021-04-06 11:56:51 -04:00
Jay Lee
15b21dd8d7 Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-06 09:18:13 -04:00
Jay Lee
caedcde49b Update build.yml 2021-04-04 19:23:29 -04:00
Ross Scroggs
8091e23e00 Implement Chrome Management API calls (#1350)
* Implement Chrome Management API calls

* User start/end in print chromeappdevices

* Handle a Chrome version without a version field
2021-04-02 14:44:58 -04:00
Jay Lee
08e1090b15 Update build.yml 2021-04-02 14:43:51 -04:00
Jay Lee
f76b5cb2eb Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-04-02 08:11:05 -04:00
Dima Scherbakov
edc4311dcb Bump google-api-python-client requirements to v2.0.0 (#1346)
We pass static_discovery keyword arg that got introduced in v2 only.
2021-03-28 15:55:56 -04:00
Jay Lee
a613bff664 Update build.yml 2021-03-25 14:36:09 -04:00
Jay Lee
8f875d2a9c Update build.yml 2021-03-25 14:35:49 -04:00
Jay Lee
fb60e0b389 enable chromemanagement reporting api 2021-03-25 11:01:14 -04:00
Ross Scroggs
2199fb2828 Add header to gam show chromepolicy to display OU and printerid/appid (#1341) 2021-03-23 16:16:58 -04:00
Ross Scroggs
b7d052a6b3 Match ENUM fields and descriptions (#1340) 2021-03-23 08:53:43 -04:00
Ross Scroggs
b333816dc8 Update policies and user invitations (#1339)
* Update policies and user invitations

Show chrome policy schemas in sorted order

Change create userintervention to send userintervention  to be consistent with API
Add state and orderby option to print userinvitations

* Sort polices in show chromepolicies
2021-03-22 09:06:04 -04:00
Ross Scroggs
90160da042 When displaying printers, add orgUnitPath (#1338) 2021-03-19 14:19:40 -04:00
Ross Scroggs
6f2ebf8d2d Add info printer command/ChromePolicy cleanup (#1337)
* Add info printer command

* ChromePolicy cleanup

Make update chromepolicy orgunit default to / like delete and print
Add `filter <String>` to print chromeschema
Make update_policy code to set additionalTargetKeys consistent with delete_policy

I left verb at print for chromepolicy/chromeschema

* When printing schemasa, use ":" instead of " - "

* Fix print policy indentation

* Chrome policy cleanup

orgunit must be specified
Use verb show, add verb print later

* Recognize all ou forms to exit from schema mode

* Don't assign multiple variables on same line
2021-03-19 12:46:07 -04:00
Jay Lee
a65635365e Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-03-18 15:43:21 -04:00
Jay Lee
0eee6979b0 limit namespaces based on id type, quote userinvitation emails 2021-03-18 15:43:07 -04:00
Ross Scroggs
ec796e9f84 Update chrome policy ducumentation (#1336) 2021-03-18 14:55:57 -04:00
Jay Lee
aaed2a6d86 GAM 6.0 2021-03-18 11:20:18 -04:00
Ross Scroggs
0ea7c500e1 Two changes (#1335)
Allow DATE as schema field type
Allow gam check isinvitable <EmailAddress>
2021-03-18 10:40:22 -04:00
Jay Lee
d90c884cf2 chromepolicy cleanup 2021-03-18 10:01:35 -04:00
Jay Lee
93700c01a8 some chromepolicy fixes (some) 2021-03-17 19:29:03 -04:00
Jay Lee
1df5662d4f invitation not invite 2021-03-17 14:43:01 -04:00
Jay Lee
338eeba944 fix v on Pyinstaller version 2021-03-17 12:59:30 -04:00
Jay Lee
9651e4abb1 move to latest PyInstaller commit 2021-03-17 12:56:44 -04:00
Ross Scroggs
ed1f3400ac Various small cleanups (#1332) 2021-03-13 13:14:24 -05:00
Ross Scroggs
e9d9353fbb Drop redundant call (#1331) 2021-03-13 12:16:47 -05:00
Jay Lee
00adf4ca46 fix circular import 2021-03-13 11:38:09 -05:00
Ross Scroggs
870fc27c72 Clean up printer commands/documentation (#1330)
* Clean up printer commands/documentation

driverless has to take value so it can be changed from true to false
Drop separate deleteprinters command, merge into delete printers

* Printer delete update

Allow a list of printer IDs
Drop cros from crosfile and croscsvfile to avoid confusion; add cros back when calling getUsersToModify
2021-03-13 11:26:30 -05:00
Jay Lee
bd38b7479f Chrome Policy rough draft, further customer_id standardization 2021-03-13 10:02:53 -05:00
Jay Lee
a567599eae Use true customer_id with licensing API 2021-03-13 09:31:03 -05:00
Jay Lee
5e6f9353c2 explicity state customer format for new APIs and cleanup as necessary 2021-03-12 16:20:20 -05:00
Jay Lee
7de1179b7e Merge branch 'main' of https://github.com/jay0lee/GAM into main 2021-03-12 16:04:37 -05:00
Jay Lee
ea7c80c3a1 don't set pageSize for printers.list 2021-03-12 16:03:43 -05:00
Ross Scroggs
f252f757f1 UserInvitations clean up (#1329)
* UserInvitations clean up

This version of Cloud Identity API wants C in customer
I commented it out in case the developers figure out that it's inconsistent with devices and groups

Delete extraneous code

* Update userinvitations.py
2021-03-12 16:03:04 -05:00
Jay Lee
b27c63d0d7 cleanup enabledasa.txt 2021-03-12 15:58:24 -05:00
Jay Lee
bcce1a4472 disable few test for now 2021-03-12 15:50:14 -05:00
Jay Lee
9d9655512d stop spamming logs with every printer model 2021-03-12 14:22:42 -05:00
Jay Lee
7af75f31e4 no filter 2021-03-12 11:34:39 -05:00
Jay Lee
83f02c377f CUPS Printer API commands 2021-03-12 11:11:58 -05:00
Jay Lee
ce4f74bc61 New User Invitation API 2021-03-11 17:07:13 -05:00
Jay Lee
66651d0eed devices calls fixed 2021-03-11 16:41:38 -05:00
Jay Lee
ec0e143361 import sleep 2021-03-11 15:29:30 -05:00
Jay Lee
250e0188f7 disable devices in actions during outage 2021-03-11 15:18:37 -05:00
Jay Lee
3123e472fc fix actions spacing 2021-03-11 14:41:51 -05:00
Jay Lee
c12f7f1123 wait_for_mailbox command to ensure user has mailbox before attempting Gmail commands. 2021-03-11 14:36:47 -05:00
Ross Scroggs
7e706518c5 Two updates (#1327)
* Add writerscanshare to file characteristics

* In print filelist, include counts for permissions, parents, owners
2021-03-11 14:01:50 -05:00
Jay Lee
d8ca573983 wait for new user mailbox create 2021-03-11 11:15:12 -05:00
Jay Lee
2225625cd8 don't use googleapiclient static files 2021-03-11 10:25:51 -05:00
Jay Lee
89f0f01fd2 updated creds for GH Actions 2021-03-11 10:18:47 -05:00
Jay Lee
a36282d114 Update __init__.py 2021-03-05 11:52:47 -05:00
Jay Lee
a8c92b7f9a Use official yubikey-manager 4.0 2021-03-04 15:43:05 -05:00
Ross Scroggs
f505dac8f3 Add new Google Workspace for Education SKUs (#1326) 2021-02-25 18:18:21 -05:00
Jay Lee
8e4730a3bd Update README.md 2021-02-25 12:09:20 -05:00
Jay Lee
b094bb344b Update requirements.txt 2021-02-24 14:37:02 -05:00
Jay Lee
2685aa049d Update __init__.py 2021-02-24 14:36:39 -05:00
Jay Lee
b738d57433 Update build.yml 2021-02-19 13:24:16 -05:00
Jay Lee
539b870754 Update build.yml 2021-02-19 12:24:21 -05:00
Jay Lee
abeb0998ea Update build.yml 2021-02-19 12:14:31 -05:00
Jay Lee
82faddd985 fix win python version 2021-02-19 12:13:44 -05:00
Jay Lee
b8084c270e Python 3.9.2 2021-02-19 11:59:18 -05:00
Jay Lee
22c7da420c Update build.yml
OpenSSL 1.1.1j
2021-02-16 20:44:37 -05:00
Ross Scroggs
45a3c89b0b Add ou <OrgUnitPath> to print browsers (#1324) 2021-02-15 21:58:08 -05:00
Ross Scroggs
8fc9e6d1ee Reissue PR #1315; avoid trap when command <CrOSCommand> missing from issuecommand (#1323) 2021-02-14 15:17:27 -05:00
Jay Lee
7f0b286d8e Allow "rotating" to a YubiKey private key 2021-02-14 20:01:14 +00:00
Jay Lee
4f664df087 VERSION hack no longer needed in .spec either 2021-02-12 15:33:50 +00:00
Jay Lee
dff48e3146 Use newer, less hacky ykman 2021-02-12 15:26:04 +00:00
Jay Lee
0fefa19f80 fix the hack 2021-02-11 21:31:42 +00:00
Jay Lee
88e07ddbaa avoid warnings about cryptography int_from_bytes 2021-02-11 20:37:15 +00:00
Jay Lee
44a3ef0d70 brew not homebrew 2021-02-11 19:39:16 +00:00
Jay Lee
5e793f171f Install swig and pyscard for MacOS 2021-02-11 19:32:20 +00:00
Jay Lee
e9bc63bee8 tell pyinstaller to manually include ykman/VERSION 2021-02-11 19:17:14 +00:00
Jay Lee
5636876e42 another attempt at Windows yubikey prereqs 2021-02-11 19:08:33 +00:00
Jay Lee
f2f7f549b0 install swig directly on Win 2021-02-11 18:46:57 +00:00
Jay Lee
1fc6e4f781 install yubikey-manager on Windows 2021-02-11 17:49:24 +00:00
Jay Lee
d641458fb4 uprev cache to force rebuilds 2021-02-11 17:26:16 +00:00
Jay Lee
517d44fa3c fix package name: 2021-02-11 17:22:41 +00:00
Jay Lee
80ee0bf9a8 install ykman prereqs 2021-02-11 17:19:23 +00:00
Jay Lee
0934b70414 add required Linux packages to install yubikey-manager 2021-02-11 16:49:00 +00:00
Jay Lee
f74168e2c7 Support for YubiKey private key storage 2021-02-11 16:38:19 +00:00
Ross Scroggs
bf4a6e6cde Fix bug in print courses ownerId is not converted to ownerEmail (#1316) 2021-02-07 14:38:51 -05:00
Jay Lee
0e09675779 fix "gam print browsertokens" with no arguments 2021-02-03 20:21:25 -05:00
Jay Lee
40e92ca3d2 stop building on Big Sur for now 2021-02-03 19:57:30 -05:00
Jay Lee
e776919bfd GAM 5.33 2021-02-03 19:55:22 -05:00
Jay Lee
84bfeffe46 handle usernames only when GC_DOMAIN not set 2021-02-03 19:42:26 -05:00
Jay Lee
1360abbecb say whether GH requests are auth or unauth 2021-02-03 16:32:50 -05:00
Jay Lee
2a13accfe4 Use GHCLIENT env variable if avail 2021-02-03 16:16:03 -05:00
Jay Lee
e26dac3993 Windows support for gam-install.sh 2021-02-03 15:16:07 -05:00
Jay Lee
1b7a43e82b avoid building cd for user commands 2021-02-03 13:32:44 -05:00
Ross Scroggs
141aca9e25 Handle issue #1277 (#1312) 2021-01-28 12:10:56 -05:00
Jay Lee
4f99eb6f07 disable contact delegation test until we regen oauth2.txt for test accounts 2021-01-19 08:22:59 -05:00
Jay Lee
81075bb000 GAM 5.32, test contact delegation 2021-01-19 08:14:26 -05:00
Jay Lee
33057faaab include contact delegation discovery in pyinstaller exe 2021-01-19 07:53:09 -05:00
Ross Scroggs
28b831c6a2 Fix bug in calendar delete ACL, code assumed a role was included (#1308)
* Fix bug in calendar delete ACL, code assumed a role was included

Update documentation

* Add support for Chrome Browser Enrollment Tokens

create browsertoken always returns  `ERROR: 400: Invalid Input - invalid`
Maybe you can figure out what's going on
2021-01-18 17:03:58 -05:00
Jay Lee
ef4d3d2659 Update build.yml 2021-01-13 11:37:53 -05:00
Ross Scroggs
09c0c18fce Add GAM_CSV_ROW_DROP_FILTER (#1304)
* Add GAM_CSV_ROW_DROP_FILTER

Allow regex column names in GAM_CSV_ROW_FILTER and GAM_CSV_ROW_DROP_FILTER.
```
# Get users with managers
$ export GAM_CSV_ROW_FILTER="relations.*.type:regex:manager"
$ gam print users query "orgUnitPath='/Test'" relations
Getting all Users in G Suite account that match query (orgUnitPath='/Test') (may take some time on a large account)...
Got 17 Users: dick@domain.com - tom@domain.com
primaryEmail,relations,relations.0.value,relations.0.type,relations.1.value,relations.1.type
testuser1@domain.com,,admin@rdschool.net,manager,,
testuser2@domain.com,,testuser1@domain.com,manager,,

# Get users without managers
$ export GAM_CSV_ROW_DROP_FILTER="relations.*.type:regex:manager"
$ gam print users query "orgUnitPath='/Test'" relations
Getting all Users in G Suite account that match query (orgUnitPath='/Test') (may take some time on a large account)...
Got 17 Users: dick@domain.com - tom@domain.com
primaryEmail,relations,relations.0.value,relations.0.type,relations.1.value,relations.1.type
dick@domain.com,,,,,
harry@domain.com,,,,,
testadmin@domain.com,,,,,
...

* Update var.py to 5.31
2021-01-13 11:37:17 -05:00
Jay Lee
ff80150216 Update build.yml 2021-01-07 12:25:23 -05:00
Jay Lee
a8203baa50 another attempt at arm64 MacOS support 2021-01-06 09:20:10 -05:00
Jay Lee
aa33dc83d4 Use universal2 Python on Big Sur 2021-01-03 19:10:55 -05:00
Jay Lee
4155e2bb64 Update build.yml 2021-01-03 17:44:17 -05:00
Jay Lee
9660cafa99 allow OpenSSL 1.1.1g since python.org Python uses 2021-01-03 13:21:19 -05:00
Jay Lee
c55b9cfe96 new cache to force rebuilds 2021-01-03 13:16:45 -05:00
Jay Lee
78ea96767e Update build.yml 2021-01-03 13:13:50 -05:00
Jay Lee
d11d7a8ffc Universal2 build for Native Apple M1 CPU support 2021-01-03 13:10:12 -05:00
Jay Lee
bec789d2fb GAM 5.31 2021-01-03 12:52:01 -05:00
Ross Scroggs
0cda3fca31 More expireTime updates (#1299) 2020-12-31 11:38:14 -05:00
Jay Lee
4f8980184f Update build.yml 2020-12-31 11:35:33 -05:00
Tim Gates
ffa096d988 docs: fix simple typo, sysyem -> system (#1300)
There is a small typo in src/gam/controlflow.py.

Should read `system` rather than `sysyem`.
2020-12-27 20:33:11 -05:00
Ross Scroggs
6e1b1ed9d5 expireTime can now be updated (#1298) 2020-12-21 20:42:06 -05:00
Ross Scroggs
48526b815e Update GamCommands.txt (#1297) 2020-12-17 07:53:03 -05:00
Jay Lee
1ded893e7b Update build.yml 2020-12-16 20:41:35 -05:00
Jay Lee
c61bd01c0f Update build.yml 2020-12-16 20:38:49 -05:00
Jay Lee
f0adcc90c7 Update build.yml 2020-12-16 20:30:37 -05:00
Jay Lee
2abb13bb4c Update build.yml 2020-12-16 15:35:30 -05:00
Ross Scroggs
8f69c4c820 Make contact delegation consistent with email delegation (#1296)
Add auth to discovery document
uid allowed in create/delete as input is converted to primaryemail
2020-12-15 15:22:23 -05:00
Jay Lee
5652c52d96 Update build.yml 2020-12-14 21:55:55 -05:00
Jay Lee
ff29cc192e Update build.yml 2020-12-14 20:54:58 -05:00
Jay Lee
7428d0e734 Update build.yml 2020-12-14 20:51:32 -05:00
Jay Lee
caad9e999c also check on contact delegation delete 2020-12-14 14:49:34 +00:00
Jay Lee
24cb225381 remove arm attempt for now 2020-12-14 14:29:46 +00:00
Jay Lee
2e3195c5ee prevent bad contact delegations 2020-12-14 14:26:22 +00:00
Jay Lee
bfa039a612 Update build.yml 2020-12-12 17:24:15 -05:00
Jay Lee
49f8988912 Update build.yml 2020-12-12 17:22:53 -05:00
Jay Lee
7e214dbe3b Update build.yml 2020-12-12 17:19:21 -05:00
Jay Lee
42ad12d8d8 Update build.yml 2020-12-12 17:16:39 -05:00
Jay Lee
842e6ef788 Update build.yml 2020-12-12 17:15:27 -05:00
Jay Lee
56b87039c2 Update build.yml
attempt to build on aarch64 and armv6
2020-12-12 17:14:25 -05:00
Ross Scroggs
1767a0889d Handle updating individual annotated fields (#1294)
* Handle updating inv=dividual annotated fields

* Update cbcm.py
2020-12-11 10:07:37 -05:00
Ross Scroggs
3036366de5 Fix browser error messages, item name map in update browser (#1293)
* Update cbcm.py

Fix error message
$ gam update browser a27590cb-61fc-4ca3-8ef7-34bf736c4973 asset FileMakerServer

ERROR: asset is not a valid argument for "gam print browsers"

Fix item name map
$ gam update browser a27590cb-61fc-4ca3-8ef7-34bf736c4973 assetid FileMakerServer location Location notes Notes user User

ERROR: 400: Invalid JSON payload received. Unknown name "annotatedAssetid" at 'browser': Cannot find field. - invalid

* Fix more error messages
2020-12-11 09:20:03 -05:00
Jay Lee
a8f1031e0f Update README.md 2020-12-09 13:45:47 -05:00
Jay Lee
054107c3b9 Update README.md 2020-12-09 13:45:32 -05:00
Jay Lee
c478b22ab9 Update README.md 2020-12-09 13:45:17 -05:00
Jay Lee
2f712499ea Update README.md 2020-12-09 13:44:43 -05:00
Jay Lee
39b9622cdb Support for Contact Delegation API 2020-12-09 11:34:05 -05:00
Jay Lee
59a3a68357 Update gam-install.sh 2020-12-08 12:23:04 -05:00
Jay Lee
d920dbd79e Update build.yml 2020-12-08 10:49:38 -05:00
Jay Lee
49dd390c6b Update build.yml 2020-12-08 10:44:02 -05:00
Jay Lee
d20b4bc334 Update build.yml 2020-12-08 10:41:09 -05:00
Jay Lee
a973807e3e Update macos-before-install.sh 2020-12-08 10:06:53 -05:00
Jay Lee
431b5f4f30 Update macos-install.sh 2020-12-08 10:03:56 -05:00
Jay Lee
636799e567 Update macos-install.sh 2020-12-08 09:48:22 -05:00
Jay Lee
d003e3fa1b Update macos-install.sh 2020-12-08 09:39:21 -05:00
Jay Lee
07edbe6619 Update macos-install.sh 2020-12-08 09:32:04 -05:00
Jay Lee
dc4a5a05fe Update macos-before-install.sh 2020-12-08 09:29:29 -05:00
Jay Lee
a8c86eb53d Update macos-before-install.sh 2020-12-08 09:21:21 -05:00
Jay Lee
8ef9a62dc9 Update macos-install.sh 2020-12-08 08:28:40 -05:00
Jay Lee
29c9ed4135 Update macos-install.sh 2020-12-08 08:24:01 -05:00
Jay Lee
0426a4ca0d Update macos-install.sh 2020-12-08 08:16:42 -05:00
Jay Lee
af7bbe3cca Update macos-install.sh 2020-12-08 07:52:25 -05:00
Jay Lee
3c55153752 Update macos-install.sh 2020-12-08 07:42:36 -05:00
Jay Lee
a82ff4bb4e Update macos-before-install.sh 2020-12-07 22:36:10 -05:00
Jay Lee
73759e9611 Update macos-before-install.sh 2020-12-07 22:32:12 -05:00
Jay Lee
71d6d08f5a Update build.yml 2020-12-07 22:16:25 -05:00
Jay Lee
2f2be201a7 Update build.yml 2020-12-07 21:49:35 -05:00
Jay Lee
49aaca7172 Update build.yml 2020-12-07 21:47:06 -05:00
Jay Lee
f29c64984b Update macos-before-install.sh 2020-12-07 20:56:40 -05:00
Jay Lee
a50329edf3 Update macos-before-install.sh 2020-12-07 20:51:32 -05:00
Jay Lee
15d163abf4 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-12-07 10:07:23 -05:00
Jay Lee
852a116c9d move per-OS build scripts out of travis folder 2020-12-07 10:07:11 -05:00
Ross Scroggs
e9c18d0c01 Add info deviceuserstate (#1290)
* Fix typos in update deviceuserstate documentation

* Add info deviceuserstate

* Update info/update deviceusertstate documentation

* Update devices.py
2020-12-07 09:38:05 -05:00
Jay Lee
5e6d4ecb1c rearrange issue types 2020-12-07 09:33:22 -05:00
Jay Lee
97635311db Update issue templates 2020-12-07 09:28:46 -05:00
Jay Lee
3c7ddfd236 Update build.yml 2020-12-07 08:49:18 -05:00
Jay Lee
e0aa0eb4a3 Update build.yml 2020-12-07 08:46:45 -05:00
Jay Lee
8eba9d252f Update build.yml 2020-12-07 08:45:05 -05:00
Jay Lee
5966680a31 Update README.md 2020-12-07 08:41:43 -05:00
Jay Lee
eb1563b1e7 Goodbye Travis, thanks for all the fish 2020-12-07 08:40:09 -05:00
Ross Scroggs
84f52668b7 update deviceuserstate cleanup/documentation (#1289)
* update deviceuserstate cleanup

* Update GamCommands.txt
2020-12-06 22:24:48 -05:00
Ross Scroggs
cc60095344 Map / to %2F in group email address for Group Settings API (#1288)
* Map / to %2F in group email address for Group Settings API

* Make update deviceuserstate consistent with other deviceuser commands

gam update deviceuserstate [id] <DeviceUserID> ...
2020-12-06 20:56:49 -05:00
Jay Lee
5a1f237b30 make vaultcount a print command 2020-12-06 16:17:00 -05:00
Jay Lee
934a671344 "gam show vaultcount" - fixes #1271 2020-12-06 16:08:25 -05:00
Jay Lee
b81ea8e8c7 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-12-06 10:58:29 -05:00
Jay Lee
817920940e Fix crash on no device users 2020-12-06 10:58:01 -05:00
Jay Lee
e0f7ebbcba Update gam.spec 2020-12-06 10:08:19 -05:00
Ross Scroggs
8ce18960fe Multiple updates (#1273)
* Multiple updates

Add member to print cigroups|cigroup-members to select groups to display
Drop Google-Coordinate product ID
Update print|show driveactivity to Drive Activity API v2
Check for more parents than 1 in create|update drivefile
Update documentation
Allow times_to_check_status with gam getcommand cros
Display deviceId and commandId when issuing/getting commands

* Fix orgunit references in vault

* Rename member to enterprisemember in print cigroups|cigroup-members

Give error message indication the Enterprise license is required

* Add lastKnownNetwork to CrOS fields

* Soft fail when deleting user photo

* Fix bug in PR #1273
2020-12-05 21:54:26 -05:00
Jay Lee
6a879927a7 rebuild cache 2020-12-05 20:57:22 -05:00
Jay Lee
9c22114aa5 remove invalid scope 2020-12-05 20:40:03 -05:00
Jay Lee
add9bef046 fix spec 2020-12-05 20:36:28 -05:00
Jay Lee
64b6cfea93 forgot the delete 2020-12-05 20:27:29 -05:00
Jay Lee
c8e76d5727 CBCM API, Device API update Client State, v5.30 2020-12-05 19:44:48 -05:00
Jay Lee
4fda0b6aaa actions take 129 2020-12-05 12:12:50 -05:00
Jay Lee
4634237879 actions take 128 2020-12-05 12:07:09 -05:00
Jay Lee
5cc91fef53 actions take 127 2020-12-05 11:27:05 -05:00
Jay Lee
4a3c408ec5 actions take 126 2020-12-05 11:21:52 -05:00
Jay Lee
23f0c55053 actions take 125 2020-12-05 10:59:19 -05:00
Jay Lee
e1cf21328a actions take 124 2020-12-05 10:53:18 -05:00
Jay Lee
7ce5f982b3 actions take 123 2020-12-05 10:42:21 -05:00
Jay Lee
8fb9439eff actions take 122 2020-12-05 10:18:59 -05:00
Jay Lee
700e348dbd actions take 121 2020-12-05 10:06:40 -05:00
Jay Lee
91a86a8663 actions take 120 2020-12-05 09:58:36 -05:00
Jay Lee
293270c03d actions take 119 2020-12-05 09:38:51 -05:00
Jay Lee
af13113161 actions take 118 2020-12-05 09:00:30 -05:00
Jay Lee
59b9dca5ec actions take 117 2020-12-04 21:32:46 -05:00
Jay Lee
bc5d4e8efb actions take 116 2020-12-04 21:23:15 -05:00
Jay Lee
91111a62f6 actions take 115 2020-12-04 21:03:02 -05:00
Jay Lee
5525324620 actions take 114 2020-12-04 20:48:54 -05:00
Jay Lee
29bd632e45 actions take 113 2020-12-04 20:33:13 -05:00
Jay Lee
369e3c7269 actions take 112 2020-12-04 20:23:57 -05:00
Jay Lee
383fed7b3d actions take 111 2020-12-04 20:14:45 -05:00
Jay Lee
849dd8d436 actions take 110 2020-12-04 19:56:55 -05:00
Jay Lee
6340a35cf2 actions take 109 2020-12-04 19:46:04 -05:00
Jay Lee
1b2ea1d4bd actions take 108 2020-12-04 19:41:22 -05:00
Jay Lee
9087872bc2 actions take 107 2020-12-04 19:36:23 -05:00
Jay Lee
d914e06f42 actions take 106 2020-12-04 19:14:29 -05:00
Jay Lee
e12af0c870 actions take 105 2020-12-04 19:01:07 -05:00
Jay Lee
b0b9e2a7de actions take 104 2020-12-04 18:58:06 -05:00
Jay Lee
5b88d8b9ca actions take 103 2020-12-04 18:50:29 -05:00
Jay Lee
b7010b099f actions take 102 2020-12-04 18:46:32 -05:00
Jay Lee
5484d39d90 actions take 101 2020-12-04 18:44:52 -05:00
Jay Lee
181a2f8949 actions take 100 2020-12-04 18:41:47 -05:00
Jay Lee
cee0f97850 actions take 99 2020-12-04 18:33:54 -05:00
Jay Lee
fd91388b7a actions take 98 2020-12-04 18:29:41 -05:00
Jay Lee
beae08a99d actions take 97 2020-12-04 18:27:20 -05:00
Jay Lee
aef614aeae actions take 96 2020-12-04 18:18:48 -05:00
Jay Lee
c87bc39ad8 actions take 95 2020-12-04 18:15:24 -05:00
Jay Lee
d0b78f8e81 actions take 94 2020-12-04 18:09:20 -05:00
Jay Lee
f126cc1d6c actions take 93 2020-12-04 17:50:22 -05:00
Jay Lee
2d8c3427c4 actions take 92 2020-12-04 17:45:32 -05:00
Jay Lee
c2acd926af actions take 91 2020-12-04 17:42:05 -05:00
Jay Lee
b904d77497 actions take 90 2020-12-04 17:40:05 -05:00
Jay Lee
c093b92c0b actions take 89 2020-12-04 16:27:17 -05:00
Jay Lee
734b8bfd40 actions take 87 2020-12-04 16:09:26 -05:00
Jay Lee
e337d1f116 actions take 87 2020-12-04 16:01:30 -05:00
Jay Lee
8434ac1e2f actions take 85 2020-12-04 15:55:16 -05:00
Jay Lee
349cdbf582 actions take 84 2020-12-04 15:53:19 -05:00
Jay Lee
693aeae9e5 actions take 83 2020-12-04 15:27:24 -05:00
Jay Lee
e4ea8e156d actions take 82 2020-12-04 15:07:20 -05:00
Jay Lee
ca2b7dd674 actions take 81 2020-12-04 14:31:35 -05:00
Jay Lee
8a744aa7fc actions take 80 2020-12-04 14:29:15 -05:00
Jay Lee
7f2beb4d80 actions take 79 2020-12-04 14:24:25 -05:00
Jay Lee
103c421b31 actions take 78 2020-12-04 14:21:19 -05:00
Jay Lee
0f4238e9a7 actions take 78 2020-12-04 14:15:59 -05:00
Jay Lee
c9508d2dac actions take 77 2020-12-04 14:00:22 -05:00
Jay Lee
5d293b4318 actions take 76 2020-12-04 13:49:40 -05:00
Jay Lee
3f4b814c0b actions take 75 2020-12-04 13:48:28 -05:00
Jay Lee
aca71d8db1 actions take 74 2020-12-04 13:08:19 -05:00
Jay Lee
87dbe3c945 actions take 73 2020-12-04 12:43:49 -05:00
Jay Lee
c254fc946f actions take 72 2020-12-04 12:41:24 -05:00
Jay Lee
5a4718eae8 actions take 71 2020-12-04 12:36:57 -05:00
Jay Lee
935c52f291 actions take 70 2020-12-04 12:25:40 -05:00
Jay Lee
04fe93d3b8 actions take 69 2020-12-04 12:21:49 -05:00
Jay Lee
22f279e309 actions take 68 2020-12-04 12:07:00 -05:00
Jay Lee
a0cff87e5f actions take 67 2020-12-04 12:02:06 -05:00
Jay Lee
943d327975 actions take 66 2020-12-04 11:55:11 -05:00
Jay Lee
6c4aced95e actions take 65 2020-12-04 11:52:43 -05:00
Jay Lee
ad80fd2a91 actions take 64 2020-12-04 09:44:16 -05:00
Jay Lee
43d50734a4 actions take 63 2020-12-04 09:29:19 -05:00
Jay Lee
52d6057365 actions take 62 2020-12-04 09:20:39 -05:00
Jay Lee
8dd5a5dd8a actions take 61 2020-12-04 09:19:20 -05:00
Jay Lee
4799b33e0e actions take 60 2020-12-04 09:16:52 -05:00
Jay Lee
d25ae7de81 actions take 59 2020-12-04 09:15:24 -05:00
Jay Lee
83cbbbf0b7 actions take 58 2020-12-04 09:13:43 -05:00
Jay Lee
4794578688 actions take 57 2020-12-04 09:12:34 -05:00
Jay Lee
446da392d9 actions take 56 2020-12-04 09:10:21 -05:00
Jay Lee
07cbd4cdbb actions take 56 2020-12-04 09:09:09 -05:00
Jay Lee
f17cbdc111 actions take 55 2020-12-04 09:03:11 -05:00
Jay Lee
28c5d277a0 actions take 55 2020-12-04 08:59:51 -05:00
Jay Lee
939840b702 actions take 54 2020-12-04 05:12:19 -05:00
Jay Lee
78485ae4e9 actions take 53 2020-12-04 05:09:24 -05:00
Jay Lee
cc47a93872 actions take 52 2020-12-04 05:05:25 -05:00
Jay Lee
af122eeb5c actions take 51 2020-12-04 04:51:46 -05:00
Jay Lee
ec118968ed actions take 50 2020-12-04 04:50:12 -05:00
Jay Lee
2de416fe81 actions take 49 2020-12-04 04:49:05 -05:00
Jay Lee
d10a3b91e3 actions take 48 2020-12-04 04:46:39 -05:00
Jay Lee
cdadf68f30 actions take 47 2020-12-04 04:37:37 -05:00
Jay Lee
900a123141 actions take 46 2020-12-04 04:35:20 -05:00
Jay Lee
4b2f9488ce actions take 45 2020-12-04 04:31:34 -05:00
Jay Lee
02d7f45988 actions take 44 2020-12-03 21:29:48 -05:00
Jay Lee
cc34dbb88e actions take 43 2020-12-03 21:23:47 -05:00
Jay Lee
5e9d99083c actions take 43 2020-12-03 21:21:23 -05:00
Jay Lee
295bf74a1b actions take 42 2020-12-03 21:16:59 -05:00
Jay Lee
7928437dc6 actions take 41 2020-12-03 21:10:59 -05:00
Jay Lee
83283b7b6b actions take 40 2020-12-03 21:08:40 -05:00
Jay Lee
09a289b4c4 actions take 39 2020-12-03 21:05:22 -05:00
Jay Lee
6b940b9d01 actions take 38 2020-12-03 21:01:46 -05:00
Jay Lee
cb492e0183 actions take 37 2020-12-03 20:41:26 -05:00
Jay Lee
92799d57ae actions take 36 2020-12-03 20:40:24 -05:00
Jay Lee
066100f218 actions take 35 2020-12-03 20:06:02 -05:00
Jay Lee
cd4dd44004 actions take 34 2020-12-03 20:02:32 -05:00
Jay Lee
40a2fdb7fd actions take 33 2020-12-03 16:34:26 -05:00
Jay Lee
b60cf11668 actions take 32 2020-12-03 15:41:42 -05:00
Jay Lee
0fa617c580 actions take 31 2020-12-03 15:39:55 -05:00
Jay Lee
1cfa08612e actions take 30 2020-12-03 15:38:57 -05:00
Jay Lee
2cebef9d4b actions take 29 2020-12-03 15:37:40 -05:00
Jay Lee
c75313cdf4 actions take 28 2020-12-03 14:33:12 -05:00
Jay Lee
ae1eaac037 actions take 27 2020-12-03 14:27:25 -05:00
Jay Lee
01465a898a actions take 26 2020-12-03 14:26:06 -05:00
Jay Lee
d6a7917ffd actions take 25 2020-12-03 14:04:23 -05:00
Jay Lee
d9946088ab actions take 24 2020-12-03 13:46:23 -05:00
Jay Lee
a2ad6a1037 actions take 23 2020-12-03 13:43:23 -05:00
Jay Lee
34e240b40a actions take 22 2020-12-03 12:42:36 -05:00
Jay Lee
ca1f33ade6 actions take 21 2020-12-03 12:26:03 -05:00
Jay Lee
d8bddb1c21 actions take 20 2020-12-03 12:05:25 -05:00
Jay Lee
64bab14483 actions take 19 2020-12-03 11:55:37 -05:00
Jay Lee
2d1830f4fc actions take 18 2020-12-03 11:53:00 -05:00
Jay Lee
ab00f2bd42 actions take 17 2020-12-03 11:50:30 -05:00
Jay Lee
6d9505a4c0 actions take 16 2020-12-03 11:42:38 -05:00
Jay Lee
40e3cb8ce5 actions take 15 2020-12-03 11:40:39 -05:00
Jay Lee
4783ec6696 actions take 14 2020-12-03 11:36:52 -05:00
Jay Lee
3bd746fe91 actions take 13 2020-12-03 11:36:09 -05:00
Jay Lee
a91a82eecc actions take 12 2020-12-03 11:34:23 -05:00
Jay Lee
a9564583cb actions take 11 2020-12-03 11:33:01 -05:00
Jay Lee
f988c8879e actions take 10 2020-12-03 11:28:29 -05:00
Jay Lee
825cad81a2 actions take 9 2020-12-03 11:22:58 -05:00
Jay Lee
b9c0ea065a actions take 8 2020-12-03 11:07:52 -05:00
Jay Lee
50ef633573 actions take 7 2020-12-03 11:07:05 -05:00
Jay Lee
10202df7d7 actions take 6 2020-12-03 11:05:31 -05:00
Jay Lee
a7815b41db actions take 5 2020-12-03 11:03:45 -05:00
Jay Lee
cf467eb868 actions take 4 2020-12-03 10:54:35 -05:00
Jay Lee
a3be19154f actions take 3 2020-12-03 10:53:11 -05:00
Jay Lee
a7c19c689c actions take 2 2020-12-03 10:50:54 -05:00
Jay Lee
1c78e3aac0 first test for GitHub actions 2020-12-03 10:47:26 -05:00
Jay Lee
b9cc3d77b3 recent commit that improves PyInstaller support for 3.9 2020-11-11 09:10:52 -05:00
Jay Lee
1feb81adf3 Update project-apis.txt 2020-11-03 14:38:17 -05:00
Jay Lee
fd937758e6 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-10-15 17:40:39 -04:00
Jay Lee
fcc3d674c2 command payload value is a JSON string, not a dict 2020-10-15 17:40:26 -04:00
Jay Lee
ce74264a01 Update .travis.yml 2020-10-15 11:23:15 -04:00
Jay Lee
aaf6448563 Support for Chrome OS remote device commands 2020-10-15 07:05:45 -04:00
Ross Scroggs
4a696635f5 Fix display of contentRestrictions in print filelist (#1268)
Update documentation
2020-10-09 17:55:30 -04:00
Jay Lee
beb14befca merge 2020-10-09 14:39:02 -04:00
Jay Lee
c91703364d Workspace SKU updates 2020-10-09 14:31:30 -04:00
Ross Scroggs
597cea17cd Add gshortcut to MIME type choices to be consistent (#1266)
Add third party MIME type shortcut
2020-10-09 12:39:06 -04:00
Ross Scroggs
9585f6c598 reason not valid woth readonly false; add contentrestrions to file field list (#1263) 2020-10-09 11:28:27 -04:00
Jay Lee
e356fe3e85 Update gam-install.sh 2020-10-09 11:25:35 -04:00
Ross Scroggs
55e5b86ec4 Make labels display useful (#1260)
With the existing code you get these columns:

labels.cloudidentity.googleapis.com/groups.discussion_forum,labels.cloudidentity.googleapis.com/groups.security

but there is no data in the columns so you can't tell whcih groups have which values; by translating '' to True you can.
2020-10-09 10:33:03 -04:00
Max Mathieu
bf29a56aeb Updated branding (#1261)
* Update branding

* Update branding

* Update branding

* Update branding

* Update branding

* Update var.py
2020-10-09 10:32:37 -04:00
Jay Lee
07c57d4197 add support for Drive shortcut creation 2020-10-09 10:31:21 -04:00
Jay Lee
146db31cb5 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-10-09 09:11:28 -04:00
Jay Lee
14239fcd47 Support Drive content restrictions 2020-10-09 09:11:14 -04:00
Jay Lee
8dc6a17295 Update .travis.yml 2020-10-07 13:51:25 -04:00
Jay Lee
76f9a6c746 Update .travis.yml 2020-10-06 08:42:05 -04:00
Jay Lee
eb155a5690 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-10-05 09:46:39 -04:00
Jay Lee
b78575aa8f Initial support for group membership expiration 2020-10-05 09:46:24 -04:00
Ross Scroggs
91a5cd5c69 Fix bug in sync devices (#1259) 2020-10-03 19:52:22 -04:00
Jay Lee
dd3e6420b6 Upgrade PyInstaller and hopefully fix Linux binary sizes 2020-10-01 09:30:29 -04:00
Jay Lee
d6a65861e0 GAM 5.22 2020-10-01 09:08:46 -04:00
Jay Lee
fe77ff3f60 stop pypy and nightly source tests that have been failing for awhile anyway 2020-10-01 08:36:00 -04:00
Jay Lee
326cccd525 Stop using batch for licensing
Licensing API seems to throw lots of errors on large batch and we weren't retrying temp errors. For now just stick with serial methods.
2020-10-01 07:36:23 -04:00
Ross Scroggs
b41ca0f0be More bug/pylint cleanup (#1258)
* More bug/pylint cleanup

* pylint cleanup groups.py

* Update GamCommands.txt
2020-09-30 16:56:42 -04:00
Jay Lee
02fa092775 fix reporting orgunit scoping 2020-09-30 16:44:48 -04:00
Ross Scroggs
57860dc5a6 Fix issue #1256 (#1257) 2020-09-30 09:43:42 -04:00
Jay Lee
e28f2fb8cd limit scope of devices listed 2020-09-29 17:23:09 -04:00
Jay Lee
0423dd4069 move device delete later 2020-09-29 17:11:14 -04:00
Ross Scroggs
5e38137916 Add view all|company|personal to print devices (#1254)
* Add view all|company|personal to print devices

Update documentation

* sync devices cleanup

* Update sync devices documentation

* Cleanup;

The advantage here is that they will be no filter errors unless you specify a particular view and a filter that doesn't match

* Simplify selection of devices to print

Default - all
Positve choices
Negative choices - backwards compatible
2020-09-29 14:47:06 -04:00
Ross Scroggs
dc90fb9c94 Update to new DwD page (#1253) 2020-09-26 10:16:08 -04:00
Jay Lee
2e2575c360 send email 2020-09-25 19:37:07 -04:00
Ross Scroggs
2732abbc93 Make sync license consistent with other license commands (#1252) 2020-09-25 08:23:07 -04:00
Jay Lee
e9d5d676a5 Update .travis.yml 2020-09-24 10:46:15 -04:00
Jay Lee
18bab4044e 'gam sync licenses' command, move licensing to separate file 2020-09-24 09:49:49 -04:00
Jay Lee
2ccc4a6932 Update .travis.yml 2020-09-24 08:06:23 -04:00
Jay Lee
d01d02e700 Update .travis.yml 2020-09-23 12:33:25 -04:00
Sean Young
56c6f6cabe Fix issue with zsh not loading gam (#1245)
Co-authored-by: syoung-quizlet <sean.young@quizlet.com>
2020-09-22 14:03:14 -04:00
Ross Scroggs
adb1e58937 GAM_ADMIN_EMAIL overrides oauth2.txt value (#1249)
pylint cleanup unused imports
2020-09-22 12:43:53 -04:00
Ross Scroggs
a59c893652 Device updates (#1247)
* Device updates

Make info device consistent with action device: id keyword is optional
Add nodeviceusers to print devices
pylint cleanup

* Fix documentation

* Sdd orderby to print devices

* Device assetTag cleanup

* Fix typo, appease pylint

* Strip C from customer ID
2020-09-21 10:14:34 -04:00
Ross Scroggs
93bcd5f43b Fix bug, handle missing required argument (#1246) 2020-09-19 12:37:40 -04:00
Ross Scroggs
d7453a7841 filter is a builtin Python function (#1244)
devices.py:118:4: W0622: Redefining built-in 'filter' (redefined-builtin)
2020-09-18 15:28:42 -04:00
Ross Scroggs
4fe3dc052a Delete duplicate code (#1243) 2020-09-18 15:00:25 -04:00
Jay Lee
c88c755785 MacOS 10.15.6, fix groups+DASA+user info 2020-09-18 10:23:55 -04:00
Jay Lee
31f83d33f5 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-09-18 07:38:45 -04:00
Ross Scroggs
597256d048 Ensure that customer_id, domain and an admin email address are present for DASA (#1242)
* Ensure that customer_id, domain and an admin email address are present for DASA

* Fix typos
2020-09-18 07:38:38 -04:00
Jay Lee
62594a2898 add id to device delete command 2020-09-17 08:16:05 -04:00
Jay Lee
00582d486c serial not serialnumber for filter 2020-09-17 08:04:18 -04:00
Jay Lee
cda626b01c minor fixes to devices, more travis testing 2020-09-17 07:55:07 -04:00
Jay Lee
7d84da1520 GAM 5.20 2020-09-16 16:54:33 -04:00
Jay Lee
11b96b488f label xcode universal as testing in travis 2020-09-16 16:48:40 -04:00
Jay Lee
1853c0ca32 Update .travis.yml 2020-09-16 16:09:19 -04:00
Jay Lee
0b8fb177c4 Update osx-install.sh 2020-09-16 16:04:57 -04:00
Jay Lee
4e80434956 simple print test for devices 2020-09-16 15:35:08 -04:00
Jay Lee
c2f53577ab Cloud Identity Devices API, 5.20 2020-09-16 15:33:55 -04:00
Jay Lee
4974150357 Update .travis.yml 2020-09-16 08:12:43 -04:00
Jay Lee
1586d97295 Update .travis.yml 2020-09-15 18:02:16 -04:00
Jay Lee
5f65898c33 fix travis paths 2020-09-15 12:11:53 -04:00
Jay Lee
88e7941db3 fix travis creds 2020-09-15 11:48:31 -04:00
Jay Lee
6c715263e0 svars-write 2020-09-15 11:46:31 -04:00
Jay Lee
7088962d44 redo travis auth setup 2020-09-15 11:40:46 -04:00
Jay Lee
429bb0957d Update svars-write.py 2020-09-15 09:16:54 -04:00
Jay Lee
424fda55dd move oauth info earlier 2020-09-14 14:20:17 -04:00
Ross Scroggs
1b26a11281 Complete adminrole commands; add signout and turnoff2sv (#1237)
* Complete create admintole

* Add update/delete to adminroles

* Update privileges options

* Separate create/update adminrole

* Sdd signout/turnoff2sv commands

* Move signout, turn_off_2sv to new users.py
2020-09-14 12:58:52 -04:00
Jay Lee
56f52c8623 Update .travis.yml 2020-09-14 11:47:07 -04:00
Ross Scroggs
908edff878 Fix error; DASA suggestions (#1236)
* userKey and customer is an invalid combination; userkey and domain is allowed

* DASA suggestions

I would not use OAUTHFILE to distinguish between normal/DASA, it seems to me that this might lead to oauth2service.json getting deleted by accident.

By using enabledasa.txt you can flip between the two modes easily.

* Update __init__.py

Is this what yuou meant?
2020-09-11 11:33:06 -04:00
Jay Lee
487e1dc4c1 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-09-10 11:36:16 -04:00
Jay Lee
244398e096 Initial support for delegated admin service accounts (DASA)
Google now allows GCP service accounts to be granted delegated admin status for a G Suite domain.
To use this, admins can grant the service account email address delegated admin rights in the admin console
and then set some environment variables for GAM to use:

OAUTHFILE=oauth2service.json
GA_DOMAIN=example.com   # your primary domain name in Google
CUSTOMER_ID=1d80dfc     # admin.google.com > Account > Account settings > Customer ID
2020-09-10 11:25:59 -04:00
Ross Scroggs
fafd9e2bd8 Fix code (#1232)
* Correct argmument

* Fix code
2020-09-08 11:47:06 -04:00
djeckle
367ea4df39 Fix seats argument reference for resoldsubscription. (#1233) 2020-09-08 11:46:28 -04:00
Jay Lee
630abbd0fc merge cleanup 2020-09-06 09:53:52 -04:00
Jay Lee
fe20428a14 initial support for security and dynamic groups 2020-09-06 09:47:46 -04:00
Jay Lee
0e36681ec1 Update .travis.yml 2020-08-31 10:20:14 -04:00
Ross Scroggs
884cbc52a3 Clean up Cloud Identity groups/Fix get drivefile csvsheet (#1228)
* Clean up Cloud Identity groups

* Fix issue in get drivefile

Updated code in downloadDriveFile to handle unexpected data in spreadsheetUrl after /edit
```
https://docs.google.com/spreadsheets/d/%3Cdocidhere%3E/edit?ouid=1234567890123456&amp;urlBuilderDomain=mydomain.edu
```
2020-08-27 14:35:48 -04:00
Jay Lee
88c17af8ef Merge branch 'master' of https://github.com/jay0lee/GAM 2020-08-27 14:33:51 -04:00
Jay Lee
549670e45f some APIs now using v2 discovery URLs 2020-08-27 14:31:47 -04:00
Jay Lee
4fa0e58e80 Update var.py 2020-08-21 08:42:01 -04:00
Jay Lee
d60b9b2b47 use new DwD page 2020-08-17 12:04:44 -04:00
Ross Scroggs
3368bd3879 Two fixes (#1226)
* Set maxtasksperchild to help avoid hangs especially on Windows

* Fix function reference
2020-08-11 12:47:03 -04:00
Jay Lee
dbc47c5420 Update .travis.yml 2020-07-20 16:02:04 -04:00
Jay Lee
f86b5a2bf3 Update .travis.yml 2020-07-20 16:01:34 -04:00
Jay Lee
0e0c126726 Python 3.8.4, update PyInstaller commit 2020-07-14 11:37:34 -04:00
Ross Scroggs
45e0e57668 Several fixes (#1218)
Have create project use http object that uses CA_FILE
Fix calls to functions in new source modules
Put deprovisionupgradetransfer back
2020-07-02 04:38:40 -04:00
Jay Lee
7ee1edbab8 fix line end 2020-06-28 20:36:28 -04:00
Jay Lee
747ad9f29a fix test create/show unicode labels 2020-06-28 19:45:20 -04:00
Jay Lee
7e128dc6c3 yet another patchelf correction 2020-06-28 19:20:14 -04:00
Jay Lee
5e1352077a one more for patchelf 2020-06-28 19:13:37 -04:00
Jay Lee
22fc54b2fa fix patchelf download/extract 2020-06-28 19:02:24 -04:00
Jay Lee
b67e068991 fix bonehead mistake 2020-06-28 18:42:24 -04:00
Jay Lee
40f5bb07d8 fix gs objects 2020-06-28 18:38:27 -04:00
Jay Lee
c1063d1967 Initial CloudIdentity Groups work, more APIs to own files 2020-06-28 17:26:21 -04:00
Ross Scroggs
964cd19949 Update CrOS actions (#1217) 2020-06-27 12:31:03 -04:00
Jay Lee
f55305a800 action deprovision_upgrade_transfer 2020-06-24 11:11:45 -04:00
Ross Scroggs
8392856ec5 Move trap statement up so it is seen before any exit command (#1215) 2020-06-24 08:16:23 -04:00
Jay Lee
01e1551838 move domain functions to own file 2020-06-19 19:34:34 -04:00
Jay Lee
d3f042433d move asps, domainaliases functions to own file 2020-06-19 19:07:51 -04:00
Jay Lee
0e5635cc2a fix project creation for @gmail.com accounts 2020-06-18 11:17:46 -04:00
Jay Lee
73677544a3 GAM 5.11 2020-06-17 14:21:49 -04:00
Jay Lee
7c46d8548e servicemanagement API to serviceusage API 2020-06-17 13:30:08 -04:00
Ross Scroggs
186381426a Update GamCommands.txt (#1211) 2020-06-06 09:35:24 -04:00
Ross Scroggs
af1e695661 Clean up csvtest (#1209)
Let your formatter redo 13382/13386, I don't understand its rules
2020-06-05 13:37:44 -04:00
Jay Lee
4ccd51269a Support base64-sha1 and base64-md5 user passwords
This allows pulling md5 and sha-1 passwords stored in OpenLDAP format into G Suite. This example commands set user password to "helloworld".

gam update user user@example.com password "{SHA}at+xg6SiyUovktq1redipHiJpaE=" base64-sha1
2020-06-04 15:59:06 -04:00
Jay Lee
560cfe225f wMerge branch 'master' of https://github.com/jay0lee/GAM 2020-06-03 13:30:56 -04:00
Jay Lee
e9e4c3d333 Add a 'gam csvtest' command to help users understand CSV batch processing 2020-06-03 13:30:50 -04:00
Ross Scroggs
dbca6e3b88 Handle 0 users in update group (#1207) 2020-06-01 16:05:26 -04:00
Jay Lee
ad465ed20c MacOS XCode 11.5 2020-06-01 15:35:08 -04:00
Jay Lee
9370f7ce15 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-06-01 13:45:13 -04:00
Jay Lee
d9151a866b 3.9 dev, allow Python 3.9 to fail, Focal is now passing 2020-06-01 13:44:12 -04:00
Ross Scroggs
7937fd00d4 Clean up group_inde (#1203) 2020-05-26 15:09:15 -04:00
Eduardo
d2199a5b9c include includeDerivedMembership option for group sync (#1198)
* include includeDerivedMembership option

in command gam course xxx sync students|teachers group yyyy
I add alternative option group_inde (INclude DErived)

* Avoid interference of new includeDerivedMembership

taers232c suggestion to avoid unexpected interference
2020-05-26 14:30:11 -04:00
Ross Scroggs
6e765325c1 Fix bug where user all was not properly recognized (#1202) 2020-05-26 14:29:10 -04:00
Jay Lee
18119b3d64 disable secrets for focal 2020-05-26 09:56:41 -04:00
Jay Lee
378a7c2d6c allow focal to fail 2020-05-24 09:09:18 -04:00
Jay Lee
1270a315b2 it wasn't the unsafe flags... 2020-05-21 10:18:36 -04:00
Jay Lee
931b2cc700 temp disable Python optimizations 2020-05-21 10:00:51 -04:00
Jay Lee
e145ac0ad1 hold on ssh-server 2020-05-21 09:19:52 -04:00
Jay Lee
ab8e882e94 focal 2020-05-21 09:03:16 -04:00
Jay Lee
b66d671b74 try upgrading pyinstaller commit 2020-05-21 08:29:55 -04:00
Jay Lee
f662a13778 another attempt to fix focal 2020-05-20 11:29:17 -04:00
Jay Lee
845aa122e1 unmute apt-get upgrade so it doesn't timeout 2020-05-20 11:07:59 -04:00
Jay Lee
bb19336d06 silence apt-get again 2020-05-20 10:52:53 -04:00
Jay Lee
774948cf9d try apt-get upgrade instead of dist-upgrade 2020-05-20 10:27:18 -04:00
Jay Lee
e26e077c83 no apt-get dist-upgrade for focal 2020-05-20 10:17:02 -04:00
Jay Lee
f264ffd040 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-05-20 10:02:07 -04:00
Jay Lee
7e16e4880b Update .travis.yml 2020-05-20 09:53:49 -04:00
Ross Scroggs
dd1ee6ff44 Fix bug (#1196)
```
$ gam calendar testsimple@rdschool.org addevent start 2020-05-17T08:00:00-07:00 end 2020-05-17T09:00:00-07:00  recurrence "RRULE:FREQ=WEEKLY;WKST=SU;COUNT=13;BYDAY=MO" summary "Monday Morning Meeting"
Traceback (most recent call last):
  File "/Users/Ross/Documents/GoogleApps/GAMO/gam.py", line 11, in <module>
    main(sys.argv)
  File "/Users/Ross/Documents/GoogleApps/GAMO/gam/__main__.py", line 45, in main
    sys.exit(gam.ProcessGAMCommand(sys.argv))
  File "/Users/Ross/Documents/GoogleApps/GAMO/gam/__init__.py", line 14413, in ProcessGAMCommand
    gapi_calendar.addOrUpdateEvent('add')
  File "/Users/Ross/Documents/GoogleApps/GAMO/gam/gapi/calendar.py", line 350, in addOrUpdateEvent
    sendUpdates, body = getEventAttributes(i, calendarId, cal, body, action)
  File "/Users/Ross/Documents/GoogleApps/GAMO/gam/gapi/calendar.py", line 537, in getEventAttributes
    if not timeZone:
UnboundLocalError: local variable 'timeZone' referenced before assignment
```
2020-05-16 09:56:48 -04:00
Jay Lee
90d628cc75 Remove deprecated CloudPrint commands 2020-05-15 18:35:48 -04:00
Jay Lee
d5a0b33f04 add MacOS 10.15 check 2020-05-15 08:16:21 -04:00
Ross Scroggs
470e7826f1 Set proper default value (#1194) 2020-05-14 17:22:04 -04:00
Jay Lee
54e9ae568f fix call to _check_full_data_available 2020-05-14 14:04:15 -04:00
Jay Lee
d2ae5173fc move variable out of loop 2020-05-14 12:58:36 -04:00
Ross Scroggs
e9b5133151 Update gam report usageparameters to account for Google API change (#1191)
* Update gam report usageparamaters to account for Google API change

* Use _check_full_data_available in report usageparameters

* Code cleanup

* Code cleanup part 2

* Code cleanup part 3
2020-05-14 12:55:38 -04:00
Jay Lee
7959d35f3f Fix listing of G Suite Essentials SKU 2020-05-14 10:19:50 -04:00
Jay Lee
b42dfb2021 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-05-14 09:39:58 -04:00
Jay Lee
b68b773b95 Handle G Suite Essentials unverified domain better 2020-05-14 09:38:21 -04:00
Jay Lee
e89a926d53 MacOS 10.15 Travis build 2020-05-14 09:31:46 -04:00
Jay Lee
6132c03893 Update .travis.yml 2020-05-14 07:17:22 -04:00
Ross Scroggs
2db54fc67a expirationTime on ACL must be set in an update (#1189) 2020-05-13 13:53:36 -04:00
Jay Lee
96095453d5 GAM 5.10 2020-05-13 13:01:37 -04:00
Jay Lee
32c02c36c9 Allow disabling short URLs with noshorturls.txt file 2020-05-13 13:00:51 -04:00
Jay Lee
1eb7ce3896 fix gam info counts 2020-05-13 12:26:06 -04:00
Jay Lee
da4f29049b fix handling of empty usage reports. Fixes #1188 2020-05-13 09:02:13 -04:00
Jay Lee
d46dd46732 GAM 5.09 2020-05-12 14:23:29 -04:00
Jay Lee
8eb72ae6e7 Fix customer/user report 2020-05-12 11:55:18 -04:00
Ross Scroggs
6a421d3b78 Add checking for 404 errors that aborts create project (#1183)
My apologies. I fixed my version, then added the code in your __init__.py to loop and wait for the not found error to disappear. By then, however, the error stopped occurring and I didn't notice that errors.py wasn't recognizing the error.
2020-05-12 09:34:21 -04:00
Jay Lee
f71a14126e Update .travis.yml 2020-05-09 12:17:59 -04:00
Jay Lee
35c2024eec older reports 2020-05-08 16:57:38 -04:00
Jay Lee
e570341f93 keep folder name short 2020-05-07 14:33:23 -04:00
Jay Lee
45a9f97fc8 roll PyInstaller back to pre-bootloader work that may be causing error messages in GAM 2020-05-07 13:44:04 -04:00
Jay Lee
6238a4c127 GAM 5.08 2020-05-07 12:01:00 -04:00
Ross Scroggs
e38ec13dac Update report documentation/fix gam create project (#1179)
* Update report documentation

* Wait for service account creation to complete

* Update __init__.py
2020-05-07 11:59:52 -04:00
Ross Scroggs
0268858784 Yet another OAuth2 token error (#1177)
* Yet another OAuth2 token error

What exactly are the circumstances that cause this?

* The dog ate it
2020-04-30 12:46:55 -04:00
ejochman
0bd4eefeca Auto-format all files using yapf and pre-commit (#1173)
Automatic fixes produced by yapf formatting using `--style=google`, as
well as common pre-commit checks such as trailing whitespace removal,
double quote fixer, and newlines at the end of a file.
2020-04-28 16:59:47 -04:00
Ross Scroggs
216f2920b9 Yet another OAuth2 token error (#1171)
* invalid_grant: The account has been deleted - Recently deleted, still exists
* invalid_request: Invalid impersonation &quot;sub&quot; field - Long gone
2020-04-28 09:38:43 -04:00
Ross Scroggs
1fe3e69c56 Another OAuth2 token error (#1170) 2020-04-27 21:04:16 -04:00
ejochman
f301dac442 Add pre-commit config for formatting and linting (#1166)
Adds a pre-commit config for development that runs several fixers, including YAPF with
"google" style and pylint for static analysis.

Use of `requirements-dev.txt` appears to be a common pattern for this
type of work:
https://pypi.org/project/requirements-dev.txt/
2020-04-26 16:51:07 -04:00
Jay Lee
dae5cff728 focal doesn't work 2020-04-25 16:49:12 -04:00
Jay Lee
f605afb647 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-04-24 19:34:06 -04:00
Jay Lee
ed832956ea Ubuntu 20.04 Focal 2020-04-24 19:33:54 -04:00
Jay Lee
402ff9e8d0 GAM 5.07 2020-04-24 14:00:13 -04:00
Jay Lee
2fc51dba17 remove whatsnew.txt from MSI 2020-04-24 12:48:15 -04:00
Jay Lee
fd8358af90 remove whatsnew.txt, keep lastupdatecheck.txt out of linux legacy package 2020-04-24 12:04:54 -04:00
Jay Lee
4cd835577a returnidonly 2020-04-24 11:35:54 -04:00
Jay Lee
bc1c11e650 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-04-24 11:23:17 -04:00
Jay Lee
765f432ef2 make travis drive uploads world readable 2020-04-24 11:22:59 -04:00
Ross Scroggs
4cd92a1372 Document new ouath create form, make consistent with check serviceaccount (#1168) 2020-04-24 10:21:49 -04:00
Jay Lee
a2b3975c12 no drive upload for test python source vms 2020-04-24 06:29:58 -04:00
Jay Lee
4b6cca8dd8 Upload draft GAM builds to Drive 2020-04-23 22:25:26 -04:00
Jay Lee
55b43b6bc0 remove old build scripts 2020-04-23 21:24:50 -04:00
Jay Lee
c987861f02 fix tar on *nix 2020-04-23 19:46:07 -04:00
Jay Lee
f92c4d18db try another technique to package 2020-04-23 19:29:18 -04:00
Jay Lee
eeebf56a78 osx fix 2020-04-23 17:06:18 -04:00
Jay Lee
a04f231c9e macos and win travis fixes 2020-04-23 16:40:07 -04:00
Jay Lee
7df2293f1b os.path.join... 2020-04-23 15:56:06 -04:00
Jay Lee
7dfdf4cdbd fix svars-write.py 2020-04-23 15:39:56 -04:00
Jay Lee
62fa5fef79 more travis cleanup 2020-04-23 15:28:57 -04:00
Jay Lee
ce9fe17994 Travis cleanup after packaging changes 2020-04-23 15:08:36 -04:00
Jay Lee
ff54449d1d specify scopes for "oauth create", cleanup create vs. use project 2020-04-23 14:55:35 -04:00
Jay Lee
43a8900c24 Set consent on "use project", ignore 409 project exists 2020-04-23 14:23:06 -04:00
ejochman
e1660aa909 Refactor into Python package format (#1165)
* Refactor into a python module format

-Updates import statements to be absolute vs implicitly relative
-Uses import syntax that minimizes the need to update references in code
and/or reformat affected lines (e.g. `import gapi.directory` becomes `from gam.gapi import directory as
gapi_directory`)
-Adds a `__main__.py` such that the module can be executed on its own
using standard `python3 -m gam` syntax
-Replaces __main__ import hack with module import
-Updates the GAM path to be the module's parent dir

* Add gam.py to /src for backwards compatibility

A stub that calls gam.__main__.main() to be used by users who are not
with the syntax of calling a module implementation. It should also
provide immediate backwards-compatibility with existing scripts with
references to this file.

* Move build tools back to the main dir and out of the package

* Fix pylint errors

* Update build spec to use new package format

Incorporates @jay0lee's patch from
https://github.com/jay0lee/GAM/pull/1165#issuecomment-618430828
2020-04-23 14:06:30 -04:00
Ross Scroggs
5f6306911f Keep those Mac OS zsh people happy/Fix documentation (#1164)
* Keep those Mac OS zsh people happy

* Drop obsolete option
2020-04-22 12:21:07 -04:00
Jay Lee
268d07938a GAM 5.06 2020-04-21 13:22:31 -04:00
Ross Scroggs
42a4ce5006 Improve report usage (#1160)
Add date range to skipdates

Make report name match dates; indicate if no data

If only enddate is specified change time period
current: now-1 month to enddate
improved: enddate-1 month to enddate
2020-04-21 13:21:53 -04:00
Jay Lee
251b0a0a93 skip pyinstaller on source only test linux builds 2020-04-21 11:43:10 -04:00
Jay Lee
153aca30dc ignore collaborator output 2020-04-21 10:23:32 -04:00
Jay Lee
d9b9aa7de4 fix matterid capture 2020-04-21 10:10:59 -04:00
Jay Lee
003d41a496 travis store matterid to speed up vault tests, openssl 1.1.1g 2020-04-21 09:54:50 -04:00
Jay Lee
18bc459850 fix pyinstaller googleapiclient handling and unify spec files again 2020-04-21 09:12:53 -04:00
Jay Lee
97f6781d8a fix showing Google API client version 2020-04-21 08:12:20 -04:00
Jay Lee
7a33c5e18c GAM 5.05 2020-04-15 08:32:25 -04:00
Ross Scroggs
971e2ff76a Make it easy to capture created drive file ID (#1159)
Linux/MacOS
fileId=`gam user user@domain.com create drivefile ...`
Windows PowerShell
$fileId = & gam user user@domain.com create drivefile ...`
2020-04-14 18:31:14 -04:00
Ross Scroggs
007a378f2b Add GAM_CSV_HEADER_DROP_FILTER (#1158)
It may be simpler to list headers you don't want that headers you do want
2020-04-11 17:07:45 -04:00
Ross Scroggs
2f02148e36 Fix bugs, cleanup, improvements (#1155)
* Fix bugs

* Appease pylint

* More report usage cleanup

* More report usage cleanup

* More report usage cleanup

* More report usage cleanup
2020-04-11 15:16:47 -04:00
Ross Scroggs
475fb4fa2e Update both bash and zsh aliases (#1153) 2020-04-07 09:41:53 -04:00
ejochman
f3d2ef86f8 Make get_token_value refresh credentials on its own, when necessary (#1152)
Any other transaction utilizing credentials will already refresh them,
as necessary, through the use of AuthorizedHttp. `get_token_value` is
one unique case where we're not actually attaching the credentials to
the HTTP request, but rather using one if its attributes as the payload.
The request, itself, is unauthenticated, so it doesn't know to refresh
on its own. Rather, the caller needs to make sure that the id_token
payload is for a currently-valid set of credentials.
2020-04-06 21:05:31 -04:00
Jay Lee
35d2fd4cbc fix travis reports 2020-04-06 20:20:29 -04:00
Ross Scroggs
c4f1a7eb70 Standarize usage/usageparameters under gam report (#1151)
gam report usage customer|user ...
gam report usageparameters customer|user
2020-04-06 19:52:12 -04:00
Jay Lee
c83430a537 ensure get_admin_credentials only returns fresh creds 2020-04-06 14:18:37 -04:00
Jay Lee
c398d30f37 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-04-06 12:44:39 -04:00
Jay Lee
f60246846f remove debug stuff from reports.py 2020-04-06 12:43:12 -04:00
Ross Scroggs
3184de1392 Credentials must be current to get token values (#1149) 2020-04-06 11:23:11 -04:00
Jay Lee
921324d968 GAM 5.04 2020-04-06 11:21:59 -04:00
Jay Lee
c74cdeb773 fix report orgUnitID 2020-04-06 10:28:38 -04:00
Jay Lee
64ecf51ad9 fix travis tests 2020-04-06 10:16:01 -04:00
Jay Lee
518ad04815 fix for orgUnits, add travis test 2020-04-06 09:14:09 -04:00
Jay Lee
12ca54f6ba gam usage and gam usageparameters commands
usageparameters prints the parameters reported for customer and user
usage. usage generates a CSV of specified parameters over a given date
range. From a Google Sheet it's useful to add a chart to get a nice
graph showing changes in G Suite service usage by users over time.
2020-04-06 08:48:00 -04:00
Jay Lee
0a0ca9ef03 http.request is a function, should be using http.credentials 2020-04-02 12:09:52 -04:00
Jay Lee
9ef7b2f80a Merge branch 'master' of https://github.com/jay0lee/GAM 2020-04-01 09:20:54 -04:00
Jay Lee
86b0ed0a04 handle unicode body in send_email 2020-04-01 09:20:38 -04:00
Ross Scroggs
65e77e07a8 Fix typo (#1144) 2020-03-31 21:23:45 -04:00
Jay Lee
309308ed59 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-31 12:43:37 -04:00
Jay Lee
bb82ca0557 OpenSSL 1.1.1f 2020-03-31 12:43:22 -04:00
Ross Scroggs
e5e5db335d Add updateevent documentation, fix bug (#1142)
* Add updateevent documentation

* Fix calendar bug

* updateevent doesn't use id|eventid
2020-03-30 21:31:35 -04:00
Ross Scroggs
490d0a7815 Fix calendar bugs (#1141) 2020-03-30 19:16:59 -04:00
Jay Lee
7ff7c71b4e Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-30 16:01:19 -04:00
Jay Lee
13fa01c4e2 Update gam-install.sh 2020-03-30 16:01:00 -04:00
Ross Scroggs
d3dfcc3248 Fix bug (424), make code consistent (447-451) (#1139) 2020-03-30 11:34:56 -04:00
Jay Lee
69d57b7a13 another fix for win32 2020-03-30 11:11:04 -04:00
Jay Lee
b4959547a3 GAM 5.03, fix x86 Windows and ARM Linux 2020-03-30 09:46:17 -04:00
Jay Lee
3c7085f073 fix all build tests 2020-03-30 07:30:14 -04:00
Jay Lee
0ffb2ab7a7 fix build testing of python/ssl, fix staticx on Xenial 2020-03-30 06:56:08 -04:00
Jay Lee
fa4f18b59e more travis cleanup 2020-03-29 20:22:55 -04:00
Jay Lee
bdbe034c13 more travis 2020-03-29 20:01:09 -04:00
Jay Lee
b677e8b4b2 Fix svars-write.py for Testing instances 2020-03-29 19:55:57 -04:00
Jay Lee
68745703f8 fix testing test, remove trusty 2020-03-29 19:43:34 -04:00
Jay Lee
615d571aef treat as one line 2020-03-29 18:10:54 -04:00
Jay Lee
d23003ab0c move then 2020-03-29 18:04:59 -04:00
Jay Lee
c29fc410ad fix logic 2020-03-29 18:00:45 -04:00
Jay Lee
cbdaa143ea Travis logic cleanup 2020-03-29 17:54:58 -04:00
Ross Scroggs
ff92cb53cc Google seems to have switched the menu back (#1137) 2020-03-28 21:00:26 -04:00
Jay Lee
3890af9e1a Drop precise, upgrade patchelf 2020-03-28 15:49:43 -04:00
Jay Lee
21d70bbcb2 figure out why we lost legacy package 2020-03-28 14:12:03 -04:00
Jay Lee
1f80e029b8 fix bash if or 2020-03-28 13:48:04 -04:00
Jay Lee
9372b87d5b test staticx on trusty, stop puling osx10.12 2020-03-28 13:31:55 -04:00
Jay Lee
be3f886a57 Report GAM type (source, pyinstaller, staticx) with gam version 2020-03-28 12:36:37 -04:00
Ross Scroggs
896d7a045a This will make GAM and GAMADV-XTD3 consistent (#1135) 2020-03-28 09:14:02 -04:00
Jay Lee
545c9ea8dd fix 32-bit Win 2020-03-27 21:49:33 -04:00
Jay Lee
ae1c658065 more windows before install cleanup 2020-03-27 21:23:55 -04:00
Jay Lee
ebea409db6 Reorganize windows before install 2020-03-27 20:31:52 -04:00
Jay Lee
f406fa2445 allow setting state on print matters 2020-03-27 18:58:47 -04:00
Jay Lee
97784c92cf Unified Travis setup per-OS 2020-03-27 16:11:29 -04:00
Jay Lee
8c59241abb Install/use older MSVC to compile bootloader 2020-03-27 15:05:38 -04:00
Jay Lee
73bfd6abaa try upgrading chocolatey packages to solve bootloader compile issue 2020-03-27 14:19:26 -04:00
Jay Lee
b4ccc83696 try to see why strnlen isn't detected 2020-03-27 13:38:26 -04:00
Jay Lee
1b557d9769 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-27 12:42:15 -04:00
Jay Lee
1f69f55437 hack to fix PyInstaller bootloader compile on Travis Windows. Fixes #1112 2020-03-27 12:42:10 -04:00
Ross Scroggs
2c049dc38e Pylint cleanup, bug fixing (#1134) 2020-03-27 09:07:44 -04:00
Jay Lee
276c14f507 temp turn off short_url tests 2020-03-26 20:43:23 -04:00
Jay Lee
117538754e Fix check service account and short URLs 2020-03-26 20:17:28 -04:00
Jay Lee
f0c22e32df GAM 5.01 2020-03-26 18:18:55 -04:00
Ross Scroggs
30d480debc Fix oauth create (#1133) 2020-03-26 18:17:35 -04:00
Jay Lee
d8bbf71c19 MacOS 10.14.6 2020-03-26 17:47:43 -04:00
Jay Lee
574a29363c missing import 2020-03-26 16:07:31 -04:00
Jay Lee
c3382d1501 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-26 15:59:32 -04:00
Ross Scroggs
d5058d153e Filter non-open matters in list (#1130) 2020-03-26 15:59:03 -04:00
Jay Lee
9b64bf422d stop testing cloudprint (turndown at EoY) 2020-03-26 15:47:15 -04:00
Jay Lee
da90239e2b fix openssl dlls 2020-03-26 15:10:07 -04:00
Jay Lee
e15a93ebcb missing ) 2020-03-26 09:39:21 -04:00
Jay Lee
286f512f40 line formatting 2020-03-26 09:31:48 -04:00
Jay Lee
ff10649a21 fix project creation 2020-03-26 08:39:15 -04:00
Jay Lee
923c74b8f0 remove dup OpenSSL MacOS compile 2020-03-26 07:16:40 -04:00
Jay Lee
95a92aec8f always use getService for building API objects 2020-03-26 07:13:04 -04:00
Jay Lee
9894f5c7fb retry 500 response on discovery doc
See example failure at: https://travis-ci.org/github/jay0lee/GAM/jobs/667171534#L879
2020-03-26 06:47:28 -04:00
Ross Scroggs
b54a3959d9 Travis cleanup (#1128)
* Travis cleanup

* Travis window cleanup, make consistent
2020-03-26 05:58:08 -04:00
Jay Lee
ee92a56ba9 Go back to compiling OpenSSL/Python on Mac 2020-03-25 11:16:01 -04:00
Jay Lee
65bbe9ffe4 fix win32 openssl filenames 2020-03-25 09:16:16 -04:00
Jay Lee
d144ce3135 set a minimum version for python/openssl 2020-03-25 09:14:06 -04:00
Jay Lee
a54a29a3ac Upgrade OpenSSL on Mac/Win 2020-03-25 08:12:07 -04:00
Jay Lee
8a18df0e7f merge PRs 2020-03-25 06:54:32 -04:00
Jay Lee
0d0e867ef6 Make 429 a default retry reason 2020-03-25 06:52:03 -04:00
Ross Scroggs
15a16135e3 Changed code to shorten the public key lifetime in gam create|user project to stay within a Google limit. (#1127) 2020-03-25 06:32:11 -04:00
ejochman
4444974a9e Centralize OAuth2.0 Credential logic (#1126)
* Centralize OAuth2.0 Credential logic

Adds a Credentials class that centralizes and handles most existing
logic related to OAuth2.0 credentials, including generation, storage,
file locking, and attribute retrieval. This is a step towards
minimizing the duplicated code that handles credentials in various
methods. The goal is to eventually get to a point where there are 2
credential entry points: `auth.get_admin_credentials()` and
`auth.get_credentials_for_user(user)`. Then, we can slowly move toward
using impersonated credentials for all operations and scrap the need
for user consented credentials all together.

* Skip test_delete_removes_lock_file when testing on Windows
2020-03-25 06:31:47 -04:00
Ross Scroggs
1a32f2a6f8 Handle optional notprimary/primary for <UserAttribute> im and website (#1125) 2020-03-22 16:35:10 -04:00
Ross Scroggs
ff43f8474e Google changed project creation (#1124)
* Google changed project creation

* Work around travis issue
2020-03-22 14:06:46 -04:00
Ross Scroggs
7577e4385c Another non-user calendar (#1123)
* Another non-user calendar

* Simplify identifying non-user calendars
2020-03-21 16:33:46 -04:00
ejochman
0feee6e007 Avoid requests to impersonate a resource calendar (#1122)
* Avoid requests to impersonate a resource calendar

Fixes jay0lee/GAM#1120

* Also avoid impersonating Group calendars
2020-03-20 13:19:48 -04:00
Ross Scroggs
d78d68b4da Fix 100MB file uploads (#1117)
See: https://github.com/googleapis/google-api-python-client/issues/803
2020-03-13 14:24:25 -04:00
Ross Scroggs
e7eea5b9d2 Fix code to account for Google API change that prevented clearing a user's recovery phone. (#1116)
Before you had to pass None and the value, now you pass an empty string just like recovery email
2020-03-13 08:24:22 -04:00
Jay Lee
0256a3f267 fix vault storage usage 2020-03-13 07:38:55 -04:00
Jay Lee
a13fef6237 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-13 07:37:55 -04:00
Jay Lee
357c295fec retry false daily limit errors on org create 2020-03-13 07:37:51 -04:00
Ross Scroggs
a7a7bc3ebe Cleanup (#1115) 2020-03-13 07:36:22 -04:00
Jay Lee
5d02d73737 break out reports, customer and cros 2020-03-10 21:47:22 -04:00
Jay Lee
4213b4739e fixes for resources.py 2020-03-09 20:41:08 -04:00
Jay Lee
b41a6b1d60 resources, buildings and features to resource.py 2020-03-09 20:15:19 -04:00
Jay Lee
587fbadd7c fix count 2020-03-09 11:04:55 -04:00
Jay Lee
9e2e0d9bb8 pep8 cleanup of gapi/calendar.py 2020-03-09 10:53:42 -04:00
Jay Lee
24282e4289 fix reports 2020-03-09 07:57:23 -04:00
Jay Lee
8659df3c4c storage API, vault fixes 2020-03-09 06:55:46 -04:00
Jay Lee
9913014c4c fix missing close quote 2020-03-09 06:17:10 -04:00
Jay Lee
04daf6f0bb PEP-8 cleanup for gapi/vault.py 2020-03-09 06:09:30 -04:00
Jay Lee
a9917432d4 More fixes 2020-03-09 04:49:44 -04:00
Jay Lee
c23cfd121e move util vars to var.py 2020-03-08 22:08:22 -04:00
Jay Lee
11efa4fc9e Move Vault API commands to gapi/vault.py 2020-03-08 21:59:00 -04:00
Jay Lee
1d0c463e3b need uuid 2020-03-08 17:38:32 -04:00
Jay Lee
87f9d8f8c3 spread a few more __main__s around 2020-03-08 17:32:15 -04:00
Jay Lee
3904177d16 more fixes 2020-03-08 17:22:33 -04:00
Jay Lee
9910bb5dc7 more cleanups 2020-03-08 17:08:25 -04:00
Jay Lee
e1d76a93c9 Move Calendar API commands to gapi/calendar.py
The primary challenge here is building the gapi object. For now I've
solved that with a "import __main__" but that's hacky and not the hope
for long term.
2020-03-08 16:50:26 -04:00
Jay Lee
6a5807e94b fix quoting 2020-03-08 13:29:19 -04:00
Jay Lee
6e9cbdd898 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-08 13:27:42 -04:00
Jay Lee
ed5f743422 use patch for event dates if possible 2020-03-08 13:27:27 -04:00
Jay Lee
e3abe13def Update osx-x86_64-before-install.sh 2020-03-08 13:10:30 -04:00
Jay Lee
e8325c13de fix group var 2020-03-07 20:29:42 -05:00
Jay Lee
ff55b452eb gam calendar ... infoevent command, few tests 2020-03-07 20:21:49 -05:00
Jay Lee
62a0a064aa allow updating various event attributes 2020-03-07 19:15:40 -05:00
Jay Lee
8d5c8f33f2 gam calendar <calendar> updateevent command 2020-03-07 16:54:55 -05:00
Ross Scroggs
c1e7af620f Add parameter to enable adding Hangouts/Meet link toevent (#1111) 2020-03-06 06:09:17 -05:00
Jay Lee
9e0641d8e1 fix retry_reasons invocations 2020-03-05 13:25:34 -05:00
Jay Lee
b5d07cf5dc fix force variable name 2020-03-05 11:58:29 -05:00
Jay Lee
e8d333a46b Merge branch 'master' of https://github.com/jay0lee/GAM 2020-03-05 10:08:25 -05:00
Jay Lee
85f8a012c7 move force file flush into fileutils.close_file 2020-03-05 10:08:04 -05:00
Jay Lee
aeaa421de6 Create stale.yml 2020-03-05 07:57:40 -05:00
Ross Scroggs
0f8bf26746 Allow hangouts/meet link to be included in an event (#1110) 2020-03-02 18:34:59 -05:00
Ross Scroggs
ee89aa649a Appease pylint, cleanup (#1109)
* Appease pylint, cleanup

* Fix typo
2020-03-02 07:53:36 -05:00
Jay Lee
8cc401a5bf Move print_json into display.py and optimize 2020-03-01 17:30:01 -05:00
Jay Lee
c69934e10c wait for Python install to finish 2020-02-28 11:22:54 -05:00
Jay Lee
152d856b24 revert to Python 3.8.1 2020-02-27 18:36:03 -05:00
Jay Lee
0541d21364 python.org for Windows install 2020-02-26 14:33:39 -05:00
Jay Lee
47bdad65c2 update choco packages on Win, enable cloudidentity for future use 2020-02-26 11:35:12 -05:00
Jay Lee
8fdc7839fb Merge branch 'master' of https://github.com/jay0lee/GAM 2020-02-26 11:29:19 -05:00
Jay Lee
69905abb9f Update var.py 2020-02-25 21:22:30 -05:00
Jay Lee
dfa80244ce GAM 4.99 2020-02-25 21:16:26 -05:00
Jay Lee
601b5fd57d Python 3.8.2 2020-02-25 20:41:45 -05:00
Jay Lee
822ba6051c Python 3.8.2 2020-02-25 20:40:06 -05:00
Ross Scroggs
c827f193f2 Delete invalid product ID (#1105) 2020-02-25 13:12:04 -05:00
Jay Lee
dfd755c0da no browser 2020-02-21 16:07:20 -05:00
Jay Lee
72b63c4339 exercize todrive, reduce report size 2020-02-21 15:53:40 -05:00
Jay Lee
52e3b0ee8e remove bash install test, add reports to testing 2020-02-21 15:28:01 -05:00
Ross Scroggs
41521f4c04 Fix gam report user/customer not being recognized (#1103) 2020-02-21 15:25:23 -05:00
Jay Lee
f35067c9ba Merge branch 'master' of https://github.com/jay0lee/GAM 2020-02-20 12:47:18 -05:00
Jay Lee
4cd538e8c1 check key age, colors for check serviceaccount 2020-02-20 12:47:02 -05:00
Ross Scroggs
9d0de5df22 Fix f string error (#1102)
I apologize
2020-02-20 11:16:55 -05:00
Jay Lee
19e9e9e287 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-02-19 11:31:20 -05:00
Jay Lee
cd450a48e6 Check key age on check serviceaccount 2020-02-19 11:31:05 -05:00
Ross Scroggs
cd1ca91b7f Fix bug in checking fro 32/64 bit mismatch (#1101) 2020-02-19 11:10:10 -05:00
Jay Lee
9fd0562f98 re-add filter_secrets for arm64 2020-02-14 14:49:08 -05:00
Jay Lee
89a4711a77 update to latest fixed google-auth 2020-02-14 13:19:49 -05:00
Jay Lee
6a7c3a60ec GAM 4.98 2020-02-14 12:48:44 -05:00
Jay Lee
0ee3f11345 decode/verify id token on each refresh 2020-02-14 12:05:13 -05:00
Jay Lee
773311439f Merge branch 'master' of https://github.com/jay0lee/GAM 2020-02-14 10:39:54 -05:00
Jay Lee
6d2ee67536 New version of google-auth may be breaking us 2020-02-14 10:39:23 -05:00
Ross Scroggs
b90f291998 Don't set consent screen on gam use project (#1095) 2020-02-14 10:15:23 -05:00
Jay Lee
d34034065f Update gam.py 2020-02-13 17:00:57 -05:00
Jay Lee
ae425d25ec be clearer about who we're comparing time with 2020-02-13 16:14:13 -05:00
Jay Lee
3c98fc460a fix user agent 2020-02-13 15:31:25 -05:00
Jay Lee
7725d32788 Simplify service account DwD by prepopulating fields with clientid/scopes 2020-02-13 14:54:14 -05:00
Jay Lee
bbd4dd736e Project create improvements
- Programmatically set Consent (Branding page) saving a user step
- record created_by in client_secrets.json for easier backtracking
- use local project-apis.txt if it exists
2020-02-13 11:53:51 -05:00
Ross Scroggs
a1967bc706 Improve error handling when invalid report is entered (#1094)
* Improve error handling when invalid report is entered

* Add chat to report list

* Use discovery document

* This will work

* Fix formatting

* These aren't necessary

* Yes, these are necessary because the user may enter the version without _ and gam has has to add it back
2020-02-10 18:22:55 -05:00
Jay Lee
d06a38d09e rollback API test 2020-02-10 18:16:09 -05:00
Jay Lee
5d8b06b239 TESTING - WILL ROLLBACK - include discovery 2020-02-10 16:55:30 -05:00
Jay Lee
2caa782b83 TESTING ONLY - WILL ROLLBACK - API Testing 2020-02-10 16:48:21 -05:00
Ross Scroggs
f085dac4a0 f string formatting, final of many (#1093)
* f string formatting, final of many

Standardize (i/count) handling
Add doc_string and follow PEP8 naming convention for page_message routines

* Clean up items in gapi.got_total_items_msg and gapi.got_total_items_first_last_msg
2020-02-10 09:25:44 -05:00
Ross Scroggs
5092e3fc65 f string formatting, sixth of many (#1091)
Got message cleanup
2020-02-09 09:05:05 -05:00
Ross Scroggs
0f0cb0f28d f string formatting, fifth of many (#1090) 2020-02-08 16:23:05 -05:00
Ross Scroggs
47cfdedd1f f string formatting, fourth of many (#1089) 2020-02-08 12:44:56 -05:00
Ross Scroggs
6347e1f779 f string formatting, first of many (#1088)
* f string formatting, first of many

* f string formatting, second of many

* f string formatting, third of many
2020-02-08 10:54:14 -05:00
Ross Scroggs
0afffb4ee2 Appease pylint over import order (#1087) 2020-02-07 17:48:15 -05:00
Jay Lee
ccc5b2ac44 fix deploy 2020-02-07 15:42:30 -05:00
Jay Lee
b52ea80ab8 more travis 2020-02-07 15:01:10 -05:00
Jay Lee
86d478f25c more .travis.yml cleanup 2020-02-07 14:34:58 -05:00
Jay Lee
07e5cfef93 cleanup .travis.yml 2020-02-07 14:13:09 -05:00
Jay Lee
f644727e1c crypt vs crypt.crypt 2020-02-07 13:08:01 -05:00
Jay Lee
a00c20296e Merge branch 'master' of https://github.com/jay0lee/GAM 2020-02-07 13:00:57 -05:00
Jay Lee
8968833003 crypt fix 2020-02-07 12:59:51 -05:00
Ross Scroggs
239fcba631 Tow updates/fixes (#1084)
* Allow : in row filter field names

export GAM_CSV_ROW_FILTER="'\"accounts:used_quota_in_mb\":count>=15000'"

* Updated code to handle Directory API issue that prevents looking up the orgUnitId of OU /

This affected `gam report` if you used the `orgunit /` option.
This affected `gam create admin <UserItem> <RoleItem> org_unit /`.
2020-02-07 12:13:48 -05:00
Jay Lee
bc555b75dc if/else rather than try/except 2020-02-07 12:10:35 -05:00
Jay Lee
30f72975f7 win32 not windows 2020-02-07 11:45:31 -05:00
Jay Lee
3acf6e50a7 Use crypt for password hash on *nix 2020-02-07 11:02:21 -05:00
Ross Scroggs
34567480a2 Update error handling and f strings (#1083) 2020-01-30 16:08:37 -05:00
Jay Lee
4323140799 move PyPy to newer version 2020-01-28 07:35:14 -06:00
Jay Lee
df04318366 Deprecate Python 3.5, start to use fstrings 2020-01-28 07:06:42 -06:00
Ross Scroggs
6a27e4388c Do update-profile even on an upgrade only (#1081)
This helps users that are installing on an additional computer; it shouldn't cause any issue when upgrading an existing installation
2020-01-23 12:17:27 -05:00
ejochman
71da849ba9 Move transport customizations to their own module (#1071)
* Move transport customizations to their own module

This helps to accomplish a few things:
1) Makes the forced user-agent customization on HTTP requests a bit
clearer by subclassing the targeted objects (as opposed to hiding the
behavior behind a forced override of the google_auth_httplib2 object
methods)
2) Standardizes the creation of HTTP objects. These objects can still
largely be customized, but using a single creation mechanism will
standardize a default and streamline creation, thereby decreasing the
code that would otherwise be replicated in the caller
3) Moves create_http() to a more general purpose module, since it will
likely be used by more than gapi-related methods.

* Use string values for TLS version tests

More closely matches [existing
behavior](4fb73e6073/src/var.py (L853))
that sets the global default to a string value.
2020-01-23 12:07:55 -05:00
Ross Scroggs
4fb73e6073 Update gam-install.sh to set .profile on a Mac as a default (#1079) 2020-01-21 04:40:49 -08:00
Ross Scroggs
1f3f23a4f8 Undocument admincreated, fix coding issue (#1078) 2020-01-18 07:26:19 -08:00
Liron Newman
64554f51a6 Correct the G Suite Enterprise for Education (Student) SKU display name (#1072) 2020-01-18 07:05:41 -08:00
ejochman
12c0b33cf1 Buffer unittests to avoid output to build log (#1070)
Requires use of a context manager within each test method for stdout/stderr patches, rather than the @patch.object decorator. Otherwise, the test runner hijacks the patched object before the method under test can use it.

Note: The `--buffer` switch in the unittest module will suppress all
output during the test, unless the test fails. However, with this implementation, anything that would have been printed to the streams within
the context manager will not be reflected in the test runner's output,
should the test fail.

See more in jay0lee/GAM#1068
2020-01-04 13:24:07 -05:00
Jay Lee
bb5eab886d require ARM success since it's regular part of GAM release now 2020-01-02 14:57:06 -05:00
Jay Lee
af48f5de3f modify ARM DNS to see if it improves reliability / performance 2020-01-02 14:56:24 -05:00
Jay Lee
6c002bb135 Merge branch 'master' of https://github.com/jay0lee/GAM 2020-01-02 14:30:31 -05:00
Jay Lee
ca77243f4f understand ip config on ARM 2020-01-02 14:30:15 -05:00
Ross Scroggs
7cbe37033d Remove unneeded function utils.convertUTF8 (#1069)
This was deprecated in move from Python 2 to 3
2020-01-02 13:19:53 -05:00
Ross Scroggs
08e790ebbb Set errors='backslashreplace' on whatever charset user has chosen (#1067)
User can set GAM_CHARSET; default is UTF8
2020-01-02 12:05:58 -05:00
Jay Lee
75eec07207 switch to backslashreplace for so generated txt can be read back in to GAM 2020-01-02 10:38:08 -05:00
Jay Lee
22d841144c Merge branch 'master' of https://github.com/jay0lee/GAM 2020-01-01 20:19:42 -05:00
Jay Lee
8a9a08a2d2 Use new sakey code during project create 2020-01-01 20:19:35 -05:00
Ross Scroggs
497251186d Cleanup (#1066)
* Cleanup

gam,py:
In show sakays, only mark USER-MANAGED keys as current: true/false

gapi/__init__.py:
pylint cleanup: import order, indentation

gapi/errors.py:
pylint cleanup: import order, unused import, indentation

Recognize 502 Bad Gateway/Gateway Timeout: treat as retryable errors

This last change does not directly handle the refresh problem in Issue #1063 but in my version this seems to be the right solution to the 502 gateways errors

* In show sakeys, indicate whcij key was used to authenticate

* Show all sakeys by default

* Include unused import

* Remove unused import, fix unit tests
2020-01-01 15:04:45 -05:00
Jay Lee
2c0a005d3e modify gapi error tests 2020-01-01 13:06:24 -05:00
Ross Scroggs
bea7981bdb When rotating an sakey, only delete the existing key, no others (#1064)
* When rotating an sakey, only delete the existing key, no others

* Make sakeys retention explicit

* Fix bug

* Rotate, local key generation default

* Allow explicit specification of retain_none in rotate sakeys

It is still the default value.
2020-01-01 08:22:57 -05:00
Ross Scroggs
0be104fd02 pylint cleanup, Code fixes, Improved sakeys commands (#1062)
* pylint cleanup, Code fixes, Improved sakeys commands

pylint cleanup:
Import order: 77
Indentation: Numerous
Unused variable: 1121/1143
Unneeded else: 1367, 2760, 3194, 5029, 5825, 10105, 10116, 10127
Type checking: 7329, 7829
Static method: 13574

Code fixes: 3803, 3806, 5962, 5969, 6041, 6067

Improved sakeys commands: 7841/7949

Use sakeys instead of keys for claity
14172/3, 14273/4, 14383/4

* Allow for future fields

Co-authored-by: Jay Lee <jay0lee@gmail.com>
2019-12-30 13:20:03 -05:00
Jay Lee
ea1cdd553c fix few parameters after restructuring of fileutils 2019-12-30 10:07:44 -05:00
ejochman
6a14964f8f Move file utilities and add tests (#1059)
* Move file utilities and add tests

Separates common file operations into their own component with
appropriate unit tests.

* Remove use of unittest.mock.mock_open

Its behavior is slightly different across Python 3.5, 3.6, and 3.7
making it difficult to test across Python versions.
2019-12-28 10:47:04 -05:00
Jay Lee
cb9f5eab14 attempt at more universal stdin/stdout unicode and test with labels 2019-12-23 16:23:11 -05:00
Jay Lee
4ad972f7fe allow generating SA keys locally 2019-12-21 15:06:48 -05:00
Jay Lee
3925d6a467 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-12-20 11:47:11 -05:00
Jay Lee
6fcc59169c gam rotate keys - rekey service accounts 2019-12-20 11:46:53 -05:00
ejochman
02eebf186c Move the page-related call() methods and add tests (#1053)
* Move callGAPIItems and add unit tests

* Move the page-related call() methods and add tests

Continues work on jay0lee/GAM#147

* Account for rand addition that rounds to 1.0

In this case, sleep time could be equal to 61
2019-12-19 19:43:03 -05:00
Jay Lee
5b7d0fd3b8 travis cleanup 2019-12-19 19:40:46 -05:00
Jay Lee
aa4e72844b Python 3.8.1 2019-12-19 14:44:51 -05:00
Jay Lee
f9617a101b GAM 4.97 2019-12-19 13:48:05 -05:00
Jay Lee
c641596d42 disable Github actions 2019-12-19 13:45:58 -05:00
Jay Lee
d389b8ad14 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-12-19 13:44:17 -05:00
Jay Lee
6248958c94 cleanup 2019-12-19 13:44:07 -05:00
Jay Lee
e0e4c46329 Two fixes for project create
- Google changed URL for consent / client_id creation
- Python 3.5 httplib2 returns content as bytes breaking short URLs
2019-12-19 10:32:32 -05:00
Jay Lee
fdca4c2822 Remove workaround and require passlib 1.7.2 2019-12-16 11:05:53 -05:00
Jay Lee
cbc6eeabda fix retry test
Wait may be exactly 61 seconds if rand = 1 so use AssertLessEqual.
2019-12-15 16:25:36 -05:00
Ross Scroggs
dea2958d9d Update code to allow recovery phone to be cleared (#1052) 2019-12-09 13:50:32 -05:00
ejochman
a0c410be0e Begin breaking apart gam.py into logical pieces (#1047)
* Begin breaking apart gam.py into logical pieces

Start with one of the deepest parts of the stack, Google API request execution calls and associated errors. Critical information printing functions and application control logic are also broken out into their own components.

This change also adds unit tests for migrated content and makes code more PEP8 compliant.

This commit starts work on  jay0lee/GAM#147

* Add unit tests to Travis config

* Swap assert_called_once() with assertEqual() and Mock.call_count

Makes tests compatible with Python 3.5. assert_called_once() is only available in Python 3.6+
2019-12-07 09:50:56 -05:00
Ross Scroggs
4cc1a97a0a Fix label deletion (#1044)
Updated `gam delete labels` to process labels in reverse hierarchial order to avoid deleting a parent label before all of its child labels are deleted.
2019-12-02 10:04:05 -05:00
Jay Lee
ae6ac851c7 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-11-08 20:10:55 -05:00
Jay Lee
0f39b991df Test with PyPy 2019-11-08 20:10:17 -05:00
Ross Scroggs
6e9068c952 Fix race condition/fix rename labels (#1043)
* Fix race condition

From filelock.py in UnixFileLock
        # Do not remove the lockfile:^M
        #^M
        #   https://github.com/benediktschmitt/py-filelock/issues/31^M
        #   https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition^M

* Encode (){} in label: query
2019-11-05 18:08:47 -05:00
Ross Scroggs
891e5967db Fix variable name (#1038) 2019-10-22 16:36:43 -04:00
Jay Lee
542f21d58d Update linux-arm64-before-install.sh 2019-10-21 20:47:44 -04:00
Jay Lee
1af3f9f196 Update linux-arm64-before-install.sh 2019-10-21 20:18:01 -04:00
Jay Lee
f0ca2e2601 fix arm install, 4.96 2019-10-21 15:55:49 -04:00
Ross Scroggs
84f0296917 Fix multiprocessing imports, check for 32-bit GAM on 64-bit Windows (#1035)
* Fix multiprocessing imports

* Cleanup multiprocessing imports

* Check for 32-bit GAM on 64-bit Windows
2019-10-21 15:54:13 -04:00
Jay Lee
96ad8c15c6 Xenial ARM, pre-install ruby 2019-10-21 15:07:28 -04:00
Jay Lee
d77d45b5bc fix arm cache 2019-10-21 14:30:56 -04:00
Jay Lee
dc788a68f8 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-10-21 12:37:22 -04:00
Jay Lee
d3af49972c install ruby on arm64 early 2019-10-21 12:37:06 -04:00
Jay Lee
c7a732a61e Update .travis.yml 2019-10-21 11:33:18 -04:00
Jay Lee
d28a412204 always show cpuinfo 2019-10-18 20:04:44 -04:00
Jay Lee
2722d97a7d show cpuinfo 2019-10-18 20:02:12 -04:00
Jay Lee
79c62d86cc latest google-auth-oauthlib while keeping code_verifier enabled 2019-10-17 13:35:42 -04:00
Jay Lee
9f1dcc4c9f fix current path so we can find requirements.txt on arm 2019-10-17 12:36:07 -04:00
Jay Lee
4230f49bd9 arm fixes 2019-10-17 11:50:08 -04:00
Jay Lee
9fe9171798 fix path 2019-10-17 10:43:23 -04:00
Jay Lee
dac3b79f4d more logging 2019-10-17 10:04:28 -04:00
Jay Lee
083c2f4e9b hack fix for passlib bug relying on deprecated time.clock on win32 2019-10-17 09:01:22 -04:00
Jay Lee
17f88eb4e7 travis win fixes 2019-10-17 06:04:31 -04:00
Jay Lee
2798e89925 pyver was issue, add * 2019-10-16 17:08:28 -04:00
Jay Lee
79db8f2df3 find the guilty one 2019-10-16 17:04:05 -04:00
Jay Lee
089aadd729 one to many ] 2019-10-16 16:59:13 -04:00
Jay Lee
201e37d185 another shot 2019-10-16 16:56:56 -04:00
Jay Lee
9d6b569ddb reverse another part 2019-10-16 16:46:06 -04:00
Jay Lee
c7b026fd1d correct cache check 2019-10-16 16:40:44 -04:00
Jay Lee
66b95abb96 test Python 3.7, fix linux cache check 2019-10-16 16:33:43 -04:00
Jay Lee
e2ef8a293d more travis 2019-10-16 16:23:41 -04:00
Jay Lee
b25f6e041c fix Python paths for pip install 2019-10-16 15:34:48 -04:00
Jay Lee
4607580e6f fix windir, fork for MacOS 2019-10-16 14:04:19 -04:00
Jay Lee
f2d48c0e8f list files on Win 2019-10-16 12:11:04 -04:00
Jay Lee
c9d12e21d8 call freeze_support() unconditionally since it's a NOOP on non-relevant platforms 2019-10-16 11:58:32 -04:00
Jay Lee
2f4764a3f2 manual pip install, no ssl copy 2019-10-16 11:31:36 -04:00
Jay Lee
8b67039fa6 use pyinstaller dev 2019-10-14 20:52:54 -04:00
Jay Lee
8cf8d51c79 fixes for Python 3.8.0 2019-10-14 20:03:46 -04:00
Jay Lee
90226c6981 Python 3.8.0 2019-10-14 19:12:04 -04:00
Jay Lee
91a248bdbe another attempt to allow arm64 to fail 2019-10-14 17:13:55 -04:00
Jay Lee
0d3bfacc84 more travis fixes 2019-10-14 16:14:25 -04:00
Jay Lee
ac3c156a0b python3 not python 2019-10-14 14:45:00 -04:00
Jay Lee
f24d403705 set pip/python vars right after they are installed 2019-10-14 14:41:54 -04:00
Jay Lee
da3b16c0d4 watch cache 2019-10-14 11:42:33 -04:00
Jay Lee
2b2cb03784 Update linux-x86_64-before-install.sh 2019-10-13 19:00:35 -04:00
Jay Lee
19d0ff3d46 Update .travis.yml 2019-10-13 18:58:27 -04:00
Ross Scroggs
04b6b0ad76 Allow simplifed versions of GAM_CSV_ROW_FILTER (#1029)
export GAM_CSV_ROW_FILTER="'suspended:boolean:true', 'suspensionReason:regex:ADMIN'"

export GAM_CSV_ROW_FILTER='{"suspended": "boolean:true", "suspensionReason": "regex:ADMIN"}'
2019-10-13 17:56:49 -04:00
Jay Lee
6a5fb33306 further linux cleanup, re-enable e2e 2019-10-13 14:06:29 -04:00
Jay Lee
d0262ea6ae Update linux-x86_64-before-install.sh 2019-10-13 12:48:17 -04:00
Jay Lee
512c2ee000 Update linux-x86_64-before-install.sh 2019-10-13 10:53:11 -04:00
Jay Lee
e708e885f6 Update linux-x86_64-before-install.sh 2019-10-13 10:25:52 -04:00
Jay Lee
cc3b7b8124 Update linux-arm64-before-install.sh 2019-10-11 20:52:43 -04:00
Jay Lee
39c9deb456 more fi 2019-10-11 19:55:38 -04:00
Jay Lee
7991790f94 reformat linux x86 before install, attempt to fix ruby on arm64 2019-10-11 19:51:36 -04:00
Jay Lee
5f418d3f1a build VM 2019-10-11 17:52:12 -04:00
Jay Lee
5047bf5466 Only one ARM version, re-disable filter_secrets 2019-10-11 17:04:07 -04:00
Jay Lee
dca7c26b9d ARM64 Xenial+Bionic, test re-enable filter_secrets 2019-10-11 16:51:59 -04:00
Jay Lee
c6173e2957 whereibelong case 2019-10-11 14:05:19 -04:00
Jay Lee
b646023c41 /home/jayhlee instead of ~ 2019-10-11 13:19:15 -04:00
Jay Lee
45e3b01b15 cleanup arm build 2019-10-11 13:10:04 -04:00
Jay Lee
97515ab758 add zlib dev packages for arm 2019-10-11 12:28:49 -04:00
Jay Lee
d85328e729 dist arm 2019-10-11 11:53:36 -04:00
Jay Lee
0aa7082391 disable arm secrets 2019-10-11 10:58:05 -04:00
Jay Lee
946431b83f arm 2019-10-11 07:58:22 -04:00
Jay Lee
a101e3e7a6 pip 2019-10-10 20:53:57 -04:00
Jay Lee
f73120dbaa try test instead of build 2019-10-10 20:48:36 -04:00
Jay Lee
a55879c93a attempt to fix arm hangs 2019-10-10 20:42:20 -04:00
Jay Lee
fe02af151d arm64 build files 2019-10-10 20:35:33 -04:00
Jay Lee
f1a963fa9c Update .travis.yml 2019-10-10 20:01:04 -04:00
Jay Lee
8c6dee4213 Arm64 compile 2019-10-10 19:59:09 -04:00
Jay Lee
9208b4c4dd fix vsort check 2019-10-10 11:24:27 -04:00
Jay Lee
0e04b34852 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-10-10 11:16:36 -04:00
Jay Lee
796e35e8a4 Perform test install on MacOS/Linux 2019-10-10 11:16:06 -04:00
Jay Lee
72f0ae906f Fix gam-install.sh on Cloud Shell and MacOS 10.12 2019-10-10 11:12:57 -04:00
Ross Scroggs
464482d197 Document check serviceaccount scopes argument (#1023) 2019-10-05 11:23:17 -04:00
Jay Lee
48ce39a645 Custom scopes for check serviceaccount 2019-10-03 21:37:03 -04:00
Jay Lee
f993240d2b quotes 2019-10-02 10:08:39 -04:00
Jay Lee
83fd9babef run github install action only on Linux/MacOS 2019-10-02 10:05:23 -04:00
Jay Lee
66fb0cf8fc fix MacOS doesn't support case insensitive, allow specifying version 2019-10-02 09:46:01 -04:00
Jay Lee
459ac84d29 fix glibc/MacOS issue where equal version failed check 2019-10-01 20:15:46 -04:00
Jay Lee
736b833d52 newer glibc 2019-10-01 15:56:48 -04:00
Jay Lee
dc37020d73 gam-install.sh for MacOS versions 2019-10-01 15:46:01 -04:00
Jay Lee
93916d4ed1 remove timeout that caused sporadic failure 2019-10-01 12:44:22 -04:00
Jay Lee
1d1e48acb7 One lock for r/w, cleanup .lock file. Fixes #1011.
Keep lock in place thru read and possible write of oauth2.txt. This
allows only a single process to refresh credentials, others won't see the token
until post-refresh and we avoid multiple refreshes in parallel.

filelock can cleanup after itself on Windows but has to avoid a deadlock on *nix.
Try to cleanup the .lock file for it.
2019-10-01 10:59:46 -04:00
Jay Lee
1884e1a111 file locking for oauth2.txt 2019-09-30 16:18:24 -04:00
Jay Lee
2d0396da21 GAM 4.95, Ross' changes in #1018, re-enable older Python tests 2019-09-28 12:15:31 -04:00
Jay Lee
cce47ba723 another attempt to fix bionic 2019-09-28 07:00:34 -04:00
Jay Lee
2831680d14 stop building MacOS 10.1[01] 2019-09-28 06:42:44 -04:00
Jay Lee
5e3374acbc unset LD_LIBRARY_PATH to fix deploy 2019-09-28 06:34:24 -04:00
Jay Lee
13d7de9501 travis 2019-09-27 22:43:14 -04:00
Jay Lee
d78abc92f2 update ruby gems 2019-09-27 21:32:16 -04:00
Jay Lee
07672eb874 use newer ruby on github 2019-09-27 21:12:15 -04:00
Jay Lee
e7225ce487 travis 2019-09-27 19:56:13 -04:00
Jay Lee
cb24d3bf78 travis 2019-09-27 19:52:37 -04:00
Jay Lee
8360019080 parallel tests 2019-09-27 18:59:52 -04:00
Jay Lee
f3b34bea26 travis 2019-09-27 16:50:33 -04:00
Jay Lee
edf09a2d7b travis 2019-09-27 16:14:47 -04:00
Jay Lee
1de445c5b8 travis 2019-09-27 15:28:31 -04:00
Jay Lee
8d7f307173 more travis 2019-09-27 14:59:46 -04:00
Jay Lee
0a23a6d084 more travis 2019-09-27 14:37:59 -04:00
Jay Lee
87fa70be2c travis 2019-09-27 13:40:41 -04:00
Jay Lee
b57c62fe1b mroe travis 2019-09-27 12:34:43 -04:00
Jay Lee
a8c1051e0f more travis work 2019-09-27 11:43:27 -04:00
Jay Lee
d7ba12e729 flush travis cache, osx libraries 2019-09-27 10:17:23 -04:00
Jay Lee
1d3c47f3fd more diag 2019-09-18 18:52:26 -04:00
Jay Lee
4ae81bae99 brew upgrade on MacOS 2019-09-18 18:19:19 -04:00
Jay Lee
2fc301d061 full path to win python 2019-09-18 18:14:58 -04:00
Jay Lee
fc6e6d1ab6 verbose logging on MacOS 2019-09-18 17:50:30 -04:00
Jay Lee
9cb4ee9d6f figure out what's up with path 2019-09-18 17:44:37 -04:00
Jay Lee
0e1da6982b call python 2019-09-18 16:40:21 -04:00
Jay Lee
28573b47a8 more build fixes 2019-09-18 16:35:28 -04:00
Jay Lee
851bd1ef14 not gam 2019-09-18 15:47:25 -04:00
Jay Lee
0c7d64563d missing $ for bash var 2019-09-18 15:35:29 -04:00
Jay Lee
b984f62bbf a_atleast_b tool 2019-09-18 15:16:16 -04:00
Jay Lee
a89e0936c2 OpenSSL 1.1.1d on Windows 2019-09-18 14:59:33 -04:00
Jay Lee
677146d905 OpenSSL 1.1.1d 2019-09-18 14:11:15 -04:00
Ross Scroggs
00b7ead8bb Standard Got messages to always show total_items (#1015) 2019-09-18 08:40:57 -04:00
Ross Scroggs
dce5016261 Add recoveryEmail/Phone to users field list (#1012) 2019-09-13 10:33:03 -04:00
Ross Scroggs
2bc759778c Keep pylint happy (#1008) 2019-09-12 18:49:46 -04:00
Jay Lee
3aa6869a4b fix MacOS vars 2019-09-06 11:21:39 -04:00
Jay Lee
209fdfd5b9 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-09-06 11:15:27 -04:00
Jay Lee
eec0df14b5 MacOS codenames 2019-09-06 11:14:03 -04:00
Ross Scroggs
7e2810d33d Fix code to avoid trap when description is long (#1004)
* Fix code to avoid trap when description is long

* Code cleanup
2019-09-06 11:12:42 -04:00
Jay Lee
78404c8cd3 cleanup MacOS 2019-09-06 10:56:22 -04:00
Jay Lee
f05ceecf8e no x86 on GitHub Actions :-/ 2019-09-06 10:45:41 -04:00
Jay Lee
bcef526213 More recognizable OS info in gam version 2019-09-06 10:44:06 -04:00
Jay Lee
00d5767246 show Python MacOS versions 2019-09-06 07:17:47 -04:00
Jay Lee
6655301bfe Merge branch 'master' of https://github.com/jay0lee/GAM 2019-09-05 19:52:08 -04:00
Jay Lee
5beff97f95 test building on multiple MacOS versions 2019-09-05 19:51:46 -04:00
Jay Lee
cfa6b49bab Update pythonpackage.yml 2019-09-05 14:42:00 -04:00
Jay Lee
a659d5fada Update pythonpackage.yml 2019-09-05 13:54:05 -04:00
Jay Lee
c1521bfa3f Update pythonpackage.yml 2019-09-05 13:47:27 -04:00
Jay Lee
096e6c911a Update pythonpackage.yml 2019-09-05 13:02:54 -04:00
Jay Lee
26f7cd38e5 add runs-on 2019-09-05 12:56:12 -04:00
Jay Lee
802541c09f Test run of GitHub Actions 2019-09-05 12:52:42 -04:00
Jay Lee
cfd36c2836 GAM 4.94, pull in Ross changes in #1003 2019-08-30 11:45:52 -04:00
Jay Lee
7689ac7bed disable ssl verify on time sync so we know when clock is WAY off 2019-08-30 11:15:56 -04:00
Jay Lee
7a5ba99b36 Even better SA check 2019-08-30 11:02:42 -04:00
Ross Scroggs
8f4a40bc9a Add timeoffset option to gam version (#1002)
* Add timeoffset option to gam version

* Update timeOffset checking
2019-08-29 14:32:45 -04:00
Jay Lee
e3ab846d70 update user passwords 2019-08-27 14:28:04 -04:00
Jay Lee
29db574bc5 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-08-27 10:19:48 -04:00
Jay Lee
4851d5b62f upgrade MUSL 2019-08-27 10:19:33 -04:00
Jay Lee
caef16bdee add email scope to SA, check serviceaccount verifies proper DwD and scopes for token 2019-08-27 10:18:36 -04:00
Ross Scroggs
1a0f9ab66a handle empty recoveryPhone (#999)
* handle empty recoveryPhone

* Test empty recoveryemail/recoveryphone

* Handle autoUpdateExpiration for CrOS
2019-08-21 15:03:05 -04:00
Ross Scroggs
021c3bfb13 Handle more errors with short URL oauth create (#998) 2019-08-18 17:34:55 -04:00
Jay Lee
b3dfa41df6 GAM user agent on short URL 2019-08-15 18:21:54 -04:00
Jay Lee
5f94263db2 Use _createHttpObj() for short URL 2019-08-15 18:15:56 -04:00
Jay Lee
68d8e46b4c force pip upgrades 2019-08-15 14:50:23 -04:00
Jay Lee
ed221b0d7b just use static recovery phone 2019-08-15 13:31:26 -04:00
Jay Lee
1243563cd4 try to make MacOS tr happy 2019-08-15 12:38:47 -04:00
Jay Lee
1170457a39 GAM 4.93, remove *MAX_RESULTS config options 2019-08-15 12:35:10 -04:00
Jay Lee
435ed9f568 use area code 212 always 2019-08-15 12:18:36 -04:00
Jay Lee
81884e48d0 Support recovery email/phone for users 2019-08-15 12:00:36 -04:00
Jay Lee
a7be6d233b confirm API call supports maxResults before checking value 2019-08-15 10:08:03 -04:00
Jay Lee
584ddba1a5 Dynamic maxResults from discovery or exception 2019-08-14 16:11:14 -04:00
Jay Lee
2bc6c8bca0 200 or bust for URL shorten 2019-08-13 08:35:06 -04:00
Jay Lee
fc1e81a01d oauthbrowser.txt, GAM 4.92 2019-08-12 14:02:59 -04:00
Jay Lee
eebfaaf373 finish pyinstaller install 2019-08-12 12:48:01 -04:00
Jay Lee
652223d9bc Pyinstaller windows 64 bit bootloader compile 2019-08-12 12:29:51 -04:00
Jay Lee
e75664fd2e roll Python 3.5 back to Xenial 2019-08-12 12:08:09 -04:00
Jay Lee
556278b216 Use bionic for Python source tests 2019-08-12 11:57:24 -04:00
Jay Lee
f9bfaa98bb fix cros/mobile print 2019-08-12 11:47:44 -04:00
Jay Lee
b6bd2da6ce Short OAuth URLs, make console flow default to reduce issues 2019-08-12 11:00:26 -04:00
Jay Lee
7c36a6b601 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-08-12 10:41:22 -04:00
Ross Scroggs
413924b11a Generalize expression to find group settings values (#994) 2019-08-12 10:41:17 -04:00
Jay Lee
251883dae5 add cros/mobile print tests 2019-08-10 15:46:52 -04:00
Jay Lee
7e4d0da8fb GAM 4.91 2019-08-10 15:39:14 -04:00
Ross Scroggs
3fc2aeed4d Fix group settings (#990)
* Fix group settings

Clean up md5MatchesFile

* Simplify doGetCustomerInfo

Avoid trap when doPrintDomains returned a domain creationTime with no fraction.
Traceback (most recent call last):
  File "gam.py", line 14761, in <module>
  File "gam.py", line 14159, in ProcessGAMCommand
  File "gam.py", line 2053, in doGetDomainInfo
  File "gam.py", line 2088, in doGetCustomerInfo
  File "_strptime.py", line 577, in _strptime_datetime
  File "_strptime.py", line 359, in _strptime
ValueError: time data '2019-04-23 16:14:56' does not match format '%Y-%m-%d %H:%
M:%S.%f'

lansa.co.uk,True,2019-04-23 16:14:13.041000,secondary,
lansa.com.au,True,2019-04-23 16:14:56,secondary
2019-08-10 15:37:44 -04:00
Ross Scroggs
7f4f785f0b Lower default limit for 500 to 200 for devices (#987)
* Lower default limit for 500 to 200 for devices

* Lower limit from 200 to 100 to handle mobile devices
2019-08-05 18:16:46 -04:00
Jay Lee
9f5920989d remove bionic for now, re-enable e2e tests 2019-08-01 11:32:23 -04:00
Jay Lee
62bceb30c5 GAM 4.90, update mobile adjustments 2019-08-01 11:15:10 -04:00
Jay Lee
8c736e52ac Empty body no longer required 2019-08-01 10:58:01 -04:00
Jay Lee
2669079a31 don't cleanup 2019-07-27 10:01:33 -04:00
Jay Lee
cbfd93e440 Timeout optimized Python build so we can cache partial testing... 2019-07-27 09:36:01 -04:00
Jay Lee
ffd1c297e5 force configure 2019-07-26 15:51:35 -04:00
Jay Lee
1a11cb04f9 clean and optimize python build 2019-07-26 15:38:23 -04:00
Jay Lee
438fd5b59a turn off unsafe to speed up Python for moment 2019-07-26 15:23:58 -04:00
Jay Lee
2fef5e2cfa minimal tests so Bionic Python 3.7 can build and cache 2019-07-26 14:22:35 -04:00
Jay Lee
db8ad38fd3 try curl instead of wget 2019-07-26 13:28:24 -04:00
Jay Lee
cbb2722291 figure out what's up with Python wget 2019-07-26 13:07:27 -04:00
Jay Lee
be1c7f2167 Bionic Beaver build 2019-07-26 12:37:00 -04:00
Jay Lee
61f4a137b0 32-bit bootloader, fix path 2019-07-26 12:34:40 -04:00
Jay Lee
dac9e91428 fix python path 2019-07-26 12:14:45 -04:00
Jay Lee
83c64f1f71 few more fixes 2019-07-26 11:53:12 -04:00
Jay Lee
443f4e707b Use MacOS Python binary, fix Win32 Pyinstaller build 2019-07-26 11:33:00 -04:00
Jay Lee
70bf2a05f3 pyinstaller version 2019-07-26 11:09:12 -04:00
Jay Lee
33a4747677 rebuild w32 PyInstaller bootloader to avoid AV issues 2019-07-26 10:43:44 -04:00
Ross Scroggs
a4cce17767 Fix typos (#981) 2019-07-26 09:27:19 -04:00
Ross Scroggs
67cd03d3f1 I suggest match_users instead of if_users (#980)
* I suggest match_users instead of if_users

* Allow if_users or match_users
2019-07-26 09:06:45 -04:00
Jay Lee
1f88c18f94 Update gam.py 2019-07-24 15:07:12 -04:00
Jay Lee
d2fc706b17 fix doit mobile update 2019-07-24 12:28:22 -04:00
Jay Lee
b5e5786813 Require doit argument to update >1 devices 2019-07-24 12:21:30 -04:00
Jay Lee
38e741c788 Update mobile devices by query 2019-07-24 11:16:54 -04:00
Jay Lee
e9a0b85682 retry notFound when changing group settings after create to handle sporadic latency issues that cause failure 2019-07-23 10:09:55 -04:00
Jay Lee
5ab3602c2a gam download storagebucket initial work 2019-07-20 10:08:48 -04:00
Jay Lee
dd4bf7b144 10 second timeout on update check (default seems to be 2 min) 2019-07-20 10:07:34 -04:00
Ross Scroggs
922326c5ce Code cleanup (#975) 2019-07-17 08:41:38 -04:00
Jay Lee
c69be414ca Update gam.py
Fix one more case.
2019-07-16 17:45:03 -04:00
Ross Scroggs
10bc47402c Cleanup (#974)
* Cleanup

parent is not valid with use project

* Cleanup

* Cleanup

* Code fix
2019-07-16 17:42:42 -04:00
Ross Scroggs
193e42cf22 Add new forms of create/use project (#973) 2019-07-16 12:50:36 -04:00
Jay Lee
e0f58e5264 Allow setting project parent 2019-07-15 13:24:54 -04:00
Jay Lee
f14e48320c noupx, strip osx/linux 2019-07-14 17:33:50 -04:00
Jay Lee
474fcd33a6 disable PyInstaller debug 2019-07-13 15:12:50 -04:00
Jay Lee
a2a9ffc895 force pip upgrades 2019-07-13 14:40:01 -04:00
Jay Lee
b02416b32c Actually use GAM_CA_FILE env var 2019-07-12 15:10:20 -04:00
Jay Lee
fa52d9e89e Merge branch 'master' of https://github.com/jay0lee/GAM 2019-07-11 09:55:41 -04:00
Jay Lee
6383aa594a Batch Drive Deletes 2019-07-11 09:55:20 -04:00
Ross Scroggs
54eb59c27b Convert team to shared in vault export; prepare for the future (#971)
* Convert team to shared in vault export

Restore _getValidCourseStates(croom), it is used by _getCourseStates in print courses/course-participants

* Update GamCommands.txt

* Fix typo

* Update gam.py
2019-07-10 15:35:06 -04:00
Ross Scroggs
3877f8309b Update GamCommands.txt (#969) 2019-07-10 12:17:53 -04:00
Jay Lee
d8b0681831 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-07-10 12:17:13 -04:00
Jay Lee
cd8303dbea GAM 4.89 2019-07-10 12:17:00 -04:00
Ross Scroggs
ab51d6e931 Update GamCommands.txt (#968) 2019-07-10 11:33:49 -04:00
Jay Lee
b7e402dca2 confidential vault, generalize enums from discovery, query RCs 2019-07-10 09:33:21 -04:00
Jay Lee
842040a8b3 run e2e tests again 2019-07-09 21:39:27 -04:00
Jay Lee
1205da5d34 Update linux-x86_64-before-install.sh 2019-07-09 20:36:33 -04:00
Jay Lee
f40824fedd disable e2e so Python 3.7.4 compile finishes 2019-07-09 13:18:29 -04:00
Jay Lee
67fa0cbc61 } 2019-07-09 12:23:29 -04:00
Jay Lee
e029c77f76 Python 3.7.4, accept newer Python/OpenSSL versions 2019-07-09 11:09:09 -04:00
Jay Lee
2b23ae4e67 remove dnspython requirement, minor fixes 2019-07-02 12:21:51 -04:00
Jay Lee
c8ecc23c9c Remove dnspython in favor of simple Google DNS JSON API 2019-07-02 11:13:31 -04:00
Ross Scroggs
94f8959879 Handle group members with no status (#962)
* Handle group members with no status

* Omit Advanced  form

* Update gam.py
2019-07-01 12:02:08 -04:00
Jay Lee
2cdb8eb44d fix message header argument, make sure we remove all headers in cases of duplicate header or non-matching case 2019-06-27 14:39:03 -04:00
Ross Scroggs
ebc1d1ecb3 Clean up sendOrDropEmail (#961)
* Clean up sendOrDropEmail

* Date allowed in all commands, only sets kwargs for import/insert

* Two updates

Allow headers in draft/import/insert/send email
Quote arguments in todrive decscription

* Make requested changes

* Don't user sendser as an alias for from as they can be different things in SMTP

* On import message, default to not checking for spam
2019-06-27 09:55:00 -04:00
Jay Lee
d9e99334d2 new options and improvements to message send/drop/draft 2019-06-25 13:24:36 -04:00
Jay Lee
a06776bbbd Update var.py 2019-06-24 10:12:32 -04:00
Jay Lee
aecd725a71 Update .travis.yml 2019-06-21 21:11:59 -04:00
Jay Lee
ad8e9364e1 Update .travis.yml 2019-06-21 20:49:33 -04:00
Ross Scroggs
b812fef1c3 Update draft/import/insert/sendemail (#959)
* Update draft/import/insert/sendemail

If possible, use same option names as already exist in my Gam for same commands.

Include charset with file.

* Code cleanup
2019-06-21 20:22:44 -04:00
Ross Scroggs
56371214b0 Document gam <UserTypeEntity> sendemail (#958) 2019-06-20 18:32:28 -04:00
Jay Lee
3669a86f41 use gam.py, send to admin 2019-06-20 16:40:27 -04:00
Jay Lee
4095bf63ef Email send/import/insert/draft 2019-06-20 16:29:46 -04:00
Jay Lee
d75321ca8a put on the breaks :-) 2019-06-20 11:52:07 -04:00
Jay Lee
c931e1cdd7 retry on version extended also 2019-06-20 11:43:45 -04:00
Jay Lee
ea8cda72c7 full email on send 2019-06-19 16:46:14 -04:00
Jay Lee
f0bcd7888a don't use runCmdforUsers() 2019-06-19 15:53:48 -04:00
Jay Lee
6a08a66221 fi 2019-06-19 15:45:58 -04:00
Jay Lee
5e58edf598 command to send (spartan) test messages 2019-06-19 15:41:01 -04:00
Jay Lee
1e79772ec1 catch/retry DNS errors if we need to refresh token on startup 2019-06-19 15:09:58 -04:00
Jay Lee
3461ce053f cleanup print jobs 2019-06-19 12:49:50 -04:00
Jay Lee
9c84ce30e8 retry on ServerNotFound DNS issues 2019-06-19 12:15:23 -04:00
Jay Lee
93ca63e133 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-06-18 14:54:49 -04:00
Jay Lee
e367c86fce fix issue with over-escaping aue model 2019-06-18 14:54:33 -04:00
Ross Scroggs
34dc12994a Three updates (#956)
Add notregex to GAM_CSV_ROW_FILTER to allow selection rows that don't have a particular value

Standarize formatting timestamps

Display mobile.patchSecurityLevel as a date/time
2019-06-18 14:03:19 -04:00
Jay Lee
df4de5ce4b move CrOS AUE dates to dynamic file 2019-06-18 11:20:24 -04:00
Jay Lee
ea630480b2 create cros-aue-dates.json 2019-06-18 11:14:43 -04:00
Jay Lee
db1159cd0d remove custom code verifier patch and force google-auth-oauthlib==0.4.0.
Next release may break code_verifier auto-gen based on
https://github.com/googleapis/google-auth-library-python-oauthlib/pull/48 so we lock at 0.4.0 for now.
2019-06-18 10:23:50 -04:00
Ross Scroggs
ccf1dc0585 Update calendar ACL commands (#953)
* Update calendar ACL commands

Your change was not backwards compatible;  sys.argv[4] was previously ignored

* Code cleanup
2019-06-17 19:52:08 -04:00
Jay Lee
1cb96cf057 Print Calendars ACLs, delete by ACL id 2019-06-12 14:25:10 -04:00
Jay Lee
2bc8a114c1 GAM 4.87 2019-06-12 13:46:14 -04:00
Ross Scroggs
7f183b9edc Prevent traps when filtering CSV rows (#951) 2019-06-12 13:44:01 -04:00
Jay Lee
f86be17834 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-06-12 13:42:48 -04:00
Jay Lee
6854e3729a prefer id_token_jwt if present in oauth2.txt. Fixes #952 2019-06-12 13:41:16 -04:00
Ross Scroggs
5f48b1e16f httplib2 throws RuntimeError when OpenSSL is below 1.1 (#948) 2019-06-07 19:15:31 -04:00
Jay Lee
aea92be8d3 Update .travis.yml 2019-06-07 17:15:16 -04:00
Jay Lee
b4c5d6c626 merge changes 2019-06-07 16:30:51 -04:00
Jay Lee
0e2845082b include headers on version request 2019-06-07 16:29:28 -04:00
Ross Scroggs
705a40d035 Handle unknown server in gam version extended location (#947)
Line 847 drops a training space
2019-06-07 16:11:34 -04:00
Jay Lee
f85a072708 downgrade patchelf to compile on precise 2019-06-07 15:34:01 -04:00
Jay Lee
e990387660 fix precise patchelf compile 2019-06-07 15:21:11 -04:00
Jay Lee
feb76f504c build musl and patchelf 2019-06-07 14:21:52 -04:00
Jay Lee
6a33173a49 Use precise for legacy build 2019-06-07 13:58:16 -04:00
Jay Lee
5e8e9765fa use 2019-06-07 12:09:20 -04:00
Jay Lee
2a6cdb9b14 fix rule 2019-06-07 11:33:52 -04:00
Jay Lee
642c0fa216 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-06-07 11:28:36 -04:00
Jay Lee
9d5e79725c generalize TLS test 2019-06-07 11:28:16 -04:00
Ross Scroggs
db301d2635 Fix case where event has no parameters (#946) 2019-06-07 10:08:49 -04:00
Jay Lee
d7283d17e2 AUE updates 2019-06-07 09:44:54 -04:00
Ross Scroggs
bd7b58ad43 Pylint cleanup (#944)
* Pylint cleanup

* Handle Boolean values in activity cleanup
2019-06-07 05:28:10 -04:00
Jay Lee
27c0e5f8a6 use httplib2 TLS min/max feature, standardize http obj creation 2019-06-06 16:40:23 -04:00
Jay Lee
7a439a3e07 GAM 4.86 2019-06-06 13:23:50 -04:00
Jay Lee
fff6e6717f Merge branch 'master' of https://github.com/jay0lee/GAM 2019-06-06 12:31:21 -04:00
Jay Lee
2671764e99 cleanup report token and other activity reports 2019-06-06 12:30:40 -04:00
Ross Scroggs
4f12e2affb Various cleanup (#943)
* Various cleanup

146, 152 - pylint
1752, 1762 - Python 3
1742, 7695/7703, 7773/7778 - Standardize getting project id from client_secrets.json

* Fix bug in update group;  specifying delivery_option causes failure
2019-06-06 12:29:59 -04:00
Jay Lee
e1faab524b OpenSSL 1.1.1c 2019-05-30 12:57:58 -04:00
Jay Lee
6c5585d059 standardize char choice strings 2019-05-30 10:12:11 -04:00
Jay Lee
dc678dd510 include punctuation in random passwords 2019-05-29 19:19:25 -04:00
Jay Lee
7b70c5a745 switch back to choice() over sample()
sample() decreases randomness because a char will only be chosen from
the pool once for the string. Consider:

random.sample(string.digits, 10)

you'll always get the numbers 0-9 in some random order whereas:

random.choice(string.digits) for _ in range(10)

will give you greater randomness as there are 10 choices for every char.
2019-05-29 16:58:08 -04:00
Jay Lee
2e8190ce29 Merge branch 'master' of https://github.com/jay0lee/GAM 2019-05-29 16:03:16 -04:00
Jay Lee
14b09b91df Temporarily implement OAuth 2.0 PKCE
Add OAuth 2.0 PKCE support while we wait for upstream
google-auth-oauthlib to implement. See
https://tools.ietf.org/html/rfc7636 for more details.
2019-05-29 16:00:10 -04:00
Ross Scroggs
b77d7eaadc Mr. Consistency strikes again (#941) 2019-05-29 14:22:55 -04:00
Jay Lee
c68e0bfbc4 Remove SA DwD enablement steps on project create
The step to enable domain-wide delegation for a service account is
unnecessary. Even when unchecked, the service account gets access to the
scopes that admin has granted in admin console (gam user <email> check
serviceaccount).
2019-05-28 14:02:46 -04:00
Jay Lee
8a26e99dfc don't store scopes 2019-05-28 10:49:10 -04:00
Ross Scroggs
9e2dd11617 Handle missing credentials, e.g., two gam oauth deletes in a row (#938)
* Handle missing credentials, e.g., two gam oauth deletes in a row

* Add scopes back to oauth2.txt

If scopes are in oauth2.txt, an advanced gam user can use it unchanged. My code does preemptive error checking to detect API scope mismatches early on.

* Suppress token details unless requested

* Bring on the details

* Update scopes used to make oauth2.txt
2019-05-27 10:25:38 -04:00
Ross Scroggs
19f01007f4 Clean up random string generation, cleanup (#937)
* Clean up random string generation

You don't want printable.

string.printable: String of characters which are considered printable. This is a combination of digits, letters, punctuation, and whitespace.
string.whitespace: A string containing all characters that are considered whitespace. On most systems this includes the characters space, tab, linefeed, return, formfeed, and vertical tab.

* Cleanup
2019-05-25 17:40:20 -04:00
Jay Lee
2c4bbbbbfb cleanup random string generation 2019-05-23 21:26:41 -04:00
Jay Lee
71536c50a2 set auth prompts equivalent to what we had with oauth2client 2019-05-23 11:10:24 -04:00
Jay Lee
1d118a9ca3 use oldest domain creation as customer creation date 2019-05-23 10:19:37 -04:00
Jay Lee
94f6c45291 expand info for gam oauth info 2019-05-22 13:00:06 -04:00
Jay Lee
fd4a64f6a7 gam oauth refresh to force refresh 2019-05-22 12:42:44 -04:00
Jay Lee
d8ba15ab98 iss seems to be with and without https:// 2019-05-22 12:22:57 -04:00
Jay Lee
a0a2e1359e more cleanup for google-auth 2019-05-22 12:12:31 -04:00
Jay Lee
34b32da1e6 change deps 2019-05-22 10:33:42 -04:00
Jay Lee
f9af688bea replace deprecaed oauth2client with google-auth
Early work, much remains to clean things up and patch all the remaining
holes...
2019-05-22 10:17:00 -04:00
Jay Lee
8829bc3a65 filter activity reports by orgUnitID 2019-05-20 10:44:51 -04:00
Jay Lee
59d8e5a853 change order to allow more time for processes to finish 2019-05-18 10:40:03 -04:00
Ross Scroggs
fddd77e87c Update events (#932)
* Update printevents

The column header should be calendarId not primaryEmail as the user could specify a resource calendar for instance.

The order should be calendarId,id: major,minor as in other print commands.

* Event cleanup

* More event cleanup
2019-05-18 10:10:53 -04:00
ejochman
eed3fb1ed9 Remove unused imports (#931)
Also corrects identified common misspellings
2019-05-18 10:08:02 -04:00
Jay Lee
fbaf9272a8 Update windows-x86-before-install.sh 2019-05-18 08:37:52 -04:00
Jay Lee
97df7c75b1 Update windows-x86_64-before-install.sh 2019-05-18 08:36:06 -04:00
Jay Lee
358892869b fix paths 2019-05-18 08:05:31 -04:00
Jay Lee
7cca371c22 Update windows-x86_64-before-install.sh 2019-05-18 07:23:16 -04:00
Jay Lee
8b1c8b36ce Update windows-x86-before-install.sh 2019-05-18 07:21:47 -04:00
Jay Lee
86154adc92 full paths 2019-05-17 22:17:31 -04:00
Jay Lee
bfc0b57f62 fix cp 2019-05-17 21:54:16 -04:00
Jay Lee
d67110e771 check for OpenSSL version 2019-05-17 21:40:01 -04:00
Jay Lee
2d7c382c2f figure out OpenSSL silent install 2019-05-17 21:38:34 -04:00
Jay Lee
4536cd13ef MainInstaller sub-folder 2019-05-17 17:27:14 -04:00
Jay Lee
627db97b30 use 7-z for extract 2019-05-17 16:45:40 -04:00
Jay Lee
bbdce9536b [ not { 2019-05-17 16:15:27 -04:00
Jay Lee
5f0644d924 extract msi for openssl 2019-05-17 16:01:08 -04:00
Jay Lee
0b5dffc5a5 more fi 2019-05-17 15:22:54 -04:00
Jay Lee
33c85e9ed6 allow PRs to succeed, Win SSL 1.1.1b 2019-05-17 15:18:41 -04:00
Jay Lee
c04164e47a fix osx build 2019-05-17 14:17:21 -04:00
Jay Lee
06e7545f33 fix before-install 2019-05-17 13:26:12 -04:00
Jay Lee
0399d96fd4 cache ssl and python, optimize python 2019-05-17 13:18:12 -04:00
Jay Lee
347688ac8c Merge branch 'master' of https://github.com/jay0lee/GAM 2019-05-17 12:07:54 -04:00
Jay Lee
37ce64acb7 print and move events 2019-05-17 12:07:24 -04:00
Ross Scroggs
4b8bc4e7ea Fix Issue #917 (#930) 2019-05-17 09:28:28 -04:00
Ross Scroggs
d9ba83217f Update parse-aue.py (#929) 2019-05-16 14:26:19 -04:00
Jay Lee
1d658ca1ac GAM 4.85 2019-05-16 12:39:49 -04:00
Jay Lee
65f94ff465 lowercase on AUE guess, many more exceptions 2019-05-16 11:55:37 -04:00
Ross Scroggs
1b010fbd07 Optimize AUE guessing (#928)
Only look up a model once, cache the result
2019-05-16 11:44:05 -04:00
Ross Scroggs
a1bce42387 Update AUE exceptions (#927) 2019-05-15 20:29:37 -04:00
Ross Scroggs
4808f18ca0 Cleanup guessAUE (#926) 2019-05-15 18:05:32 -04:00
Jay Lee
b41baf19b4 another model 2019-05-15 16:42:36 -04:00
Jay Lee
9d78fa8825 GAM 4.84 2019-05-15 16:23:07 -04:00
Jay Lee
2a6a424ce0 AUE is 1st of month, fix few models 2019-05-15 16:20:48 -04:00
Jay Lee
c05c040241 Guess CrOS AUE date 2019-05-15 12:30:22 -04:00
Ross Scroggs
3d3f2b535b Fix bug, encoded deviceId not included in output (#924) 2019-05-14 10:42:10 -04:00
Ross Scroggs
49bf1f675a Code cleanup (#923)
keys(), we don't need no stinkin' keys()
2019-05-12 17:08:13 -04:00
Ross Scroggs
50f3ac493c Update GamCommands.txt (#922) 2019-05-12 12:39:31 -04:00
Jay Lee
690302f2b3 Full support for archived user 2019-05-11 11:24:06 -04:00
128 changed files with 135889 additions and 18990 deletions

View File

@@ -1,11 +1,11 @@
The issue tracker is for reporting product deficiencies. "How do I?" questions should be posted to the discussion forum at https://groups.google.com/group/google-apps-manager. When in doubt, start at the discussion forum and return here only when instructed to do so.
Please confirm the following:
* I have upgraded to the latest GAM release from https://git.io/gamreleases and I still have this issue.
* I am typing the command as described in the GAM Wiki at https://github.com/jay0lee/gam/wiki
* I have upgraded to the latest GAM release from https://github.com/GAM-team/GAM/releases and I still have this issue.
* I am typing the command as described in the GAM Wiki at https://github.com/GAM-team/GAM/wiki
Full steps to reproduce the issue:
1.
1.
2.
3.

14
.github/ISSUE_TEMPLATE/aa-question.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: Question about using GAM
about: Help with using GAM or running it for the first time
title: Please use the GAM discussion group
labels: invalid
assignees: ''
---
If you need help with GAM, please do not file an issue here, it will be closed and ignored.
Please post your question to the GAM discussion group where other admins are ready and willing to help:
https://groups.google.com/g/google-apps-manager

23
.github/ISSUE_TEMPLATE/za-bug-report.md vendored Normal file
View File

@@ -0,0 +1,23 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: jay0lee
---
The issue tracker is for reporting product deficiencies. "How do I?" questions should be posted to the discussion forum at https://groups.google.com/group/google-apps-manager. When in doubt, start at the discussion forum and return here only when instructed to do so.
Please confirm the following:
* I have upgraded to the latest GAM release from https://github.com/GAM-team/GAM/releases and I still have this issue.
* I am typing the command as described in the GAM Wiki at https://github.com/jay0lee/gam/wiki
Full steps to reproduce the issue:
1.
2.
3.
Expected outcome (what are you trying to do?):
Actual outcome (what errors or bad behavior do you see instead?):

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for GAM
title: ''
labels: enhancement
assignees: jay0lee
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

BIN
.github/actions/creds.tar.xz.gpg vendored Normal file

Binary file not shown.

38
.github/actions/decrypt.sh vendored Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
credspath="$3"
if [ ! -d "$credspath" ]; then
echo "creating ${credspath}"
mkdir -p "$credspath"
fi
gpgfile="$1"
if [ -f "$gpgfile" ]; then
echo "source file is ${gpgfile}"
else
echo "ERROR: ${gpgfile} does not exist"
exit 1
fi
credsfile="$2"
echo "target file is ${credsfile}"
if [ -z ${PASSCODE+x} ]; then
echo "ERROR: PASSCODE is unset";
exit 2
else
echo "PASSCODE is set";
fi
gpg --batch \
--yes \
--decrypt \
--passphrase="$PASSCODE" \
--output "$credsfile" \
"$gpgfile"
if [[ "$RUNNER_OS" == "macOS" ]]; then
tar="gtar"
else
tar="tar"
fi
"$tar" xlvvf "$credsfile" --directory "$credspath"
rm -rvf "$gpgfile"
rm -rvf "$credsfile"

13
.github/actions/entitlements.plist vendored Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- These are required for binaries built by PyInstaller -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
oauth2.txt
nobrowser.txt
enabledasa.txt
lastupdatecheck.txt
*.lck
*.csv

61
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 90
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- pinned
- enhancement
- help wanted
- security
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: wontfix
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

1061
.github/workflows/build.yml vendored Normal file

File diff suppressed because it is too large Load Diff

70
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '25 10 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

52
.github/workflows/get-cacerts.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Check for Google Root CA Updates
on:
push:
pull_request:
schedule:
- cron: '23 23 * * *'
defaults:
run:
shell: bash
working-directory: src
jobs:
check-apis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
- name: Get Current cacerts.pem hash
run: |
export CURRENT_HASH=$(sha256sum ./cacerts.pem)
echo "Current hash is: ${CURRENT_HASH}"
echo "CURRENT_HASH=${CURRENT_HASH}" >> $GITHUB_ENV
- name: Get latest cacerts.pem file from Google
run: |
curl -o ./cacerts.pem -vvvv https://pki.goog/roots.pem
- name: Compare hashes
run: |
export NEW_HASH=$(sha256sum ./cacerts.pem)
if [ "$NEW_HASH" == "$CURRENT_HASH" ]; then
echo "Same file."
else
echo "New file content. Was ${CURRENT_HASH} and now is ${NEW_HASH}"
fi
- name: Commit file
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add cacerts.pem
git diff --quiet && git diff --staged --quiet || git commit -am '[ci skip] Updated cacerts.pem'
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

32
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,32 @@
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: double-quote-string-fixer
- id: check-yaml
- id: check-docstring-first
- id: name-tests-test
- id: requirements-txt-fixer
- id: check-merge-conflict
- repo: https://github.com/pre-commit/mirrors-yapf
rev: v0.30.0
hooks:
- id: yapf
args: [--style=google, --in-place]
- repo: https://github.com/PyCQA/pylint
rev: pylint-2.5.0
hooks:
- id: pylint
args: [--output-format=colorized]
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py37-plus]

View File

@@ -1,213 +0,0 @@
if: tag IS blank
env:
global:
- secure: "FSKvLaiqhKz21SVgAQZI3bSX34Ffyev4l+R2G//QXNDu6UVQcuFsykzw+eZEG7fkhotXr8BMDL7xIkookiL8eLwUtcd/Z95HCjPBBHcmCSQleyvuuJBxdrQ9xldmiGLzMCYiumSH9OH4uJhQ39Yjnjsa8TK+PlTci6a/BTzlYyBSyDYDf7Iv/uhfQPDHL3pNwrQPHf4fL6/jcvo+uaPcv83AVZkNzZjjyoi9Aa+uh9xlbyHg11jp44463qqxoxTdYik3pYuXRBPjknjOGcnFHqn+QOVSdRQoiwbmT8xVuYuCzTv9THhuJ//i5u7s4y3Xyl7u17B3tdm86UlMpQHy/w9EsYaSBPOU4oPNomRtOnTSugh0v9ZBwptP5XfbslII/iA+LQdzTHhchn0W0CRyDqjOMSestWlrsq5NZJtBJTYHbebllOhEI7xbj9tY+re1zFWSPMOPgHJP23ovsdk3hD9OT93AzRHInCx5IxL6QvEgRhAancRuGkf2rGP0g/vX9fQ0Il3rNMSQxHB5CyHUBtUJ9nhU79YkMDZicD0jFMEwjWJO3itAp3ynoLXRgktgQCYUfgc9SpdWKD5SXLCYnSo22JD3D1P6h2EertRHaoKRLb+CRXQC/lM8uh/W+BjA2Xe6Vut2I/72ndjM+10T7E2xk1CFyCH37a5p8cH26Fs="
- secure: "J9380tGLOZWa7dSH1y5Il8T5JQpN6ad81gI6VR1HIU0svpRdjgikyDA7ca2MKYDUYYY9yVSkTV6gCl6iIU/9+SKaYugpP+tkvdGYkC2moJdcTgYM/WOnIK9ExQ3BPhN1neGxJjPTwKo1ft27mtZ2I5vuCiBwIcnKWLnKPyW3PD+mWpfqiLuEzkHoAh6G3jC4qbcCrZDeX/knE+PzqESUEi+8k1G8gYcSDWujba9ypSsqZ8T/MXagGla6l7y2Rz+/KZTJmFHwKAA10V+xPLVqxoiqi4ar66yUqy0BamwRXPcseI+ns3Q+4lUpMqVQ5GlRy7LF1xC8myjmcAexXk0F9hg+CMzewKI8UgmQH/ZJvQZEh8s6mW26+CqA4d3zMQkWaR0WtEtpiuH7AGHCflIqvEQ6UiG7ia3B8iZfW2wl0j/kqx4OuHkS3r0pWKVVIIvCj9Ow2BHP7SpiV1AcUGsVxzwbgTh67fitna3Z3c6Uj8ccQlNr7ZIt1az6Wf3w5njijkLOiBpQSLKunTTCTSge/JzBTKUcie3RE9vzirl58gUxAt36nDtPWnory+RttMZrOkBVbTeSxp+IUe8pNwLFPHABsafXsjkfzBOtFmm+0ZXWt2Rlog5NvlemJfQUWDlsL4g+BSakzN+4sIPKzSauWDHyaEeULY7Uprkil6c5zwo="
- secure: "szcjWHPr0Bf1KCkyTrV5Fu3ADhWk+pg8YWucjXHdybmhaQIKG7iBNg8LJ5d0OBTwAg31wK4ZgyLVSa2gKrAZ3UeDjykJFsR711xDSQOod51Wrgqu4FbXDewE817DUk3Cwe1l5DCu3/fjEw4vbm8B/qb7iMTRKCq6hJd97FwT5oauP0QHNPer9JjrW4F0Hk9ttkgEU2dXWvBMsTJsDOGNI3ddABE2HskxV4T4thelDYGKBDHhUOAsRwSjXgWy77Tvz98psPIvd+6+WPYNRdRWcPDyAR3Z1O/fNjUymrQI6eMaHoSFrmhDS5lbhjINRfdUmECyfCfIFeLWWiw4g4bq7l+4HBORbei55tAIjhEsxJQoqHi0Q5dD5TFh8IiWqowkFbpvNonMSIpKtB0cyT5jU1G/jRA7MPcIvSrdzHaDkoDNHJgAeZfgjOhzTGYYD19lGIljz5BQBcNFZY2dJbja+Jr4He2CMAOBOdERa4Zn1VyNfOmd8Bn5hu0C9D2ybnSCxjXXq5TRiktR8X7WycVZYfqMZXAwP9FEHVitJ4MZEGUc7S92K5gX4wmjcJjLS+Xo/0nsduQm8PuiMjbcPM7/oGx8Xm1KuSfHdKWMBoaesPaDvRX+YcuiNstXf1DkCWl72TsFABzddlNUMl/s2YSKkCSHAJ5ILqrB28Gx89kzVlg="
- secure: "CPsDgSoZIHLyjpUbYEsx1GbB+UZcPXCEsz9qT6XRM+qMFKLlSnHxoJ7gMrJtqfjTh+1gLB3UTjQjFr+jAenqLWzaJh7Zdtpg9BOG6aXC8CAi1h0U5ZMNSA/+5lQxOXuhN8HmXI1r8xPNRFXBdZFea+072/2HJTwmgYlVTTQ8FrbXQJCzs2cFqxnVeFmuG3N49AJuoy3B+P2DMpqPzABbQt7Jf5H9Foq+16iXxhRkYA8/8H2nF7ZE8IdJuRpqhBUoPF/8Mt2QBLIlvNIdIzFEy2O7ZhwL9Dt08AG9v5c91QPzjsLok2e+5hFGaeMpGQJCE1V3uHyrOAeyZs1QYr7qBWbjQCVh0Phxz9yOA9RPfnQdjyJTq4QEj6vVYvCi5K/CGp/DnnLnGyYJKZOt7nBx02fTVI136UXqt29eF5NRkCpnUqah2s0OXkijsw5Y9LsbwiUxELKtCthESOwN8e/ZNvn/gjPfZWIaB0gupRNugL8Xo9Cx6vFmaW8wzm1IutJvo1mWvkWMvuYYjvd4aDyP6s7PFnSX7DoD/pfxoQuzjwHO2OD93nCOx0ofnNojLNooeJPKLikiwS4qKc8exWd+TlnccKSkXO8Y8S+XRgeE652YNlf+9DH79lNLeK0N0W2tRExX5JaEyJQCuvK0WZi02kxvjmUHhwLAOv9ueC2UCRs="
- secure: "JMv9mkSQBJXvUznXcyvngFaOfd2fHYEQQTH8BnS03pqAL0HkWSheG/R2HFJlJv1VJ9MDMf+wVzwMvU/kzkOT68nIgyFWnLBkT6fw+Mw7t/dG96/nOh7DPuaTVzKS0xRbMhDaqZOA9GW13TVnpVdIw79vbhQM69N9Gj80j8oM1cHgMi+fkJSDU3EN/vMJOGKSB3DTpyqAG/nYyZ38tLib8ic12za/YL3HIu8QRHa3fr37+cyrVKgGebGg++yK34p8lC1W4apiO30drmHVQhKWrWnmdcssdGmVM7NystMGGAzUwsJcmRFJuREv1LXiijDzjIRVduceeRYgPi1KHB5ZdL9vji0gM1eHYZZefhcJb6WgPDbCtbjdlCId4v+1bNfsh+dMmhM+vBZDtDEt3UC3MBeYTmklQT2w9zCXHuPBQigj7W4zLm6GxnAXife0SQMfmr736QBvSLUJWtd2tRgS+dRG/LvWxrP5Urvfgs8iRtEVZLDpRR+bSjvLs1UEKLN13KMKYuVwieHbxJn2kY7d5wmZVBYdaokl0yrTkZZ6J9xIphxM8GXJU1BnMZY9zn+Xq3jm576QYnNYUwCtUjOis00Ct4UVuuFqIqZ7bJL7GT4AHTENAk+9GtXVCo3/jnv161rxgoSdnUG6VmrpnyA9jSpcIvMVcE129oghBJ2+PkU="
- secure: "otePbb9W6CAuwzayL0dDAvCryzF2s5HHAIytvMW/xnzOuRMR03lumj9bhg56YCB/nIuTncAjToYmsMh2Acrp1Xcx8/DzqKse1K9nkfJgsB+EYeXmy8pVJnCxhHeLCzUPJjUfRoPBm+5GHAkeoviUyxenwbOFm3/Uhtay7i2ZU8K1FsECqx4FZXVh8rrGHqFGzHNimqDDvFUQM6f9a+BevEio8+/aDooaFfvVqPixDYXpi2+99DB/0hZKwcUpj6pOUUszATkAl0kJdOSWI6E7bQa63i6SfhcBNHfvbDqhpcAGs1TIXHbXwWGfySABKgT9mkq64CY3bc/QZ6HeWe6P5tJmt4mGBxDMOWMYj4qtCskQCCCiY9+sCx61Sj8W5w8exjQvvvFA088cKtbCKAx8FIil4CuYPtIjDQFkiNI2bC6BmkUen7qe4z7dSF2AZPb6CuSsBjoXL8Ezle3e1pRrkR+SYbxMSaZVcQoG8hinTqaXhlS5gXi97ZzRrJWn3tUB6JWEBeEkIfTJmrJolbLYIMcADNhKenrW8k6nV32JkvMsCgMFCIkJsIZeuQ9ZYgSZ3CXPODux/D2/4/gNa+353Fs3DTlDQxRTgoaYi9UDIRrKZAkoELFclxuGSKMCCheevQ8FMCmXfxUocwLSgjlO7g4rTJa9Kggn7VltucXiVWY="
- secure: "WKdB+WpZG/7SKpPpgM6DAwzVg0QQuxFMJEZE324pagJ74xv+GlObTLm6kU4SAZf6TuRSChTXDAD4paJXkxpq3LlXjp9aKxPASbG5PgZMnGL6bZ40c/UUqrwVy2HLnXPKSNuDBX1RidGXmH3u4YvufjguNnlOLvHYfMHIRGjiEL4ZvC38GB/3YDmID1zI6w8NzTCpFvxeNdg1qhhOBUKyt+icRUwBu8DfgLidzTrO0j5jo3UeqO/w3E9t3nnRgSiO25mBYwWySm1QBK1VS3F5iG9jo1J6GKMOFbWi3lOBoqnWotpfwID+p1vMNX35phHwmMrtoBYfMTV4A2CvQpGyQhn58qyMoKnhLz+NIOxlHN83qcu65bTMG+7ji0pgUl3jhp3ZPyWUjRYQpoVAg5f3UAnUzJgBrOUC0N60ukJVacT/kvkO10CLfz+0+eefW53r+GCkTi2m8iDezZn1olinpLs+Mt0M4VfQ52RVtq3WB6uxN7RjgtrK5XGi2zVAsvfHp+vqFQ6uu+iioiWNji88cTlMuKheo+FWwozNQzd8+4Vxe9w01mLek57Q0dpXiKWL3vMS4Qc4T9E6UzutllDyg/c61LW6Afcqw3jL4HN0UNG3zFefno47oKrmB13HcxakLEC8sdNfE1kWGvB7jqD0snXsz/8rz7rf0IqnK0kaCAc="
- secure: "Lah0Q4bWyEJXTBLZHCNkuEuU5wlDQzLF6aQwW47RyVtyRDYW8uQRQFkbb/3oj4QAAgXl0sOcDFnRaaWmlOStPIIYKKVY8Mk6ufyDCz8inWoPNJoSbdqbAi761HacGUsEfSNDrPNB7fst47UZaX7WNAO3q1QjCCGSEJQVpJE2MDAjcSJhAgLPt3JRFSOSwvqxcDLZI+wF9AM81OWNp6QisAdI4LPUJK3L4M4dLh9+apFRb1OMld++scWah1SB5Qj6tPzMvX96mp1XfWB1fJXuf8Yvks02H6ZcAXubK2HXe3iJZKVqGB67kShNN52P+wg0ZZO4OP4kZ2PXahnB7hhxIfEfWsNVy/w4ww1N6K907BfT6RDmsgNP1ZP8kpq6H4pTnWgAy9WDxjatzbNFAHtMzakGjYJNFxZJVco2FL0ipNQ7htoVAA4sUb+VbRQv4O/oZTLMNnnco19+TFJzuZuS4Rjxj/zX63gXkj/W7wou3hw+NpI/PL2hUXIc5imXSLfVQwri8Nl+6IOjV2gWR/vR1VhQqbLsTF6TZQKNI4lvbRTs1nNeqNMW1lHizI3r9Kernj2noAsxJK7wFTZ64OUkQvSNphfmVow29JYQKXbpxbmRrdnmfmtnMsxUngpx9WsTPhrprt5hIAqiBspHemrs+H3LiIml6IY/3l9bcPlc0gA="
- secure: "sNc7kC0CuH/TCZh2WwEN51GcA1fSpcliCHpFB+WX7ieQiRu3xKn2avby/T7vbvX0viXRER59arFGQF4i/dyr2g4tlZLVRYjPeiApfduKZ7Lb+vZGro3cWesfHG6Abk2VcgZZli1IDrgrHH5qAWnA9xNnKvKBL9NDM73Zj92BmlDFVEzadTii8brWvced/YP3jNXEmM5ZIufgpe2yidBB2bLWYJXb3Cf1MvzMG4tqNAtZTrI32q50mokz/uTqp3MRJ+cR8sOI+2+2xSbT0zZGLSRZf96/7FKtE0QIDxdWAe4XdlHq1CluRVk30Ju5BEn0QzoYLryCIuw3JjDl1Yksw4IA5imljZJlOmWa2l6fX0HNxMw+z0R/1d2HARA8BY7/uQKv4guV3Cf3jpsWoKSsM1WxqOqsuEFOoRQ2eQNJEaSuC6+j/vzNoj61pOuG0R9OC2PFcFCZ9fomIrZMse+7M3WIj4+mp7e+JDK8DgVdUlqkBVCx1Ospseb5pm6lDx8F5NbgqZgGXgyoWVpqZnyYOoOutezMoD6MI2wXzJaepV/L3+LD5f6q3DAa/sRAEEsBFGyMHXiPYbziEiy8Hz09Sz3inT5rzS8OLOinwAI2sHiIYHTl340XfWdYz6AlNhYLCGwwmtkntbjOj5UVW06IgBBx44ujpZSUjv7SOrACPGU="
- secure: "t9/mC8eSsxXIB2vjcZGtGISxrSY3Yd+XS4+/i1YG1mxSov3R6UdhVl2blLgrvFfVCSo61YMAzJbXKtZlXPzhLDXxpsSlWiatjNrKKo4D2unnlHsyEMJ4wfz8cJ8pKyynP7Kc1ZuaqTSMcEZgk85tlew8Zy/VH6g3Mc/7DvP4SxEDRsP+DdCplZc0vbxHDaV3iC93bwNRfy1UQypwJJ2WQviRema3Umneg8hVl2V35zbaBoy45ubCkUoCbRCDaUyoHA10GrE1OUOLsioar/dj6K2W3EhAtehHLWrUZhhl07rayrrRDQYDTdebifB/MWlvR5FjM/Dr5M4k2ciss4ol3IR5LypRLD+/YBtzeIuqkDbUkaBowY+oUj6OWlzEbzAUrUNa5mnyR2jhr8ivZUeEEWLxljsu8gWq65mzgiZt/u+kVCnMLciUv0//0nrsNsEMI9pau2ZxbcpItFVKdZYXFdmHWG+qPCgMcbgsUM3xqaIc7fNwbk2Aa6erIGqD2VkwWzD/xksweg4lsgQ0N1tXMfoWWKh4Xj/OFom+S+3w9uSx/jQma7nXm+PKQL8dIo7rqza3fz9biq5T6mhwUrqCpFIJv7mrMwaTT1UfOchjiLL3CGeO7Amv7Avmh3fhMPbypF0sws79d7ewZbyv+oSzn+pxlCdzBU1GYx6veApbzhg="
- secure: "ljVx3TgpBJ/ylMKDVmXabi9UNi5YvrRM5UBTrRk7XPu1YFYS4FI1GcGlyvYhToc4fKt4jLhX9qU+s/rZY+odO0x/HpmJglMBCrY+QcWOzuyaP1U5dCET+evuqFdEAZIzLQc4VDjL1aQLZh+OG7bjoBClVAan6a+pmW0yxBC6rNtCWTESG4rY3wOeTpoI0Q1gM7gg5Zkj4Z+yLvYeJdoKHijM7C3/R/VVTqUFqArk+Js7Qb2qTqm03SHP0ahRQA8XSfbPebSkJyX9oLbidanBEaQE6sqnp9Qh+8VGcnn7VkSu6oq2+ZXz4xlSMrH2Iv2JXl68Td51LsLo9BxaMCL68ssgTFfXPSrrcLwholNEt1pXk5nhBl1l6MZ1UwUJyBm+AXZp/4sCK9/P0rGa2d1rOcpOz7nobH7BDktqEJkrR6VzkTMx1aOwtF+JSt7SJQ1RrRdm9uKfOZZsnw17+VgVAHo/ttY0C3cRl10oaF1C/IdliDfa5gJdZ2VSZtJxyewqKwGiZrqCRv2fQyIuGsqfHXsyHVL6q1KfVcHjaXBvh0o6xZ6duieFT4FNHg7clv1qPQV+cLh4L11nugiihRTeYQtKyUnP5YIL+jlcGNM6KqKhF9RN5c+zOqWNmEcz6O8nljY5mFWdIxL6dFfE3+4wpw7snFP0PrWIWl5SmrU5ipY="
- secure: "L0ivSUmbOHNmKWVR2zeYcVR+Xr6780dYA829MyksXfg9OrieTS+qVqSODKexFW89dp4Wf8xFdT9f16xSqjA/xSuX12uiISMiTcFKP39ZnQZ//NDkx1T4pZaeNiysqT+2Ys9OaKTWxn8luFtAYp+DaluancQtEw6+M8H3jQyQZimGHl0QB6BK2A5VA2vko+7ebIdwu5Df5E7lc/LG42H+DdSFkSj7Meu5XMyPHSZRAdOE5doO++tqFKzgs2WbDRHRUP4R4LqtDlGn8+5qnQtQKUN4V9UGrKM95R34BhgUlgOqOFAjFDug71/1/rRyv9XnzKkAdTIbxV7nmxSL+APhQDqpwPr01EP9gtZBOycswV/igJYotgqkhzwNAYrmwOA5Ta8S18Ck0feDEqT20w8yKS4QwV2Ihg4q7CqDFu7i+9iSRUCd/RVrGtG0U5Zo1b3+1JcNxXH/ErUeyHPfrk4vktxfHmU+omqwkfvTRy5upn0Ycr57YHOJc/Iyur7vE07HcnBfAwV0d5KO6HJ7M1n6hmMxeyKmf+qiyQQnphySvHHAfa/9Sec7omwwKv4bn33DwFGc8GWvL6cZXWhmGhFvd+LslpZl0vZ+7Bz0tXlAg4t8V48y/ZtyoSpny0HP4UstdA43PttvZ6q2y8LUNk4LBP5btKmp27Fszuj/rldtj5g="
- secure: "Dox8JthAJqWT9eh3Jt4Morbf4pGN9OjduJXe/lYMsmFvqNg7b94P2QdumWBPmVjDq4YjDVirMejBA/TNwORgKfg7pI7MOw+qqoHpT9xyPecXi3ecyBay13e16p0GNRlc5pUu5JcU8sgCpttvM0EAw6bOuQIhnnkIFesbOvwoxGYjMzjmWMNuikR3CjKbo0LDtD5NJXT1OMSqrRuh8NM/BoKyn/kCdSaq9wI2GUMbkg09/kFJkQOvtMXPkM7dIhr/9UC0ouMIyqe/MHa8O6Y4xESdqiTql9uz1+eZfHIRrgFlHfxDvkMv87Cx5OuL+O+qeT/a+RYLCRJspMoq94IYHGg2iyEfBO2YAkogl53wiEf2KF2JdiNGT0xId7bxCJj3efTuCAXV1oqaHpJli1Mhvs7zPEtf78B4tkWEgjhGr5pBLIlbhNjS5wtTHJX4BUzoiP+wODj4h7rjPAah42nWF8XOMlboVi56sOCLjiHBOvYObqyhSfiQxoi2XHphsrZqw6H03tr4Kqd9HVmuoSvRiv+NOu24Ubr6MrrQM2/G72TrTx0/aBlt8Dx5nx2oWZ9ZMiDUR3XlvDLUi45SpY5qESXz08nRlcdS9EvUpK7C+77bNvX+A3dIhsxnxuNaf2naf+QnYYbvh7q4Qbrj4v6EMYS90Uky1JHdoc2wMua8J+w="
- secure: "Is2Lv/rxKKrXnxFns9KQYseD02tjY9qbgSteVtJavG1cLJDvkTwb6X+Thvgo4cxk5fQPiXScrQaYzHjVVuNleD+dyD1HC/8CU2Xq+tjBhPjdcccHFSbk06DpcETmLGRyMORXG9JkYlgXHLLXtu/9icppWEHgra+zvchVL2YDhofYne8FMNBb/lq0AAC2wgzAS33tW1+57HaYnzl0hf6+Q6lwqoH2/aTfGMRFDgyJ0HK+5IVfLnQJ+OuGFSrj8/0FWSggR5+EXDIddDgovFgaCghMjHYp21bzn0eIAJtuNFFultwk/UC1lT9joXTKEzgLTAh+w13yz1T3x9rNuv6FDKCotBIS/ZDtPmgvyZ8xvB4SzyULnTRSVn7YvspKR6PAO/qxGNudUD5H8tRKer4qKnKjHzSUcVBlRHb4yE6FqqY1Z9RLEcomWO43nJwb6saNHR9BYedyi0gA+EbA+P259QFClW1dWEQ2LQhDa+0VRssOqZ0BQblPFyz+e5Vc9kfAMbOuoss8fjkiYv+twXv7nT27xrVT5okfKDSiy5opZD6d36N5FibZPYiMrVx00YZdkFB+5EqQuJ7lqKUMkZJTeApLzj+h+/4aAOWd3paj5ghv7m+9ReohsNKFHyjaSy97RhMAZjzqgMMdD8rjUSKDhvNKvvQECWHlaXwL129GB0s="
- secure: "l7vWxfcu1RgXbStq76Mzz2I5Iu4e31729OyLYqulXZzft3wO+idvgQKy/JSwajiKgOxlpBuI0wrncgIUYshcRvE4yB0y9+QIMDTegJzTADtRSUyVNCIZfTgvtOvzrlW0iCdVsxLBtYcJWJVPdjF2q59ED1jahd1AuJJqX5e61gfr0eZ9+cNiHbX1u3VpmGchFNWQF4KvebE4WKs5xWEds+AtbTODdQq3H6kKQK3fTVJnbz6WMO+bEWgWI7orfSE20lku/3Q3eMLhNOcPwH8WnUoTTvDWol5Cq5NfPhkKF5aV7kIbNXkxswM7yBPAPumBiXdM1BHpfd4+0YQ/fqRtnqxw85HEYpT8dRewHimCl4IccgGCR+G0tK8RNleKL28GWrz86gRVpXMEhOU3ILwb8as3SdQWLwhXXy5uKGJmsdrCNAH4/8eu3XczO5VN2wOo7narYuBgGcl2eLW9TOLyNVKFKxbQnDLBiOybLNoOV42DCRYt7v3Eknkv1Z0dmX6n23q1z9if9kkfAFgRQWsTbNZyWeIwWuX8b2a0Zq0znS3JflSKxzqS7RHADfBOJEVM86AiGkw0XkR4o31yDrY+zOrkJ3GxfV/HpqG7LzCd9tFeexanneDCE1FJhCkDjpnc0Mdyx+1gVf+u2MkgrU0BbCf2EESBAlC/FTRvxTmk/6s="
- secure: "bvtQ348bxKwTtB8X0zMxeTsM0jEJozbS6/rzH/88Fk90a+KO8SdXen0Kj9/LahV4duMn2xTTRmxMCVj424FbcVTgBkJpIO7btqTcNASORkmK+9wGTK6Bgb9R5sHLbVrbrMYJzsMQR0MWxE8ibPLlyom+ssUIqr7HAjnRyYSDiKChGhgBfdE/0G9OE/DuQaU/ZkTuEYfc4527QNLJ8Bt1aLDdCHJLxzCojNaTHB215Tz7dmpnJjWa45BXxkMwLTpxIJuY7wA7K+2UBJfLvZv5QiPYyeUlosV7FwhCN9e90+dc2x8HPJbwe/Ysv5dm8/FfNTgTe6IkKw1z9kev9/W1tYCtqMzn9GnlIH2000ZUomhHKbc4UUl8sskF2jGr14rSz7pfaTyvXNvK7nKLKM7mZAO/cAaQvZoGEx0s6B7a7YX38NmJWcM0UUD603n4G9uVZNoxjyr8HWC6pho8MY8/u5aFKMPd+C8DaDWeSzNJDZRyi62v+t2iyyZuQUtVXtnDpv8GQW4tYFIJCkkrTm5VNNgD2x3WRsEr3LsBa3BonOmi3a1VrdIpyidDzBEWFUR59a/C0lU5J2UX5W1vu/Pnr9/8p898sDvvDbluz47OR9xoVOjtmGdt/ENJa4EOY1q/eRIN6zrt/cwwjIKgTcYOVk7DFDMXQuYlDeEFuHSJ5Xs="
- secure: "I05ZVphCT2Alu4najchCjDLIgflsdSCR/Z20OkMbcESprwJB5h7nb64kuVkqPQT7GeMcXMnK1xahx0KvE1Gn8OqOlDPt5WgnvcYERnVOKEJabmRXws8nM20AehwAzRoc6uDhaTnmwHRuliPSeuxiwY2Rkyj5hdyvEMzaOSY+qoIOYtDYQu0MM1XIC3cAjSbEfEGuqnKcN0p9VG0l7WscEUtcKPSFBShOlJZWDiHy7lisgO6OEzvAeDpZU/1ZdljXBl0RoDX8l4LqH4SzQqE68kK7qqIhZNmx4hkrh7qtx8tVqVKy/R3IUYhdxrJ84eJxrex6RQb9SgJQRGwi/3+rkKxVS41KiQ4quJHJhnqd2A1+5rDMN/fsjbjtM1I3VIl6w4oaT1C1QtwSjQOvuZCKDLIszVutW0PuGHveNyjwqQSm2PboOkLTg0dNrFIflT2hGMynv1s19WzGY8qQDP2UgODNR4EQVBy0PRk43ne5W/AFtzY1wUUUCBfKi7WYi4uURG/1Xu456GEElbIOwx9F1nC0s3z6ZFVJ3bVbmFxUlHtCyL5wJ3fiVHkAoPSygVARvv2UhHmXvJXXjxBMOvsnZZbpjvcbTeZoguffxMZEMNhuI4W22WjLdVTLxi9uh1VTdm8vkfAeNjMPw53gwPaSz7Jv6A82LFqpmbwAHxNAEy8="
- secure: "BSZK3v2RYsNKv/8lBZ/dKagYF+znGXIeDY271A2nCS8DXx+y0octwI5RT08+UqdD1AvhPOPjdnSXG+M2NOSLlfBoXF/0t9S39+qy3EhGgxYAcWcVDXnrOrHEOALg1cQkCA2D/CG+eeG/36SmAn6FINTLaAOilxWGGCeL0KOB5mqPPnPogaYhowIwDkj0Hfsfrw8011XzgbufNr15GIYJ+nP7f41NcgIbnNkqXY6Q1jiWs1DuKXNDr5WGPqztHtVf7RtcpVmShzptAcAMdRqCGKF7atCZhXPbd69j3qf7F533/tCSCIrszR/Wp4BKlJfVCRCk1oiEcfRvprJqeFJ+0WJCVzyD7hXfnkBg2Tb5PmzvxOFM+hsqRu4mY3UdjqXukzAe5O0O6Uo8sqzqQUIjUooRnNQ4GdPd+7wMbyBZn4PJaW6YTi/7zg7mAegqot6uyEGGpWb6iFYrf6DX75GUfTciNktv+ez0AeqYFwNBLgcOsmaq+3V+aR+dIxsxIzC/i5GCTHvMYOIp6Q2tPCuIug0tX6uxm++vMOoMLK+vG1fVQ0Cd8m6yQIWEXUu0VBs1MTlJD+vX6LsK8CGo0Dt3ZS3JmC4TGGo9CBSEkeDvnKvQeX6x3NBIFWvgt+Hjxh4S9U+vW+AaUXpV9k+NEhesC/8Ys0UGbGYsTDzHdx9TMBY="
- secure: "sskZYJ/+xmHh5GNvw3QRf10+sBGOjlub29jOTxjXIRYUyZfkhjsF8CR9NP59CBFuqgN716Mj1uEVEcx0aaepr/zWweQSnqa9lZgFD9nDYALVNh1b4oyqfhYG1sw57ZHdBsJOBF4mKBnahly/QQj11Ya25GyIS2IewwCWVNtCOJYietSssG9l0+qc+RPG5Ub/lEKA3VRrtbUuApcIYszt33DumgZ4wzkzICl1SuOy8V15vHVlkBqASJheEDa4Hia+eAMo6e7OCE5KWjl7K2MxTvtszwFi7lgMCyPCOy6DkaULACfBnQeloh42B2Qhd/ta04vuRKg6y4fKSrnegpeOAa9aGxF1ufvG9IvPsRTsu4+w63b9xsQUN9MyDgxcJe0YeUHPgPYL6mqAjCIKvL62LlIyrQ8IAteoh3MC+4Xb8crXaLGINTcLwYvLwxsHMuC/58hdQ23I4DqnyZGAS3L1IhpX4QvYN6xc7H+ptaiQttweoH5VpMAduSrmSnNmvLOc4g2PvbRES6D95moQ7qk7iX6vpu+PevL5HtQCbB8SFyFLTYWsqZaG+4NrjpIi2hLzUT35meHwrvxG/MsfeqOVlnBfa93VnX75vxOkRFNY56sOtrTJaiVZ+rQUdszAZz3KGPbyrSlz3KxV+ZKxZH6/0oFteAJttXFjWQdICnKGDSo="
- secure: "sdzU5bPs1w7Nzf3F5Gtk/iq2Kfq3zfLQNGcehLZp1gJXzNf7F6HZLOn6GaXQ/5RVlhqR5nOmzMpVQs88rZv+6PE6YqGMugTxHIQeNmXtGnuEDJSBvGT9Ok8ENxcwKwL93g9SCd9P8mTspxklOsW2Bk3No2+Zlc/aQguBcX44TwYF42KuBU4O7oS6pUg8NjnuQp2zTyhp0ouzyAudatPyu1BLci/3lbx+MehutQw1y4Om6g8tfwf950UONZQdqq9MBluu7yYb1oHkdC1J4qgwdCZkJslWIwQHCH5UE4AW9iVG0qVrLpzBGtV27Kfy/Vf8r2gMYzbiur2h2+zzWSDm8/bk8YLn7u1FBpjGJdJ0pX0ZrZr+hMV2vH3e54NvA5WyRU7tw8mZ1PoDYd/FM5KXIYbscSbSRCqTsbPgyVIHuoOWXeeSe+/Ef1ifZv3HHf6ARfUIWupKfAipxChc7QUMI/HEQ9QPsqgBaooZD9chGsWAgv+8tFxdteqkx4Yh+AuZp1rVykB/9vAamUBebQxy0oeGm65j6X1rksfjAPkfeDYB7L4Ruy7tUwPtvYrAHPoWrf9O0g/qDRsw0vdqp42CjszpIxhuPhVRDx0i0wquqw2LnIU3ejRv2R8d1SecVKBBcVsWLFvc9iR4rNIi5JnxITRtiwL1Xv3Vcgx7WwxExtE="
- secure: "f9n1KmU5NuV4jGkrhLNiPD+3Cy7t4D7Rq8YsPlmyB2A6u6IHMuOVP95IwH6Zt0cmMDBrZGthj3/0iu5kzxzqD0m135PT17wSEqsDfDMyKRZJQuYSO/ESVxnSca3afRH7Ds7/ipQVd/ljZgwEnW3JMaOQiIdbbIquNOOTeY0/wsXkreDamXZaKKqUoeadkAV4AkKhM0xcMg+Vni1i71TYPBWrZPLVAu3ZrSvU/cE5mtBUIkbr9EgsEE+WR23QCgtwxKzNxrXetBcPXDsJb98/ABgpoItm5Ko/Zk6pkib44f+iQtn7Y6j3lieELCH5Sn0uy3RrMxkl7xicB7zPYME94NEPHCmshyVsH3RxWfcBG4kauRNBCLYLl5HYF2t1lWZ6In5qlx8xN3Tf0KrbM3vzAEOnnfZt83h3q5OuWl+jzTOcv9xHmeW0lnwEEfS0nxUV3KDqLFBczcUxKBmsA2aWnJZ2HV+kls6OaWZ987m6V2pIGR2uviGT7I4ngjCSOJzbwYbvJbJqYAI97FWP/5pqv97xHLCSSJh6TBO4NMQ7Ib/W1XT6NZyPOjNGSLpd79UA3cTzU2+UYr/7RxZpAKONSAMTJh7CX451XQwgovpFZ2quXs2BzqcVpy8AlUc45ygnFOALOANAkcRP5QFhmff0jpXstjPW83/GksbtaiLhIiQ="
matrix:
include:
- os: linux
name: "Linux 64-bit Xenial"
dist: xenial
language: bash
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=build
- os: linux
name: "Linux 64-bit Trusty"
dist: trusty
language: bash
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=build
- os: linux
name: "Linux 64-bit Precise"
dist: precise
language: bash
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=build
- os: linux
name: "Linux 64-bit Xenial - Python 3.5 Source Testing"
dist: xenial
language: python
python:
- "3.5"
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=test
- os: linux
name: "Linux 64-bit Xenial - Python 3.6 Source Testing"
dist: xenial
language: python
python:
- "3.6"
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=test
- os: linux
name: "Linux 64-bit Xenial - Python 3.8-dev Source Testing"
dist: xenial
language: python
python:
- "3.8-dev"
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=test
- os: linux
name: "Linux 64-bit Xenial - Python nightly Source Testing"
dist: xenial
language: python
python:
- "nightly"
env:
- GAMOS=linux
- PLATFORM=x86_64
- VMTYPE=test
- os: osx
name: "MacOS 64-bit"
language: generic
osx_image: xcode9.2
env:
- GAMOS=macos
- PLATFORM=x86_64
- VMTYPE=build
- os: windows
name: "Windows 64-bit"
language: shell
filter_secrets: false
env:
- GAMOS=windows
- PLATFORM=x86_64
- VMTYPE=build
- os: windows
name: "Windows 32-bit"
language: shell
filter_secrets: false
env:
- GAMOS=windows
- PLATFORM=x86
- VMTYPE=build
before_install:
- source src/travis/$TRAVIS_OS_NAME-$PLATFORM-before-install.sh
install:
- source src/travis/$TRAVIS_OS_NAME-$PLATFORM-install.sh
script:
- $gam version extended
- $gam version | grep travis # travis should be part of the path (not /tmp or such)
- if [ "$VMTYPE" == "build" ]; then $gam version | grep "Python 3\.7\.3"; fi # We should be building with Python 3.7.3
- if [ "$VMTYPE" == "build" ]; then $gam version extended | grep TLSv1\.[23]; fi # Builds should support TLS 1.2 or 1.3 to Google
- export jid="$(cut -d'.' -f2 <<<"$TRAVIS_JOB_NUMBER")"
- export gam_user=gam-travis-$jid@pdl.jaylee.us
- openssl aes-256-cbc -K $encrypted_ab10ec38326e_key -iv $encrypted_ab10ec38326e_iv -in travis/oauth2service.json.enc -out $gampath/oauth2service.json -d
- cat travis/cfg_template.json | python travis/svars-write.py &> /dev/null
- $gam info domain
- $gam info user
- export tstamp=$(date +%s%3N);
export newbase=travis-test-$jid-$tstamp;
export newuser=$newbase@pdl.jaylee.us;
export newgroup=$newbase-group@pdl.jaylee.us;
export newalias=$newbase-alias@pdl.jaylee.us;
export newbuilding=$newbase-building;
export newresource=$newbase-resource;
export GAM_THREADS=5;
- echo email > sample.csv;
for i in {01..20};
do echo $newbase-bulkuser-$i >> sample.csv;
done
- $gam create user $newuser firstname Travis lastname $jid password random travis.jid $jid
- $gam create group $newgroup name "Travis $jid group" description "This is a description" isarchived true
- $gam user $newuser add license gsuitebusiness
- $gam update group $newgroup add owner $gam_user
- $gam update group $newgroup add member $newuser
- $gam csv sample.csv gam create user ~~email~~ firstname "Travis Bulk" lastname ~~email~~ travis.jid $jid
- $gam csv sample.csv gam user ~email add license gsuitebusiness
- $gam csv sample.csv gam update group $newgroup add member ~email
- $gam info group $newgroup
- $gam user $gam_user check serviceaccount
- $gam user $newuser imap on
- $gam user $newuser show imap
- $gam csv sample.csv gam user $newuser delegate to ~email
- $gam user $newuser show delegates
- $gam users "$newbase-bulkuser-01 $newbase-bulkuser-02 $newbase-bulkuser-03" delete messages query in:anywhere maxtodelete 99999 doit
- $gam users "$newbase-bulkuser-04 $newbase-bulkuser-05 $newbase-bulkuser-06" trash messages query in:anywhere maxtotrash 99999 doit
- $gam users "$newbase-bulkuser-07 $newbase-bulkuser-08 $newbase-bulkuser-09" modify messages query in:anywhere maxtomodify 99999 addlabel IMPORTANT addlabel STARRED doit
- $gam create feature name Whiteboard-$newbase
- $gam create feature name VC-$newbase
- $gam create building "My Building - $newbase" id $newbuilding floors 1,2,3,4,5,6,7,8,9,10,11,12,14,15 description "No 13th floor here..."
- $gam create resource $newresource "Resource Calendar $tstamp" capacity 25 features Whiteboard-$newbase,VC-$newbase building $newbuilding floor 15 type Room
- $gam info resource $newresource
- $gam user $newuser show filelist
- $gam calendar $newuser update read domain
- $gam calendar $newuser add editor $gam_user
- $gam calendar $newuser showacl
- $gam printer register
- source travis/set_printer_csv_filter.sh
- $gam print printers > printers.csv
- unset GAM_CSV_ROW_FILTER
- $gam csv printers.csv gam printer ~id add USER $newgroup
- $gam csv printers.csv gam printjob ~id submit https://www.github.com/jay0lee/GAM
- $gam csv printers.csv gam info printer ~id
- $gam print printjobs
- $gam csv printers.csv gam printjob ~id fetch
- $gam csv printers.csv gam delete printer ~id
#- $gam calendar id:$newresource add editor $newuser
#- $gam calendar id:$newresource update read domain
#- $gam calendar id:$newresource showacl
- $gam csv sample.csv gam user ~email add calendar id:$newresource
- $gam delete resource $newresource
- $gam delete feature Whiteboard-$newbase
- $gam delete feature VC-$newbase
- $gam delete building $newbuilding
- $gam delete group $newgroup
- $gam create alias $newalias user $newuser
- $gam whatis $newuser
- $gam user $gam_user show tokens
- $gam delete user $newuser
- $gam print users query "travis.jid=$jid" | $gam csv - gam delete user ~primaryEmail
before_deploy:
- export TRAVIS_TAG="preview"
deploy:
provider: releases
api_key:
secure: bzambMcQwyv/o5c5GrKGCsZHgE5R85tg8sNFvPfpISz3+uosCjnBXas7wvCKzT75XUFi2ztfbYak6HdKf4sGnNHk0saEicB3slH+ghPyZbYzp76yvvduhFO2nWW3/F01tL+Yfqqt4/q8wFaWGjrC5km+6GLVyB4lWA/Uyu49qKnz02uSwyhBD/VFbO7DOQ65a1iWk9HngyMsu0Oi7HIbSjSLtxTHedNfOf3waW0NivTTxYXiYGX/MCu3GWhgIGj47a+H3A6FcQ/9QWvnKgnoixdgPBUz7kDb7ktsWwQsILPGStgH7iMuG49ZlXdEFmqwifBri2wvzmFEevBGZjHcupy1IGrNFRG+IUGKMotio+OkLHlLjuv7ZJtqCz/Vf5SNFgNyMSanx6jKEUJuYvndVg99IRXmYVwHFwPu5BAcJACpU6C0AfyGmmSqqwxCd46uXL62ynxNFpHuRfOqlDnmCTfZgjOciJSlDDpf+Xz9fF7+oCoeCi3mrcZVFjhd3tT6Oxw5HrsDtm0ZNld1cdLidaq8H6vOFgHMd0A9yNYZzTzXTvpmxzkXT4Zc7s+PYKN6z5fRZ+pJeckUjRXblvVEfs5HFSymavcOc5AkRwxpvOsTQMNmlnaJCBo5UNs0K/rVmRi5cFmaiwTcBCY0kTllOBJ4zWsfq8seiokWwNUNK2g=
file_glob: true
overwrite: true
file: gam-$GAMVERSION-*
skip_cleanup: true
draft: true
all_branches: true
on:
repo: jay0lee/GAM
condition: $VMTYPE = build

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,24 +1,41 @@
GAM is a command line tool for Google G Suite Administrators to manage domain and user settings quickly and easily. [![Build Status](https://travis-ci.org/jay0lee/GAM.svg?branch=master)](https://travis-ci.org/jay0lee/GAM)
# Quick Start
## Linux / MacOS
Open a terminal and run:
```
bash <(curl -s -S -L https://git.io/install-gam)
```
this will download GAM, install it and start setup.
## Windows
Download the MSI Installer from the [GitHub Releases] page. Install the MSI and you'll be prompted to setup GAM.
# Documentation
The GAM documentation is hosted in the [GitHub Wiki]
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
# IM Room
[![Join the chat at https://gitter.im/jay0lee-GAM/community](https://badges.gitter.im/jay0lee-GAM/community.svg)](https://gitter.im/jay0lee-GAM/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Author
GAM is maintained by <a href="mailto:jay0lee@gmail.com">Jay Lee</a>. Please direct "how do I?" questions to [Google Groups].
GAM is a command line tool for Google Workspace admins to manage domain and user settings quickly and easily.
[GAM release]: https://git.io/gamreleases
[GitHub Releases]: https://github.com/jay0lee/GAM/releases
[GitHub]: https://github.com/jay0lee/GAM/tree/master
[GitHub Wiki]: https://github.com/jay0lee/GAM/wiki/
[![Build StatusM](https://github.com/GAM-team/GAM/actions/workflows/build.yml/badge.svg)](https://github.com/GAM-team/GAM/actions/workflows/build.yml)
# Quick Start
## Linux / MacOS
Open a terminal and run:
```sh
bash <(curl -s -S -L https://gam-shortn.appspot.com/gam-install)
```
this will download GAM, install it and start setup.
## Windows
Download the MSI Installer from the [GitHub Releases] page. Install the MSI and you'll be prompted to setup GAM.
# Documentation
The GAM documentation is hosted in the [GitHub Wiki]
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
# Chat Room
There is a public chat room hosted in Google Chat. [Instructions to join](https://github.com/GAM-team/GAM/wiki/GAM-Public-Chat-Room).
# Author
GAM is maintained by [Jay (James) Lee](mailto:jay0lee@gmail.com) and [Ross Scroggs](mailto:ross.scroggs@gmail.com). Please direct "how do I?" questions to [Google Groups].
[GAM release]: https://github.com/GAM-team/GAM/releases
[GitHub Releases]: https://github.com/GAM-team/GAM/releases
[GitHub]: https://github.com/GAM-team/GAM/tree/master
[GitHub Wiki]: https://github.com/GAM-team/GAM/wiki/
[Google Groups]: http://groups.google.com/group/google-apps-manager

2
src/.gitignore vendored
View File

@@ -64,7 +64,7 @@ nobrowser.txt
nocache.txt
noverifyssl.txt
gamcache/
gam/
dist/
gam-64/
*.zip
*.msi

File diff suppressed because it is too large Load Diff

18866
src/GamUpdate.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,547 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
APACHE HTTP SERVER SUBCOMPONENTS:
The Apache HTTP Server includes a number of subcomponents with
separate copyright notices and license terms. Your use of the source
code for the these subcomponents is subject to the terms and
conditions of the following licenses.
For the mod_mime_magic component:
/*
* mod_mime_magic: MIME type lookup via file magic numbers
* Copyright (c) 1996-1997 Cisco Systems, Inc.
*
* This software was submitted by Cisco Systems to the Apache Group in July
* 1997. Future revisions and derivatives of this source code must
* acknowledge Cisco Systems as the original contributor of this module.
* All other licensing and usage conditions are those of the Apache Group.
*
* Some of this code is derived from the free version of the file command
* originally posted to comp.sources.unix. Copyright info for that program
* is included below as required.
* ---------------------------------------------------------------------------
* - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.
*
* This software is not subject to any license of the American Telephone and
* Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on any
* computer system, and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources, credits
* must appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users ever read
* sources, credits must appear in the documentation.
*
* 4. This notice may not be removed or altered.
* -------------------------------------------------------------------------
*
*/
For the modules\mappers\mod_imagemap.c component:
"macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
For the server\util_md5.c component:
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* md5.c: NCSA HTTPd code which uses the md5c.c RSA Code
*
* Original Code Copyright (C) 1994, Jeff Hostetler, Spyglass, Inc.
* Portions of Content-MD5 code Copyright (C) 1993, 1994 by Carnegie Mellon
* University (see Copyright below).
* Portions of Content-MD5 code Copyright (C) 1991 Bell Communications
* Research, Inc. (Bellcore) (see Copyright below).
* Portions extracted from mpack, John G. Myers - jgm+@cmu.edu
* Content-MD5 Code contributed by Martin Hamilton (martin@net.lut.ac.uk)
*
*/
/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */
/* (C) Copyright 1993,1994 by Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of Carnegie
* Mellon University not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. Carnegie Mellon University makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
*
* Permission to use, copy, modify, and distribute this material
* for any purpose and without fee is hereby granted, provided
* that the above copyright notice and this permission notice
* appear in all copies, and that the name of Bellcore not be
* used in advertising or publicity pertaining to this
* material without the specific, prior written permission
* of an authorized representative of Bellcore. BELLCORE
* MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
* OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
*/
For the srclib\apr\include\apr_md5.h component:
/*
* This is work is derived from material Copyright RSA Data Security, Inc.
*
* The RSA copyright statement and Licence for that original material is
* included below. This is followed by the Apache copyright statement and
* licence for the modifications made to that material.
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
For the srclib\apr\passwd\apr_md5.c component:
/*
* This is work is derived from material Copyright RSA Data Security, Inc.
*
* The RSA copyright statement and Licence for that original material is
* included below. This is followed by the Apache copyright statement and
* licence for the modifications made to that material.
*/
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/*
* The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
* MD5 crypt() function, which is licenced as follows:
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*/
For the srclib\apr-util\crypto\apr_md4.c component:
* This is derived from material copyright RSA Data Security, Inc.
* Their notice is reproduced below in its entirety.
*
* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* rights reserved.
*
* License to copy and use this software is granted provided that it
* is identified as the "RSA Data Security, Inc. MD4 Message-Digest
* Algorithm" in all material mentioning or referencing this software
* or this function.
*
* License is also granted to make and use derivative works provided
* that such works are identified as "derived from the RSA Data
* Security, Inc. MD4 Message-Digest Algorithm" in all material
* mentioning or referencing the derived work.
*
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*/
For the srclib\apr-util\include\apr_md4.h component:
*
* This is derived from material copyright RSA Data Security, Inc.
* Their notice is reproduced below in its entirety.
*
* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* rights reserved.
*
* License to copy and use this software is granted provided that it
* is identified as the "RSA Data Security, Inc. MD4 Message-Digest
* Algorithm" in all material mentioning or referencing this software
* or this function.
*
* License is also granted to make and use derivative works provided
* that such works are identified as "derived from the RSA Data
* Security, Inc. MD4 Message-Digest Algorithm" in all material
* mentioning or referencing the derived work.
*
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*/
For the srclib\apr-util\test\testmd4.c component:
*
* This is derived from material copyright RSA Data Security, Inc.
* Their notice is reproduced below in its entirety.
*
* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
* rights reserved.
*
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*/
For the srclib\apr-util\xml\expat\conftools\install-sh component:
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
For the test\zb.c component:
/* ZeusBench V1.01
===============
This program is Copyright (C) Zeus Technology Limited 1996.
This program may be used and copied freely providing this copyright notice
is not removed.
This software is provided "as is" and any express or implied waranties,
including but not limited to, the implied warranties of merchantability and
fitness for a particular purpose are disclaimed. In no event shall
Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
exemplary, or consequential damaged (including, but not limited to,
procurement of substitute good or services; loss of use, data, or profits;
or business interruption) however caused and on theory of liability. Whether
in contract, strict liability or tort (including negligence or otherwise)
arising in any way out of the use of this software, even if advised of the
possibility of such damage.
Written by Adam Twiss (adam@zeus.co.uk). March 1996
Thanks to the following people for their input:
Mike Belshe (mbelshe@netscape.com)
Michael Campanella (campanella@stevms.enet.dec.com)
*/
For the expat xml parser component:
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
and Clark Cooper
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
====================================================================

1
src/LICENSE Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE

1128
src/cacerts.pem Normal file

File diff suppressed because it is too large Load Diff

21
src/callgam.py Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Sample Python script to call GAM"""
import multiprocessing
import platform
from gam import initializeLogging, CallGAMCommand
if __name__ == '__main__':
# One time initialization
if platform.system() != 'Linux':
multiprocessing.freeze_support()
multiprocessing.set_start_method('spawn')
initializeLogging()
#
CallGAMCommand(['gam', 'version'])
# Issue command, output goes to stdout/stderr
rc = CallGAMCommand(['gam', 'info', 'domain'])
# Issue command, redirect stdout/stderr
rc = CallGAMCommand(['gam', 'redirect', 'stdout', 'domain.txt', 'redirect', 'stderr', 'stdout', 'info', 'domain'])

View File

@@ -1,486 +0,0 @@
{
"kind": "discovery#restDescription",
"discoveryVersion": "v1",
"id": "cloudprint:v2",
"name": "cloudprint",
"version": "v2",
"revision": "20150605",
"title": "Cloud Print API",
"description": "Lets you access Cloud Print Printers",
"ownerDomain": "google.com",
"ownerName": "Google",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"documentationLink": "https://developers.google.com/cloud-print",
"protocol": "rest",
"baseUrl": "https://www.google.com/",
"basePath": "/cloudprint/",
"rootUrl": "https://www.google.com/",
"servicePath": "/cloudprint/",
"parameters": {
"prettyPrint": {
"type": "boolean",
"description": "Returns response with indentations and line breaks.",
"default": "true",
"location": "query"
}
},
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/cloudprint": {
"description": "Manage Cloud Print"
}
}
}
},
"schemas": {
"Job": {
"id": "Job",
"type": "object",
"description": "Job Object",
"properties": {
"title": {
"type": "string",
"description": "Job Title"
},
"id": {
"type": "string",
"description": "Unique ID"
}
}
},
"Jobs": {
"id": "Jobs",
"type": "object",
"description": "List of Jobs.",
"properties": {
"jobs": {
"type": "array",
"description": "List of job objects.",
"items": {
"$ref": "Job"
}
}
}
},
"Printer": {
"id": "Printer",
"type": "object",
"description": "Printer Object",
"properties": {
"displayName": {
"type": "string",
"description": "Display Name"
},
"id": {
"type": "string",
"description": "Unique ID"
}
}
},
"Printers": {
"id": "Printers",
"type": "object",
"description": "List of Printers.",
"properties": {
"printers": {
"type": "array",
"description": "List of printer objects.",
"items": {
"$ref": "Printer"
}
}
}
}
},
"resources": {
"jobs": {
"methods": {
"delete": {
"id": "cloudprint.jobs.delete",
"path": "deletejob",
"httpMethod": "GET",
"parameters": {
"jobid": {
"type": "string",
"location": "query",
"required": "true"
}
}
},
"fetch": {
"id": "cloudprint.jobs.fetch",
"path": "fetch",
"httpMethod": "GET",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
}
},
"response": {
"$ref": "Jobs"
}
},
"getticket": {
"id": "cloudprint.jobs.getticket",
"path": "ticket",
"httpMethod": "GET",
"parameters": {
"jobid": {
"type": "string",
"required": "true",
"location": "query"
},
"use_cjt": {
"type": "boolean",
"required": "true",
"location": "query"
}
}
},
"list": {
"id": "cloudprint.jobs.list",
"path": "jobs",
"httpMethod": "GET",
"parameters": {
"printerid": {
"type": "string",
"location": "query"
},
"owner": {
"type": "string",
"location": "query"
},
"status": {
"type": "string",
"location": "query"
},
"q": {
"type": "string",
"location": "query"
},
"offset": {
"type": "string",
"location": "query"
},
"limit": {
"type": "string",
"location": "query"
},
"sortorder": {
"type": "string",
"location": "query"
}
},
"response": {
"$ref": "Jobs"
}
},
"update": {
"id": "cloudprint.jobs.update",
"path": "control",
"httpMethod": "GET",
"parameters": {
"jobid": {
"type": "string",
"required": "true",
"location": "query"
},
"semantic_state_diff": {
"type": "string",
"required": "true",
"location": "query"
}
},
"response": {
"$ref": "Jobs"
}
},
"resubmit": {
"id": "cloudprint.jobs.resubmit",
"path": "resubmit",
"httpMethod": "POST",
"description": "resubmit a job to new printer.",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"jobid": {
"type": "string",
"required": "true",
"location": "query"
},
"ticket": {
"type": "string",
"location": "query"
}
},
"response": {
"$ref": "Job"
}
},
"submit": {
"id": "cloudprint.jobs.submit",
"path": "submit",
"httpMethod": "POST",
"description": "Send a print job to cloud print.",
"request": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"title": {
"type": "string",
"location": "query"
},
"ticket": {
"type": "string",
"location": "query"
},
"content": {
"type": "string",
"location": "query"
},
"contentType": {
"type": "string",
"location": "query"
},
"tag": {
"type": "string",
"location": "query"
}
},
"response": {
"$ref": "Job"
}
}
}
},
"printers": {
"methods": {
"get": {
"id": "cloudprint.printers.get",
"path": "printer",
"httpMethod": "GET",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"extra_fields": {
"type": "string",
"location": "query"
}
},
"response": {
"$ref": "Printer"
}
},
"list": {
"id": "cloudprint.printers.list",
"path": "search",
"httpMethod": "GET",
"description": "List all printers",
"parameters": {
"q": {
"type": "string",
"description": "Query list of printers",
"location": "query"
},
"type": {
"type": "string",
"description": "limit results to printers of type",
"location": "query"
},
"connection_status": {
"type": "string",
"description": "limit results to printers with this status",
"location": "query"
},
"extra_fields": {
"type": "string",
"description": "include extra fields",
"location": "query"
}
},
"response": {
"$ref": "Printers"
}
},
"share": {
"id": "cloudprint.printers.share",
"path": "share",
"httpMethod": "GET",
"description": "Share printer with user, group or domain",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"scope": {
"type": "string",
"location": "query"
},
"role": {
"type": "string",
"location": "query"
},
"type": {
"type": "string",
"location": "query"
},
"skip_notification": {
"type": "boolean",
"location": "query"
},
"public": {
"type": "boolean",
"location": "query"
}
}
},
"unshare": {
"id": "cloudprint.printers.unshare",
"path": "unshare",
"httpMethod": "GET",
"description": "unshare printer with user, group or domain",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"scope": {
"type": "string",
"location": "query"
},
"public": {
"type": "string",
"location": "query"
}
}
},
"delete": {
"id": "cloudprint.printers.delete",
"path": "delete",
"httpMethod": "GET",
"description": "delete a printer",
"parameters": {
"printerid": {
"type": "string",
"required": "true",
"location": "query"
}
}
},
"update": {
"id": "cloudprint.printers.update",
"path": "update",
"httpMethod": "GET",
"description": "update a printer",
"parameters": {
"isTosAccepted": {
"type": "boolean",
"location": "query"
},
"gcpVersion": {
"type": "string",
"location": "query"
},
"setupUrl": {
"type": "string",
"location": "query"
},
"supportUrl": {
"type": "string",
"location": "query"
},
"firmware": {
"type": "string",
"location": "query"
},
"currentQuota": {
"type": "string",
"location": "query"
},
"type": {
"type": "string",
"location": "query"
},
"public": {
"type": "boolean",
"location": "query"
},
"status": {
"type": "string",
"location": "query"
},
"proxy": {
"type": "string",
"location": "query"
},
"manufacturer": {
"type": "string",
"location": "query"
},
"defaultDisplayName": {
"type": "string",
"location": "query"
},
"displayName": {
"type": "string",
"location": "query"
},
"name": {
"type": "string",
"location": "query"
},
"uuid": {
"type": "string",
"location": "query"
},
"updateUrl": {
"type": "string",
"location": "query"
},
"ownerId": {
"type": "string",
"location": "query"
},
"model": {
"type": "string",
"location": "query"
},
"description": {
"type": "string",
"location": "query"
},
"printerid": {
"type": "string",
"required": "true",
"location": "query"
},
"quotaEnabled": {
"type": "boolean",
"location": "query"
},
"dailyQuota": {
"type": "string",
"location": "query"
}
}
}
}
}
}
}

View File

@@ -10,36 +10,42 @@ OPTIONS:
-d Directory where gam folder will be installed. Default is \$HOME/bin/
-a Architecture to install (i386, x86_64, x86_64_legacy, arm, arm64). Default is to detect your arch with "uname -m".
-o OS we are running (linux, macos). Default is to detect your OS with "uname -s".
-b OS version. Default is to detect on MacOS and Linux.
-l Just upgrade GAM to latest version. Skips project creation and auth.
-p Profile update (true, false). Should script add gam command to environment. Default is true.
-u Admin user email address to use with GAM. Default is to prompt.
-r Regular user email address. Used to test service account access to user data. Default is to prompt.
-v Version to install (latest, prerelease, draft, 3.8, etc). Default is latest.
-s Strip gam component from extracted files, files will be downloaded directly to $target_dir
EOF
}
target_dir="$HOME/bin"
target_gam="gam7/gam"
gamarch=$(uname -m)
gamos=$(uname -s)
osversion=""
update_profile=true
upgrade_only=false
gamversion="latest"
adminuser=""
regularuser=""
gam_glibc_vers="2.23 2.19 2.15"
strip_gam="--strip-components 0"
while getopts "hd:a:o:lp:u:r:v:" OPTION
while getopts "hd:a:o:b:lp:u:r:v:s" OPTION
do
case $OPTION in
h) usage; exit;;
d) target_dir="$OPTARG";;
a) gamarch="$OPTARG";;
o) gamos="$OPTARG";;
b) osversion="$OPTARG";;
l) upgrade_only=true;;
p) update_profile="$OPTARG";;
u) adminuser="$OPTARG";;
r) regularuser="$OPTARG";;
v) gamversion="$OPTARG";;
s) strip_gam="--strip-components 1"; target_gam="gam";;
?) usage; exit;;
esac
done
@@ -48,15 +54,15 @@ done
target_dir=${target_dir%/}
update_profile() {
[ -f "$1" ] || return 1
[ "$2" -eq 1 ] || [ -f "$1" ] || return 1
grep -F "$alias_line" "$1" > /dev/null 2>&1
if [ $? -ne 0 ]; then
grep -F "$alias_line" "$1" > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo_yellow "Adding gam alias to profile file $1."
echo -e "\n$alias_line" >> "$1"
echo -e "\n$alias_line" >> "$1"
else
echo_yellow "gam alias already exists in profile file $1. Skipping add."
fi
fi
}
echo_red()
@@ -79,59 +85,50 @@ echo -e '\x1B[0m'
version_gt()
{
test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"
# MacOS < 10.13 doesn't support sort -V
echo "" | sort -V > /dev/null 2>&1
vsort_failed=$?
if [ "${1}" = "${2}" ]; then
true
elif (( $vsort_failed != 0 )); then
false
else
test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"
fi
}
case $gamos in
[lL]inux)
gamos="linux"
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
echo "This Linux distribution uses glibc $this_glibc_ver"
useglibc="legacy"
for gam_glibc_ver in $gam_glibc_vers; do
if version_gt $this_glibc_ver $gam_glibc_ver; then
useglibc="glibc$gam_glibc_ver"
echo_green "Using GAM compiled against $useglibc"
break
fi
done
case $gamarch in
x86_64) gamfile="linux-x86_64-$useglibc.tar.xz";;
i?86) gamfile="linux-i686.tar.xz";;
arm|armv7l) gamfile="linux-armv7l.tar.xz";;
arm64|aarch64) gamfile="linux-aarch64.tar.xz";;
*)
echo_red "ERROR: this installer currently only supports i386, x86_64, arm and arm64 Linux. Looks like you're running on $gamarch. Exiting."
exit
esac
;;
[Mm]ac[Oo][sS]|[Dd]arwin)
osver=$(sw_vers -productVersion | awk -F'.' '{print $2}')
if (( $osver < 13 )); then
echo_red "ERROR: GAM currently requires MacOS 10.13 or newer. You are running MacOS 10.$osver. Please upgrade."
exit
else
echo_green "Good, you're running MacOS 10.$osver..."
fi
gamos="macos"
gamfile="macos-x86_64.tar.xz"
;;
*)
echo_red "Sorry, this installer currently only supports Linux and MacOS. Looks like you're runnning on $gamos. Exiting."
exit
;;
esac
if [ "$gamversion" == "latest" -o "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
release_url="https://api.github.com/repos/jay0lee/GAM/releases"
if [ "$gamversion" == "latest" ]; then
release_url="https://api.github.com/repos/GAM-team/GAM/releases/latest"
elif [ "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
release_url="https://api.github.com/repos/GAM-team/GAM/releases"
else
release_url="https://api.github.com/repos/jay0lee/GAM/releases/tags/v$gamversion"
release_url="https://api.github.com/repos/GAM-team/GAM/releases/tags/v$gamversion"
fi
echo_yellow "Checking GitHub URL $release_url for $gamversion GAM release..."
release_json=$(curl -s $release_url 2>&1 /dev/null)
if [ -z ${GHCLIENT+x} ]; then
check_type="unauthenticated"
curl_opts=( )
else
check_type="authenticated"
curl_opts=( "$GHCLIENT" )
fi
echo_yellow "Checking GitHub URL $release_url for $gamversion GAM release ($check_type)..."
release_json=$(curl \
--silent \
"${curl_opts[@]}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"$release_url" \
--fail-with-body)
curl_exit_code=$?
if [ $curl_exit_code -ne 0 ]; then
echo_red "ERROR retrieving URL: ${release_json}"
exit
else
echo_green "done"
fi
echo_yellow "Getting file and download URL..."
echo_yellow "Calculating download URL for this device..."
# Python is sadly the nearest to universal way to safely handle JSON with Bash
# At least this code should be compatible with just about any Python version ever
# unlike GAM itself. If some users don't have Python we can try grep / sed / etc
@@ -153,19 +150,27 @@ if type(release) is list:
break
try:
for asset in release['assets']:
if asset[attrib].endswith('$gamfile'):
print(asset[attrib])
break
else:
print('ERROR: Attribute: {0} for $gamfile version {1} not found'.format(attrib, gamversion))
print(asset[attrib])
#else:
# print('ERROR: Attribute: {0} for version {1} not found'.format(attrib, gamversion))
except KeyError:
print('ERROR: assets value not found in JSON value of:\n\n%s' % release)"
pycmd="python"
pycmd="python3"
$pycmd -V >/dev/null 2>&1
rc=$?
if (( $rc != 0 )); then
pycmd="python3"
pycmd="python"
fi
$pycmd -V >/dev/null 2>&1
rc=$?
if (( $rc != 0 )); then
pycmd="/usr/bin/python3"
fi
$pycmd -V >/dev/null 2>&1
rc=$?
if (( $rc != 0 )); then
pycmd="python2"
fi
$pycmd -V >/dev/null 2>&1
rc=$?
@@ -173,28 +178,163 @@ if (( $rc != 0 )); then
echo_red "ERROR: No version of python installed."
exit
fi
# also sort the URLs once so we're evaluating newest OS version first
download_urls=$(echo "$release_json" | \
$pycmd -c "$pycode" browser_download_url "$gamversion" | \
sort --version-sort --reverse)
if [[ ${download_urls:0:5} = "ERROR" ]]; then
echo_red "${download_urls}"
exit
fi
case $gamos in
[lL]inux)
gamos="linux"
download_urls=$(echo -e "$download_urls" | grep "\-linux-")
if [ "$osversion" == "" ]; then
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
else
this_glibc_ver=$osversion
fi
echo "This Linux distribution uses glibc $this_glibc_ver"
case $gamarch in
x86_64)
download_urls=$(echo -e "$download_urls" | grep "\-x86_64-")
gam_x86_64_glibc_vers=$(echo -e "$download_urls" | \
grep --only-matching 'glibc[0-9\.]*\.tar\.xz$' \
| cut -c 6-9 )
useglibc="legacy"
for gam_glibc_ver in $gam_x86_64_glibc_vers; do
if version_gt $this_glibc_ver $gam_glibc_ver; then
useglibc="glibc$gam_glibc_ver"
echo_green "Using GAM compiled against $useglibc"
break
fi
done
download_url=$(echo -e "$download_urls" | grep "$useglibc")
;;
arm|arm64|aarch64)
download_urls=$(echo -e "$download_urls" | grep "\-aarch64-")
gam_arm64_glibc_vers=$(echo -e "$download_urls" | \
grep --only-matching 'glibc[0-9\.]*\.tar\.xz$' | \
cut -c 6-9)
useglibc="legacy"
for gam_glibc_ver in $gam_arm64_glibc_vers; do
if version_gt $this_glibc_ver $gam_glibc_ver; then
useglibc="glibc$gam_glibc_ver"
echo_green "Using GAM compiled against $useglibc"
break
fi
done
download_url=$(echo -e "$download_urls" | grep "$useglibc")
;;
*)
echo_red "ERROR: this installer currently only supports x86_64 and arm64 Linux. Looks like you're running on $gamarch. Exiting."
exit
esac
;;
[Mm]ac[Oo][sS]|[Dd]arwin)
gamos="macos"
currentversion=$(sw_vers -productVersion | awk -F '.' '{print $1 "." $2}')
# override osversion only if it wasn't set by cli arguments
osversion=${osversion:-${currentversion}}
# override osversion only if it wasn't set by cli arguments
download_urls=$(echo -e "$download_urls" | grep "\-macos")
case $gamarch in
x86_64)
archgrep="\-x86_64"
;;
arm|arm64|aarch64)
archgrep="\-aarch64"
;;
*)
echo_red "ERROR: this installer currently only supports x86_64 and arm64 MacOS. Looks like you're running on ${gamarch}. Exiting."
exit
;;
esac
gam_macos_urls=$(echo -e "$download_urls" | \
grep "$archgrep")
versionless_urls=$(echo -e "$gam_macos_urls" | \
grep "\-macos-")
if [ "$versionless_urls" == "" ]; then
# versions after 7.00.38 include MacOS version info
gam_macos_vers=$(echo -e "$gam_macos_urls" | \
grep --only-matching '\-macos[0-9\.]*' | \
cut -c 7-10)
for gam_mac_ver in $gam_macos_vers; do
if version_gt $currentversion $gam_mac_ver; then
download_url=$(echo -e "$gam_macos_urls" | grep "$gam_mac_ver")
echo_green "You are running MacOS ${currentversion} Using GAM compiled against ${gam_mac_ver}"
break
fi
done
if [ -z ${download_url+x} ]; then
echo_red "Sorry, you are running MacOS ${osversion} but GAM on ${gamarch} requires MacOS ${gam_mac_ver} or newer. Exiting."
exit
fi
else
# versions 7.00.38 and older don't include version info
case $gamarch in
x86_64)
minimum_version=13
download_url=$(echo -e "$download_urls" | grep "\-x86_64")
;;
arm|arm64|aarch64)
download_url=$(echo -e "$download_urls" | grep "\-aarch64")
minimum_version=14
;;
esac
if version_gt "$osversion" "$minimum_version"; then
echo_green "You are running MacOS ${osversion}, good. Downloading GAM from ${download_url}."
else
echo_red "Sorry, you are running MacOS ${osversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting."
exit
fi
if [ -z ${download_url+x} ]; then
echo_red "Sorry, you are running MacOS ${currentversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting."
exit
fi
fi
;;
MINGW64_NT*)
gamos="windows"
echo "You are running Windows"
download_url=$(echo -e "$download_urls" | \
grep "\-windows-" | \
grep ".zip")
;;
*)
echo_red "Sorry, this installer currently only supports Linux and MacOS. Looks like you're running on ${gamos}. Exiting."
exit
;;
esac
browser_download_url=$(echo "$release_json" | $pycmd -c "$pycode" browser_download_url $gamversion)
if [[ ${browser_download_url:0:5} = "ERROR" ]]; then
echo_red "${browser_download_url}"
exit
fi
name=$(echo "$release_json" | $pycmd -c "$pycode" name $gamversion)
if [[ ${name:0:5} = "ERROR" ]]; then
echo_red "${name}"
exit
fi
# Temp dir for archive
#temp_archive_dir=$(mktemp -d)
temp_archive_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
echo_yellow "Downloading file $name from $browser_download_url to $temp_archive_dir."
# Clean up after ourselves even if we are killed with CTRL-C
trap "rm -rf $temp_archive_dir" EXIT
# hack to grab the end of the URL which should be the filename.
name=$(echo -e "$download_url" | rev | cut -f1 -d "/" | rev)
echo_yellow "Downloading ${download_url} to $temp_archive_dir ($check_type)..."
# Save archive to temp w/o losing our path
(cd $temp_archive_dir && curl -O -L $browser_download_url)
(cd "$temp_archive_dir" && curl -O -L -s "${curl_opts[@]}" "$download_url")
mkdir -p "$target_dir"
echo_yellow "Deleting contents of $target_dir/gam7/lib"
rm -frv "$target_dir/gam7/lib"
echo_yellow "Extracting archive to $target_dir"
tar xf $temp_archive_dir/$name -C "$target_dir"
if [[ "$name" =~ tar.xz|tar.gz|tar ]]; then
tar $strip_gam -xf "$temp_archive_dir"/"$name" -C "$target_dir"
elif [[ "$name" == *.zip ]]; then
unzip -o "${temp_archive_dir}/${name}" -d "${target_dir}"
else
echo "I don't know what to do with files like ${name}. Giving up."
exit 1
fi
rc=$?
if (( $rc != 0 )); then
echo_red "ERROR: extracting the GAM archive with tar failed with error $rc. Exiting."
@@ -203,12 +343,26 @@ else
echo_green "Finished extracting GAM archive."
fi
# Update profile to add gam command
if [ "$update_profile" = true ]; then
alias_line="alias gam=\"${target_dir// /\\ }/$target_gam\""
if [ "$gamos" == "linux" ]; then
update_profile "$HOME/.bash_aliases" 0 || update_profile "$HOME/.bash_profile" 0 || update_profile "$HOME/.bashrc" 0
update_profile "$HOME/.zshrc" 0
elif [ "$gamos" == "macos" ]; then
update_profile "$HOME/.bash_aliases" 0 || update_profile "$HOME/.bash_profile" 0 || update_profile "$HOME/.bashrc" 0 || update_profile "$HOME/.profile" 1
update_profile "$HOME/.zshrc" 1
fi
else
echo_yellow "skipping profile update."
fi
if [ "$upgrade_only" = true ]; then
echo_green "Here's information about your GAM upgrade:"
"$target_dir/gam/gam" version
"$target_dir/$target_gam" version extended
rc=$?
if (( $rc != 0 )); then
echo_red "ERROR: Failed running GAM for the first time with $rc. Please report this error to GAM mailing list. Exiting."
echo_red "ERROR: Failed running GAM for the first time with return code $rc. Please report this error to GAM mailing list. Exiting."
exit
fi
@@ -216,17 +370,8 @@ if [ "$upgrade_only" = true ]; then
exit
fi
# Update profile to add gam command
if [ "$update_profile" = true ]; then
alias_line="gam() { \"$target_dir/gam/gam\" \"\$@\" ; }"
if [ "$gamos" == "linux" ]; then
update_profile "$HOME/.bashrc" || update_profile "$HOME/.bash_profile"
elif [ "$gamos" == "macos" ]; then
update_profile "$HOME/.profile" || update_profile "$HOME/.bash_profile"
fi
else
echo_yellow "skipping profile update."
fi
# Set config command
#config_cmd="config no_browser false"
while true; do
read -p "Can you run a full browser on this machine? (usually Y for MacOS, N for Linux if you SSH into this machine) " yn
@@ -235,7 +380,8 @@ while true; do
break
;;
[Nn]*)
touch "$target_dir/gam/nobrowser.txt" > /dev/null 2>&1
# config_cmd="config no_browser true"
touch "$target_dir/gam7/nobrowser.txt" > /dev/null 2>&1
break
;;
*)
@@ -251,9 +397,10 @@ while true; do
case $yn in
[Yy]*)
if [ "$adminuser" == "" ]; then
read -p "Please enter your G Suite admin email address: " adminuser
read -p "Please enter your Google Workspace admin email address: " adminuser
fi
"$target_dir/gam/gam" create project $adminuser
# "$target_dir/$target_gam" $config_cmd create project $adminuser
"$target_dir/$target_gam" create project $adminuser
rc=$?
if (( $rc == 0 )); then
echo_green "Project creation complete."
@@ -275,10 +422,11 @@ done
admin_authorized=false
while $project_created; do
read -p "Are you ready to authorize GAM to perform G Suite management operations as your admin account? (yes or no) " yn
read -p "Are you ready to authorize GAM to perform Google Workspace management operations as your admin account? (yes or no) " yn
case $yn in
[Yy]*)
"$target_dir/gam/gam" oauth create $adminuser
# "$target_dir/$target_gam" $config_cmd oauth create $adminuser
"$target_dir/$target_gam" oauth create $adminuser
rc=$?
if (( $rc == 0 )); then
echo_green "Admin authorization complete."
@@ -299,15 +447,16 @@ while $project_created; do
done
service_account_authorized=false
while $project_created; do
read -p "Are you ready to authorize GAM to manage G Suite user data and settings? (yes or no) " yn
while $admin_authorized; do
read -p "Are you ready to authorize GAM to manage Google Workspace user data and settings? (yes or no) " yn
case $yn in
[Yy]*)
if [ "$regularuser" == "" ]; then
read -p "Please enter the email address of a regular G Suite user: " regularuser
read -p "Please enter the email address of a regular Google Workspace user: " regularuser
fi
echo_yellow "Great! Checking service account scopes.This will fail the first time. Follow the steps to authorize and retry. It can take a few minutes for scopes to PASS after they've been authorized in the admin console."
"$target_dir/gam/gam" user $adminuser check serviceaccount
# "$target_dir/$target_gam" $config_cmd user $regularuser check serviceaccount
"$target_dir/$target_gam" user $regularuser check serviceaccount
rc=$?
if (( $rc == 0 )); then
echo_green "Service account authorization complete."
@@ -318,7 +467,7 @@ while $project_created; do
fi
;;
[Nn]*)
echo -e "\nYou can authorize a service account later by running:\n\ngam check serviceaccount\n"
echo -e "\nYou can authorize a service account later by running:\n\ngam user $adminuser check serviceaccount\n"
break
;;
*)
@@ -328,7 +477,8 @@ while $project_created; do
done
echo_green "Here's information about your new GAM installation:"
"$target_dir/gam/gam" version
#"$target_dir/$target_gam" $config_cmd save version extended
"$target_dir/$target_gam" version extended
rc=$?
if (( $rc != 0 )); then
echo_red "ERROR: Failed running GAM for the first time with $rc. Please report this error to GAM mailing list. Exiting."
@@ -339,6 +489,3 @@ echo_green "GAM installation and setup complete!"
if [ "$update_profile" = true ]; then
echo_green "Please restart your terminal shell or to get started right away run:\n\n$alias_line"
fi
# Clean up after ourselves even if we are killed with CTRL-C
trap "rm -rf $temp_archive_dir" EXIT

View File

@@ -1,83 +1,84 @@
:neworupgrade
@echo(
@set /p nu= "Is this a new install or an upgrade? [n or u] "
@echo.
@set /p nu= "If you have installed any version of GAM on any computer for your domain, enter u to upgrade, otherwise enter n? [u or n] "
@if /I "%nu%"=="u" (
@ echo GAM installation and setup complete!
@ goto alldone
)
@if /I not "%nu%"=="n" (
@ echo(
@ echo.
@ echo Please answer n or u.
@ goto neworupgrade
)
:createproject
@echo(
@echo.
@set /p yn= "Are you ready to set up a Google API project for GAM? [y or n] "
@if /I "%yn%"=="n" (
@ echo(
@ echo.
@ echo You can create an API project later by running:
@ echo(
@ echo.
@ echo gam create project
@ goto alldone
)
@if /I not "%yn%"=="y" (
@ echo(
@ echo.
@ echo Please answer y or n.
@ goto createproject
)
@echo(
@set /p adminemail= "Please enter your G Suite admin email address: "
@set /p adminemail= "Please enter your Google Workspace admin email address: "
@gam create project %adminemail%
@if not ERRORLEVEL 1 goto projectdone
@echo(
@echo.
@echo Project creation failed. Trying again. Say n to skip project creation.
@goto createproject
:projectdone
:adminauth
@echo(
@set /p yn= "Are you ready to authorize GAM to perform G Suite management operations as your admin account? [y or n] "
@echo.
@set /p yn= "Are you ready to authorize GAM to perform Google Workspace management operations as your admin account? [y or n] "
@if /I "%yn%"=="n" (
@ echo(
@ echo.
@ echo You can authorize an admin later by running:
@ echo(
@ echo.
@ echo gam oauth create %adminemail%
@ goto admindone
)
@if /I not "%yn%"=="y" (
@ echo(
@ echo.
@ echo Please answer y or n.
@ goto adminauth
)
@gam oauth create %adminemail%
@if not ERRORLEVEL 1 goto admindone
@echo(
@echo.
@echo Admin authorization failed. Trying again. Say n to skip admin authorization.
@goto adminauth
:admindone
:saauth
@echo(
@set /p yn= "Are you ready to authorize GAM to manage G Suite user data and settings? [y or n] "
@echo.
@set /p yn= "Are you ready to authorize GAM to manage Google Workspace user data and settings? [y or n] "
@if /I "%yn%"=="n" (
@ echo(
@ echo.
@ echo You can authorize a service account later by running:
@ echo(
@ echo.
@ echo gam user %adminemail% check serviceaccount
@ goto sadone
)
@if /I not "%yn%"=="y" (
@ echo(
@ echo.
@ echo Please answer y or n.
@ goto saauth
)
@echo(
@set /p regularuser= "Please enter the email address of a regular G Suite user: "
@echo.
@set /p regularuser= "Please enter the email address of a regular Google Workspace user: "
@echo Great! Checking service account scopes. This will fail the first time. Follow the steps to authorize and retry. It can take a few minutes for scopes to PASS after they've been authorized in the admin console.
@gam user %regularuser% check serviceaccount
@if not ERRORLEVEL 1 goto sadone
@echo(
@echo.
@echo Service account authorization failed. Confirm you entered the scopes correctly in the admin console. It can take a few minutes for scopes to PASS after they are entered in the admin console so if you're sure you entered them correctly, go grab a coffee and then hit Y to try again. Say N to skip admin authorization.
@goto saauth
:sadone

11
src/gam.exe.manifest Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 8.1 / Server 2012 R2 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10+ / Server 2016+ -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

14265
src/gam.py

File diff suppressed because it is too large Load Diff

151
src/gam.spec Normal file
View File

@@ -0,0 +1,151 @@
# -*- mode: python ; coding: utf-8 -*-
from os import getenv
import re
from sys import platform
from PyInstaller.utils.hooks import copy_metadata
from gam.gamlib.glverlibs import GAM_VER_LIBS
with open("gam/__init__.py") as f:
version_file = f.read()
version = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M).group(1)
version_list = [int(i) for i in version.split('.')]
while len(version_list) < 4:
version_list.append(0)
version_tuple = tuple(version_list)
version_str = str(version_tuple)
with open("version_info.txt.in") as f:
version_info = f.read()
version_info = version_info.replace("{VERSION}", version).replace(
"{VERSION_TUPLE}", version_str
)
with open("version_info.txt", "w") as f:
f.write(version_info)
print(version_info)
datas = []
for pkg in GAM_VER_LIBS:
datas += copy_metadata(pkg, recursive=True)
datas += [('gam/cbcm-v1.1beta1.json', '.')]
datas += [('gam/contactdelegation-v1.json', '.')]
datas += [('gam/datastudio-v1.json', '.')]
datas += [('gam/serviceaccountlookup-v1.json', '.')]
datas += [('cacerts.pem', '.')]
hiddenimports = [
'gam.gamlib.yubikey',
]
runtime_hooks = []
a = Analysis(
['gam/__main__.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=runtime_hooks,
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
#print(f"datas from analysis:\n{a.datas}")
for d in a.datas:
if 'pyconfig' in d[0]:
a.datas.remove(d)
break
#print(f"datas after pyconfig cleanup:\n{a.datas}")
pyz = PYZ(a.pure,
a.zipped_data,
cipher=None)
# requires Python 3.10+ but no one should be compiling
# GAM with older versions anyway
target_arch = None
codesign_identity = None
entitlements_file = None
manifest = None
version = 'version_info.txt'
match platform:
case "darwin":
if getenv('arch') == 'universal2':
target_arch = "universal2"
codesign_identity = getenv('codesign_identity')
if codesign_identity:
entitlements_file = '../.github/actions/entitlements.plist'
strip = True
case "win32":
target_arch = None
strip = False
manifest = 'gam.exe.manifest'
case _:
target_arch = None
strip = True
name = 'gam'
debug = False
bootloader_ignore_signals = False
upx = False
console = True
disable_windowed_traceback = False
argv_emulation = False
if getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
# Build one directory
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name=name,
debug=debug,
bootloader_ignore_signals=bootloader_ignore_signals,
strip=strip,
manifest=manifest,
upx=upx,
console=console,
# put most everyting under a lib/ subfolder
contents_directory='lib',
disable_windowed_traceback=disable_windowed_traceback,
argv_emulation=argv_emulation,
target_arch=target_arch,
codesign_identity=codesign_identity,
entitlements_file=entitlements_file,
version=version,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=strip,
upx=upx,
upx_exclude=[],
name=name,
)
else:
# Build one file
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name=name,
debug=debug,
bootloader_ignore_signals=bootloader_ignore_signals,
manifest=manifest,
strip=strip,
upx=upx,
console=console,
disable_windowed_traceback=disable_windowed_traceback,
argv_emulation=argv_emulation,
target_arch=target_arch,
codesign_identity=codesign_identity,
entitlements_file=entitlements_file,
version=version,
)

View File

@@ -2,11 +2,11 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" >
<Product
Id="*"
Name="GAM"
Name="GAM7"
Language="1033"
Version="$(env.GAMVERSION)"
Manufacturer="Jay Lee - jay0lee@gmail.com"
UpgradeCode="15C5FD61-B04C-4E04-A26D-CD8424C19D9F">
Manufacturer="GAM Team - google-apps-manager@googlegroups.com"
UpgradeCode="D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319">
<Package
InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
@@ -22,17 +22,21 @@
<Feature
Id="gam"
Title="GAM"
Title="GAM7"
Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<SetDirectory Id="WINDOWSVOLUME" Value="[WindowsVolume]"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ROOTDRIVE">
<Directory Id="INSTALLFOLDER" Name="GAM" />
</Directory>
<Directory Id="WINDOWSVOLUME">
<Directory Id="INSTALLFOLDER" Name="GAM7">
<Directory Id="lib" Name="lib">
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
@@ -41,23 +45,27 @@
<ComponentGroup
Id="ProductComponents"
Directory="INSTALLFOLDER"
Source="gam-64">
<Component Id="gam_exe" Guid="886abc07-73c5-4acc-9f71-58daf62aabc1">
Source="dist/gam/gam7">
<Component Id="gam_exe" Guid="d046ea24-c9f8-40ca-84db-70b0119933ff">
<File Name="gam.exe" KeyPath="yes" />
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="yes" Part="last" Action="set" System="yes" />
</Component>
<Component Id="license" Guid="7a15de2e-fb91-4d0a-b8bf-c8b19c68f569">
<Component Id="license" Guid="c76864c5-d005-44d5-bb7c-a27e5923792d">
<File Name="LICENSE" KeyPath="yes" />
</Component>
<Component Id="whatsnew_txt" Guid="6aa9863c-90d9-412f-9b73-fda82549a950">
<File Name="whatsnew.txt" KeyPath="yes" />
</Component>
<Component Id="gam_setup_bat" Guid="ef01f93a-4b50-488a-9c04-ec5e13e66218">
<Component Id="gam_setup_bat" Guid="5e6bbacb-d86f-4d80-a10b-89b81ee63fcb">
<File Name="gam-setup.bat" KeyPath="yes" />
</Component>
<Component Id="gamcommands_txt" Guid="58ff9c45-a7c9-4e22-8845-a9a92610c1f3">
<File Name="gamcommands.txt" KeyPath="yes" />
<Component Id="GamCommands_txt" Guid="a2dca862-b222-469e-a637-95ea2a1c53e7">
<File Name="GamCommands.txt" KeyPath="yes" />
</Component>
<Component Id="GamUpdate_txt" Guid="1b7cdd48-0fff-4943-a219-102fcd14c755">
<File Name="GamUpdate.txt" KeyPath="yes" />
</Component>
<Component Id="cacerts_pem" Guid="61fe2b2d-1646-4bed-b844-193965e97727">
<File Name="cacerts.pem" KeyPath="yes" />
</Component>
<ComponentGroupRef Id="Lib" />
</ComponentGroup>
</Fragment>
@@ -66,9 +74,5 @@
<ExecuteAction />
<Show Dialog="WelcomeDlg" Before="ProgressDlg" />
</InstallUISequence>
<CustomAction Id="setup_gam" ExeCommand="[INSTALLFOLDER]gam-setup.bat" Directory="INSTALLFOLDER" Execute="commit" Impersonate="yes" Return="asyncWait"/>
<InstallExecuteSequence>
<Custom Action="setup_gam" After="InstallFiles" >NOT Installed AND NOT UPGRADINGPRODUCTCODE AND NOT WIX_UPGRADE_DETECTED</Custom>
</InstallExecuteSequence>
</Fragment>
</Wix>

77542
src/gam/__init__.py Executable file

File diff suppressed because it is too large Load Diff

40
src/gam/__main__.py Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GAM
#
# Copyright 2023, All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import multiprocessing
import platform
import sys
import gam
def main():
gam.initializeLogging()
rc = gam.ProcessGAMCommand(sys.argv)
try:
sys.stdout.flush()
except (IOError, ValueError):
pass
sys.exit(rc)
# Run from command line
if __name__ == '__main__':
if platform.system() != 'Linux':
multiprocessing.freeze_support()
multiprocessing.set_start_method('spawn')
main()

1460
src/gam/atom/__init__.py Normal file

File diff suppressed because it is too large Load Diff

41
src/gam/atom/auth.py Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License 2.0;
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This module is used for version 2 of the Google Data APIs.
# __author__ = 'j.s@google.com (Jeff Scudder)'
import base64
class BasicAuth(object):
"""Sets the Authorization header as defined in RFC1945"""
def __init__(self, user_id, password):
self.basic_cookie = base64.encodestring(
'%s:%s' % (user_id, password)).strip()
def modify_request(self, http_request):
http_request.headers['Authorization'] = 'Basic %s' % self.basic_cookie
ModifyRequest = modify_request
class NoAuth(object):
def modify_request(self, http_request):
pass

214
src/gam/atom/client.py Normal file
View File

@@ -0,0 +1,214 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License 2.0;
"""AtomPubClient provides CRUD ops. in line with the Atom Publishing Protocol.
"""
# __author__ = 'j.s@google.com (Jeff Scudder)'
import atom.http_core
class Error(Exception):
pass
class MissingHost(Error):
pass
class AtomPubClient(object):
host = None
auth_token = None
ssl = False # Whether to force all requests over https
xoauth_requestor_id = None
def __init__(self, http_client=None, host=None, auth_token=None, source=None,
xoauth_requestor_id=None, **kwargs):
"""Creates a new AtomPubClient instance.
Args:
source: The name of your application.
http_client: An object capable of performing HTTP requests through a
request method. This object is used to perform the request
when the AtomPubClient's request method is called. Used to
allow HTTP requests to be directed to a mock server, or use
an alternate library instead of the default of httplib to
make HTTP requests.
host: str The default host name to use if a host is not specified in the
requested URI.
auth_token: An object which sets the HTTP Authorization header when its
modify_request method is called.
"""
self.http_client = http_client or atom.http_core.ProxiedHttpClient()
if host is not None:
self.host = host
if auth_token is not None:
self.auth_token = auth_token
self.xoauth_requestor_id = xoauth_requestor_id
self.source = source
def request(self, method=None, uri=None, auth_token=None,
http_request=None, **kwargs):
"""Performs an HTTP request to the server indicated.
Uses the http_client instance to make the request.
Args:
method: The HTTP method as a string, usually one of 'GET', 'POST',
'PUT', or 'DELETE'
uri: The URI desired as a string or atom.http_core.Uri.
http_request:
auth_token: An authorization token object whose modify_request method
sets the HTTP Authorization header.
Returns:
The results of calling self.http_client.request. With the default
http_client, this is an HTTP response object.
"""
# Modify the request based on the AtomPubClient settings and parameters
# passed in to the request.
http_request = self.modify_request(http_request)
if isinstance(uri, str):
uri = atom.http_core.Uri.parse_uri(uri)
if uri is not None:
uri.modify_request(http_request)
if isinstance(method, str):
http_request.method = method
# Any unrecognized arguments are assumed to be capable of modifying the
# HTTP request.
for name, value in kwargs.items():
if value is not None:
if hasattr(value, 'modify_request'):
value.modify_request(http_request)
else:
http_request.uri.query[name] = str(value)
# Default to an http request if the protocol scheme is not set.
if http_request.uri.scheme is None:
http_request.uri.scheme = 'http'
# Override scheme. Force requests over https.
if self.ssl:
http_request.uri.scheme = 'https'
if http_request.uri.path is None:
http_request.uri.path = '/'
# Add the Authorization header at the very end. The Authorization header
# value may need to be calculated using information in the request.
if auth_token:
auth_token.modify_request(http_request)
elif self.auth_token:
self.auth_token.modify_request(http_request)
# Check to make sure there is a host in the http_request.
if http_request.uri.host is None:
raise MissingHost('No host provided in request %s %s' % (
http_request.method, str(http_request.uri)))
# Perform the fully specified request using the http_client instance.
# Sends the request to the server and returns the server's response.
return self.http_client.request(http_request)
Request = request
def get(self, uri=None, auth_token=None, http_request=None, **kwargs):
"""Performs a request using the GET method, returns an HTTP response."""
return self.request(method='GET', uri=uri, auth_token=auth_token,
http_request=http_request, **kwargs)
Get = get
def post(self, uri=None, data=None, auth_token=None, http_request=None,
**kwargs):
"""Sends data using the POST method, returns an HTTP response."""
return self.request(method='POST', uri=uri, auth_token=auth_token,
http_request=http_request, data=data, **kwargs)
Post = post
def put(self, uri=None, data=None, auth_token=None, http_request=None,
**kwargs):
"""Sends data using the PUT method, returns an HTTP response."""
return self.request(method='PUT', uri=uri, auth_token=auth_token,
http_request=http_request, data=data, **kwargs)
Put = put
def delete(self, uri=None, auth_token=None, http_request=None, **kwargs):
"""Performs a request using the DELETE method, returns an HTTP response."""
return self.request(method='DELETE', uri=uri, auth_token=auth_token,
http_request=http_request, **kwargs)
Delete = delete
def modify_request(self, http_request):
"""Changes the HTTP request before sending it to the server.
Sets the User-Agent HTTP header and fills in the HTTP host portion
of the URL if one was not included in the request (for this it uses
the self.host member if one is set). This method is called in
self.request.
Args:
http_request: An atom.http_core.HttpRequest() (optional) If one is
not provided, a new HttpRequest is instantiated.
Returns:
An atom.http_core.HttpRequest() with the User-Agent header set and
if this client has a value in its host member, the host in the request
URL is set.
"""
if http_request is None:
http_request = atom.http_core.HttpRequest()
if self.host is not None and http_request.uri.host is None:
http_request.uri.host = self.host
if self.xoauth_requestor_id is not None:
http_request.uri.query['xoauth_requestor_id'] = self.xoauth_requestor_id
# Set the user agent header for logging purposes.
if self.source:
http_request.headers['User-Agent'] = '%s gdata-py/2.0.18' % self.source
else:
http_request.headers['User-Agent'] = 'gdata-py/2.0.17'
return http_request
ModifyRequest = modify_request
class CustomHeaders(object):
"""Add custom headers to an http_request.
Usage:
>>> custom_headers = atom.client.CustomHeaders(header1='value1',
header2='value2')
>>> client.get(uri, custom_headers=custom_headers)
"""
def __init__(self, **kwargs):
"""Creates a CustomHeaders instance.
Initialize the headers dictionary with the arguments list.
"""
self.headers = kwargs
def modify_request(self, http_request):
"""Changes the HTTP request before sending it to the server.
Adds the custom headers to the HTTP request.
Args:
http_request: An atom.http_core.HttpRequest().
Returns:
An atom.http_core.HttpRequest() with the added custom headers.
"""
for name, value in self.headers.items():
if value is not None:
http_request.headers[name] = value
return http_request

535
src/gam/atom/core.py Normal file
View File

@@ -0,0 +1,535 @@
#!/usr/bin/env python
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This module is used for version 2 of the Google Data APIs.
# __author__ = 'j.s@google.com (Jeff Scudder)'
import inspect
import lxml.etree as ElementTree
try:
from xml.dom.minidom import parseString as xmlString
except ImportError:
xmlString = None
STRING_ENCODING = 'utf-8'
class XmlElement(object):
"""Represents an element node in an XML document.
The text member is a UTF-8 encoded str or unicode.
"""
_qname = None
_other_elements = None
_other_attributes = None
# The rule set contains mappings for XML qnames to child members and the
# appropriate member classes.
_rule_set = None
_members = None
text = None
def __init__(self, text=None, *args, **kwargs):
if ('_members' not in self.__class__.__dict__
or self.__class__._members is None):
self.__class__._members = tuple(self.__class__._list_xml_members())
for member_name, member_type in self.__class__._members:
if member_name in kwargs:
setattr(self, member_name, kwargs[member_name])
else:
if isinstance(member_type, list):
setattr(self, member_name, [])
else:
setattr(self, member_name, None)
self._other_elements = []
self._other_attributes = {}
if text is not None:
self.text = text
def _list_xml_members(cls):
"""Generator listing all members which are XML elements or attributes.
The following members would be considered XML members:
foo = 'abc' - indicates an XML attribute with the qname abc
foo = SomeElement - indicates an XML child element
foo = [AnElement] - indicates a repeating XML child element, each instance
will be stored in a list in this member
foo = ('att1', '{http://example.com/namespace}att2') - indicates an XML
attribute which has different parsing rules in different versions of
the protocol. Version 1 of the XML parsing rules will look for an
attribute with the qname 'att1' but verion 2 of the parsing rules will
look for a namespaced attribute with the local name of 'att2' and an
XML namespace of 'http://example.com/namespace'.
"""
members = []
for pair in inspect.getmembers(cls):
if not pair[0].startswith('_') and pair[0] != 'text':
member_type = pair[1]
if (isinstance(member_type, tuple) or isinstance(member_type, list)
or isinstance(member_type, str)
or (inspect.isclass(member_type)
and issubclass(member_type, XmlElement))):
members.append(pair)
return members
_list_xml_members = classmethod(_list_xml_members)
def _get_rules(cls, version):
"""Initializes the _rule_set for the class which is used when parsing XML.
This method is used internally for parsing and generating XML for an
XmlElement. It is not recommended that you call this method directly.
Returns:
A tuple containing the XML parsing rules for the appropriate version.
The tuple looks like:
(qname, {sub_element_qname: (member_name, member_class, repeating), ..},
{attribute_qname: member_name})
To give a couple of concrete example, the atom.data.Control _get_rules
with version of 2 will return:
('{http://www.w3.org/2007/app}control',
{'{http://www.w3.org/2007/app}draft': ('draft',
<class 'atom.data.Draft'>,
False)},
{})
Calling _get_rules with version 1 on gdata.data.FeedLink will produce:
('{http://schemas.google.com/g/2005}feedLink',
{'{http://www.w3.org/2005/Atom}feed': ('feed',
<class 'gdata.data.GDFeed'>,
False)},
{'href': 'href', 'readOnly': 'read_only', 'countHint': 'count_hint',
'rel': 'rel'})
"""
# Initialize the _rule_set to make sure there is a slot available to store
# the parsing rules for this version of the XML schema.
# Look for rule set in the class __dict__ proxy so that only the
# _rule_set for this class will be found. By using the dict proxy
# we avoid finding rule_sets defined in superclasses.
# The four lines below provide support for any number of versions, but it
# runs a bit slower then hard coding slots for two versions, so I'm using
# the below two lines.
# if '_rule_set' not in cls.__dict__ or cls._rule_set is None:
# cls._rule_set = []
# while len(cls.__dict__['_rule_set']) < version:
# cls._rule_set.append(None)
# If there is no rule set cache in the class, provide slots for two XML
# versions. If and when there is a version 3, this list will need to be
# expanded.
if '_rule_set' not in cls.__dict__ or cls._rule_set is None:
cls._rule_set = [None, None]
# If a version higher than 2 is requested, fall back to version 2 because
# 2 is currently the highest supported version.
if version > 2:
return cls._get_rules(2)
# Check the dict proxy for the rule set to avoid finding any rule sets
# which belong to the superclass. We only want rule sets for this class.
if cls._rule_set[version - 1] is None:
# The rule set for each version consists of the qname for this element
# ('{namespace}tag'), a dictionary (elements) for looking up the
# corresponding class member when given a child element's qname, and a
# dictionary (attributes) for looking up the corresponding class member
# when given an XML attribute's qname.
elements = {}
attributes = {}
if ('_members' not in cls.__dict__ or cls._members is None):
cls._members = tuple(cls._list_xml_members())
for member_name, target in cls._members:
if isinstance(target, list):
# This member points to a repeating element.
elements[_get_qname(target[0], version)] = (member_name, target[0],
True)
elif isinstance(target, tuple):
# This member points to a versioned XML attribute.
if version <= len(target):
attributes[target[version - 1]] = member_name
else:
attributes[target[-1]] = member_name
elif isinstance(target, str):
# This member points to an XML attribute.
attributes[target] = member_name
elif issubclass(target, XmlElement):
# This member points to a single occurance element.
elements[_get_qname(target, version)] = (member_name, target, False)
version_rules = (_get_qname(cls, version), elements, attributes)
cls._rule_set[version - 1] = version_rules
return version_rules
else:
return cls._rule_set[version - 1]
_get_rules = classmethod(_get_rules)
def get_elements(self, tag=None, namespace=None, version=1):
"""Find all sub elements which match the tag and namespace.
To find all elements in this object, call get_elements with the tag and
namespace both set to None (the default). This method searches through
the object's members and the elements stored in _other_elements which
did not match any of the XML parsing rules for this class.
Args:
tag: str
namespace: str
version: int Specifies the version of the XML rules to be used when
searching for matching elements.
Returns:
A list of the matching XmlElements.
"""
matches = []
ignored1, elements, ignored2 = self.__class__._get_rules(version)
if elements:
for qname, element_def in elements.items():
member = getattr(self, element_def[0])
if member:
if _qname_matches(tag, namespace, qname):
if element_def[2]:
# If this is a repeating element, copy all instances into the
# result list.
matches.extend(member)
else:
matches.append(member)
for element in self._other_elements:
if _qname_matches(tag, namespace, element._qname):
matches.append(element)
return matches
GetElements = get_elements
# FindExtensions and FindChildren are provided for backwards compatibility
# to the atom.AtomBase class.
# However, FindExtensions may return more results than the v1 atom.AtomBase
# method does, because get_elements searches both the expected children
# and the unexpected "other elements". The old AtomBase.FindExtensions
# method searched only "other elements" AKA extension_elements.
FindExtensions = get_elements
FindChildren = get_elements
def get_attributes(self, tag=None, namespace=None, version=1):
"""Find all attributes which match the tag and namespace.
To find all attributes in this object, call get_attributes with the tag
and namespace both set to None (the default). This method searches
through the object's members and the attributes stored in
_other_attributes which did not fit any of the XML parsing rules for this
class.
Args:
tag: str
namespace: str
version: int Specifies the version of the XML rules to be used when
searching for matching attributes.
Returns:
A list of XmlAttribute objects for the matching attributes.
"""
matches = []
ignored1, ignored2, attributes = self.__class__._get_rules(version)
if attributes:
for qname, attribute_def in attributes.items():
if isinstance(attribute_def, (list, tuple)):
attribute_def = attribute_def[0]
member = getattr(self, attribute_def)
# TODO: ensure this hasn't broken existing behavior.
# member = getattr(self, attribute_def[0])
if member:
if _qname_matches(tag, namespace, qname):
matches.append(XmlAttribute(qname, member))
for qname, value in self._other_attributes.items():
if _qname_matches(tag, namespace, qname):
matches.append(XmlAttribute(qname, value))
return matches
GetAttributes = get_attributes
def _harvest_tree(self, tree, version=1):
"""Populates object members from the data in the tree Element."""
qname, elements, attributes = self.__class__._get_rules(version)
for element in tree:
if elements and element.tag in elements:
definition = elements[element.tag]
# If this is a repeating element, make sure the member is set to a
# list.
if definition[2]:
if getattr(self, definition[0]) is None:
setattr(self, definition[0], [])
getattr(self, definition[0]).append(_xml_element_from_tree(element,
definition[1], version))
else:
setattr(self, definition[0], _xml_element_from_tree(element,
definition[1], version))
else:
self._other_elements.append(_xml_element_from_tree(element, XmlElement,
version))
for attrib, value in tree.attrib.items():
if attributes and attrib in attributes:
setattr(self, attributes[attrib], value)
else:
self._other_attributes[attrib] = value
if tree.text:
self.text = tree.text
def _to_tree(self, version=1):
new_tree = ElementTree.Element(_get_qname(self, version))
self._attach_members(new_tree, version)
return new_tree
def _attach_members(self, tree, version=1):
"""Convert members to XML elements/attributes and add them to the tree.
Args:
tree: An ElementTree.Element which will be modified. The members of
this object will be added as child elements or attributes
according to the rules described in _expected_elements and
_expected_attributes. The elements and attributes stored in
other_attributes and other_elements are also added a children
of this tree.
version: int Ingnored in this method but used by VersionedElement.
encoding: str (optional)
"""
qname, elements, attributes = self.__class__._get_rules(version)
encoding = STRING_ENCODING
# Add the expected elements and attributes to the tree.
if elements:
for tag, element_def in elements.items():
member = getattr(self, element_def[0])
# If this is a repeating element and there are members in the list.
if member and element_def[2]:
for instance in member:
instance._become_child(tree, version)
elif member:
member._become_child(tree, version)
if attributes:
for attribute_tag, member_name in attributes.items():
value = getattr(self, member_name)
if value:
tree.attrib[attribute_tag] = value
# Add the unexpected (other) elements and attributes to the tree.
for element in self._other_elements:
element._become_child(tree, version)
for key, value in self._other_attributes.items():
# I'm not sure if unicode can be used in the attribute name, so for now
# we assume the encoding is correct for the attribute name.
if not isinstance(value, str):
value = value.decode(encoding)
tree.attrib[key] = value
if self.text:
if isinstance(self.text, str):
tree.text = self.text
else:
tree.text = self.text.decode(encoding)
def to_string(self, version=1, encoding=None, pretty_print=None):
"""Converts this object to XML."""
tree_string = ElementTree.tostring(self._to_tree(version))
if pretty_print and xmlString is not None:
return xmlString(tree_string).toprettyxml()
return tree_string
ToString = to_string
def __str__(self):
return self.to_string()
def _become_child(self, tree, version=1):
"""Adds a child element to tree with the XML data in self."""
new_child = ElementTree.Element(_get_qname(self, version))
tree.append(new_child)
new_child.tag = _get_qname(self, version)
self._attach_members(new_child, version)
def __get_extension_elements(self):
return self._other_elements
def __set_extension_elements(self, elements):
self._other_elements = elements
extension_elements = property(__get_extension_elements,
__set_extension_elements,
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
def __get_extension_attributes(self):
return self._other_attributes
def __set_extension_attributes(self, attributes):
self._other_attributes = attributes
extension_attributes = property(__get_extension_attributes,
__set_extension_attributes,
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
def _get_tag(self, version=1):
qname = _get_qname(self, version)
if qname:
return qname[qname.find('}') + 1:]
return None
def _get_namespace(self, version=1):
qname = _get_qname(self, version)
if qname.startswith('{'):
return qname[1:qname.find('}')]
else:
return None
def _set_tag(self, tag):
if isinstance(self._qname, tuple):
self._qname = self._qname.copy()
if self._qname[0].startswith('{'):
self._qname[0] = '{%s}%s' % (self._get_namespace(1), tag)
else:
self._qname[0] = tag
else:
if self._qname is not None and self._qname.startswith('{'):
self._qname = '{%s}%s' % (self._get_namespace(), tag)
else:
self._qname = tag
def _set_namespace(self, namespace):
tag = self._get_tag(1)
if tag is None:
tag = ''
if isinstance(self._qname, tuple):
self._qname = self._qname.copy()
if namespace:
self._qname[0] = '{%s}%s' % (namespace, tag)
else:
self._qname[0] = tag
else:
if namespace:
self._qname = '{%s}%s' % (namespace, tag)
else:
self._qname = tag
tag = property(_get_tag, _set_tag,
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
namespace = property(_get_namespace, _set_namespace,
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
# Provided for backwards compatibility to atom.ExtensionElement
children = extension_elements
attributes = extension_attributes
def _get_qname(element, version):
if isinstance(element._qname, tuple):
if version <= len(element._qname):
return element._qname[version - 1]
else:
return element._qname[-1]
else:
return element._qname
def _qname_matches(tag, namespace, qname):
"""Logic determines if a QName matches the desired local tag and namespace.
This is used in XmlElement.get_elements and XmlElement.get_attributes to
find matches in the element's members (among all expected-and-unexpected
elements-and-attributes).
Args:
expected_tag: string
expected_namespace: string
qname: string in the form '{xml_namespace}localtag' or 'tag' if there is
no namespace.
Returns:
boolean True if the member's tag and namespace fit the expected tag and
namespace.
"""
# If there is no expected namespace or tag, then everything will match.
if qname is None:
member_tag = None
member_namespace = None
else:
if qname.startswith('{'):
member_namespace = qname[1:qname.index('}')]
member_tag = qname[qname.index('}') + 1:]
else:
member_namespace = None
member_tag = qname
return ((tag is None and namespace is None)
# If there is a tag, but no namespace, see if the local tag matches.
or (namespace is None and member_tag == tag)
# There was no tag, but there was a namespace so see if the namespaces
# match.
or (tag is None and member_namespace == namespace)
# There was no tag, and the desired elements have no namespace, so check
# to see that the member's namespace is None.
or (tag is None and namespace == ''
and member_namespace is None)
# The tag and the namespace both match.
or (tag == member_tag
and namespace == member_namespace)
# The tag matches, and the expected namespace is the empty namespace,
# check to make sure the member's namespace is None.
or (tag == member_tag and namespace == ''
and member_namespace is None))
def parse(xml_string, target_class=None, version=1):
"""Parses the XML string according to the rules for the target_class.
Args:
xml_string: bytes
target_class: XmlElement or a subclass. If None is specified, the
XmlElement class is used.
version: int (optional) The version of the schema which should be used when
converting the XML into an object. The default is 1.
encoding: str (optional) The character encoding of the bytes in the
xml_string. Default is 'UTF-8'.
"""
if target_class is None:
target_class = XmlElement
if not isinstance(xml_string, bytes):
raise Exception("This function only accepts bytes")
tree = ElementTree.fromstring(xml_string)
return _xml_element_from_tree(tree, target_class, version)
Parse = parse
xml_element_from_string = parse
XmlElementFromString = xml_element_from_string
def _xml_element_from_tree(tree, target_class, version=1):
if target_class._qname is None:
instance = target_class()
instance._qname = tree.tag
instance._harvest_tree(tree, version)
return instance
# TODO handle the namespace-only case
# Namespace only will be used with Google Spreadsheets rows and
# Google Base item attributes.
elif tree.tag == _get_qname(target_class, version):
instance = target_class()
instance._harvest_tree(tree, version)
return instance
return None
class XmlAttribute(object):
def __init__(self, qname, value):
self._qname = qname
self.value = value

327
src/gam/atom/data.py Normal file
View File

@@ -0,0 +1,327 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License 2.0;
# This module is used for version 2 of the Google Data APIs.
# __author__ = 'j.s@google.com (Jeff Scudder)'
import atom.core
XML_TEMPLATE = '{http://www.w3.org/XML/1998/namespace}%s'
ATOM_TEMPLATE = '{http://www.w3.org/2005/Atom}%s'
APP_TEMPLATE_V1 = '{http://purl.org/atom/app#}%s'
APP_TEMPLATE_V2 = '{http://www.w3.org/2007/app}%s'
class Name(atom.core.XmlElement):
"""The atom:name element."""
_qname = ATOM_TEMPLATE % 'name'
class Email(atom.core.XmlElement):
"""The atom:email element."""
_qname = ATOM_TEMPLATE % 'email'
class Uri(atom.core.XmlElement):
"""The atom:uri element."""
_qname = ATOM_TEMPLATE % 'uri'
class Person(atom.core.XmlElement):
"""A foundation class which atom:author and atom:contributor extend.
A person contains information like name, email address, and web page URI for
an author or contributor to an Atom feed.
"""
name = Name
email = Email
uri = Uri
class Author(Person):
"""The atom:author element.
An author is a required element in Feed unless each Entry contains an Author.
"""
_qname = ATOM_TEMPLATE % 'author'
class Contributor(Person):
"""The atom:contributor element."""
_qname = ATOM_TEMPLATE % 'contributor'
class Link(atom.core.XmlElement):
"""The atom:link element."""
_qname = ATOM_TEMPLATE % 'link'
href = 'href'
rel = 'rel'
type = 'type'
hreflang = 'hreflang'
title = 'title'
length = 'length'
class Generator(atom.core.XmlElement):
"""The atom:generator element."""
_qname = ATOM_TEMPLATE % 'generator'
uri = 'uri'
version = 'version'
class Text(atom.core.XmlElement):
"""A foundation class from which atom:title, summary, etc. extend.
This class should never be instantiated.
"""
type = 'type'
class Title(Text):
"""The atom:title element."""
_qname = ATOM_TEMPLATE % 'title'
class Subtitle(Text):
"""The atom:subtitle element."""
_qname = ATOM_TEMPLATE % 'subtitle'
class Rights(Text):
"""The atom:rights element."""
_qname = ATOM_TEMPLATE % 'rights'
class Summary(Text):
"""The atom:summary element."""
_qname = ATOM_TEMPLATE % 'summary'
class Content(Text):
"""The atom:content element."""
_qname = ATOM_TEMPLATE % 'content'
src = 'src'
class Category(atom.core.XmlElement):
"""The atom:category element."""
_qname = ATOM_TEMPLATE % 'category'
term = 'term'
scheme = 'scheme'
label = 'label'
class Id(atom.core.XmlElement):
"""The atom:id element."""
_qname = ATOM_TEMPLATE % 'id'
class Icon(atom.core.XmlElement):
"""The atom:icon element."""
_qname = ATOM_TEMPLATE % 'icon'
class Logo(atom.core.XmlElement):
"""The atom:logo element."""
_qname = ATOM_TEMPLATE % 'logo'
class Draft(atom.core.XmlElement):
"""The app:draft element which indicates if this entry should be public."""
_qname = (APP_TEMPLATE_V1 % 'draft', APP_TEMPLATE_V2 % 'draft')
class Control(atom.core.XmlElement):
"""The app:control element indicating restrictions on publication.
The APP control element may contain a draft element indicating whether or
not this entry should be publicly available.
"""
_qname = (APP_TEMPLATE_V1 % 'control', APP_TEMPLATE_V2 % 'control')
draft = Draft
class Date(atom.core.XmlElement):
"""A parent class for atom:updated, published, etc."""
class Updated(Date):
"""The atom:updated element."""
_qname = ATOM_TEMPLATE % 'updated'
class Published(Date):
"""The atom:published element."""
_qname = ATOM_TEMPLATE % 'published'
class LinkFinder(object):
"""An "interface" providing methods to find link elements
Entry elements often contain multiple links which differ in the rel
attribute or content type. Often, developers are interested in a specific
type of link so this class provides methods to find specific classes of
links.
This class is used as a mixin in Atom entries and feeds.
"""
def find_url(self, rel):
"""Returns the URL (as a string) in a link with the desired rel value."""
for link in self.link:
if link.rel == rel and link.href:
return link.href
return None
FindUrl = find_url
def get_link(self, rel):
"""Returns a link object which has the desired rel value.
If you are interested in the URL instead of the link object,
consider using find_url instead.
"""
for link in self.link:
if link.rel == rel and link.href:
return link
return None
GetLink = get_link
def find_self_link(self):
"""Find the first link with rel set to 'self'
Returns:
A str containing the link's href or None if none of the links had rel
equal to 'self'
"""
return self.find_url('self')
FindSelfLink = find_self_link
def get_self_link(self):
return self.get_link('self')
GetSelfLink = get_self_link
def find_edit_link(self):
return self.find_url('edit')
FindEditLink = find_edit_link
def get_edit_link(self):
return self.get_link('edit')
GetEditLink = get_edit_link
def find_edit_media_link(self):
link = self.find_url('edit-media')
# Search for media-edit as well since Picasa API used media-edit instead.
if link is None:
return self.find_url('media-edit')
return link
FindEditMediaLink = find_edit_media_link
def get_edit_media_link(self):
link = self.get_link('edit-media')
if link is None:
return self.get_link('media-edit')
return link
GetEditMediaLink = get_edit_media_link
def find_next_link(self):
return self.find_url('next')
FindNextLink = find_next_link
def get_next_link(self):
return self.get_link('next')
GetNextLink = get_next_link
def find_license_link(self):
return self.find_url('license')
FindLicenseLink = find_license_link
def get_license_link(self):
return self.get_link('license')
GetLicenseLink = get_license_link
def find_alternate_link(self):
return self.find_url('alternate')
FindAlternateLink = find_alternate_link
def get_alternate_link(self):
return self.get_link('alternate')
GetAlternateLink = get_alternate_link
class FeedEntryParent(atom.core.XmlElement, LinkFinder):
"""A super class for atom:feed and entry, contains shared attributes"""
author = [Author]
category = [Category]
contributor = [Contributor]
id = Id
link = [Link]
rights = Rights
title = Title
updated = Updated
def __init__(self, atom_id=None, text=None, *args, **kwargs):
if atom_id is not None:
self.id = atom_id
atom.core.XmlElement.__init__(self, text=text, *args, **kwargs)
class Source(FeedEntryParent):
"""The atom:source element."""
_qname = ATOM_TEMPLATE % 'source'
generator = Generator
icon = Icon
logo = Logo
subtitle = Subtitle
class Entry(FeedEntryParent):
"""The atom:entry element."""
_qname = ATOM_TEMPLATE % 'entry'
content = Content
published = Published
source = Source
summary = Summary
control = Control
class Feed(Source):
"""The atom:feed element which contains entries."""
_qname = ATOM_TEMPLATE % 'feed'
entry = [Entry]
class ExtensionElement(atom.core.XmlElement):
"""Provided for backwards compatibility to the v1 atom.ExtensionElement."""
def __init__(self, tag=None, namespace=None, attributes=None,
children=None, text=None, *args, **kwargs):
if namespace:
self._qname = '{%s}%s' % (namespace, tag)
else:
self._qname = tag
self.children = children or []
self.attributes = attributes or {}
self.text = text
_BecomeChildElement = atom.core.XmlElement._become_child

354
src/gam/atom/http.py Normal file
View File

@@ -0,0 +1,354 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
"""HttpClients in this module use httplib to make HTTP requests.
This module make HTTP requests based on httplib, but there are environments
in which an httplib based approach will not work (if running in Google App
Engine for example). In those cases, higher level classes (like AtomService
and GDataService) can swap out the HttpClient to transparently use a
different mechanism for making HTTP requests.
HttpClient: Contains a request method which performs an HTTP call to the
server.
ProxiedHttpClient: Contains a request method which connects to a proxy using
settings stored in operating system environment variables then
performs an HTTP call to the endpoint server.
"""
# __author__ = 'api.jscudder (Jeff Scudder)'
import base64
import http.client
import os
import socket
import atom.http_core
import atom.http_interface
import atom.url
ssl_imported = False
ssl = None
try:
import ssl
ssl_imported = True
except ImportError:
pass
class ProxyError(atom.http_interface.Error):
pass
class TestConfigurationError(Exception):
pass
DEFAULT_CONTENT_TYPE = 'application/atom+xml'
class HttpClient(atom.http_interface.GenericHttpClient):
# Added to allow old v1 HttpClient objects to use the new
# http_code.HttpClient. Used in unit tests to inject a mock client.
v2_http_client = None
def __init__(self, headers=None):
self.debug = False
self.headers = headers or {}
def request(self, operation, url, data=None, headers=None):
"""Performs an HTTP call to the server, supports GET, POST, PUT, and
DELETE.
Usage example, perform and HTTP GET on http://www.google.com/:
import atom.http
client = atom.http.HttpClient()
http_response = client.request('GET', 'http://www.google.com/')
Args:
operation: str The HTTP operation to be performed. This is usually one
of 'GET', 'POST', 'PUT', or 'DELETE'
data: filestream, list of parts, or other object which can be converted
to a string. Should be set to None when performing a GET or DELETE.
If data is a file-like object which can be read, this method will
read a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be
evaluated and sent.
url: The full URL to which the request should be sent. Can be a string
or atom.url.Url.
headers: dict of strings. HTTP headers which should be sent
in the request.
"""
all_headers = self.headers.copy()
if headers:
all_headers.update(headers)
# If the list of headers does not include a Content-Length, attempt to
# calculate it based on the data object.
if data and 'Content-Length' not in all_headers:
if isinstance(data, (str,)):
all_headers['Content-Length'] = str(len(data))
else:
raise atom.http_interface.ContentLengthRequired('Unable to calculate '
'the length of the data parameter. Specify a value for '
'Content-Length')
# Set the content type to the default value if none was set.
if 'Content-Type' not in all_headers:
all_headers['Content-Type'] = DEFAULT_CONTENT_TYPE
if self.v2_http_client is not None:
http_request = atom.http_core.HttpRequest(method=operation)
atom.http_core.Uri.parse_uri(str(url)).modify_request(http_request)
http_request.headers = all_headers
if data:
http_request._body_parts.append(data)
return self.v2_http_client.request(http_request=http_request)
if not isinstance(url, atom.url.Url):
if isinstance(url, str):
url = atom.url.parse_url(url)
else:
raise atom.http_interface.UnparsableUrlObject('Unable to parse url parameter because it was not a string or atom.url.Url')
connection = self._prepare_connection(url, all_headers)
if self.debug:
connection.debuglevel = 1
connection.putrequest(operation, self._get_access_url(url), skip_host=True)
if url.port is not None:
connection.putheader('Host', '%s:%s' % (url.host, url.port))
else:
connection.putheader('Host', url.host)
# Overcome a bug in Python 2.4 and 2.5
# httplib.HTTPConnection.putrequest adding
# HTTP request header 'Host: www.google.com:443' instead of
# 'Host: www.google.com', and thus resulting the error message
# 'Token invalid - AuthSub token has wrong scope' in the HTTP response.
if (url.protocol == 'https' and int(url.port or 443) == 443 and
hasattr(connection, '_buffer') and
isinstance(connection._buffer, list)):
header_line = 'Host: %s:443' % url.host
replacement_header_line = 'Host: %s' % url.host
try:
connection._buffer[connection._buffer.index(header_line)] = (
replacement_header_line)
except ValueError: # header_line missing from connection._buffer
pass
# Send the HTTP headers.
for header_name in all_headers:
connection.putheader(header_name, all_headers[header_name])
connection.endheaders()
# If there is data, send it in the request.
if data:
if isinstance(data, list):
for data_part in data:
_send_data_part(data_part, connection)
else:
_send_data_part(data, connection)
# Return the HTTP Response from the server.
return connection.getresponse()
def _prepare_connection(self, url, headers):
if not isinstance(url, atom.url.Url):
if isinstance(url, (str,)):
url = atom.url.parse_url(url)
else:
raise atom.http_interface.UnparsableUrlObject('Unable to parse url '
'parameter because it was not a string or atom.url.Url')
if url.protocol == 'https':
if not url.port:
return http.client.HTTPSConnection(url.host)
return http.client.HTTPSConnection(url.host, int(url.port))
else:
if not url.port:
return http.client.HTTPConnection(url.host)
return http.client.HTTPConnection(url.host, int(url.port))
def _get_access_url(self, url):
return url.to_string()
class ProxiedHttpClient(HttpClient):
"""Performs an HTTP request through a proxy.
The proxy settings are obtained from enviroment variables. The URL of the
proxy server is assumed to be stored in the environment variables
'https_proxy' and 'http_proxy' respectively. If the proxy server requires
a Basic Auth authorization header, the username and password are expected to
be in the 'proxy-username' or 'proxy_username' variable and the
'proxy-password' or 'proxy_password' variable, or in 'http_proxy' or
'https_proxy' as "protocol://[username:password@]host:port".
After connecting to the proxy server, the request is completed as in
HttpClient.request.
"""
def _prepare_connection(self, url, headers):
proxy_settings = os.environ.get('%s_proxy' % url.protocol)
if not proxy_settings:
# The request was HTTP or HTTPS, but there was no appropriate proxy set.
return HttpClient._prepare_connection(self, url, headers)
else:
proxy_auth = _get_proxy_auth(proxy_settings)
proxy_netloc = _get_proxy_net_location(proxy_settings)
if url.protocol == 'https':
# Set any proxy auth headers
if proxy_auth:
proxy_auth = 'Proxy-Authorization: %s' % proxy_auth
# Construct the proxy connect command.
port = url.port
if not port:
port = '443'
proxy_connect = 'CONNECT %s:%s HTTP/1.0\r\n' % (url.host, port)
# Set the user agent to send to the proxy
if headers and 'User-Agent' in headers:
user_agent = 'User-Agent: %s\r\n' % (headers['User-Agent'])
else:
user_agent = 'User-Agent: python\r\n'
proxy_pieces = '%s%s%s\r\n' % (proxy_connect, proxy_auth, user_agent)
# Find the proxy host and port.
proxy_url = atom.url.parse_url(proxy_netloc)
if not proxy_url.port:
proxy_url.port = '80'
# Connect to the proxy server, very simple recv and error checking
p_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
p_sock.connect((proxy_url.host, int(proxy_url.port)))
#p_sock.sendall(proxy_pieces)
p_sock.sendall(proxy_pieces.encode('utf-8'))
response = ''
# Wait for the full response.
while response.find("\r\n\r\n") == -1:
#response += p_sock.recv(8192)
response += p_sock.recv(8192).decode('utf-8')
p_status = response.split()[1]
if p_status != str(200):
raise ProxyError('Error status=%s' % str(p_status))
# Trivial setup for ssl socket.
sslobj = None
if ssl_imported:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.minimum_version = ssl.TLSVersion.TLSv1_2
sslobj = context.wrap_socket(p_sock, server_hostname=url.host)
else:
sock_ssl = socket.ssl(p_sock, None, None)
sslobj = http.client.FakeSocket(p_sock, sock_ssl)
# Initalize httplib and replace with the proxy socket.
connection = http.client.HTTPConnection(proxy_url.host)
connection.sock = sslobj
return connection
else:
# If protocol was not https.
# Find the proxy host and port.
proxy_url = atom.url.parse_url(proxy_netloc)
if not proxy_url.port:
proxy_url.port = '80'
if proxy_auth:
headers['Proxy-Authorization'] = proxy_auth.strip()
return http.client.HTTPConnection(proxy_url.host, int(proxy_url.port))
def _get_access_url(self, url):
return url.to_string()
def _get_proxy_auth(proxy_settings):
"""Returns proxy authentication string for header.
Will check environment variables for proxy authentication info, starting with
proxy(_/-)username and proxy(_/-)password before checking the given
proxy_settings for a [protocol://]username:password@host[:port] string.
Args:
proxy_settings: String from http_proxy or https_proxy environment variable.
Returns:
Authentication string for proxy, or empty string if no proxy username was
found.
"""
proxy_username = None
proxy_password = None
proxy_username = os.environ.get('proxy-username')
if not proxy_username:
proxy_username = os.environ.get('proxy_username')
proxy_password = os.environ.get('proxy-password')
if not proxy_password:
proxy_password = os.environ.get('proxy_password')
if not proxy_username:
if '@' in proxy_settings:
protocol_and_proxy_auth = proxy_settings.split('@')[0].split(':')
if len(protocol_and_proxy_auth) == 3:
# 3 elements means we have [<protocol>, //<user>, <password>]
proxy_username = protocol_and_proxy_auth[1].lstrip('/')
proxy_password = protocol_and_proxy_auth[2]
elif len(protocol_and_proxy_auth) == 2:
# 2 elements means we have [<user>, <password>]
proxy_username = protocol_and_proxy_auth[0]
proxy_password = protocol_and_proxy_auth[1]
if proxy_username:
user_auth = base64.b64encode(('%s:%s' % (proxy_username, proxy_password)).encode('utf-8'))
return 'Basic %s\r\n' % (user_auth.strip().decode('utf-8'))
else:
return ''
def _get_proxy_net_location(proxy_settings):
"""Returns proxy host and port.
Args:
proxy_settings: String from http_proxy or https_proxy environment variable.
Must be in the form of protocol://[username:password@]host:port
Returns:
String in the form of protocol://host:port
"""
if '@' in proxy_settings:
protocol = proxy_settings.split(':')[0]
netloc = proxy_settings.split('@')[1]
return '%s://%s' % (protocol, netloc)
else:
return proxy_settings
def _send_data_part(data, connection):
if isinstance(data, (str,)):
connection.send(data)
return
# Check to see if data is a file-like object that has a read method.
elif hasattr(data, 'read'):
# Read the file and send it a chunk at a time.
while 1:
binarydata = data.read(100000)
if binarydata == b'': break
connection.send(binarydata)
return
else:
# The data object was not a file.
# Try to convert to a string and send the data.
#connection.send(str(data))
connection.send(str(data).encode('utf-8'))
return

599
src/gam/atom/http_core.py Normal file
View File

@@ -0,0 +1,599 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License 2.0;
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This module is used for version 2 of the Google Data APIs.
# TODO: add proxy handling.
# __author__ = 'j.s@google.com (Jeff Scudder)'
import http.client
import io
import os
import urllib.error
import urllib.parse
import urllib.request
ssl = None
try:
import ssl
except ImportError:
pass
class Error(Exception):
pass
class UnknownSize(Error):
pass
class ProxyError(Error):
pass
MIME_BOUNDARY = 'END_OF_PART'
def get_headers(http_response):
"""Retrieves all HTTP headers from an HTTP response from the server.
This method is provided for backwards compatibility for Python2.2 and 2.3.
The httplib.HTTPResponse object in 2.2 and 2.3 does not have a getheaders
method so this function will use getheaders if available, but if not it
will retrieve a few using getheader.
"""
if hasattr(http_response, 'getheaders'):
return http_response.getheaders()
else:
headers = []
for header in (
'location', 'content-type', 'content-length', 'age', 'allow',
'cache-control', 'content-location', 'content-encoding', 'date',
'etag', 'expires', 'last-modified', 'pragma', 'server',
'set-cookie', 'transfer-encoding', 'vary', 'via', 'warning',
'www-authenticate', 'gdata-version'):
value = http_response.getheader(header, None)
if value is not None:
headers.append((header, value))
return headers
class HttpRequest(object):
"""Contains all of the parameters for an HTTP 1.1 request.
The HTTP headers are represented by a dictionary, and it is the
responsibility of the user to ensure that duplicate field names are combined
into one header value according to the rules in section 4.2 of RFC 2616.
"""
method = None
uri = None
def __init__(self, uri=None, method=None, headers=None):
"""Construct an HTTP request.
Args:
uri: The full path or partial path as a Uri object or a string.
method: The HTTP method for the request, examples include 'GET', 'POST',
etc.
headers: dict of strings The HTTP headers to include in the request.
"""
self.headers = headers or {}
self._body_parts = []
if method is not None:
self.method = method
if isinstance(uri, str):
uri = Uri.parse_uri(uri)
self.uri = uri or Uri()
def add_body_part(self, data, mime_type, size=None):
"""Adds data to the HTTP request body.
If more than one part is added, this is assumed to be a mime-multipart
request. This method is designed to create MIME 1.0 requests as specified
in RFC 1341.
Args:
data: str or a file-like object containing a part of the request body.
mime_type: str The MIME type describing the data
size: int Required if the data is a file like object. If the data is a
string, the size is calculated so this parameter is ignored.
"""
if hasattr(data, '__len__'):
size = len(data)
if size is None:
# TODO: support chunked transfer if some of the body is of unknown size.
raise UnknownSize('Each part of the body must have a known size.')
if 'Content-Length' in self.headers:
content_length = int(self.headers['Content-Length'])
else:
content_length = 0
# If this is the first part added to the body, then this is not a multipart
# request.
if len(self._body_parts) == 0:
self.headers['Content-Type'] = mime_type
content_length = size
self._body_parts.append(data)
elif len(self._body_parts) == 1:
# This is the first member in a mime-multipart request, so change the
# _body_parts list to indicate a multipart payload.
self._body_parts.insert(0, 'Media multipart posting')
boundary_string = '\r\n--%s\r\n' % (MIME_BOUNDARY,)
content_length += len(boundary_string) + size
self._body_parts.insert(1, boundary_string)
content_length += len('Media multipart posting')
# Put the content type of the first part of the body into the multipart
# payload.
original_type_string = 'Content-Type: %s\r\n\r\n' % (
self.headers['Content-Type'],)
self._body_parts.insert(2, original_type_string)
content_length += len(original_type_string)
boundary_string = '\r\n--%s\r\n' % (MIME_BOUNDARY,)
self._body_parts.append(boundary_string)
content_length += len(boundary_string)
# Change the headers to indicate this is now a mime multipart request.
self.headers['Content-Type'] = 'multipart/related; boundary="%s"' % (
MIME_BOUNDARY,)
self.headers['MIME-version'] = '1.0'
# Include the mime type of this part.
type_string = 'Content-Type: %s\r\n\r\n' % (mime_type)
self._body_parts.append(type_string)
content_length += len(type_string)
self._body_parts.append(data)
ending_boundary_string = '\r\n--%s--' % (MIME_BOUNDARY,)
self._body_parts.append(ending_boundary_string)
content_length += len(ending_boundary_string)
else:
# This is a mime multipart request.
boundary_string = '\r\n--%s\r\n' % (MIME_BOUNDARY,)
self._body_parts.insert(-1, boundary_string)
content_length += len(boundary_string) + size
# Include the mime type of this part.
type_string = 'Content-Type: %s\r\n\r\n' % (mime_type)
self._body_parts.insert(-1, type_string)
content_length += len(type_string)
self._body_parts.insert(-1, data)
self.headers['Content-Length'] = str(content_length)
# I could add an "append_to_body_part" method as well.
AddBodyPart = add_body_part
def add_form_inputs(self, form_data,
mime_type='application/x-www-form-urlencoded'):
"""Form-encodes and adds data to the request body.
Args:
form_data: dict or sequnce or two member tuples which contains the
form keys and values.
mime_type: str The MIME type of the form data being sent. Defaults
to 'application/x-www-form-urlencoded'.
"""
body = urllib.parse.urlencode(form_data)
self.add_body_part(body, bytes(mime_type, 'ascii'))
AddFormInputs = add_form_inputs
def _copy(self):
"""Creates a deep copy of this request."""
copied_uri = Uri(self.uri.scheme, self.uri.host, self.uri.port,
self.uri.path, self.uri.query.copy())
new_request = HttpRequest(uri=copied_uri, method=self.method,
headers=self.headers.copy())
new_request._body_parts = self._body_parts[:]
return new_request
def _dump(self):
"""Converts to a printable string for debugging purposes.
In order to preserve the request, it does not read from file-like objects
in the body.
"""
output = 'HTTP Request\n method: %s\n url: %s\n headers:\n' % (
self.method, str(self.uri))
for header, value in self.headers.items():
output += ' %s: %s\n' % (header, value)
output += ' body sections:\n'
i = 0
for part in self._body_parts:
if isinstance(part, str):
output += ' %s: %s\n' % (i, part)
else:
output += ' %s: <file like object>\n' % i
i += 1
return output
def _apply_defaults(http_request):
if http_request.uri.scheme is None:
if http_request.uri.port == 443:
http_request.uri.scheme = 'https'
else:
http_request.uri.scheme = 'http'
class Uri(object):
"""A URI as used in HTTP 1.1"""
scheme = None
host = None
port = None
path = None
def __init__(self, scheme=None, host=None, port=None, path=None, query=None):
"""Constructor for a URI.
Args:
scheme: str This is usually 'http' or 'https'.
host: str The host name or IP address of the desired server.
post: int The server's port number.
path: str The path of the resource following the host. This begins with
a /, example: '/calendar/feeds/default/allcalendars/full'
query: dict of strings The URL query parameters. The keys and values are
both escaped so this dict should contain the unescaped values.
For example {'my key': 'val', 'second': '!!!'} will become
'?my+key=val&second=%21%21%21' which is appended to the path.
"""
self.query = query or {}
if scheme is not None:
self.scheme = scheme
if host is not None:
self.host = host
if port is not None:
self.port = port
if path:
self.path = path
def _get_query_string(self):
param_pairs = []
for key, value in self.query.items():
quoted_key = urllib.parse.quote_plus(str(key))
if value is None:
param_pairs.append(quoted_key)
else:
quoted_value = urllib.parse.quote_plus(str(value))
param_pairs.append('%s=%s' % (quoted_key, quoted_value))
return '&'.join(param_pairs)
def _get_relative_path(self):
"""Returns the path with the query parameters escaped and appended."""
param_string = self._get_query_string()
if self.path is None:
path = '/'
else:
path = self.path
if param_string:
return '?'.join([path, param_string])
else:
return path
def _to_string(self):
if self.scheme is None and self.port == 443:
scheme = 'https'
elif self.scheme is None:
scheme = 'http'
else:
scheme = self.scheme
if self.path is None:
path = '/'
else:
path = self.path
if self.port is None:
return '%s://%s%s' % (scheme, self.host, self._get_relative_path())
else:
return '%s://%s:%s%s' % (scheme, self.host, str(self.port),
self._get_relative_path())
def __str__(self):
return self._to_string()
def modify_request(self, http_request=None):
"""Sets HTTP request components based on the URI."""
if http_request is None:
http_request = HttpRequest()
if http_request.uri is None:
http_request.uri = Uri()
# Determine the correct scheme.
if self.scheme:
http_request.uri.scheme = self.scheme
if self.port:
http_request.uri.port = self.port
if self.host:
http_request.uri.host = self.host
# Set the relative uri path
if self.path:
http_request.uri.path = self.path
if self.query:
http_request.uri.query = self.query.copy()
return http_request
ModifyRequest = modify_request
def parse_uri(uri_string):
"""Creates a Uri object which corresponds to the URI string.
This method can accept partial URIs, but it will leave missing
members of the Uri unset.
"""
parts = urllib.parse.urlparse(uri_string)
uri = Uri()
if parts[0]:
uri.scheme = parts[0]
if parts[1]:
host_parts = parts[1].split(':')
if host_parts[0]:
uri.host = host_parts[0]
if len(host_parts) > 1:
uri.port = int(host_parts[1])
if parts[2]:
uri.path = parts[2]
if parts[4]:
param_pairs = parts[4].split('&')
for pair in param_pairs:
pair_parts = pair.split('=')
if len(pair_parts) > 1:
uri.query[urllib.parse.unquote_plus(pair_parts[0])] = (
urllib.parse.unquote_plus(pair_parts[1]))
elif len(pair_parts) == 1:
uri.query[urllib.parse.unquote_plus(pair_parts[0])] = None
return uri
parse_uri = staticmethod(parse_uri)
ParseUri = parse_uri
parse_uri = Uri.parse_uri
ParseUri = Uri.parse_uri
class HttpResponse(object):
status = None
reason = None
_body = None
def __init__(self, status=None, reason=None, headers=None, body=None):
self._headers = headers or {}
if status is not None:
self.status = status
if reason is not None:
self.reason = reason
if body is not None:
if hasattr(body, 'read'):
self._body = body
else:
self._body = io.StringIO(body)
def getheader(self, name, default=None):
if name in self._headers:
return self._headers[name]
else:
return default
def getheaders(self):
return self._headers
def read(self, amt=None):
if self._body is None:
return None
if not amt:
return self._body.read()
else:
return self._body.read(amt)
def _dump_response(http_response):
"""Converts to a string for printing debug messages.
Does not read the body since that may consume the content.
"""
output = 'HttpResponse\n status: %s\n reason: %s\n headers:' % (
http_response.status, http_response.reason)
headers = get_headers(http_response)
if isinstance(headers, dict):
for header, value in headers.items():
output += ' %s: %s\n' % (header, value)
else:
for pair in headers:
output += ' %s: %s\n' % (pair[0], pair[1])
return output
class HttpClient(object):
"""Performs HTTP requests using httplib."""
debug = None
def request(self, http_request):
return self._http_request(http_request.method, http_request.uri,
http_request.headers, http_request._body_parts)
Request = request
def _get_connection(self, uri, headers=None):
"""Opens a socket connection to the server to set up an HTTP request.
Args:
uri: The full URL for the request as a Uri object.
headers: A dict of string pairs containing the HTTP headers for the
request.
"""
connection = None
if uri.scheme == 'https':
if not uri.port:
connection = http.client.HTTPSConnection(uri.host)
else:
connection = http.client.HTTPSConnection(uri.host, int(uri.port))
else:
if not uri.port:
connection = http.client.HTTPConnection(uri.host)
else:
connection = http.client.HTTPConnection(uri.host, int(uri.port))
return connection
def _http_request(self, method, uri, headers=None, body_parts=None):
"""Makes an HTTP request using httplib.
Args:
method: str example: 'GET', 'POST', 'PUT', 'DELETE', etc.
uri: str or atom.http_core.Uri
headers: dict of strings mapping to strings which will be sent as HTTP
headers in the request.
body_parts: list of strings, objects with a read method, or objects
which can be converted to strings using str. Each of these
will be sent in order as the body of the HTTP request.
"""
if isinstance(uri, str):
uri = Uri.parse_uri(uri)
connection = self._get_connection(uri, headers=headers)
if self.debug:
connection.debuglevel = 1
if connection.host != uri.host:
connection.putrequest(method, str(uri))
else:
connection.putrequest(method, uri._get_relative_path())
# Overcome a bug in Python 2.4 and 2.5
# httplib.HTTPConnection.putrequest adding
# HTTP request header 'Host: www.google.com:443' instead of
# 'Host: www.google.com', and thus resulting the error message
# 'Token invalid - AuthSub token has wrong scope' in the HTTP response.
if (uri.scheme == 'https' and int(uri.port or 443) == 443 and
hasattr(connection, '_buffer') and
isinstance(connection._buffer, list)):
header_line = 'Host: %s:443' % uri.host
replacement_header_line = 'Host: %s' % uri.host
try:
connection._buffer[connection._buffer.index(header_line)] = (
replacement_header_line)
except ValueError: # header_line missing from connection._buffer
pass
# Send the HTTP headers.
for header_name, value in headers.items():
connection.putheader(header_name, value)
connection.endheaders()
# If there is data, send it in the request.
if body_parts and [x for x in body_parts if x != '']:
for part in body_parts:
_send_data_part(part, connection)
# Return the HTTP Response from the server.
return connection.getresponse()
def _send_data_part(data, connection):
if isinstance(data, str):
# I might want to just allow str, not unicode.
connection.send(data.encode())
# Check to see if data is a file-like object that has a read method.
elif hasattr(data, 'read'):
# Read the file and send it a chunk at a time.
while 1:
binarydata = data.read(100000)
if binarydata == '': break
connection.send(binarydata)
else:
# The data object was not a file.
# Try to convert to a string and send the data.
connection.send(data)
class ProxiedHttpClient(HttpClient):
def _get_connection(self, uri, headers=None):
# Check to see if there are proxy settings required for this request.
proxy = None
if uri.scheme == 'https':
proxy = os.environ.get('https_proxy')
elif uri.scheme == 'http':
proxy = os.environ.get('http_proxy')
if not proxy:
return HttpClient._get_connection(self, uri, headers=headers)
# Now we have the URL of the appropriate proxy server.
# Get a username and password for the proxy if required.
proxy_auth = _get_proxy_auth()
if uri.scheme == 'https':
import socket
if proxy_auth:
proxy_auth = 'Proxy-Authorization: %s' % proxy_auth
# Construct the proxy connect command.
port = uri.port
if not port:
port = 443
proxy_connect = 'CONNECT %s:%s HTTP/1.0\r\n' % (uri.host, port)
# Set the user agent to send to the proxy
user_agent = ''
if headers and 'User-Agent' in headers:
user_agent = 'User-Agent: %s\r\n' % (headers['User-Agent'])
proxy_pieces = '%s%s%s\r\n' % (proxy_connect, proxy_auth, user_agent)
# Find the proxy host and port.
proxy_uri = Uri.parse_uri(proxy)
if not proxy_uri.port:
proxy_uri.port = '80'
# Connect to the proxy server, very simple recv and error checking
p_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
p_sock.connect((proxy_uri.host, int(proxy_uri.port)))
#p_sock.sendall(proxy_pieces)
p_sock.sendall(proxy_pieces.encode('utf-8'))
response = ''
# Wait for the full response.
while response.find("\r\n\r\n") == -1:
#response += p_sock.recv(8192)
response += p_sock.recv(8192).decode('utf-8')
p_status = response.split()[1]
if p_status != str(200):
raise ProxyError('Error status=%s' % str(p_status))
# Trivial setup for ssl socket.
sslobj = None
if ssl is not None:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.minimum_version = ssl.TLSVersion.TLSv1_2
sslobj = context.wrap_socket(p_sock, server_hostname=uri.host)
else:
sock_ssl = socket.ssl(p_sock, None, None)
sslobj = http.client.FakeSocket(p_sock, sock_ssl)
# Initalize httplib and replace with the proxy socket.
connection = http.client.HTTPConnection(proxy_uri.host)
connection.sock = sslobj
return connection
elif uri.scheme == 'http':
proxy_uri = Uri.parse_uri(proxy)
if not proxy_uri.port:
proxy_uri.port = '80'
if proxy_auth:
headers['Proxy-Authorization'] = proxy_auth.strip()
return http.client.HTTPConnection(proxy_uri.host, int(proxy_uri.port))
return None
def _get_proxy_auth():
import base64
proxy_username = os.environ.get('proxy-username')
if not proxy_username:
proxy_username = os.environ.get('proxy_username')
proxy_password = os.environ.get('proxy-password')
if not proxy_password:
proxy_password = os.environ.get('proxy_password')
if proxy_username:
user_auth = base64.b64encode(('%s:%s' % (proxy_username, proxy_password)).encode('utf-8'))
return 'Basic %s\r\n' % (user_auth.strip().decode('utf-8'))
else:
return ''

View File

@@ -0,0 +1,144 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
"""This module provides a common interface for all HTTP requests.
HttpResponse: Represents the server's response to an HTTP request. Provides
an interface identical to httplib.HTTPResponse which is the response
expected from higher level classes which use HttpClient.request.
GenericHttpClient: Provides an interface (superclass) for an object
responsible for making HTTP requests. Subclasses of this object are
used in AtomService and GDataService to make requests to the server. By
changing the http_client member object, the AtomService is able to make
HTTP requests using different logic (for example, when running on
Google App Engine, the http_client makes requests using the App Engine
urlfetch API).
"""
# __author__ = 'api.jscudder (Jeff Scudder)'
import io
USER_AGENT = '%s GData-Python/2.0.18'
class Error(Exception):
pass
class UnparsableUrlObject(Error):
pass
class ContentLengthRequired(Error):
pass
class HttpResponse(object):
def __init__(self, body=None, status=None, reason=None, headers=None):
"""Constructor for an HttpResponse object.
HttpResponse represents the server's response to an HTTP request from
the client. The HttpClient.request method returns a httplib.HTTPResponse
object and this HttpResponse class is designed to mirror the interface
exposed by httplib.HTTPResponse.
Args:
body: A file like object, with a read() method. The body could also
be a string, and the constructor will wrap it so that
HttpResponse.read(self) will return the full string.
status: The HTTP status code as an int. Example: 200, 201, 404.
reason: The HTTP status message which follows the code. Example:
OK, Created, Not Found
headers: A dictionary containing the HTTP headers in the server's
response. A common header in the response is Content-Length.
"""
if body:
if hasattr(body, 'read'):
self._body = body
else:
self._body = io.StringIO(body)
else:
self._body = None
if status is not None:
self.status = int(status)
else:
self.status = None
self.reason = reason
self._headers = headers or {}
def getheader(self, name, default=None):
if name in self._headers:
return self._headers[name]
else:
return default
def read(self, amt=None):
if not amt:
return self._body.read()
else:
return self._body.read(amt)
class GenericHttpClient(object):
debug = False
def __init__(self, http_client, headers=None):
"""
Args:
http_client: An object which provides a request method to make an HTTP
request. The request method in GenericHttpClient performs a
call-through to the contained HTTP client object.
headers: A dictionary containing HTTP headers which should be included
in every HTTP request. Common persistent headers include
'User-Agent'.
"""
self.http_client = http_client
self.headers = headers or {}
def request(self, operation, url, data=None, headers=None):
all_headers = self.headers.copy()
if headers:
all_headers.update(headers)
return self.http_client.request(operation, url, data=data,
headers=all_headers)
def get(self, url, headers=None):
return self.request('GET', url, headers=headers)
def post(self, url, data, headers=None):
return self.request('POST', url, data=data, headers=headers)
def put(self, url, data, headers=None):
return self.request('PUT', url, data=data, headers=headers)
def delete(self, url, headers=None):
return self.request('DELETE', url, headers=headers)
class GenericToken(object):
"""Represents an Authorization token to be added to HTTP requests.
Some Authorization headers included calculated fields (digital
signatures for example) which are based on the parameters of the HTTP
request. Therefore the token is responsible for signing the request
and adding the Authorization header.
"""
def perform_request(self, http_client, operation, url, data=None,
headers=None):
"""For the GenericToken, no Authorization token is set."""
return http_client.request(operation, url, data=data, headers=headers)
def valid_for_scope(self, url):
"""Tells the caller if the token authorizes access to the desired URL.
Since the generic token doesn't add an auth header, it is not valid for
any scope.
"""
return False

123
src/gam/atom/mock_http.py Normal file
View File

@@ -0,0 +1,123 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
# __author__ = 'api.jscudder (Jeff Scudder)'
import atom.http_interface
import atom.url
class Error(Exception):
pass
class NoRecordingFound(Error):
pass
class MockRequest(object):
"""Holds parameters of an HTTP request for matching against future requests.
"""
def __init__(self, operation, url, data=None, headers=None):
self.operation = operation
if isinstance(url, str):
url = atom.url.parse_url(url)
self.url = url
self.data = data
self.headers = headers
class MockResponse(atom.http_interface.HttpResponse):
"""Simulates an httplib.HTTPResponse object."""
def __init__(self, body=None, status=None, reason=None, headers=None):
if body and hasattr(body, 'read'):
self.body = body.read()
else:
self.body = body
if status is not None:
self.status = int(status)
else:
self.status = None
self.reason = reason
self._headers = headers or {}
def read(self):
return self.body
class MockHttpClient(atom.http_interface.GenericHttpClient):
def __init__(self, headers=None, recordings=None, real_client=None):
"""An HttpClient which responds to request with stored data.
The request-response pairs are stored as tuples in a member list named
recordings.
The MockHttpClient can be switched from replay mode to record mode by
setting the real_client member to an instance of an HttpClient which will
make real HTTP requests and store the server's response in list of
recordings.
Args:
headers: dict containing HTTP headers which should be included in all
HTTP requests.
recordings: The initial recordings to be used for responses. This list
contains tuples in the form: (MockRequest, MockResponse)
real_client: An HttpClient which will make a real HTTP request. The
response will be converted into a MockResponse and stored in
recordings.
"""
self.recordings = recordings or []
self.real_client = real_client
self.headers = headers or {}
def add_response(self, response, operation, url, data=None, headers=None):
"""Adds a request-response pair to the recordings list.
After the recording is added, future matching requests will receive the
response.
Args:
response: MockResponse
operation: str
url: str
data: str, Currently the data is ignored when looking for matching
requests.
headers: dict of strings: Currently the headers are ignored when
looking for matching requests.
"""
request = MockRequest(operation, url, data=data, headers=headers)
self.recordings.append((request, response))
def request(self, operation, url, data=None, headers=None):
"""Returns a matching MockResponse from the recordings.
If the real_client is set, the request will be passed along and the
server's response will be added to the recordings and also returned.
If there is no match, a NoRecordingFound error will be raised.
"""
if self.real_client is None:
if isinstance(url, str):
url = atom.url.parse_url(url)
for recording in self.recordings:
if recording[0].operation == operation and recording[0].url == url:
return recording[1]
raise NoRecordingFound('No recodings found for %s %s' % (
operation, url))
else:
# There is a real HTTP client, so make the request, and record the
# response.
response = self.real_client.request(operation, url, data=data,
headers=headers)
# TODO: copy the headers
stored_response = MockResponse(body=response, status=response.status,
reason=response.reason)
self.add_response(stored_response, operation, url, data=data,
headers=headers)
return stored_response

View File

@@ -0,0 +1,313 @@
#!/usr/bin/env python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License 2.0;
# This module is used for version 2 of the Google Data APIs.
# __author__ = 'j.s@google.com (Jeff Scudder)'
import io
import os.path
import pickle
import tempfile
import atom.http_core
class Error(Exception):
pass
class NoRecordingFound(Error):
pass
class MockHttpClient(object):
debug = None
real_client = None
last_request_was_live = False
# The following members are used to construct the session cache temp file
# name.
# These are combined to form the file name
# /tmp/cache_prefix.cache_case_name.cache_test_name
cache_name_prefix = 'gdata_live_test'
cache_case_name = ''
cache_test_name = ''
def __init__(self, recordings=None, real_client=None):
self._recordings = recordings or []
if real_client is not None:
self.real_client = real_client
def add_response(self, http_request, status, reason, headers=None,
body=None):
response = MockHttpResponse(status, reason, headers, body)
# TODO Scrub the request and the response.
self._recordings.append((http_request._copy(), response))
AddResponse = add_response
def request(self, http_request):
"""Provide a recorded response, or record a response for replay.
If the real_client is set, the request will be made using the
real_client, and the response from the server will be recorded.
If the real_client is None (the default), this method will examine
the recordings and find the first which matches.
"""
request = http_request._copy()
_scrub_request(request)
if self.real_client is None:
self.last_request_was_live = False
for recording in self._recordings:
if _match_request(recording[0], request):
return recording[1]
else:
# Pass along the debug settings to the real client.
self.real_client.debug = self.debug
# Make an actual request since we can use the real HTTP client.
self.last_request_was_live = True
response = self.real_client.request(http_request)
scrubbed_response = _scrub_response(response)
self.add_response(request, scrubbed_response.status,
scrubbed_response.reason,
dict(atom.http_core.get_headers(scrubbed_response)),
scrubbed_response.read())
# Return the recording which we just added.
return self._recordings[-1][1]
raise NoRecordingFound('No recoding was found for request: %s %s' % (
request.method, str(request.uri)))
Request = request
def _save_recordings(self, filename):
recording_file = open(os.path.join(tempfile.gettempdir(), filename),
'wb')
pickle.dump(self._recordings, recording_file)
recording_file.close()
def _load_recordings(self, filename):
recording_file = open(os.path.join(tempfile.gettempdir(), filename),
'rb')
self._recordings = pickle.load(recording_file)
recording_file.close()
def _delete_recordings(self, filename):
full_path = os.path.join(tempfile.gettempdir(), filename)
if os.path.exists(full_path):
os.remove(full_path)
def _load_or_use_client(self, filename, http_client):
if os.path.exists(os.path.join(tempfile.gettempdir(), filename)):
self._load_recordings(filename)
else:
self.real_client = http_client
def use_cached_session(self, name=None, real_http_client=None):
"""Attempts to load recordings from a previous live request.
If a temp file with the recordings exists, then it is used to fulfill
requests. If the file does not exist, then a real client is used to
actually make the desired HTTP requests. Requests and responses are
recorded and will be written to the desired temprary cache file when
close_session is called.
Args:
name: str (optional) The file name of session file to be used. The file
is loaded from the temporary directory of this machine. If no name
is passed in, a default name will be constructed using the
cache_name_prefix, cache_case_name, and cache_test_name of this
object.
real_http_client: atom.http_core.HttpClient the real client to be used
if the cached recordings are not found. If the default
value is used, this will be an
atom.http_core.HttpClient.
"""
if real_http_client is None:
real_http_client = atom.http_core.HttpClient()
if name is None:
self._recordings_cache_name = self.get_cache_file_name()
else:
self._recordings_cache_name = name
self._load_or_use_client(self._recordings_cache_name, real_http_client)
def close_session(self):
"""Saves recordings in the temporary file named in use_cached_session."""
if self.real_client is not None:
self._save_recordings(self._recordings_cache_name)
def delete_session(self, name=None):
"""Removes recordings from a previous live request."""
if name is None:
self._delete_recordings(self._recordings_cache_name)
else:
self._delete_recordings(name)
def get_cache_file_name(self):
return '%s.%s.%s' % (self.cache_name_prefix, self.cache_case_name,
self.cache_test_name)
def _dump(self):
"""Provides debug information in a string."""
output = 'MockHttpClient\n real_client: %s\n cache file name: %s\n' % (
self.real_client, self.get_cache_file_name())
output += ' recordings:\n'
i = 0
for recording in self._recordings:
output += ' recording %i is for: %s %s\n' % (
i, recording[0].method, str(recording[0].uri))
i += 1
return output
def _match_request(http_request, stored_request):
"""Determines whether a request is similar enough to a stored request
to cause the stored response to be returned."""
# Check to see if the host names match.
if (http_request.uri.host is not None
and http_request.uri.host != stored_request.uri.host):
return False
# Check the request path in the URL (/feeds/private/full/x)
elif http_request.uri.path != stored_request.uri.path:
return False
# Check the method used in the request (GET, POST, etc.)
elif http_request.method != stored_request.method:
return False
# If there is a gsession ID in either request, make sure that it is matched
# exactly.
elif ('gsessionid' in http_request.uri.query
or 'gsessionid' in stored_request.uri.query):
if 'gsessionid' not in stored_request.uri.query:
return False
elif 'gsessionid' not in http_request.uri.query:
return False
elif (http_request.uri.query['gsessionid']
!= stored_request.uri.query['gsessionid']):
return False
# Ignores differences in the query params (?start-index=5&max-results=20),
# the body of the request, the port number, HTTP headers, just to name a
# few.
return True
def _scrub_request(http_request):
""" Removes email address and password from a client login request.
Since the mock server saves the request and response in plantext, sensitive
information like the password should be removed before saving the
recordings. At the moment only requests sent to a ClientLogin url are
scrubbed.
"""
if (http_request and http_request.uri and http_request.uri.path and
http_request.uri.path.endswith('ClientLogin')):
# Remove the email and password from a ClientLogin request.
http_request._body_parts = []
http_request.add_form_inputs(
{'form_data': 'client login request has been scrubbed'})
else:
# We can remove the body of the post from the recorded request, since
# the request body is not used when finding a matching recording.
http_request._body_parts = []
return http_request
def _scrub_response(http_response):
return http_response
class EchoHttpClient(object):
"""Sends the request data back in the response.
Used to check the formatting of the request as it was sent. Always responds
with a 200 OK, and some information from the HTTP request is returned in
special Echo-X headers in the response. The following headers are added
in the response:
'Echo-Host': The host name and port number to which the HTTP connection is
made. If no port was passed in, the header will contain
host:None.
'Echo-Uri': The path portion of the URL being requested. /example?x=1&y=2
'Echo-Scheme': The beginning of the URL, usually 'http' or 'https'
'Echo-Method': The HTTP method being used, 'GET', 'POST', 'PUT', etc.
"""
def request(self, http_request):
return self._http_request(http_request.uri, http_request.method,
http_request.headers, http_request._body_parts)
def _http_request(self, uri, method, headers=None, body_parts=None):
body = io.StringIO()
response = atom.http_core.HttpResponse(status=200, reason='OK', body=body)
if headers is None:
response._headers = {}
else:
# Copy headers from the request to the response but convert values to
# strings. Server response headers always come in as strings, so an int
# should be converted to a corresponding string when echoing.
for header, value in headers.items():
response._headers[header] = str(value)
response._headers['Echo-Host'] = '%s:%s' % (uri.host, str(uri.port))
response._headers['Echo-Uri'] = uri._get_relative_path()
response._headers['Echo-Scheme'] = uri.scheme
response._headers['Echo-Method'] = method
for part in body_parts:
if isinstance(part, str):
body.write(part)
elif hasattr(part, 'read'):
body.write(part.read())
body.seek(0)
return response
class SettableHttpClient(object):
"""An HTTP Client which responds with the data given in set_response."""
def __init__(self, status, reason, body, headers):
"""Configures the response for the server.
See set_response for details on the arguments to the constructor.
"""
self.set_response(status, reason, body, headers)
self.last_request = None
def set_response(self, status, reason, body, headers):
"""Determines the response which will be sent for each request.
Args:
status: An int for the HTTP status code, example: 200, 404, etc.
reason: String for the HTTP reason, example: OK, NOT FOUND, etc.
body: The body of the HTTP response as a string or a file-like
object (something with a read method).
headers: dict of strings containing the HTTP headers in the response.
"""
self.response = atom.http_core.HttpResponse(status=status, reason=reason,
body=body)
self.response._headers = headers.copy()
def request(self, http_request):
self.last_request = http_request
return self.response
class MockHttpResponse(atom.http_core.HttpResponse):
def __init__(self, status=None, reason=None, headers=None, body=None):
self._headers = headers or {}
if status is not None:
self.status = status
if reason is not None:
self.reason = reason
if body is not None:
# Instead of using a file-like object for the body, store as a string
# so that reads can be repeated.
if hasattr(body, 'read'):
self._body = body.read()
else:
self._body = body
def read(self):
return self._body

View File

@@ -0,0 +1,235 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
"""MockService provides CRUD ops. for mocking calls to AtomPub services.
MockService: Exposes the publicly used methods of AtomService to provide
a mock interface which can be used in unit tests.
"""
import pickle
import atom.service
# __author__ = 'api.jscudder (Jeffrey Scudder)'
# Recordings contains pairings of HTTP MockRequest objects with MockHttpResponse objects.
recordings = []
# If set, the mock service HttpRequest are actually made through this object.
real_request_handler = None
def ConcealValueWithSha(source):
import sha
return sha.new(source[:-5]).hexdigest()
def DumpRecordings(conceal_func=ConcealValueWithSha):
if conceal_func:
for recording_pair in recordings:
recording_pair[0].ConcealSecrets(conceal_func)
return pickle.dumps(recordings)
def LoadRecordings(recordings_file_or_string):
if isinstance(recordings_file_or_string, str):
atom.mock_service.recordings = pickle.loads(recordings_file_or_string)
elif hasattr(recordings_file_or_string, 'read'):
atom.mock_service.recordings = pickle.loads(
recordings_file_or_string.read())
def HttpRequest(service, operation, data, uri, extra_headers=None,
url_params=None, escape_params=True, content_type='application/atom+xml'):
"""Simulates an HTTP call to the server, makes an actual HTTP request if
real_request_handler is set.
This function operates in two different modes depending on if
real_request_handler is set or not. If real_request_handler is not set,
HttpRequest will look in this module's recordings list to find a response
which matches the parameters in the function call. If real_request_handler
is set, this function will call real_request_handler.HttpRequest, add the
response to the recordings list, and respond with the actual response.
Args:
service: atom.AtomService object which contains some of the parameters
needed to make the request. The following members are used to
construct the HTTP call: server (str), additional_headers (dict),
port (int), and ssl (bool).
operation: str The HTTP operation to be performed. This is usually one of
'GET', 'POST', 'PUT', or 'DELETE'
data: ElementTree, filestream, list of parts, or other object which can be
converted to a string.
Should be set to None when performing a GET or PUT.
If data is a file-like object which can be read, this method will read
a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be evaluated
and sent.
uri: The beginning of the URL to which the request should be sent.
Examples: '/', '/base/feeds/snippets',
'/m8/feeds/contacts/default/base'
extra_headers: dict of strings. HTTP headers which should be sent
in the request. These headers are in addition to those stored in
service.additional_headers.
url_params: dict of strings. Key value pairs to be added to the URL as
URL parameters. For example {'foo':'bar', 'test':'param'} will
become ?foo=bar&test=param.
escape_params: bool default True. If true, the keys and values in
url_params will be URL escaped when the form is constructed
(Special characters converted to %XX form.)
content_type: str The MIME type for the data being sent. Defaults to
'application/atom+xml', this is only used if data is set.
"""
full_uri = atom.service.BuildUri(uri, url_params, escape_params)
(server, port, ssl, uri) = atom.service.ProcessUrl(service, uri)
current_request = MockRequest(operation, full_uri, host=server, ssl=ssl,
data=data, extra_headers=extra_headers, url_params=url_params,
escape_params=escape_params, content_type=content_type)
# If the request handler is set, we should actually make the request using
# the request handler and record the response to replay later.
if real_request_handler:
response = real_request_handler.HttpRequest(service, operation, data, uri,
extra_headers=extra_headers, url_params=url_params,
escape_params=escape_params, content_type=content_type)
# TODO: need to copy the HTTP headers from the real response into the
# recorded_response.
recorded_response = MockHttpResponse(body=response.read(),
status=response.status, reason=response.reason)
# Insert a tuple which maps the request to the response object returned
# when making an HTTP call using the real_request_handler.
recordings.append((current_request, recorded_response))
return recorded_response
else:
# Look through available recordings to see if one matches the current
# request.
for request_response_pair in recordings:
if request_response_pair[0].IsMatch(current_request):
return request_response_pair[1]
return None
class MockRequest(object):
"""Represents a request made to an AtomPub server.
These objects are used to determine if a client request matches a recorded
HTTP request to determine what the mock server's response will be.
"""
def __init__(self, operation, uri, host=None, ssl=False, port=None,
data=None, extra_headers=None, url_params=None, escape_params=True,
content_type='application/atom+xml'):
"""Constructor for a MockRequest
Args:
operation: str One of 'GET', 'POST', 'PUT', or 'DELETE' this is the
HTTP operation requested on the resource.
uri: str The URL describing the resource to be modified or feed to be
retrieved. This should include the protocol (http/https) and the host
(aka domain). For example, these are some valud full_uris:
'http://example.com', 'https://www.google.com/accounts/ClientLogin'
host: str (optional) The server name which will be placed at the
beginning of the URL if the uri parameter does not begin with 'http'.
Examples include 'example.com', 'www.google.com', 'www.blogger.com'.
ssl: boolean (optional) If true, the request URL will begin with https
instead of http.
data: ElementTree, filestream, list of parts, or other object which can be
converted to a string. (optional)
Should be set to None when performing a GET or PUT.
If data is a file-like object which can be read, the constructor
will read the entire file into memory. If the data is a list of
parts to be sent, each part will be evaluated and stored.
extra_headers: dict (optional) HTTP headers included in the request.
url_params: dict (optional) Key value pairs which should be added to
the URL as URL parameters in the request. For example uri='/',
url_parameters={'foo':'1','bar':'2'} could become '/?foo=1&bar=2'.
escape_params: boolean (optional) Perform URL escaping on the keys and
values specified in url_params. Defaults to True.
content_type: str (optional) Provides the MIME type of the data being
sent.
"""
self.operation = operation
self.uri = _ConstructFullUrlBase(uri, host=host, ssl=ssl)
self.data = data
self.extra_headers = extra_headers
self.url_params = url_params or {}
self.escape_params = escape_params
self.content_type = content_type
def ConcealSecrets(self, conceal_func):
"""Conceal secret data in this request."""
if 'Authorization' in self.extra_headers:
self.extra_headers['Authorization'] = conceal_func(
self.extra_headers['Authorization'])
def IsMatch(self, other_request):
"""Check to see if the other_request is equivalent to this request.
Used to determine if a recording matches an incoming request so that a
recorded response should be sent to the client.
The matching is not exact, only the operation and URL are examined
currently.
Args:
other_request: MockRequest The request which we want to check this
(self) MockRequest against to see if they are equivalent.
"""
# More accurate matching logic will likely be required.
return (self.operation == other_request.operation and self.uri ==
other_request.uri)
def _ConstructFullUrlBase(uri, host=None, ssl=False):
"""Puts URL components into the form http(s)://full.host.strinf/uri/path
Used to construct a roughly canonical URL so that URLs which begin with
'http://example.com/' can be compared to a uri of '/' when the host is
set to 'example.com'
If the uri contains 'http://host' already, the host and ssl parameters
are ignored.
Args:
uri: str The path component of the URL, examples include '/'
host: str (optional) The host name which should prepend the URL. Example:
'example.com'
ssl: boolean (optional) If true, the returned URL will begin with https
instead of http.
Returns:
String which has the form http(s)://example.com/uri/string/contents
"""
if uri.startswith('http'):
return uri
if ssl:
return 'https://%s%s' % (host, uri)
else:
return 'http://%s%s' % (host, uri)
class MockHttpResponse(object):
"""Returned from MockService crud methods as the server's response."""
def __init__(self, body=None, status=None, reason=None, headers=None):
"""Construct a mock HTTPResponse and set members.
Args:
body: str (optional) The HTTP body of the server's response.
status: int (optional)
reason: str (optional)
headers: dict (optional)
"""
self.body = body
self.status = status
self.reason = reason
self.headers = headers or {}
def read(self):
return self.body
def getheader(self, header_name):
return self.headers[header_name]

723
src/gam/atom/service.py Normal file
View File

@@ -0,0 +1,723 @@
#
# Copyright (C) 2006, 2007, 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
"""AtomService provides CRUD ops. in line with the Atom Publishing Protocol.
AtomService: Encapsulates the ability to perform insert, update and delete
operations with the Atom Publishing Protocol on which GData is
based. An instance can perform query, insertion, deletion, and
update.
HttpRequest: Function that performs a GET, POST, PUT, or DELETE HTTP request
to the specified end point. An AtomService object or a subclass can be
used to specify information about the request.
"""
# __author__ = 'api.jscudder (Jeff Scudder)'
import base64
import http.client
import os
import socket
import urllib.error
import urllib.parse
import urllib.request
import warnings
import atom.http
import atom.http_interface
import atom.token_store
import atom.url
import lxml.etree as ElementTree
import atom
class AtomService(object):
"""Performs Atom Publishing Protocol CRUD operations.
The AtomService contains methods to perform HTTP CRUD operations.
"""
# Default values for members
port = 80
ssl = False
# Set the current_token to force the AtomService to use this token
# instead of searching for an appropriate token in the token_store.
current_token = None
auto_store_tokens = True
auto_set_current_token = True
def _get_override_token(self):
return self.current_token
def _set_override_token(self, token):
self.current_token = token
override_token = property(_get_override_token, _set_override_token)
# @atom.v1_deprecated('Please use atom.client.AtomPubClient instead.')
def __init__(self, server=None, additional_headers=None,
application_name='', http_client=None, token_store=None):
"""Creates a new AtomService client.
Args:
server: string (optional) The start of a URL for the server
to which all operations should be directed. Example:
'www.google.com'
additional_headers: dict (optional) Any additional HTTP headers which
should be included with CRUD operations.
http_client: An object responsible for making HTTP requests using a
request method. If none is provided, a new instance of
atom.http.ProxiedHttpClient will be used.
token_store: Keeps a collection of authorization tokens which can be
applied to requests for a specific URLs. Critical methods are
find_token based on a URL (atom.url.Url or a string), add_token,
and remove_token.
"""
self.http_client = http_client or atom.http.ProxiedHttpClient()
self.token_store = token_store or atom.token_store.TokenStore()
self.server = server
self.additional_headers = additional_headers or {}
self.additional_headers['User-Agent'] = atom.http_interface.USER_AGENT % (
application_name,)
# If debug is True, the HTTPConnection will display debug information
self._set_debug(False)
__init__ = atom.v1_deprecated(
'Please use atom.client.AtomPubClient instead.')(
__init__)
def _get_debug(self):
return self.http_client.debug
def _set_debug(self, value):
self.http_client.debug = value
debug = property(_get_debug, _set_debug,
doc='If True, HTTP debug information is printed.')
def use_basic_auth(self, username, password, scopes=None):
if username is not None and password is not None:
if scopes is None:
scopes = [atom.token_store.SCOPE_ALL]
base_64_string = base64.encodestring('%s:%s' % (username, password))
token = BasicAuthToken('Basic %s' % base_64_string.strip(),
scopes=[atom.token_store.SCOPE_ALL])
if self.auto_set_current_token:
self.current_token = token
if self.auto_store_tokens:
return self.token_store.add_token(token)
return True
return False
def UseBasicAuth(self, username, password, for_proxy=False):
"""Sets an Authenticaiton: Basic HTTP header containing plaintext.
Deprecated, use use_basic_auth instead.
The username and password are base64 encoded and added to an HTTP header
which will be included in each request. Note that your username and
password are sent in plaintext.
Args:
username: str
password: str
"""
self.use_basic_auth(username, password)
# @atom.v1_deprecated('Please use atom.client.AtomPubClient for requests.')
def request(self, operation, url, data=None, headers=None,
url_params=None):
if isinstance(url, str):
if url.startswith('http:') and self.ssl:
# Force all requests to be https if self.ssl is True.
url = atom.url.parse_url('https:' + url[5:])
elif not url.startswith('http') and self.ssl:
url = atom.url.parse_url('https://%s%s' % (self.server, url))
elif not url.startswith('http'):
url = atom.url.parse_url('http://%s%s' % (self.server, url))
else:
url = atom.url.parse_url(url)
if url_params:
for name, value in url_params.items():
url.params[name] = value
all_headers = self.additional_headers.copy()
if headers:
all_headers.update(headers)
# If the list of headers does not include a Content-Length, attempt to
# calculate it based on the data object.
if data and 'Content-Length' not in all_headers:
content_length = CalculateDataLength(data)
if content_length:
all_headers['Content-Length'] = str(content_length)
# Find an Authorization token for this URL if one is available.
if self.override_token:
auth_token = self.override_token
else:
auth_token = self.token_store.find_token(url)
return auth_token.perform_request(self.http_client, operation, url,
data=data, headers=all_headers)
request = atom.v1_deprecated(
'Please use atom.client.AtomPubClient for requests.')(
request)
# CRUD operations
def Get(self, uri, extra_headers=None, url_params=None, escape_params=True):
"""Query the APP server with the given URI
The uri is the portion of the URI after the server value
(server example: 'www.google.com').
Example use:
To perform a query against Google Base, set the server to
'base.google.com' and set the uri to '/base/feeds/...', where ... is
your query. For example, to find snippets for all digital cameras uri
should be set to: '/base/feeds/snippets?bq=digital+camera'
Args:
uri: string The query in the form of a URI. Example:
'/base/feeds/snippets?bq=digital+camera'.
extra_headers: dicty (optional) Extra HTTP headers to be included
in the GET request. These headers are in addition to
those stored in the client's additional_headers property.
The client automatically sets the Content-Type and
Authorization headers.
url_params: dict (optional) Additional URL parameters to be included
in the query. These are translated into query arguments
in the form '&dict_key=value&...'.
Example: {'max-results': '250'} becomes &max-results=250
escape_params: boolean (optional) If false, the calling code has already
ensured that the query will form a valid URL (all
reserved characters have been escaped). If true, this
method will escape the query and any URL parameters
provided.
Returns:
httplib.HTTPResponse The server's response to the GET request.
"""
return self.request('GET', uri, data=None, headers=extra_headers,
url_params=url_params)
def Post(self, data, uri, extra_headers=None, url_params=None,
escape_params=True, content_type='application/atom+xml'):
"""Insert data into an APP server at the given URI.
Args:
data: string, ElementTree._Element, or something with a __str__ method
The XML to be sent to the uri.
uri: string The location (feed) to which the data should be inserted.
Example: '/base/feeds/items'.
extra_headers: dict (optional) HTTP headers which are to be included.
The client automatically sets the Content-Type,
Authorization, and Content-Length headers.
url_params: dict (optional) Additional URL parameters to be included
in the URI. These are translated into query arguments
in the form '&dict_key=value&...'.
Example: {'max-results': '250'} becomes &max-results=250
escape_params: boolean (optional) If false, the calling code has already
ensured that the query will form a valid URL (all
reserved characters have been escaped). If true, this
method will escape the query and any URL parameters
provided.
Returns:
httplib.HTTPResponse Server's response to the POST request.
"""
if extra_headers is None:
extra_headers = {}
if content_type:
extra_headers['Content-Type'] = content_type
return self.request('POST', uri, data=data, headers=extra_headers,
url_params=url_params)
def Put(self, data, uri, extra_headers=None, url_params=None,
escape_params=True, content_type='application/atom+xml'):
"""Updates an entry at the given URI.
Args:
data: string, ElementTree._Element, or xml_wrapper.ElementWrapper The
XML containing the updated data.
uri: string A URI indicating entry to which the update will be applied.
Example: '/base/feeds/items/ITEM-ID'
extra_headers: dict (optional) HTTP headers which are to be included.
The client automatically sets the Content-Type,
Authorization, and Content-Length headers.
url_params: dict (optional) Additional URL parameters to be included
in the URI. These are translated into query arguments
in the form '&dict_key=value&...'.
Example: {'max-results': '250'} becomes &max-results=250
escape_params: boolean (optional) If false, the calling code has already
ensured that the query will form a valid URL (all
reserved characters have been escaped). If true, this
method will escape the query and any URL parameters
provided.
Returns:
httplib.HTTPResponse Server's response to the PUT request.
"""
if extra_headers is None:
extra_headers = {}
if content_type:
extra_headers['Content-Type'] = content_type
return self.request('PUT', uri, data=data, headers=extra_headers,
url_params=url_params)
def Delete(self, uri, extra_headers=None, url_params=None,
escape_params=True):
"""Deletes the entry at the given URI.
Args:
uri: string The URI of the entry to be deleted. Example:
'/base/feeds/items/ITEM-ID'
extra_headers: dict (optional) HTTP headers which are to be included.
The client automatically sets the Content-Type and
Authorization headers.
url_params: dict (optional) Additional URL parameters to be included
in the URI. These are translated into query arguments
in the form '&dict_key=value&...'.
Example: {'max-results': '250'} becomes &max-results=250
escape_params: boolean (optional) If false, the calling code has already
ensured that the query will form a valid URL (all
reserved characters have been escaped). If true, this
method will escape the query and any URL parameters
provided.
Returns:
httplib.HTTPResponse Server's response to the DELETE request.
"""
return self.request('DELETE', uri, data=None, headers=extra_headers,
url_params=url_params)
class BasicAuthToken(atom.http_interface.GenericToken):
def __init__(self, auth_header, scopes=None):
"""Creates a token used to add Basic Auth headers to HTTP requests.
Args:
auth_header: str The value for the Authorization header.
scopes: list of str or atom.url.Url specifying the beginnings of URLs
for which this token can be used. For example, if scopes contains
'http://example.com/foo', then this token can be used for a request to
'http://example.com/foo/bar' but it cannot be used for a request to
'http://example.com/baz'
"""
self.auth_header = auth_header
self.scopes = scopes or []
def perform_request(self, http_client, operation, url, data=None,
headers=None):
"""Sets the Authorization header to the basic auth string."""
if headers is None:
headers = {'Authorization': self.auth_header}
else:
headers['Authorization'] = self.auth_header
return http_client.request(operation, url, data=data, headers=headers)
def __str__(self):
return self.auth_header
def valid_for_scope(self, url):
"""Tells the caller if the token authorizes access to the desired URL.
"""
if isinstance(url, str):
url = atom.url.parse_url(url)
for scope in self.scopes:
if scope == atom.token_store.SCOPE_ALL:
return True
if isinstance(scope, str):
scope = atom.url.parse_url(scope)
if scope == url:
return True
# Check the host and the path, but ignore the port and protocol.
elif scope.host == url.host and not scope.path:
return True
elif scope.host == url.host and scope.path and not url.path:
continue
elif scope.host == url.host and url.path.startswith(scope.path):
return True
return False
def PrepareConnection(service, full_uri):
"""Opens a connection to the server based on the full URI.
This method is deprecated, instead use atom.http.HttpClient.request.
Examines the target URI and the proxy settings, which are set as
environment variables, to open a connection with the server. This
connection is used to make an HTTP request.
Args:
service: atom.AtomService or a subclass. It must have a server string which
represents the server host to which the request should be made. It may also
have a dictionary of additional_headers to send in the HTTP request.
full_uri: str Which is the target relative (lacks protocol and host) or
absolute URL to be opened. Example:
'https://www.google.com/accounts/ClientLogin' or
'base/feeds/snippets' where the server is set to www.google.com.
Returns:
A tuple containing the httplib.HTTPConnection and the full_uri for the
request.
"""
deprecation('calling deprecated function PrepareConnection')
(server, port, ssl, partial_uri) = ProcessUrl(service, full_uri)
if ssl:
# destination is https
proxy = os.environ.get('https_proxy')
if proxy:
(p_server, p_port, p_ssl, p_uri) = ProcessUrl(service, proxy, True)
proxy_username = os.environ.get('proxy-username')
if not proxy_username:
proxy_username = os.environ.get('proxy_username')
proxy_password = os.environ.get('proxy-password')
if not proxy_password:
proxy_password = os.environ.get('proxy_password')
if proxy_username:
user_auth = base64.encodestring('%s:%s' % (proxy_username,
proxy_password))
proxy_authorization = ('Proxy-authorization: Basic %s\r\n' % (
user_auth.strip()))
else:
proxy_authorization = ''
proxy_connect = 'CONNECT %s:%s HTTP/1.0\r\n' % (server, port)
user_agent = 'User-Agent: %s\r\n' % (
service.additional_headers['User-Agent'])
proxy_pieces = (proxy_connect + proxy_authorization + user_agent
+ '\r\n')
# now connect, very simple recv and error checking
p_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
p_sock.connect((p_server, p_port))
p_sock.sendall(proxy_pieces)
response = ''
# Wait for the full response.
while response.find("\r\n\r\n") == -1:
response += p_sock.recv(8192)
p_status = response.split()[1]
if p_status != str(200):
raise atom.http.ProxyError('Error status=%s' % p_status)
# Trivial setup for ssl socket.
ssl = socket.ssl(p_sock, None, None)
fake_sock = http.client.FakeSocket(p_sock, ssl)
# Initalize httplib and replace with the proxy socket.
connection = http.client.HTTPConnection(server)
connection.sock = fake_sock
full_uri = partial_uri
else:
connection = http.client.HTTPSConnection(server, port)
full_uri = partial_uri
else:
# destination is http
proxy = os.environ.get('http_proxy')
if proxy:
(p_server, p_port, p_ssl, p_uri) = ProcessUrl(service.server, proxy, True)
proxy_username = os.environ.get('proxy-username')
if not proxy_username:
proxy_username = os.environ.get('proxy_username')
proxy_password = os.environ.get('proxy-password')
if not proxy_password:
proxy_password = os.environ.get('proxy_password')
if proxy_username:
UseBasicAuth(service, proxy_username, proxy_password, True)
connection = http.client.HTTPConnection(p_server, p_port)
if not full_uri.startswith("http://"):
if full_uri.startswith("/"):
full_uri = "http://%s%s" % (service.server, full_uri)
else:
full_uri = "http://%s/%s" % (service.server, full_uri)
else:
connection = http.client.HTTPConnection(server, port)
full_uri = partial_uri
return (connection, full_uri)
def UseBasicAuth(service, username, password, for_proxy=False):
"""Sets an Authenticaiton: Basic HTTP header containing plaintext.
Deprecated, use AtomService.use_basic_auth insread.
The username and password are base64 encoded and added to an HTTP header
which will be included in each request. Note that your username and
password are sent in plaintext. The auth header is added to the
additional_headers dictionary in the service object.
Args:
service: atom.AtomService or a subclass which has an
additional_headers dict as a member.
username: str
password: str
"""
deprecation('calling deprecated function UseBasicAuth')
base_64_string = base64.encodestring('%s:%s' % (username, password))
base_64_string = base_64_string.strip()
if for_proxy:
header_name = 'Proxy-Authorization'
else:
header_name = 'Authorization'
service.additional_headers[header_name] = 'Basic %s' % (base_64_string,)
def ProcessUrl(service, url, for_proxy=False):
"""Processes a passed URL. If the URL does not begin with https?, then
the default value for server is used
This method is deprecated, use atom.url.parse_url instead.
"""
if not isinstance(url, atom.url.Url):
url = atom.url.parse_url(url)
server = url.host
ssl = False
port = 80
if not server:
if hasattr(service, 'server'):
server = service.server
else:
server = service
if not url.protocol and hasattr(service, 'ssl'):
ssl = service.ssl
if hasattr(service, 'port'):
port = service.port
else:
if url.protocol == 'https':
ssl = True
elif url.protocol == 'http':
ssl = False
if url.port:
port = int(url.port)
elif port == 80 and ssl:
port = 443
return (server, port, ssl, url.get_request_uri())
def DictionaryToParamList(url_parameters, escape_params=True):
"""Convert a dictionary of URL arguments into a URL parameter string.
This function is deprcated, use atom.url.Url instead.
Args:
url_parameters: The dictionaty of key-value pairs which will be converted
into URL parameters. For example,
{'dry-run': 'true', 'foo': 'bar'}
will become ['dry-run=true', 'foo=bar'].
Returns:
A list which contains a string for each key-value pair. The strings are
ready to be incorporated into a URL by using '&'.join([] + parameter_list)
"""
# Choose which function to use when modifying the query and parameters.
# Use quote_plus when escape_params is true.
transform_op = [str, urllib.parse.quote_plus][bool(escape_params)]
# Create a list of tuples containing the escaped version of the
# parameter-value pairs.
parameter_tuples = [(transform_op(param), transform_op(value))
for param, value in list((url_parameters or {}).items())]
# Turn parameter-value tuples into a list of strings in the form
# 'PARAMETER=VALUE'.
return ['='.join(x) for x in parameter_tuples]
def BuildUri(uri, url_params=None, escape_params=True):
"""Converts a uri string and a collection of parameters into a URI.
This function is deprcated, use atom.url.Url instead.
Args:
uri: string
url_params: dict (optional)
escape_params: boolean (optional)
uri: string The start of the desired URI. This string can alrady contain
URL parameters. Examples: '/base/feeds/snippets',
'/base/feeds/snippets?bq=digital+camera'
url_parameters: dict (optional) Additional URL parameters to be included
in the query. These are translated into query arguments
in the form '&dict_key=value&...'.
Example: {'max-results': '250'} becomes &max-results=250
escape_params: boolean (optional) If false, the calling code has already
ensured that the query will form a valid URL (all
reserved characters have been escaped). If true, this
method will escape the query and any URL parameters
provided.
Returns:
string The URI consisting of the escaped URL parameters appended to the
initial uri string.
"""
# Prepare URL parameters for inclusion into the GET request.
parameter_list = DictionaryToParamList(url_params, escape_params)
# Append the URL parameters to the URL.
if parameter_list:
if uri.find('?') != -1:
# If there are already URL parameters in the uri string, add the
# parameters after a new & character.
full_uri = '&'.join([uri] + parameter_list)
else:
# The uri string did not have any URL parameters (no ? character)
# so put a ? between the uri and URL parameters.
full_uri = '%s%s' % (uri, '?%s' % ('&'.join([] + parameter_list)))
else:
full_uri = uri
return full_uri
def HttpRequest(service, operation, data, uri, extra_headers=None,
url_params=None, escape_params=True, content_type='application/atom+xml'):
"""Performs an HTTP call to the server, supports GET, POST, PUT, and DELETE.
This method is deprecated, use atom.http.HttpClient.request instead.
Usage example, perform and HTTP GET on http://www.google.com/:
import atom.service
client = atom.service.AtomService()
http_response = client.Get('http://www.google.com/')
or you could set the client.server to 'www.google.com' and use the
following:
client.server = 'www.google.com'
http_response = client.Get('/')
Args:
service: atom.AtomService object which contains some of the parameters
needed to make the request. The following members are used to
construct the HTTP call: server (str), additional_headers (dict),
port (int), and ssl (bool).
operation: str The HTTP operation to be performed. This is usually one of
'GET', 'POST', 'PUT', or 'DELETE'
data: ElementTree, filestream, list of parts, or other object which can be
converted to a string.
Should be set to None when performing a GET or PUT.
If data is a file-like object which can be read, this method will read
a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be evaluated
and sent.
uri: The beginning of the URL to which the request should be sent.
Examples: '/', '/base/feeds/snippets',
'/m8/feeds/contacts/default/base'
extra_headers: dict of strings. HTTP headers which should be sent
in the request. These headers are in addition to those stored in
service.additional_headers.
url_params: dict of strings. Key value pairs to be added to the URL as
URL parameters. For example {'foo':'bar', 'test':'param'} will
become ?foo=bar&test=param.
escape_params: bool default True. If true, the keys and values in
url_params will be URL escaped when the form is constructed
(Special characters converted to %XX form.)
content_type: str The MIME type for the data being sent. Defaults to
'application/atom+xml', this is only used if data is set.
"""
deprecation('call to deprecated function HttpRequest')
full_uri = BuildUri(uri, url_params, escape_params)
(connection, full_uri) = PrepareConnection(service, full_uri)
if extra_headers is None:
extra_headers = {}
# Turn on debug mode if the debug member is set.
if service.debug:
connection.debuglevel = 1
connection.putrequest(operation, full_uri)
# If the list of headers does not include a Content-Length, attempt to
# calculate it based on the data object.
if (data and 'Content-Length' not in service.additional_headers and
'Content-Length' not in extra_headers):
content_length = CalculateDataLength(data)
if content_length:
extra_headers['Content-Length'] = str(content_length)
if content_type:
extra_headers['Content-Type'] = content_type
# Send the HTTP headers.
if isinstance(service.additional_headers, dict):
for header in service.additional_headers:
connection.putheader(header, service.additional_headers[header])
if isinstance(extra_headers, dict):
for header in extra_headers:
connection.putheader(header, extra_headers[header])
connection.endheaders()
# If there is data, send it in the request.
if data:
if isinstance(data, list):
for data_part in data:
__SendDataPart(data_part, connection)
else:
__SendDataPart(data, connection)
# Return the HTTP Response from the server.
return connection.getresponse()
def __SendDataPart(data, connection):
"""This method is deprecated, use atom.http._send_data_part"""
deprecated('call to deprecated function __SendDataPart')
if isinstance(data, str):
# TODO add handling for unicode.
connection.send(data)
return
elif ElementTree.iselement(data):
connection.send(ElementTree.tostring(data))
return
# Check to see if data is a file-like object that has a read method.
elif hasattr(data, 'read'):
# Read the file and send it a chunk at a time.
while 1:
binarydata = data.read(100000)
if binarydata == '': break
connection.send(binarydata)
return
else:
# The data object was not a file.
# Try to convert to a string and send the data.
connection.send(str(data))
return
def CalculateDataLength(data):
"""Attempts to determine the length of the data to send.
This method will respond with a length only if the data is a string or
and ElementTree element.
Args:
data: object If this is not a string or ElementTree element this funtion
will return None.
"""
if isinstance(data, str):
return len(data)
elif isinstance(data, list):
return None
elif ElementTree.iselement(data):
return len(ElementTree.tostring(data))
elif hasattr(data, 'read'):
# If this is a file-like object, don't try to guess the length.
return None
else:
return len(str(data).encode('utf-8'))
def deprecation(message):
warnings.warn(message, DeprecationWarning, stacklevel=2)

105
src/gam/atom/token_store.py Normal file
View File

@@ -0,0 +1,105 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
"""This module provides a TokenStore class which is designed to manage
auth tokens required for different services.
Each token is valid for a set of scopes which is the start of a URL. An HTTP
client will use a token store to find a valid Authorization header to send
in requests to the specified URL. If the HTTP client determines that a token
has expired or been revoked, it can remove the token from the store so that
it will not be used in future requests.
"""
# __author__ = 'api.jscudder (Jeff Scudder)'
import atom.http_interface
import atom.url
SCOPE_ALL = 'http'
class TokenStore(object):
"""Manages Authorization tokens which will be sent in HTTP headers."""
def __init__(self, scoped_tokens=None):
self._tokens = scoped_tokens or {}
def add_token(self, token):
"""Adds a new token to the store (replaces tokens with the same scope).
Args:
token: A subclass of http_interface.GenericToken. The token object is
responsible for adding the Authorization header to the HTTP request.
The scopes defined in the token are used to determine if the token
is valid for a requested scope when find_token is called.
Returns:
True if the token was added, False if the token was not added becase
no scopes were provided.
"""
if not hasattr(token, 'scopes') or not token.scopes:
return False
for scope in token.scopes:
self._tokens[str(scope)] = token
return True
def find_token(self, url):
"""Selects an Authorization header token which can be used for the URL.
Args:
url: str or atom.url.Url or a list containing the same.
The URL which is going to be requested. All
tokens are examined to see if any scopes begin match the beginning
of the URL. The first match found is returned.
Returns:
The token object which should execute the HTTP request. If there was
no token for the url (the url did not begin with any of the token
scopes available), then the atom.http_interface.GenericToken will be
returned because the GenericToken calls through to the http client
without adding an Authorization header.
"""
if url is None:
return None
if isinstance(url, str):
url = atom.url.parse_url(url)
if url in self._tokens:
token = self._tokens[url]
if token.valid_for_scope(url):
return token
else:
del self._tokens[url]
for scope, token in self._tokens.items():
if token.valid_for_scope(url):
return token
return atom.http_interface.GenericToken()
def remove_token(self, token):
"""Removes the token from the token_store.
This method is used when a token is determined to be invalid. If the
token was found by find_token, but resulted in a 401 or 403 error stating
that the token was invlid, then the token should be removed to prevent
future use.
Returns:
True if a token was found and then removed from the token
store. False if the token was not in the TokenStore.
"""
token_found = False
scopes_to_delete = []
for scope, stored_token in self._tokens.items():
if stored_token == token:
scopes_to_delete.append(scope)
token_found = True
for scope in scopes_to_delete:
del self._tokens[scope]
return token_found
def remove_all_tokens(self):
self._tokens = {}

130
src/gam/atom/url.py Normal file
View File

@@ -0,0 +1,130 @@
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License 2.0;
# __author__ = 'api.jscudder (Jeff Scudder)'
import urllib.error
import urllib.parse
import urllib.parse
import urllib.request
DEFAULT_PROTOCOL = 'http'
DEFAULT_PORT = 80
def parse_url(url_string):
"""Creates a Url object which corresponds to the URL string.
This method can accept partial URLs, but it will leave missing
members of the Url unset.
"""
parts = urllib.parse.urlparse(url_string)
url = Url()
if parts[0]:
url.protocol = parts[0]
if parts[1]:
host_parts = parts[1].split(':')
if host_parts[0]:
url.host = host_parts[0]
if len(host_parts) > 1:
url.port = host_parts[1]
if parts[2]:
url.path = parts[2]
if parts[4]:
param_pairs = parts[4].split('&')
for pair in param_pairs:
pair_parts = pair.split('=')
if len(pair_parts) > 1:
url.params[urllib.parse.unquote_plus(pair_parts[0])] = (
urllib.parse.unquote_plus(pair_parts[1]))
elif len(pair_parts) == 1:
url.params[urllib.parse.unquote_plus(pair_parts[0])] = None
return url
class Url(object):
"""Represents a URL and implements comparison logic.
URL strings which are not identical can still be equivalent, so this object
provides a better interface for comparing and manipulating URLs than
strings. URL parameters are represented as a dictionary of strings, and
defaults are used for the protocol (http) and port (80) if not provided.
"""
def __init__(self, protocol=None, host=None, port=None, path=None,
params=None):
self.protocol = protocol
self.host = host
self.port = port
self.path = path
self.params = params or {}
def to_string(self):
url_parts = ['', '', '', '', '', '']
if self.protocol:
url_parts[0] = self.protocol
if self.host:
if self.port:
url_parts[1] = ':'.join((self.host, str(self.port)))
else:
url_parts[1] = self.host
if self.path:
url_parts[2] = self.path
if self.params:
url_parts[4] = self.get_param_string()
return urllib.parse.urlunparse(url_parts)
def get_param_string(self):
param_pairs = []
for key, value in self.params.items():
param_pairs.append('='.join((urllib.parse.quote_plus(key),
urllib.parse.quote_plus(str(value)))))
return '&'.join(param_pairs)
def get_request_uri(self):
"""Returns the path with the parameters escaped and appended."""
param_string = self.get_param_string()
if param_string:
return '?'.join([self.path, param_string])
else:
return self.path
def __cmp__(self, other):
if not isinstance(other, Url):
return cmp(self.to_string(), str(other))
difference = 0
# Compare the protocol
if self.protocol and other.protocol:
difference = cmp(self.protocol, other.protocol)
elif self.protocol and not other.protocol:
difference = cmp(self.protocol, DEFAULT_PROTOCOL)
elif not self.protocol and other.protocol:
difference = cmp(DEFAULT_PROTOCOL, other.protocol)
if difference != 0:
return difference
# Compare the host
difference = cmp(self.host, other.host)
if difference != 0:
return difference
# Compare the port
if self.port and other.port:
difference = cmp(self.port, other.port)
elif self.port and not other.port:
difference = cmp(self.port, DEFAULT_PORT)
elif not self.port and other.port:
difference = cmp(DEFAULT_PORT, other.port)
if difference != 0:
return difference
# Compare the path
difference = cmp(self.path, other.path)
if difference != 0:
return difference
# Compare the parameters
return cmp(self.params, other.params)
def __str__(self):
return self.to_string()

1130
src/gam/cacerts.pem Normal file

File diff suppressed because it is too large Load Diff

593
src/gam/cbcm-v1.1beta1.json Normal file
View File

@@ -0,0 +1,593 @@
{
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers": {
"description": "View and manage your Chrome browsers registered with Cloud Management"
},
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly": {
"description": "View your Chrome browsers registered with Cloud Management"
}
}
}
},
"basePath": "",
"baseUrl": "https://admin.googleapis.com/admin/directory/v1.1beta1/customer/",
"batchPath": "batch",
"canonicalName": "cbcm",
"discoveryVersion": "v1",
"documentationLink": "https://support.google.com/chrome/a/answer/9681204",
"fullyEncodeReservedExpansion": true,
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"id": "cbcm:v1.1beta1",
"kind": "discovery#restDescription",
"mtlsRootUrl": "https://admin.mtls.googleapis.com/",
"name": "cbcm",
"ownerDomain": "google.com",
"ownerName": "Jay Lee",
"packagePath": "cbcm",
"parameters": {
"$.xgafv": {
"description": "V1 error format.",
"enum": [
"1",
"2"
],
"enumDescriptions": [
"v1 error format",
"v2 error format"
],
"location": "query",
"type": "string"
},
"access_token": {
"description": "OAuth access token.",
"location": "query",
"type": "string"
},
"alt": {
"default": "json",
"description": "Data format for response.",
"enum": [
"json",
"media",
"proto"
],
"enumDescriptions": [
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location": "query",
"type": "string"
},
"callback": {
"description": "JSONP",
"location": "query",
"type": "string"
},
"fields": {
"description": "Selector specifying which fields to include in a partial response.",
"location": "query",
"type": "string"
},
"key": {
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query",
"type": "string"
},
"oauth_token": {
"description": "OAuth 2.0 token for the current user.",
"location": "query",
"type": "string"
},
"prettyPrint": {
"default": "true",
"description": "Returns response with indentations and line breaks.",
"location": "query",
"type": "boolean"
},
"quotaUser": {
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location": "query",
"type": "string"
},
"uploadType": {
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location": "query",
"type": "string"
},
"upload_protocol": {
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\").",
"location": "query",
"type": "string"
}
},
"protocol": "rest",
"resources": {
"chromebrowsers": {
"methods": {
"delete": {
"description": "Deletes a browser.",
"flatPath": "{customer}/devices/chromebrowsers/{deviceId}",
"httpMethod": "DELETE",
"id": "cbcm.chromebrowsers.delete",
"parameterOrder": [
"customer",
"deviceId"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"deviceId": {
"description": "Immutable ID of the browser.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "{customer}/devices/chromebrowsers/{deviceId}",
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"
]
},
"get": {
"description": "Retrieves a browser.",
"flatPath": "{customer}/devices/chromebrowsers/{deviceId}",
"httpMethod": "GET",
"id": "cbcm.chromebrowsers.get",
"parameterOrder": [
"customer",
"deviceId"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"deviceId": {
"description": "Immutable ID of the browser.",
"location": "path",
"required": true,
"type": "string"
},
"projection": {
"description": "Restrict information returned to a set of selected fields. FULL or BASIC.",
"location": "query",
"type": "string"
}
},
"path": "{customer}/devices/chromebrowsers/{deviceId}",
"response": {
"$ref": "ChromeBrowser"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers",
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly"
]
},
"list": {
"description": "Retrieves a paginated list of all the browsers in a domain.",
"flatPath": "{customer}/devices/chromebrowsers",
"httpMethod": "GET",
"id": "cbcm.chromebrowsers.list",
"parameterOrder": [
"customer"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"maxResults": {
"description": "Maximum number of results to return.",
"format": "int32",
"location": "query",
"maximum": "100",
"minimum": "1",
"type": "integer"
},
"orderBy": {
"description": "property to use for sorting results.",
"location": "query",
"type": "string"
},
"orgUnitPath": {
"description": "The full path of the organizational unit or its unique ID.",
"location": "query",
"type": "string"
},
"pageToken": {
"description": "Token to specify the next page in the list.",
"location": "query",
"type": "string"
},
"projection": {
"description": "Restrict information returned to a set of selected fields. FULL or BASIC.",
"location": "query",
"type": "string"
},
"query": {
"description": "Search string using the list page query language.",
"location": "query",
"type": "string"
},
"sortOrder": {
"description": "Whether to return results in ascending or descending order. Must be used with the orderBy parameter.",
"location": "query",
"type": "string"
}
},
"path": "{customer}/devices/chromebrowsers",
"response": {
"$ref": "ChromeBrowsers"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers",
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly"
]
},
"moveChromeBrowsersToOu": {
"description": "Move Chrome Browsers Device between Organization Units",
"flatPath": "{customer}/devices/chromebrowsers/moveChromeBrowsersToOu",
"httpMethod": "POST",
"id": "cbcm.chromebrowsers.moveChromeBrowsersToOu",
"parameterOrder": [
"customer"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "{customer}/devices/chromebrowsers/moveChromeBrowsersToOu",
"request": {
"$ref": "MoveChromeBrowsersRequest"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"
]
},
"update": {
"description": "Updates a browser.",
"flatPath": "{customer}/devices/chromebrowsers/{deviceId}",
"httpMethod": "PUT",
"id": "cbcm.chromebrowsers.update",
"parameterOrder": [
"customer",
"deviceId"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"deviceId": {
"description": "Immutable ID of the browser.",
"location": "path",
"required": true,
"type": "string"
},
"projection": {
"description": "BASIC or FULL",
"location": "query",
"type": "string"
}
},
"path": "{customer}/devices/chromebrowsers/{deviceId}",
"request": {
"$ref": "ChromeBrowser"
},
"response": {
"$ref": "ChromeBrowser"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"
]
}
}
},
"enrollmentTokens": {
"methods": {
"list": {
"description": "Retrieves a paginated list of all the browser entollment tokens in a domain.",
"flatPath": "{customer}/chrome/enrollmentTokens",
"httpMethod": "GET",
"id": "cbcm.enrollmentTokens.list",
"parameterOrder": [
"customer"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"pageSize": {
"description": "Maximum number of results to return.",
"format": "int32",
"location": "query",
"maximum": "100",
"minimum": "1",
"type": "integer"
},
"orgUnitPath": {
"description": "The full path of the organizational unit or its unique ID.",
"location": "query",
"type": "string"
},
"pageToken": {
"description": "Token to specify the next page in the list.",
"location": "query",
"type": "string"
},
"query": {
"description": "Search string using the list page query language.",
"location": "query",
"type": "string"
}
},
"path": "{customer}/chrome/enrollmentTokens",
"response": {
"$ref": "EnrollmentTokens"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers",
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly"
]
},
"create": {
"description": "Creates a browser enrollment token in a domain.",
"flatPath": "{customer}/chrome/enrollmentTokens",
"httpMethod": "POST",
"id": "cbcm.enrollmentTokens.create",
"parameterOrder": [
"customer"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "{customer}/chrome/enrollmentTokens",
"request": {
"$ref": "CreateEnrollmentTokenRequest"
},
"response": {
"$ref": "EnrollmentToken"
},
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"
]
},
"revoke": {
"description": "Revokes a browser enrollment token in a domain.",
"flatPath": "{customer}/chrome/enrollmentTokens/{tokenPermanentId}:revoke",
"httpMethod": "POST",
"id": "cbcm.enrollmentTokens.revoke",
"parameterOrder": [
"customer",
"tokenPermanentId"
],
"parameters": {
"customer": {
"description": "Immutable ID of the G Suite account.",
"location": "path",
"required": true,
"type": "string"
},
"tokenPermanentId": {
"description": "Unique identifier for an enrollment token.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "{customer}/chrome/enrollmentTokens/{tokenPermanentId}:revoke",
"scopes": [
"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"
]
}
}
}
},
"revision": "20201203",
"rootUrl": "https://admin.googleapis.com/admin/directory/v1.1beta1/customer/",
"schemas": {
"ChromeBrowser": {
"id": "ChromeBrowser",
"properties": {
"annotatedAssetId": {
"description": "Asset identifier as annotated by the administrator or specified during enrollment.",
"type": "string"
},
"annotatedLocation": {
"description": "Address or location of the device as annotated by the administrator.",
"type": "string"
},
"annotatedNotes": {
"description": "Notes about this device as annotated by the administrator",
"type": "string"
},
"annotatedUser": {
"description": "User of the device as annotated by the administrator.",
"type": "string"
},
"deviceId": {
"annotations": {
"required": [
"cbcm.chromebrowsers.update"
]
},
"description": "The unique ID of the device.",
"type": "string"
}
},
"type": "object"
},
"ChromeBrowsers": {
"id": "ChromeBrowsers",
"properties": {
"browsers": {
"description": "List of Chrome browser objects.",
"items": {
"$ref": "ChromeBrowser"
},
"type": "array"
},
"etag": {
"description": "ETag of the resource.",
"type": "string"
},
"kind": {
"default": "admin#directory#chromeosdevices",
"description": "Kind of resource this is.",
"type": "string"
},
"nextPageToken": {
"description": "Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"type": "string"
}
},
"type": "object"
},
"EnrollmentToken": {
"id": "EnrollmentToken",
"properties": {
"kind": {
"default": "admin#directory#chromeEnrollmentToken",
"description": "Kind of resource this is.",
"type": "string"
},
"tokenId": {
"description": "Enrollment Token ID.",
"type": "string"
},
"tokenPermanentId": {
"description": "Enrollment Token Permanent ID.",
"type": "string"
},
"customerId": {
"description": "Immutable ID of the G Suite account.",
"type": "string"
},
"orgUnitPath": {
"description": "The full path of the organizational unit or its unique ID.",
"type": "string"
},
"creatorId": {
"description": "Creator ID.",
"type": "string"
},
"createTime": {
"description": "Creation Time.",
"type": "string"
},
"revokerId": {
"description": "Revoker ID.",
"type": "string"
},
"revokeTime": {
"description": "Revoke Time",
"type": "string"
}
},
"type": "object"
},
"EnrollmentTokens": {
"id": "EnrollmentTokens",
"properties": {
"chrome_enrollment_tokens": {
"description": "List of Chrome browser enrollment token objects.",
"items": {
"$ref": "EnrollmentToken"
},
"type": "array"
},
"kind": {
"default": "admin#directory#chromeEnrollmentTokens",
"description": "Kind of resource this is.",
"type": "string"
},
"nextPageToken": {
"description": "Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"type": "string"
}
},
"type": "object"
},
"CreateEnrollmentTokenRequest": {
"id": "CreateEnrollmentTokenRequest",
"properties": {
"org_unit_path": {
"description": "The full path of the organizational unit or its unique ID.",
"type": "string"
},
"expire_time": {
"description": "Expiration Time.",
"type": "string"
},
"token_type": {
"id": "token_type",
"annotations": {
"required": [
"cbcm.enrollmentTokens.create"
]
},
"description": "CHROME_BROWSER.",
"type": "string"
}
}
},
"MoveChromeBrowsersRequest": {
"id": "MoveChromeBrowsersRequest",
"type": "object",
"properties": {
"org_unit_path": {
"annotations": {
"required": [
"cbcm.chromebrowsers.moveChromeBrowsersToOu"
]
},
"description": "Destination organization unit to move devices to. Full path of the organizational unit or its ID prefixed with id:",
"type": "string"
},
"resource_ids": {
"annotations": {
"required": [
"cbcm.chromebrowsers.moveChromeBrowsersToOu"
]
},
"description": "List of unique device IDs of Chrome Browser Devices to move. A maximum of 600 browsers may be moved per request.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"servicePath": "",
"title": "Admin SDK API",
"version": "cbcm_v1.1beta1"
}

View File

@@ -0,0 +1,249 @@
{
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/admin.contact.delegation": {
"description": "View and manage your Contact Delegation"
},
"https://www.googleapis.com/auth/admin.contact.delegation.readonly": {
"description": "View your Contact Delegation"
}
}
}
},
"basePath": "",
"baseUrl": "https://admin.googleapis.com/admin/contacts/v1/",
"batchPath": "batch",
"canonicalName": "contactdelegation",
"description": "The Contact Delegation API allows Admins to delegate access of one user's, called the delegator, contacts to another user, called the delegate.",
"discoveryVersion": "v1",
"documentationLink": "https://developers.google.com/admin-sdk/contact-delegation",
"fullyEncodeReservedExpansion": true,
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"id": "contactdelegation:v1",
"kind": "discovery#restDescription",
"name": "contactdelegation",
"ownerDomain": "google.com",
"ownerName": "Google",
"packagePath": "admin",
"parameters": {
"$.xgafv": {
"description": "V1 error format.",
"enum": [
"1",
"2"
],
"enumDescriptions": [
"v1 error format",
"v2 error format"
],
"location": "query",
"type": "string"
},
"access_token": {
"description": "OAuth access token.",
"location": "query",
"type": "string"
},
"alt": {
"default": "json",
"description": "Data format for response.",
"enum": [
"json",
"media",
"proto"
],
"enumDescriptions": [
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location": "query",
"type": "string"
},
"callback": {
"description": "JSONP",
"location": "query",
"type": "string"
},
"fields": {
"description": "Selector specifying which fields to include in a partial response.",
"location": "query",
"type": "string"
},
"key": {
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query",
"type": "string"
},
"oauth_token": {
"description": "OAuth 2.0 token for the current user.",
"location": "query",
"type": "string"
},
"prettyPrint": {
"default": "true",
"description": "Returns response with indentations and line breaks.",
"location": "query",
"type": "boolean"
},
"quotaUser": {
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location": "query",
"type": "string"
},
"uploadType": {
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location": "query",
"type": "string"
},
"upload_protocol": {
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\").",
"location": "query",
"type": "string"
}
},
"protocol": "rest",
"resources": {
"delegates": {
"methods": {
"create": {
"description": "Creates a contact delegations",
"flatPath": "users/{user}/delegates",
"httpMethod": "POST",
"id": "contactdelegations.delegates.create",
"parameterOrder": [
"user"
],
"parameters": {
"user": {
"description": "Email address of the delegator.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "users/{user}/delegates/{delegate}",
"request": {
"$ref": "Delegate"
},
"scopes": [
"https://www.googleapis.com/auth/admin.contact.delegation"
]
},
"delete": {
"description": "Deletes a contact delegation.",
"flatPath": "users/{user}/delegates/{delegate}",
"httpMethod": "DELETE",
"id": "contactdelegations.delegates.delete",
"parameterOrder": [
"user",
"delegate"
],
"parameters": {
"delegate": {
"description": "Email address of the delegate",
"location": "path",
"required": true,
"type": "string"
},
"user": {
"description": "Email address of the delegator.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "users/{user}/delegates/{delegate}",
"scopes": [
"https://www.googleapis.com/auth/admin.contact.delegation"
]
},
"list": {
"description": "Lists contact delegates for a user",
"flatPath": "users/{user}/delegates",
"httpMethod": "GET",
"id": "contactdelegations.delegates.list",
"parameterOrder": [
"user"
],
"parameters": {
"pageSize": {
"description": "Determines how many delegates are returned in each response. ",
"format": "int32",
"location": "query",
"minimum": "1",
"type": "integer"
},
"pageToken": {
"description": "Token to specify the next page in the list.",
"location": "query",
"type": "string"
},
"user": {
"description": "Email address of the delegator.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "users/{user}/delegates",
"response": {
"$ref": "Delegates"
},
"scopes": [
"https://www.googleapis.com/auth/admin.contact.delegation",
"https://www.googleapis.com/auth/admin.contact.delegation.readonly"
]
}
}
}
},
"rootUrl": "https://admin.googleapis.com/admin/contacts/v1/",
"schemas": {
"Delegate": {
"description": "JSON template for a delegate.",
"id": "Delegate",
"properties": {
"email": {
"description": "Email of the delegate.",
"type": "string"
}
},
"type": "object"
},
"Delegates": {
"id": "Delegates",
"properties": {
"delegates": {
"description": "List of delegates.",
"items": {
"$ref": "Delegate"
},
"type": "array"
},
"etag": {
"description": "ETag of the resource.",
"type": "string"
},
"kind": {
"default": "",
"description": "Kind of resource this is.",
"type": "string"
},
"nextPageToken": {
"description": "Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"type": "string"
}
},
"type": "object"
}
},
"servicePath": "",
"title": "Contact Delegation API",
"version": "v1",
"version_module": true
}

486
src/gam/datastudio-v1.json Normal file
View File

@@ -0,0 +1,486 @@
{
"basePath": "",
"discoveryVersion": "v1",
"documentationLink": "https://support.google.com/datastudio",
"canonicalName": "Data Studio",
"id": "datastudio:v1",
"ownerName": "Google",
"description": "Allows programmatic viewing and editing of Data Studio assets.",
"rootUrl": "https://datastudio.googleapis.com/",
"ownerDomain": "google.com",
"mtlsRootUrl": "https://datastudio.mtls.googleapis.com/",
"batchPath": "batch",
"version_module": true,
"version": "v1",
"schemas": {
"Asset": {
"id": "Asset",
"properties": {
"title": {
"description": "The title of the asset.",
"type": "string"
},
"createTime": {
"format": "google-datetime",
"description": "Date the asset was created.",
"type": "string"
},
"lastViewByMeTime": {
"type": "string",
"description": "Date the asset was last viewed by me.",
"format": "google-datetime"
},
"owner": {
"type": "string",
"description": "The owner of the asset."
},
"name": {
"type": "string",
"description": "The name of the asset."
},
"trashed": {
"type": "boolean",
"description": "Value indicating if the asset is in the trash."
},
"updateTime": {
"format": "google-datetime",
"description": "Date the asset was last modified.",
"type": "string"
},
"updateByMeTime": {
"description": "Date the asset was last modified by me.",
"type": "string",
"format": "google-datetime"
},
"assetType": {
"enumDescriptions": [
"Asset type not specified.",
"A report asset.",
"A data Source asset."
],
"enum": [
"ASSET_TYPE_UNSPECIFIED",
"REPORT",
"DATA_SOURCE"
],
"description": "The type of the asset.",
"type": "string"
}
},
"description": "A Data Studio asset.",
"type": "object"
},
"SearchAssetsResponse": {
"id": "SearchAssetsResponse",
"properties": {
"assets": {
"items": {
"$ref": "Asset"
},
"type": "array",
"description": "The list of assets."
},
"nextPageToken": {
"type": "string",
"description": "A token to retrieve next page of results. Pass this value in the SearchAssetsRequest.page_token field in the subsequent call to `SearchAssets` method to retrieve the next page of results."
}
},
"description": "Response message for DataStudioService.SearchAssets",
"type": "object"
},
"UpdatePermissionsRequest": {
"description": "Request message for DataStudioService.UpdatePermissions",
"properties": {
"updateMask": {
"description": "The list of fields to be updated. Currently not supported.",
"type": "string",
"format": "google-fieldmask"
},
"permissions": {
"description": "The permissions object to update.",
"$ref": "Permissions"
}
},
"id": "UpdatePermissionsRequest",
"type": "object"
},
"AddMembersRequest": {
"properties": {
"members": {
"type": "array",
"items": {
"type": "string"
},
"description": "Required. The members to add to the role. The format of a member is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com"
},
"role": {
"type": "string",
"enumDescriptions": [
"Role not specified.",
"A viewer.",
"An editor.",
"An owner.",
"Link shared viewer.",
"Link shared editor."
],
"enum": [
"ROLE_UNSPECIFIED",
"VIEWER",
"EDITOR",
"OWNER",
"LINK_VIEWER",
"LINK_EDITOR"
],
"description": "Required. The role to add members to."
}
},
"type": "object",
"id": "AddMembersRequest",
"description": "Request message for DataStudioService.AddMembers"
},
"Permissions": {
"type": "object",
"id": "Permissions",
"description": "A Data Studio asset's Permissions.",
"properties": {
"permissions": {
"description": "A map from a Role to a list of members. Role is a string representation of the Role enum. One of: - OWNER - EDITOR - VIEWER",
"additionalProperties": {
"$ref": "Members"
},
"type": "object"
},
"etag": {
"format": "byte",
"description": "etag to detect and fail concurrent modifications",
"type": "string"
}
}
},
"RevokeAllPermissionsRequest": {
"description": "Request message for DataStudioService.RevokeAllPermissions",
"id": "RevokeAllPermissionsRequest",
"type": "object",
"properties": {
"members": {
"description": "Required. The members that are having their access revoked. The format of a member is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com",
"items": {
"type": "string"
},
"type": "array"
}
}
},
"Members": {
"description": "A wrapper message for a list of members.",
"properties": {
"members": {
"description": "Format of string is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com",
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object",
"id": "Members"
}
},
"name": "datastudio",
"protocol": "rest",
"baseUrl": "https://datastudio.googleapis.com/",
"title": "Data Studio API",
"revision": "20210412",
"fullyEncodeReservedExpansion": true,
"icons": {
"x32": "http://www.google.com/images/icons/product/search-32.gif",
"x16": "http://www.google.com/images/icons/product/search-16.gif"
},
"parameters": {
"quotaUser": {
"location": "query",
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"type": "string"
},
"prettyPrint": {
"location": "query",
"type": "boolean",
"description": "Returns response with indentations and line breaks.",
"default": "true"
},
"callback": {
"location": "query",
"type": "string",
"description": "JSONP"
},
"uploadType": {
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"type": "string",
"location": "query"
},
"upload_protocol": {
"type": "string",
"location": "query",
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\")."
},
"$.xgafv": {
"enumDescriptions": [
"v1 error format",
"v2 error format"
],
"description": "V1 error format.",
"location": "query",
"type": "string",
"enum": [
"1",
"2"
]
},
"oauth_token": {
"type": "string",
"location": "query",
"description": "OAuth 2.0 token for the current user."
},
"alt": {
"type": "string",
"enum": [
"json",
"media",
"proto"
],
"location": "query",
"description": "Data format for response.",
"enumDescriptions": [
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"default": "json"
},
"fields": {
"description": "Selector specifying which fields to include in a partial response.",
"location": "query",
"type": "string"
},
"access_token": {
"type": "string",
"description": "OAuth access token.",
"location": "query"
},
"key": {
"type": "string",
"location": "query",
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token."
}
},
"servicePath": "",
"kind": "discovery#restDescription",
"resources": {
"assets": {
"methods": {
"getPermissions": {
"parameters": {
"name": {
"type": "string",
"location": "path",
"description": "Required. The name of the asset.",
"required": true
},
"role": {
"enumDescriptions": [
"Role not specified.",
"A viewer.",
"An editor.",
"An owner.",
"Link shared viewer.",
"Link shared editor."
],
"type": "string",
"location": "query",
"description": "The role of the permssion.",
"enum": [
"ROLE_UNSPECIFIED",
"VIEWER",
"EDITOR",
"OWNER",
"LINK_VIEWER",
"LINK_EDITOR"
]
}
},
"id": "datastudio.assets.getPermissions",
"response": {
"$ref": "Permissions"
},
"flatPath": "v1/assets/{name}/permissions",
"path": "v1/assets/{name}/permissions",
"description": "Gets the asset's permission for a given role.",
"parameterOrder": [
"name"
],
"httpMethod": "GET"
},
"updatePermissions": {
"id": "datastudio.assets.updatePermissions",
"parameterOrder": [
"name"
],
"flatPath": "v1/assets/{name}/permissions",
"description": "Updates a permission.",
"request": {
"$ref": "UpdatePermissionsRequest"
},
"path": "v1/assets/{name}/permissions",
"parameters": {
"name": {
"description": "Required. The name of the asset.",
"location": "path",
"type": "string",
"required": true
}
},
"response": {
"$ref": "Permissions"
},
"httpMethod": "PATCH"
},
"get": {
"path": "v1/{+name}",
"id": "datastudio.assets.get",
"parameterOrder": [
"name"
],
"description": "Gets the asset by name.",
"parameters": {
"name": {
"description": "Required. The name of the asset. Format: assets/{asset}",
"location": "path",
"required": true,
"pattern": "^assets/[^/]+$",
"type": "string"
}
},
"flatPath": "v1/assets/{assetsId}",
"response": {
"$ref": "Asset"
},
"httpMethod": "GET"
},
"search": {
"response": {
"$ref": "SearchAssetsResponse"
},
"path": "v1/assets:search",
"parameters": {
"pageToken": {
"type": "string",
"location": "query",
"description": "A token identifying a page of results the server should return. Use the value of SearchAssetsResponse.next_page_token returned from the previous call to `SearchAssets` method."
},
"assetTypes": {
"type": "string",
"repeated": true,
"description": "Exactly one AssetType must be specified.",
"enumDescriptions": [
"Asset type not specified.",
"A report asset.",
"A data Source asset."
],
"location": "query",
"enum": [
"ASSET_TYPE_UNSPECIFIED",
"REPORT",
"DATA_SOURCE"
]
},
"title": {
"description": "The title of assets to include. Not an exact match, works the same as search from the UI.",
"location": "query",
"type": "string"
},
"owner": {
"type": "string",
"location": "query",
"description": "The email of the owner of the asset."
},
"pageSize": {
"description": "Requested page size. If unspecified, server will pick an appropriate default.",
"location": "query",
"type": "integer",
"format": "int32"
},
"orderBy": {
"location": "query",
"description": "How the results should be ordered. Valid options are: - title",
"type": "string"
},
"includeTrashed": {
"location": "query",
"type": "boolean",
"description": "Value indicating if assets in trash should be included."
}
},
"flatPath": "v1/assets:search",
"httpMethod": "GET",
"description": "Searches assets.",
"id": "datastudio.assets.search",
"parameterOrder": []
}
},
"resources": {
"permissions": {
"methods": {
"revokeAllPermissions": {
"path": "v1/assets/{name}/permissions:revokeAllPermissions",
"response": {
"$ref": "Permissions"
},
"flatPath": "v1/assets/{name}/permissions:revokeAllPermissions",
"id": "datastudio.assets.permissions.revokeAllPermissions",
"description": "Revokes one or more members' access to an asset.",
"parameters": {
"name": {
"required": true,
"type": "string",
"location": "path",
"description": "Required. The name of the asset."
}
},
"parameterOrder": [
"name"
],
"httpMethod": "POST",
"request": {
"$ref": "RevokeAllPermissionsRequest"
}
},
"addMembers": {
"path": "v1/assets/{name}/permissions:addMembers",
"parameters": {
"name": {
"required": true,
"location": "path",
"type": "string",
"description": "Required. The name of the asset."
}
},
"httpMethod": "POST",
"parameterOrder": [
"name"
],
"response": {
"$ref": "Permissions"
},
"id": "datastudio.assets.permissions.addMembers",
"request": {
"$ref": "AddMembersRequest"
},
"description": "Adds one or more members to a role.",
"flatPath": "v1/assets/{name}/permissions:addMembers"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

308
src/gam/gamlib/glaction.py Normal file
View File

@@ -0,0 +1,308 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM action processing
"""
class GamAction():
# Keys into NAMES; arbitrary values but must be unique
ACCEPT = 'acpt'
ADD = 'add '
ADD_PREVIEW = 'addp'
APPEND = 'apnd'
APPROVE = 'aprv'
ARCHIVE = 'arch'
BACKUP = 'back'
BLOCK = 'blok'
CANCEL = 'canc'
CANCEL_WIPE = 'canw'
CHECK = 'chek'
CLAIM = 'clai'
CLAIM_OWNERSHIP = 'clow'
CLEAR = 'clea'
CLOSE = 'clos'
COLLECT = 'coll'
COMMENT = 'comm'
COPY = 'copy'
COPY_MERGE = 'copm'
CREATE = 'crea'
CREATE_PREVIEW = 'crep'
CREATE_SHORTCUT = 'crsc'
DEDUP = 'dedu'
DELETE = 'dele'
DELETE_EMPTY = 'delm'
DELETE_PREVIEW = 'delp'
DELETE_SHORTCUT = 'desc'
DEPROVISION = 'depr'
DISABLE = 'disa'
DOWNLOAD = 'down'
DRAFT = 'draf'
EMPTY = 'empt'
ENABLE = 'enbl'
END = 'end '
EXISTS = 'exis'
EXPORT = 'expo'
EXTRACT = 'extr'
GET_COMMAND_RESULT = 'gtcr'
FETCH = 'fetc'
FORWARD = 'forw'
HIDE = 'hide'
IMPORT = 'impo'
INFO = 'info'
INITIALIZE = 'init'
INSERT = 'insr'
INVALIDATE = 'inva'
ISSUE_COMMAND = 'isco'
LIST = 'list'
LOOKUP = 'look'
MERGE = 'merg'
MODIFY = 'modi'
MOVE = 'move'
MOVE_MERGE = 'movm'
NOACTION = 'noac'
NOACTION_PREVIEW = 'noap'
OBLITERATE = 'obli'
PERFORM = 'perf'
PRE_PROVISIONED_DISABLE ='ppdi'
PRE_PROVISIONED_REENABLE ='ppre'
PRINT = 'prin'
PROCESS = 'proc'
PROCESS_PREVIEW = 'prop'
PURGE = 'purg'
RECREATE = 'recr'
REENABLE = 'reen'
REFRESH = 'refr'
RELABEL = 'rela'
REMOVE = 'remo'
REMOVE_PREVIEW = 'remp'
RENAME = 'rena'
REOPEN = 'reop'
REPLACE = 'repl'
REPLACE_DOMAIN = 'repd'
REPORT = 'repo'
RESET_YUBIKEY_PIV = 'rpiv'
RESPOND = 'resp'
RESTORE = 'rest'
RESUBMIT = 'res'
RETAIN = 'reta'
RETRIEVE_DATA = 'retd'
REVOKE = 'revo'
SAVE = 'save'
SEND = 'send'
SENDEMAIL = 'snem'
SET = 'set '
SETUP = 'setu'
SHARE = 'shar'
SHOW = 'show'
SIGNOUT = 'siou'
SKIP = 'skip'
SPAM = 'spam'
SUBMIT = 'subm'
SUSPEND = 'susp'
SYNC = 'sync'
TRANSFER = 'tran'
TRANSFER_OWNERSHIP = 'trow'
TRASH = 'tras'
TURNOFF2SV = 'to2s'
UNDELETE = 'unde'
UNHIDE = 'unhi'
UNSUSPEND = 'unsu'
UNTRASH = 'untr'
UPDATE = 'upda'
UPDATE_MOVE = 'upmo'
UPDATE_OWNER = 'updo'
UPDATE_PREVIEW = 'updp'
UPLOAD = 'uplo'
UNZIP = 'unzi'
USE = 'use '
VERIFY = 'vrfy'
WAITFORMAILBOX = 'wamb'
WATCH = 'watc'
WIPE = 'wipe'
WIPE_PREVIEW = 'wipp'
# Usage:
# ACTION_NAMES[1] n Items - Delete 10 Users
# Item xxx ACTION_NAMES[0] - User xxx Deleted
# These values can be translated into other languages
_NAMES = {
ACCEPT: ['Accepted', 'Accept'],
ADD: ['Added', 'Add'],
ADD_PREVIEW: ['Added (Preview)', 'Add (Preview)'],
APPEND: ['Appended', 'Append'],
APPROVE: ['Approved', 'Approve'],
ARCHIVE: ['Archived', 'Archive'],
BACKUP: ['Backed up', 'Backup'],
BLOCK: ['Blocked', 'Block'],
CANCEL: ['Cancelled', 'Cancel'],
CANCEL_WIPE: ['Wipe Cancelled', 'Cancel Wipe'],
CHECK: ['Checked', 'Check'],
CLAIM: ['Claimed', 'Claim'],
CLAIM_OWNERSHIP: ['Ownership Claimed', 'Claim Ownership'],
CLEAR: ['Cleared', 'Clear'],
CLOSE: ['Closed', 'Close'],
COLLECT: ['Collected', 'Collect'],
COMMENT: ['Commented', 'Comment'],
COPY: ['Copied', 'Copy'],
COPY_MERGE: ['Copied(Merge)', 'Copy(Merge)'],
CREATE: ['Created', 'Create'],
CREATE_PREVIEW: ['Created (Preview)', 'Create (Preview)'],
CREATE_SHORTCUT: ['Created Shortcut', 'Create Shortcut'],
DEDUP: ['Duplicates Deleted', 'Delete Duplicates'],
DELETE: ['Deleted', 'Delete'],
DELETE_EMPTY: ['Deleted', 'Delete Empty'],
DELETE_PREVIEW: ['Deleted (Preview)', 'Delete (Preview)'],
DELETE_SHORTCUT: ['Deleted Shortcut', 'Delete Shortcut'],
DEPROVISION: ['Deprovisioned', 'Deprovision'],
DISABLE: ['Disabled', 'Disable'],
DOWNLOAD: ['Downloaded', 'Download'],
DRAFT: ['Drafted', 'Draft'],
EMPTY: ['Emptied', 'Empty'],
ENABLE: ['Enabled', 'Enable'],
END: ['Ended', 'End'],
EXISTS: ['Exists', 'Exists'],
EXPORT: ['Exported', 'Export'],
EXTRACT: ['Extracted', 'Extract'],
FORWARD: ['Forwarded', 'Forward'],
GET_COMMAND_RESULT: ['Got Command Result', 'Get Command Result'],
HIDE: ['Hidden', 'Hide'],
IMPORT: ['Imported', 'Import'],
INFO: ['Shown', 'Show Info'],
INITIALIZE: ['Initialized', 'Initialize'],
INSERT: ['Inserted', 'Insert'],
INVALIDATE: ['Invalidated', 'Invalidate'],
ISSUE_COMMAND: ['Command Issued', 'Issue Command'],
LIST: ['Listed', 'List'],
LOOKUP: ['Lookedup', 'Lookup'],
MERGE: ['Merged', 'Merge'],
MODIFY: ['Modified', 'Modify'],
MOVE: ['Moved', 'Move'],
MOVE_MERGE: ['Moved(Merge)', 'Move(Merge)'],
NOACTION: ['No Action', 'No Action'],
NOACTION_PREVIEW: ['No Action (Preview)', 'No Action (Preview)'],
OBLITERATE: ['Obliterated', 'Obliterate'],
PERFORM: ['Action Performed', 'Perform Action'],
PRE_PROVISIONED_DISABLE: ['PreProvisioned Disabled', 'PreProvisioned Disable'],
PRE_PROVISIONED_REENABLE: ['PreProvisioned Reenabled', 'PreProvisioned Reenable'],
PRINT: ['Printed', 'Print'],
PROCESS: ['Processed', 'Process'],
PROCESS_PREVIEW: ['Processed (Preview)', 'Process (Preview)'],
PURGE: ['Purged', 'Purge'],
RECREATE: ['Recreated', 'Recreate'],
REENABLE: ['Reenabled', 'Reenable'],
REFRESH: ['Refreshed', 'Refresh'],
RELABEL: ['Relabeled', 'Relabel'],
REMOVE: ['Removed', 'Remove'],
REMOVE_PREVIEW: ['Removed (Preview)', 'Remove (Preview)'],
RENAME: ['Renamed', 'Rename'],
REOPEN: ['Reopened', 'Reopen'],
REPLACE: ['Replaced', 'Replace'],
REPLACE_DOMAIN: ['Domain Replaced', 'Replace Domain'],
REPORT: ['Reported', 'Report'],
RESET_YUBIKEY_PIV: ['Yubikey PIV Reset', 'Reset Yubikey PIV'],
RESPOND: ['Responded', 'Respond'],
RESTORE: ['Restored', 'Restore'],
RESUBMIT: ['Resubmitted', 'Resubmit'],
RETAIN: ['Retained', 'Retain'],
RETRIEVE_DATA: ['Data Retrieved', 'Retrieve Data'],
REVOKE: ['Revoked', 'Revoke'],
SAVE: ['Saved', 'Save'],
SEND: ['Sent', 'Send'],
SENDEMAIL: ['Email Sent', 'Send Email'],
SET: ['Set', 'Set'],
SETUP: ['Set Up', 'Set Up'],
SHARE: ['Shared', 'Share'],
SHOW: ['Shown', 'Show'],
SIGNOUT: ['Signed Out', 'Signout'],
SKIP: ['Skipped', 'Skip'],
SPAM: ['Marked as Spam', 'Mark as Spam'],
SUBMIT: ['Submitted', 'Submit'],
SUSPEND: ['Suspended', 'Suspend'],
SYNC: ['Synced', 'Sync'],
TRANSFER: ['Transferred', 'Transfer'],
TRANSFER_OWNERSHIP: ['Ownership Transferred', 'Transfer Ownership'],
TRASH: ['Trashed', 'Trash'],
TURNOFF2SV: ['2-Step Verification Turned Off', 'Turn Off 2-Step Verification'],
UNDELETE: ['Undeleted', 'Undelete'],
UNHIDE: ['Unhidden', 'Unhide'],
UNSUSPEND: ['Unsuspended', 'Unsuspend'],
UNTRASH: ['Untrashed', 'Untrash'],
UNZIP: ['Unzipped', 'Unzip'],
UPDATE: ['Updated', 'Update'],
UPDATE_MOVE: ['Updated/Moved', 'Update/Move'],
UPDATE_OWNER: ['Updated to Owner', 'Update to Owner'],
UPDATE_PREVIEW: ['Updated (Preview)', 'Update (Preview)'],
UPLOAD: ['Uploaded', 'Upload'],
USE: ['Used', 'Use'],
VERIFY: ['Verified', 'Verify'],
WAITFORMAILBOX: ['Mailbox is Setup', 'Check Mailbox is Setup'],
WATCH: ['Watched', 'Watch'],
WIPE: ['Wiped', 'Wipe'],
WIPE_PREVIEW: ['Wiped (Preview)', 'Wipe (Preview)'],
}
#
MODIFIER_CONTENTS_WITH = 'contents with'
MODIFIER_FOR = 'for'
MODIFIER_FROM = 'from'
MODIFIER_IN = 'in'
MODIFIER_INTO = 'into'
MODIFIER_PREVIOUSLY_IN = 'previously in'
MODIFIER_TO = 'to'
MODIFIER_WITH_COTEACHER_OWNER = 'with co-teacher as owner'
MODIFIER_WITH_NEW_TEACHER_OWNER = 'with new teacher as owner'
MODIFIER_WITH_CURRENT_OWNER = 'with current owner'
MODIFIER_WITH = 'with'
MODIFIER_WITH_CONTENT_FROM = 'with content from'
PREFIX_NOT = 'Not'
PREVIEW = 'Preview'
SUCCESS = 'Success'
SUFFIX_FAILED = 'Failed'
def __init__(self):
self.action = None
def Set(self, action):
self.action = action
def Get(self):
return self.action
def ToPerform(self):
return self._NAMES[self.action][1]
def Performed(self):
return self._NAMES[self.action][0]
def Failed(self):
return f'{self._NAMES[self.action][1]} {self.SUFFIX_FAILED}'
def NotPerformed(self):
actionWords = self._NAMES[self.action][0].split(' ')
if len(actionWords) != 2:
return f'{self.PREFIX_NOT} {self._NAMES[self.action][0]}'
return f'{actionWords[0]} {self.PREFIX_NOT} {actionWords[1]}'
def PerformedName(self, action):
return self._NAMES[action][0]
def ToPerformName(self, action):
return self._NAMES[action][1]
def csvFormat(self):
return self.action == self.PRINT

837
src/gam/gamlib/glapi.py Normal file
View File

@@ -0,0 +1,837 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Google API resources
"""
# APIs
ACCESSCONTEXTMANAGER = 'accesscontextmanager'
ALERTCENTER = 'alertcenter'
ANALYTICS = 'analytics'
ANALYTICS_ADMIN = 'analyticsadmin'
CALENDAR = 'calendar'
CBCM = 'cbcm'
CHAT = 'chat'
CHAT_EVENTS = 'chatevents'
CHAT_MEMBERSHIPS = 'chatmemberships'
CHAT_MEMBERSHIPS_ADMIN = 'chatmembershipsadmin'
CHAT_MESSAGES = 'chatmessages'
CHAT_SPACES = 'chatspaces'
CHAT_SPACES_ADMIN = 'chatspacesadmin'
CHAT_SPACES_DELETE = 'chatspacesdelete'
CHAT_SPACES_DELETE_ADMIN = 'chatspacesdeleteadmin'
CHROMEMANAGEMENT = 'chromemanagement'
CHROMEMANAGEMENT_APPDETAILS = 'chromemanagementappdetails'
CHROMEMANAGEMENT_CHROMEPROFILES = 'chromemanagementchromeprofiles'
CHROMEMANAGEMENT_TELEMETRY = 'chromemanagementtelemetry'
CHROMEPOLICY = 'chromepolicy'
CHROMEVERSIONHISTORY = 'versionhistory'
CLASSROOM = 'classroom'
CLOUDCHANNEL = 'cloudchannel'
CLOUDIDENTITY_DEVICES = 'cloudidentitydevices'
CLOUDIDENTITY_GROUPS = 'cloudidentitygroups'
CLOUDIDENTITY_GROUPS_BETA = 'cloudidentitygroupsbeta'
CLOUDIDENTITY_INBOUND_SSO = 'cloudidentityinboundsso'
CLOUDIDENTITY_ORGUNITS = 'cloudidentityorgunits'
CLOUDIDENTITY_ORGUNITS_BETA = 'cloudidentityorgunitsbeta'
CLOUDIDENTITY_POLICY = 'cloudidentitypolicy'
CLOUDIDENTITY_USERINVITATIONS = 'cloudidentityuserinvitations'
CLOUDRESOURCEMANAGER = 'cloudresourcemanager'
CONTACTS = 'contacts'
CONTACTDELEGATION = 'contactdelegation'
DATATRANSFER = 'datatransfer'
DIRECTORY = 'directory'
DOCS = 'docs'
DRIVE2 = 'drive2'
DRIVE3 = 'drive3'
DRIVETD = 'drivetd'
DRIVEACTIVITY = 'driveactivity'
DRIVELABELS = 'drivelabels'
DRIVELABELS_ADMIN = 'drivelabelsadmin'
DRIVELABELS_USER = 'drivelabelsuser'
EMAIL_AUDIT = 'email-audit'
FORMS = 'forms'
GMAIL = 'gmail'
GROUPSMIGRATION = 'groupsmigration'
GROUPSSETTINGS = 'groupssettings'
IAM = 'iam'
IAM_CREDENTIALS = 'iamcredentials'
KEEP = 'keep'
LICENSING = 'licensing'
LOOKERSTUDIO = 'datastudio'
MEET = 'meet'
OAUTH2 = 'oauth2'
ORGPOLICY = 'orgpolicy'
PEOPLE = 'people'
PEOPLE_DIRECTORY = 'peopledirectory'
PEOPLE_OTHERCONTACTS = 'peopleothercontacts'
PRINTERS = 'printers'
PUBSUB = 'pubsub'
REPORTS = 'reports'
RESELLER = 'reseller'
SERVICEACCOUNTLOOKUP = 'serviceaccountlookup'
SERVICEMANAGEMENT = 'servicemanagement'
SERVICEUSAGE = 'serviceusage'
SHEETS = 'sheets'
SHEETSTD = 'sheetstd'
SITES = 'sites'
SITEVERIFICATION = 'siteVerification'
STORAGE = 'storage'
STORAGEREAD = 'storageread'
STORAGEWRITE = 'storagewrite'
TASKS = 'tasks'
VAULT = 'vault'
YOUTUBE = 'youtube'
#
CHROMEVERSIONHISTORY_URL = 'https://versionhistory.googleapis.com/v1/chrome/platforms'
DRIVE_SCOPE = 'https://www.googleapis.com/auth/drive'
GMAIL_SEND_SCOPE = 'https://www.googleapis.com/auth/gmail.send'
GOOGLE_AUTH_PROVIDER_X509_CERT_URL = 'https://www.googleapis.com/oauth2/v1/certs'
GOOGLE_OAUTH2_ENDPOINT = 'https://accounts.google.com/o/oauth2/v2/auth'
GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://oauth2.googleapis.com/token'
CLOUD_PLATFORM_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'
IAM_SCOPE = 'https://www.googleapis.com/auth/iam'
PEOPLE_SCOPE = 'https://www.googleapis.com/auth/contacts'
STORAGE_READONLY_SCOPE = 'https://www.googleapis.com/auth/devstorage.read_only'
STORAGE_READWRITE_SCOPE = 'https://www.googleapis.com/auth/devstorage.read_write'
USERINFO_EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email' # email
USERINFO_PROFILE_SCOPE = 'https://www.googleapis.com/auth/userinfo.profile' # profile
VAULT_SCOPES = ['https://www.googleapis.com/auth/ediscovery', 'https://www.googleapis.com/auth/ediscovery.readonly']
REQUIRED_SCOPES = [USERINFO_EMAIL_SCOPE, USERINFO_PROFILE_SCOPE]
REQUIRED_SCOPES_SET = set(REQUIRED_SCOPES)
#
JWT_APIS = {
ACCESSCONTEXTMANAGER: [CLOUD_PLATFORM_SCOPE],
CHAT: ['https://www.googleapis.com/auth/chat.bot'],
CLOUDRESOURCEMANAGER: [CLOUD_PLATFORM_SCOPE],
ORGPOLICY: [CLOUD_PLATFORM_SCOPE],
}
#
SCOPELESS_APIS = {
CHROMEVERSIONHISTORY,
OAUTH2,
SERVICEACCOUNTLOOKUP,
}
#
APIS_NEEDING_ACCESS_TOKEN = {
CBCM: ['https://www.googleapis.com/auth/admin.directory.device.chromebrowsers']
}
#
REFRESH_PERM_ERRORS = [
'invalid_grant: reauth related error (rapt_required)', # no way to reauth today
'invalid_grant: Token has been expired or revoked',
]
OAUTH2_TOKEN_ERRORS = [
'access_denied',
'access_denied: Requested client not authorized',
'access_denied: Account restricted',
'internal_failure: Backend Error',
'internal_failure: None',
'invalid_grant',
'invalid_grant: Bad Request',
'invalid_grant: Invalid email or User ID',
'invalid_grant: Not a valid email',
'invalid_grant: Invalid JWT: No valid verifier found for issuer',
'invalid_grant: reauth related error (invalid_rapt)',
'invalid_grant: The account has been deleted',
'invalid_request: Invalid impersonation prn email address'
]
OAUTH2_UNAUTHORIZED_ERRORS = [
'unauthorized_client: Client is unauthorized to retrieve access tokens using this method',
'unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested',
'unauthorized_client: Unauthorized client or scope in request',
]
PROJECT_APIS = [
'accesscontextmanager.googleapis.com',
'admin.googleapis.com',
'alertcenter.googleapis.com',
'analytics.googleapis.com',
'analyticsadmin.googleapis.com',
# 'audit.googleapis.com',
'calendar-json.googleapis.com',
'chat.googleapis.com',
'chromemanagement.googleapis.com',
'chromepolicy.googleapis.com',
'classroom.googleapis.com',
'cloudchannel.googleapis.com',
'cloudidentity.googleapis.com',
'cloudresourcemanager.googleapis.com',
'contacts.googleapis.com',
'datastudio.googleapis.com',
'docs.googleapis.com',
'drive.googleapis.com',
'driveactivity.googleapis.com',
'drivelabels.googleapis.com',
'forms.googleapis.com',
'gmail.googleapis.com',
'groupsmigration.googleapis.com',
'groupssettings.googleapis.com',
'iam.googleapis.com',
'keep.googleapis.com',
'licensing.googleapis.com',
'meet.googleapis.com',
'people.googleapis.com',
'pubsub.googleapis.com',
'reseller.googleapis.com',
'sheets.googleapis.com',
'siteverification.googleapis.com',
'storage-api.googleapis.com',
'tasks.googleapis.com',
'vault.googleapis.com',
'youtube.googleapis.com',
]
_INFO = {
ACCESSCONTEXTMANAGER: {'name': 'Access Context Manager API', 'version': 'v1', 'v2discovery': True},
ALERTCENTER: {'name': 'AlertCenter API', 'version': 'v1beta1', 'v2discovery': True},
ANALYTICS: {'name': 'Analytics API', 'version': 'v3', 'v2discovery': False},
ANALYTICS_ADMIN: {'name': 'Analytics Admin API', 'version': 'v1beta', 'v2discovery': True},
CALENDAR: {'name': 'Calendar API', 'version': 'v3', 'v2discovery': True, 'mappedAPI': 'calendar-json'},
CBCM: {'name': 'Chrome Browser Cloud Management API', 'version': 'v1.1beta1', 'v2discovery': True, 'localjson': True},
CHAT: {'name': 'Chat API', 'version': 'v1', 'v2discovery': True},
CHAT_EVENTS: {'name': 'Chat API - Events', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_MEMBERSHIPS: {'name': 'Chat API - Memberships', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_MEMBERSHIPS_ADMIN: {'name': 'Chat API - Memberships Admin', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_MESSAGES: {'name': 'Chat API - Messages', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_SPACES: {'name': 'Chat API - Spaces', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_SPACES_ADMIN: {'name': 'Chat API - Spaces Admin', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_SPACES_DELETE: {'name': 'Chat API - Spaces Delete', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_SPACES_DELETE_ADMIN: {'name': 'Chat API - Spaces Delete Admin', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CLASSROOM: {'name': 'Classroom API', 'version': 'v1', 'v2discovery': True},
CHROMEMANAGEMENT: {'name': 'Chrome Management API', 'version': 'v1', 'v2discovery': True},
CHROMEMANAGEMENT_APPDETAILS: {'name': 'Chrome Management API - AppDetails', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHROMEMANAGEMENT},
CHROMEMANAGEMENT_TELEMETRY: {'name': 'Chrome Management API - Telemetry', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHROMEMANAGEMENT},
CHROMEPOLICY: {'name': 'Chrome Policy API', 'version': 'v1', 'v2discovery': True},
CHROMEVERSIONHISTORY: {'name': 'Chrome Version History API', 'version': 'v1', 'v2discovery': True},
CLOUDCHANNEL: {'name': 'Channel Channel API', 'version': 'v1', 'v2discovery': True},
CLOUDIDENTITY_DEVICES: {'name': 'Cloud Identity Devices API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_GROUPS: {'name': 'Cloud Identity Groups API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_GROUPS_BETA: {'name': 'Cloud Identity Groups API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_INBOUND_SSO: {'name': 'Cloud Identity Inbound SSO API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_ORGUNITS: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_ORGUNITS_BETA: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_POLICY: {'name': 'Cloud Identity Policy API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_USERINVITATIONS: {'name': 'Cloud Identity User Invitations API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True},
CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False},
CONTACTDELEGATION: {'name': 'Contact Delegation API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
DATATRANSFER: {'name': 'Data Transfer API', 'version': 'datatransfer_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DIRECTORY: {'name': 'Directory API', 'version': 'directory_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DOCS: {'name': 'Docs API', 'version': 'v1', 'v2discovery': True},
DRIVE2: {'name': 'Drive API v2', 'version': 'v2', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3: {'name': 'Drive API v3', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVETD: {'name': 'Drive API v3 - todrive', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVEACTIVITY: {'name': 'Drive Activity API v2', 'version': 'v2', 'v2discovery': True},
DRIVELABELS_ADMIN: {'name': 'Drive Labels API - Admin', 'version': 'v2', 'v2discovery': True, 'mappedAPI': DRIVELABELS},
DRIVELABELS_USER: {'name': 'Drive Labels API - User', 'version': 'v2', 'v2discovery': True, 'mappedAPI': DRIVELABELS},
EMAIL_AUDIT: {'name': 'Email Audit API', 'version': 'v1', 'v2discovery': False},
FORMS: {'name': 'Forms API', 'version': 'v1', 'v2discovery': True},
GMAIL: {'name': 'Gmail API', 'version': 'v1', 'v2discovery': True},
GROUPSMIGRATION: {'name': 'Groups Migration API', 'version': 'v1', 'v2discovery': False},
GROUPSSETTINGS: {'name': 'Groups Settings API', 'version': 'v1', 'v2discovery': True},
IAM: {'name': 'Identity and Access Management API', 'version': 'v1', 'v2discovery': True},
IAM_CREDENTIALS: {'name': 'Identity and Access Management Credentials API', 'version': 'v1', 'v2discovery': True},
KEEP: {'name': 'Keep API', 'version': 'v1', 'v2discovery': True},
LICENSING: {'name': 'License Manager API', 'version': 'v1', 'v2discovery': True},
LOOKERSTUDIO: {'name': 'Looker Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
MEET: {'name': 'Meet API', 'version': 'v2', 'v2discovery': True},
OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False},
ORGPOLICY: {'name': 'Organization Policy API', 'version': 'v2', 'v2discovery': True},
PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True},
PEOPLE_DIRECTORY: {'name': 'People Directory API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': PEOPLE},
PEOPLE_OTHERCONTACTS: {'name': 'People API - Other Contacts', 'version': 'v1', 'v2discovery': True, 'mappedAPI': PEOPLE},
PRINTERS: {'name': 'Directory API Printers', 'version': 'directory_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
PUBSUB: {'name': 'Pub / Sub API', 'version': 'v1', 'v2discovery': True},
REPORTS: {'name': 'Reports API', 'version': 'reports_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
RESELLER: {'name': 'Reseller API', 'version': 'v1', 'v2discovery': True},
SERVICEACCOUNTLOOKUP: {'name': 'Service Account Lookup pseudo-API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
SERVICEMANAGEMENT: {'name': 'Service Management API', 'version': 'v1', 'v2discovery': True},
SERVICEUSAGE: {'name': 'Service Usage API', 'version': 'v1', 'v2discovery': True},
SHEETS: {'name': 'Sheets API', 'version': 'v4', 'v2discovery': True},
SHEETSTD: {'name': 'Sheets API - todrive', 'version': 'v4', 'v2discovery': True, 'mappedAPI': SHEETS},
SITES: {'name': 'Sites API', 'version': 'v1', 'v2discovery': False},
SITEVERIFICATION: {'name': 'Site Verification API', 'version': 'v1', 'v2discovery': True},
STORAGE: {'name': 'Cloud Storage API', 'version': 'v1', 'v2discovery': True},
STORAGEREAD: {'name': 'Cloud Storage API - Read', 'version': 'v1', 'v2discovery': True, 'mappedAPI': STORAGE},
STORAGEWRITE: {'name': 'Cloud Storage API - Write', 'version': 'v1', 'v2discovery': True, 'mappedAPI': STORAGE},
TASKS: {'name': 'Tasks API', 'version': 'v1', 'v2discovery': True},
VAULT: {'name': 'Vault API', 'version': 'v1', 'v2discovery': True},
YOUTUBE: {'name': 'Youtube API', 'version': 'v3', 'v2discovery': True},
}
READONLY = ['readonly',]
_CLIENT_SCOPES = [
{'name': 'Calendar API',
'api': CALENDAR,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/calendar'},
{'name': 'Chrome Browser Cloud Management API',
'api': CBCM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.device.chromebrowsers'},
{'name': 'Chrome Management API - read only',
'api': CHROMEMANAGEMENT,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/chrome.management.reports.readonly'},
{'name': 'Chrome Management API - AppDetails read only',
'api': CHROMEMANAGEMENT_APPDETAILS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/chrome.management.appdetails.readonly'},
{'name': 'Chrome Management API - Profiles',
'api': CHROMEMANAGEMENT_CHROMEPROFILES,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chrome.management.profiles'},
{'name': 'Chrome Management API - Telemetry read only',
'api': CHROMEMANAGEMENT_TELEMETRY,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/chrome.management.telemetry.readonly'},
{'name': 'Chrome Policy API',
'api': CHROMEPOLICY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chrome.management.policy'},
{'name': 'Chrome Printer Management API',
'api': PRINTERS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.chrome.printers'},
{'name': 'Chrome Version History API',
'api': CHROMEVERSIONHISTORY,
'subscopes': [],
'scope': ''},
{'name': 'Classroom API - Courses',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.courses'},
{'name': 'Classroom API - Course Announcements',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.announcements'},
{'name': 'Classroom API - Course Topics',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.topics'},
{'name': 'Classroom API - Course Work/Materials',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.courseworkmaterials'},
{'name': 'Classroom API - Course Work/Submissions',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.coursework.students'},
{'name': 'Classroom API - Student Guardians',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.guardianlinks.students'},
{'name': 'Classroom API - Profile Emails',
'api': CLASSROOM,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/classroom.profile.emails'},
{'name': 'Classroom API - Profile Photos',
'api': CLASSROOM,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/classroom.profile.photos'},
{'name': 'Classroom API - Rosters',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.rosters'},
{'name': 'Cloud Channel API',
'api': CLOUDCHANNEL,
'subscopes': READONLY,
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/apps.order'},
{'name': 'Cloud Identity Groups API',
'api': CLOUDIDENTITY_GROUPS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity.groups'},
{'name': 'Cloud Identity Groups API Beta (Enables group locking/unlocking)',
'api': CLOUDIDENTITY_GROUPS_BETA,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/cloud-identity.groups'},
{'name': 'Cloud Identity - Inbound SSO Settings',
'api': CLOUDIDENTITY_INBOUND_SSO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity.inboundsso'},
{'name': 'Cloud Identity OrgUnits API',
'api': CLOUDIDENTITY_ORGUNITS_BETA,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity.orgunits'},
{'name': 'Cloud Identity - Policy',
'api': CLOUDIDENTITY_POLICY,
'subscopes': READONLY,
'roByDefault': True,
'scope': 'https://www.googleapis.com/auth/cloud-identity.policies'
},
{'name': 'Cloud Identity User Invitations API',
'api': CLOUDIDENTITY_USERINVITATIONS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity.userinvitations'},
{'name': 'Cloud Storage API (Read Only, Vault/Takeout Download, Cloud Storage)',
'api': STORAGEREAD,
'subscopes': [],
'offByDefault': True,
'scope': STORAGE_READONLY_SCOPE},
{'name': 'Cloud Storage API (Read/Write, Vault/Takeout Copy/Download, Cloud Storage)',
'api': STORAGEWRITE,
'subscopes': [],
'offByDefault': True,
'scope': STORAGE_READWRITE_SCOPE},
{'name': 'Contacts API - Domain Shared Contacts and GAL',
'api': CONTACTS,
'subscopes': [],
'scope': 'https://www.google.com/m8/feeds'},
{'name': 'Contact Delegation API',
'api': CONTACTDELEGATION,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.contact.delegation'},
{'name': 'Data Transfer API',
'api': DATATRANSFER,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.datatransfer'},
{'name': 'Directory API - Chrome OS Devices',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.device.chromeos'},
{'name': 'Directory API - Customers',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.customer'},
{'name': 'Directory API - Domains',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.domain'},
{'name': 'Directory API - Groups',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.group'},
{'name': 'Directory API - Mobile Devices Directory',
'api': DIRECTORY,
'subscopes': ['readonly', 'action'],
'scope': 'https://www.googleapis.com/auth/admin.directory.device.mobile'},
{'name': 'Directory API - Organizational Units',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.orgunit'},
{'name': 'Directory API - Resource Calendars',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.resource.calendar'},
{'name': 'Directory API - Roles',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.rolemanagement'},
{'name': 'Directory API - User Schemas',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.userschema'},
{'name': 'Directory API - User Security',
'api': DIRECTORY,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/admin.directory.user.security'},
{'name': 'Directory API - Users',
'api': DIRECTORY,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/admin.directory.user'},
{'name': 'Email Audit API',
'api': EMAIL_AUDIT,
'subscopes': [],
'offByDefault': True,
'scope': 'https://apps-apis.google.com/a/feeds/compliance/audit/'},
{'name': 'Groups Migration API',
'api': GROUPSMIGRATION,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.groups.migration'},
{'name': 'Groups Settings API',
'api': GROUPSSETTINGS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.groups.settings'},
{'name': 'License Manager API',
'api': LICENSING,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.licensing'},
{'name': 'People Directory API - read only',
'api': PEOPLE_DIRECTORY,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/directory.readonly'},
{'name': 'People API',
'api': PEOPLE,
'subscopes': READONLY,
'scope': PEOPLE_SCOPE},
{'name': 'Pub / Sub API',
'api': PUBSUB,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/pubsub'},
{'name': 'Reports API - Audit Reports',
'api': REPORTS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/admin.reports.audit.readonly'},
{'name': 'Reports API - Usage Reports',
'api': REPORTS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/admin.reports.usage.readonly'},
{'name': 'Reseller API',
'api': RESELLER,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/apps.order'},
{'name': 'Service Account Lookup pseudo-API',
'api': SERVICEACCOUNTLOOKUP,
'subscopes': [],
'scope': ''},
{'name': 'Site Verification API',
'api': SITEVERIFICATION,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/siteverification'},
{'name': 'Sites API',
'api': SITES,
'subscopes': [],
'offByDefault': True,
'scope': 'https://sites.google.com/feeds'},
{'name': 'Vault API',
'api': VAULT,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/ediscovery'},
]
_TODRIVE_CLIENT_SCOPES = [
{'name': 'Drive API - todrive_clientaccess',
'api': DRIVE3,
'subscopes': [],
'scope': DRIVE_SCOPE},
{'name': 'Drive File API - todrive_clientaccess',
'api': DRIVE3,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/drive.file'},
{'name': 'Gmail API - todrive_clientaccess',
'api': GMAIL,
'subscopes': [],
'scope': GMAIL_SEND_SCOPE},
{'name': 'Sheets API - todrive_clientaccess',
'api': SHEETS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/spreadsheets'},
]
OAUTH2SA_SCOPES = 'us_scopes'
_SVCACCT_SCOPES = [
{'name': 'AlertCenter API',
'api': ALERTCENTER,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.alerts'},
{'name': 'Analytics API - read only',
'api': ANALYTICS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/analytics.readonly'},
{'name': 'Analytics Admin API - read only',
'api': ANALYTICS_ADMIN,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/analytics.readonly'},
{'name': 'Calendar API',
'api': CALENDAR,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/calendar'},
{'name': 'Chat API - Memberships',
'api': CHAT_MEMBERSHIPS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.memberships'},
{'name': 'Chat API - Memberships Admin',
'api': CHAT_MEMBERSHIPS_ADMIN,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.admin.memberships'},
{'name': 'Chat API - Messages',
'api': CHAT_MESSAGES,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.messages'},
{'name': 'Chat API - Spaces',
'api': CHAT_SPACES,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.spaces'},
{'name': 'Chat API - Spaces Admin',
'api': CHAT_SPACES_ADMIN,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.admin.spaces'},
{'name': 'Chat API - Spaces Delete',
'api': CHAT_SPACES_DELETE,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/chat.delete'},
{'name': 'Chat API - Spaces Delete Admin',
'api': CHAT_SPACES_DELETE_ADMIN,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/chat.admin.delete'},
{'name': 'Classroom API - Course Announcements',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.announcements'},
{'name': 'Classroom API - Course Topics',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.topics'},
{'name': 'Classroom API - Course Work/Materials',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.courseworkmaterials'},
{'name': 'Classroom API - Course Work/Submissions',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.coursework.students'},
{'name': 'Classroom API - Profile Emails',
'api': CLASSROOM,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/classroom.profile.emails'},
{'name': 'Classroom API - Profile Photos',
'api': CLASSROOM,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/classroom.profile.photos'},
{'name': 'Classroom API - Rosters',
'api': CLASSROOM,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/classroom.rosters'},
{'name': 'Cloud Identity Devices API',
'api': CLOUDIDENTITY_DEVICES,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/cloud-identity'},
# {'name': 'Cloud Identity User Invitations API',
# 'api': CLOUDIDENTITY_USERINVITATIONS,
# 'subscopes': READONLY,
# 'scope': 'https://www.googleapis.com/auth/cloud-identity'},
# {'name': 'Contacts API - Users',
# 'api': CONTACTS,
# 'subscopes': [],
# 'scope': 'https://www.google.com/m8/feeds'},
{'name': 'Drive API',
'api': DRIVE3,
'subscopes': READONLY,
'scope': DRIVE_SCOPE},
{'name': 'Drive Activity API v2 - must pair with Drive API',
'api': DRIVEACTIVITY,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/drive.activity'},
{'name': 'Drive Labels API - Admin',
'api': DRIVELABELS_ADMIN,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/drive.admin.labels'},
{'name': 'Drive Labels API - User',
'api': DRIVELABELS_USER,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/drive.labels'},
{'name': 'Docs API',
'api': DOCS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/documents'},
{'name': 'Forms API',
'api': FORMS,
'subscopes': [],
'scope': DRIVE_SCOPE},
{'name': 'Gmail API - Full Access (Labels, Messages)',
'api': GMAIL,
'subscopes': [],
'scope': 'https://mail.google.com/'},
{'name': 'Gmail API - Full Access (Labels, Messages) except delete message',
'api': GMAIL,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/gmail.modify'},
{'name': 'Gmail API - Basic Settings (Filters,IMAP, Language, POP, Vacation) - read/write, Sharing Settings (Delegates, Forwarding, SendAs) - read',
'api': GMAIL,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/gmail.settings.basic'},
{'name': 'Gmail API - Sharing Settings (Delegates, Forwarding, SendAs) - write',
'api': GMAIL,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/gmail.settings.sharing'},
{'name': 'Identity and Access Management API',
'api': IAM,
'subscopes': [],
'scope': CLOUD_PLATFORM_SCOPE},
{'name': 'Keep API',
'api': KEEP,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/keep'},
{'name': 'Looker Studio API',
'api': LOOKERSTUDIO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/datastudio'},
{'name': 'Meet API',
'api': MEET,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/meetings.space.created',
'roscope': 'https://www.googleapis.com/auth/meetings.space.readonly'},
{'name': 'OAuth2 API',
'api': OAUTH2,
'subscopes': [],
'scope': USERINFO_PROFILE_SCOPE},
{'name': 'People API',
'api': PEOPLE,
'subscopes': READONLY,
'scope': PEOPLE_SCOPE},
{'name': 'People Directory API - read only',
'api': PEOPLE_DIRECTORY,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/directory.readonly'},
{'name': 'People API - Other Contacts - read only',
'api': PEOPLE_OTHERCONTACTS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/contacts.other.readonly'},
{'name': 'Sheets API',
'api': SHEETS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/spreadsheets'},
{'name': 'Sites API',
'api': SITES,
'subscopes': [],
'scope': 'https://sites.google.com/feeds'},
{'name': 'Tasks API',
'api': TASKS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/tasks'},
{'name': 'Youtube API - read only',
'api': YOUTUBE,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/youtube.readonly'},
]
_SVCACCT_SPECIAL_SCOPES = [
{'name': 'Drive API - todrive',
'api': DRIVETD,
'subscopes': [],
'scope': DRIVE_SCOPE},
{'name': 'Gmail API - Full Access - read only',
'api': GMAIL,
'subscopes': [],
'offByDefault': True,
'scope': 'https://www.googleapis.com/auth/gmail.readonly'},
{'name': 'Gmail API - Send Messages - including todrive',
'api': GMAIL,
'subscopes': [],
'offByDefault': True,
'scope': GMAIL_SEND_SCOPE},
{'name': 'Sheets API - todrive',
'api': SHEETSTD,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/spreadsheets'},
]
_USER_SVCACCT_ONLY_SCOPES = [
{'name': 'Groups Migration API',
'api': GROUPSMIGRATION,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.groups.migration'},
]
DRIVE3_TO_DRIVE2_ABOUT_FIELDS_MAP = {
'displayName': 'name',
'limit': 'quotaBytesTotal',
'usage': 'quotaBytesUsedAggregate',
'usageInDrive': 'quotaBytesUsed',
'usageInDriveTrash': 'quotaBytesUsedInTrash',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_FIELDS_MAP = {
'canComment': 'canComment',
'canReadRevisions': 'canReadRevisions',
'canCopy': 'copyable',
'canEdit': 'editable',
'canShare': 'shareable',
}
DRIVE3_TO_DRIVE2_CAPABILITIES_NAMES_MAP = {
'canChangeViewersCanCopyContent': 'canChangeRestrictedDownload',
}
DRIVE3_TO_DRIVE2_FILES_FIELDS_MAP = {
'allowFileDiscovery': 'withLink',
'createdTime': 'createdDate',
'expirationTime': 'expirationDate',
'modifiedByMe': 'modified',
'modifiedByMeTime': 'modifiedByMeDate',
'modifiedTime': 'modifiedDate',
'name': 'title',
'restrictionTime': 'restrictionDate',
'sharedWithMeTime': 'sharedWithMeDate',
'size': 'fileSize',
'trashedTime': 'trashedDate',
'viewedByMe': 'viewed',
'viewedByMeTime': 'lastViewedByMeDate',
'webViewLink': 'alternateLink',
}
DRIVE3_TO_DRIVE2_LABELS_MAP = {
'modifiedByMe': 'modified',
'starred': 'starred',
'trashed': 'trashed',
'viewedByMe': 'viewed',
}
DRIVE3_TO_DRIVE2_REVISIONS_FIELDS_MAP = {
'modifiedTime': 'modifiedDate',
'keepForever': 'pinned',
'size': 'fileSize',
}
def getAPIName(api):
return _INFO[api]['name']
def getVersion(api):
version = _INFO[api]['version']
v2discovery = _INFO[api]['v2discovery']
api = _INFO[api].get('mappedAPI', api)
return (api, version, v2discovery)
def getClientScopesSet(api):
return {scope['scope'] for scope in _CLIENT_SCOPES if scope['api'] == api}
def getClientScopesList(todriveClientAccess):
caScopes = _CLIENT_SCOPES[:]
if todriveClientAccess:
caScopes.extend(_TODRIVE_CLIENT_SCOPES)
return sorted(caScopes, key=lambda k: k['name'])
def getClientScopesURLs(todriveClientAccess):
caScopes = _CLIENT_SCOPES[:]
if todriveClientAccess:
caScopes.extend(_TODRIVE_CLIENT_SCOPES)
return sorted({scope['scope'] for scope in _CLIENT_SCOPES})
def getSvcAcctScopeAPI(uscope):
for scope in _SVCACCT_SCOPES:
if uscope == scope['scope'] or (uscope.endswith('.readonly') and 'readonly' in scope['subscopes']):
return scope['api']
return None
def getSvcAcctScopes(userServiceAccountAccessOnly, svcAcctSpecialScopes):
saScopes = [scope['scope'] for scope in _SVCACCT_SCOPES]
if userServiceAccountAccessOnly:
saScopes.extend([scope['scope'] for scope in _USER_SVCACCT_ONLY_SCOPES])
if svcAcctSpecialScopes:
saScopes.extend([scope['scope'] for scope in _SVCACCT_SPECIAL_SCOPES])
return saScopes
def getSvcAcctScopesList(userServiceAccountAccessOnly, svcAcctSpecialScopes):
saScopes = _SVCACCT_SCOPES[:]
if userServiceAccountAccessOnly:
saScopes.extend(_USER_SVCACCT_ONLY_SCOPES)
if svcAcctSpecialScopes:
saScopes.extend(_SVCACCT_SPECIAL_SCOPES)
return sorted(saScopes, key=lambda k: k['name'])
def hasLocalJSON(api):
return _INFO[api].get('localjson', False)

616
src/gam/gamlib/glcfg.py Normal file
View File

@@ -0,0 +1,616 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM gam.cfg variables
"""
import os
TRUE = 'true'
FALSE = 'false'
DEFAULT_CHARSET = 'utf-8'
MY_CUSTOMER = 'my_customer'
NEVER = 'Never'
TLS_CHOICE_MAP = {
'': '',
'tlsv1_2': 'TLSv1_2', 'tlsv1.2': 'TLSv1_2',
'tlsv1_3': 'TLSv1_3', 'tlsv1.3': 'TLSv1_3',
}
FN_CACERTS_PEM = 'cacerts.pem'
FN_CLIENT_SECRETS_JSON = 'client_secrets.json'
FN_EXTRA_ARGS_TXT = 'extra-args.txt'
FN_OAUTH2_TXT = 'oauth2.txt'
FN_OAUTH2SERVICE_JSON = 'oauth2service.json'
# Global variables defined in gam.cfg
# The following XXX constants are the names of the items in gam.cfg
# When retrieving lists of Google Drive activities from API, how many should be retrieved in each chunk
ACTIVITY_MAX_RESULTS = 'activity_max_results'
# Admin email address, required when enable_dasa is true, overrides oauth2.txt value otherwise
ADMIN_EMAIL = 'admin_email'
# Check if API calls rate exceeds limit
API_CALLS_RATE_CHECK = 'api_calls_rate_check'
# API calls per 100 seconds limit
API_CALLS_RATE_LIMIT = 'api_calls_rate_limit'
# API calls tries limit
API_CALLS_TRIES_LIMIT = 'api_calls_tries_limit'
# Automatically generate gam batch command if number of users specified in gam users xxx command exceeds this number
# Default: 0, do not automatically generate gam batch commands
AUTO_BATCH_MIN = 'auto_batch_min'
# When bailing on internal errors, how many total tries should be performed
BAIL_ON_INTERNAL_ERROR_TRIES = 'bail_on_internal_error_tries'
# When processing items in batches, how many should be processed in each batch
BATCH_SIZE = 'batch_size'
# Location of cacerts.pem for API calls
CACERTS_PEM = 'cacerts_pem'
# GAM cache directory
CACHE_DIR = 'cache_dir'
# GAM cache discovery only. If no_cache is False, only API discovery calls will be cached
CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
# Channel custmerId from gam.cfg
CHANNEL_CUSTOMER_ID = 'channel_customer_id'
# Character set of batch, csv, data files
CHARSET = 'charset'
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
CLASSROOM_MAX_RESULTS = 'classroom_max_results'
# Path to client_secrets.json
CLIENT_SECRETS_JSON = 'client_secrets_json'
# Allowed clock skew in seconds
CLOCK_SKEW_IN_SECONDS = 'clock_skew_in_seconds'
# Command logging filename
CMDLOG = 'cmdlog'
# Bogus Command logging maximum number of backup log files
CMDLOG_MAX__BACKUPS = 'cmdlog_max__backups'
# Command logging maximum number of backup log files
CMDLOG_MAX_BACKUPS = 'cmdlog_max_backups'
# Command logging max kilo bytes per log file
CMDLOG_MAX_KILO_BYTES = 'cmdlog_max_kilo_bytes'
# GAM config directory containing client_secrets.json, oauth2.txt, oauth2service.json, extra_args.txt
CONFIG_DIR = 'config_dir'
# When retrieving lists of Google Contacts from API, how many should be retrieved in each chunk
CONTACT_MAX_RESULTS = 'contact_max_results'
# Column delimiter in CSV input file
CSV_INPUT_COLUMN_DELIMITER = 'csv_input_column_delimiter'
# No escape character in CSV input file
CSV_INPUT_NO_ESCAPE_CHAR = 'csv_input_no_escape_char'
# Quote character in CSV input file
CSV_INPUT_QUOTE_CHAR = 'csv_input_quote_char'
# Filter for input column values
CSV_INPUT_ROW_FILTER = 'csv_input_row_filter'
# Mode (and|or) for input column values
CSV_INPUT_ROW_FILTER_MODE = 'csv_input_row_filter_mode'
# Filter for input column drop values
CSV_INPUT_ROW_DROP_FILTER = 'csv_input_row_drop_filter'
# Mode (and|or) for input column drop values
CSV_INPUT_ROW_DROP_FILTER_MODE = 'csv_input_row_drop_filter_mode'
# Limit number of input rows
CSV_INPUT_ROW_LIMIT = 'csv_input_row_limit'
# Convert newlines in text fields to "\n" in CSV output file
CSV_OUTPUT_CONVERT_CR_NL = 'csv_output_convert_cr_nl'
# Column delimiter in CSV output file
CSV_OUTPUT_COLUMN_DELIMITER = 'csv_output_column_delimiter'
# No escape character in CSV output file
CSV_OUTPUT_NO_ESCAPE_CHAR = 'csv_output_no_escape_char'
# Field list delimiter in CSV output file
CSV_OUTPUT_FIELD_DELIMITER = 'csv_output_field_delimiter'
# Filter for output column headers
CSV_OUTPUT_HEADER_FILTER = 'csv_output_header_filter'
# Filter for output column headers to drop
CSV_OUTPUT_HEADER_DROP_FILTER = 'csv_output_header_drop_filter'
# Force output column headers
CSV_OUTPUT_HEADER_FORCE = 'csv_output_header_force'
# Orde output column headers
CSV_OUTPUT_HEADER_ORDER = 'csv_output_header_order'
# Line terminator in CSV output file
CSV_OUTPUT_LINE_TERMINATOR = 'csv_output_line_terminator'
# Quote character in CSV output file
CSV_OUTPUT_QUOTE_CHAR = 'csv_output_quote_char'
# Filter for output column values
CSV_OUTPUT_ROW_FILTER = 'csv_output_row_filter'
# Mode (and|or) for output column values
CSV_OUTPUT_ROW_FILTER_MODE = 'csv_output_row_filter_mode'
# Filter for output column drop values
CSV_OUTPUT_ROW_DROP_FILTER = 'csv_output_row_drop_filter'
# Mode (and|or) for output column drop values
CSV_OUTPUT_ROW_DROP_FILTER_MODE = 'csv_output_row_drop_filter_mode'
# Limit number of output rows
CSV_OUTPUT_ROW_LIMIT = 'csv_output_row_limit'
# Output sort headers
CSV_OUTPUT_SORT_HEADERS = 'csv_output_sort_headers'
# Column header subfield name delimiter in CSV output file
CSV_OUTPUT_SUBFIELD_DELIMITER = 'csv_output_subfield_delimiter'
# Add timestamp column to CSV output file
CSV_OUTPUT_TIMESTAMP_COLUMN = 'csv_output_timestamp_column'
# Output rows for users even if they do not have the print object (delegate, filters, ...)
CSV_OUTPUT_USERS_AUDIT = 'csv_output_users_audit'
# custmerId from gam.cfg or retrieved from Google
CUSTOMER_ID = 'customer_id'
# If debug_level > 0: extra_args['prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
DEBUG_LEVEL = 'debug_level'
# When retrieving lists of ChromeOS devices from API, how many should be retrieved in each chunk
DEVICE_MAX_RESULTS = 'device_max_results'
# Domain obtained from gam.cfg or oauth2.txt
DOMAIN = 'domain'
# Google Drive download directory
DRIVE_DIR = 'drive_dir'
# When retrieving lists of Drive files/folders from API, how many should be retrieved in each chunk
DRIVE_MAX_RESULTS = 'drive_max_results'
# Use Drive V3 beta
DRIVE_V3_BETA = 'drive_v3_beta'
# Use Drive V3 ntive names
DRIVE_V3_NATIVE_NAMES = 'drive_v3_native_names'
# When processing email messages in batches, how many should be processed in each batch
EMAIL_BATCH_SIZE = 'email_batch_size'
# Enable Delegated Admin Service Account
ENABLE_DASA = 'enable_dasa'
# Enable Cloud Session Reauthentication by borrowing a RAPT token from gcloud command
ENABLE_GCLOUD_REAUTH = 'enable_gcloud_reauth'
# When retrieving lists of calendar events from API, how many should be retrieved in each chunk
EVENT_MAX_RESULTS = 'event_max_results'
# Path to extra_args.txt
EXTRA_ARGS = 'extra_args'
# Gmail CSE certificates directory
GMAIL_CSE_INCERT_DIR = 'gmail_cse_incert_dir'
# Gmail CSE KACL wrapped key files
GMAIL_CSE_INKEY_DIR = 'gmail_cse_inkey_dir'
# When processing items in batches, how many seconds should GAM wait between batches
INTER_BATCH_WAIT = 'inter_batch_wait'
# When retrieving lists of licenses from API, how many should be retrieved in each chunk
LICENSE_MAX_RESULTS = 'license_max_results'
# License SKUs to process
LICENSE_SKUS = 'license_skus'
# When retrieving lists of Google Group members from API, how many should be retrieved in each chunk
MEMBER_MAX_RESULTS = 'member_max_results'
# When deleting or modifying Gmail messages, how many should be processed in each batch
MESSAGE_BATCH_SIZE = 'message_batch_size'
# When retrieving lists of Gmail messages from API, how many should be retrieved in each chunk
MESSAGE_MAX_RESULTS = 'message_max_results'
# When retrieving lists of Mobile devices from API, how many should be retrieved in each chunk
MOBILE_MAX_RESULTS = 'mobile_max_results'
# Number of parallel multiprocess pool.apply_async calls; -1: no limit, 0: NUM_THREADS, >0: specific limit
MULTIPROCESS_POOL_LIMIT = 'multiprocess_pool_limit'
# Value to substitute for NEVER_TIME
NEVER_TIME = 'never_time'
# If no_browser is False, writeCSVfile won't open a browser when todrive is set
# and doOAuthRequest prints a link and waits for the verification code when oauth2.txt is being created
NO_BROWSER = 'no_browser'
# Disable GAM API caching
NO_CACHE = 'no_cache'
# Do noit use URL shortner for authentication URLs
NO_SHORT_URLS = 'no_short_urls'
# Disable GAM update check
NO_UPDATE_CHECK = 'no_update_check'
# Disable SSL certificate validation
NO_VERIFY_SSL = 'no_verify_ssl'
# Number of threads for gam tbatch
NUM_TBATCH_THREADS = 'num_tbatch_threads'
# Number of threads for gam batch/csv
NUM_THREADS = 'num_threads'
# Path to oauth2.txt
OAUTH2_TXT = 'oauth2_txt'
# Path to oauth2service.json
OAUTH2SERVICE_JSON = 'oauth2service_json'
# Output date format, empty defalts to ISOFormat
OUTPUT_DATEFORMAT = 'output_dateformat'
# Output time format, empty defalts to ISOFormat
OUTPUT_TIMEFORMAT = 'output_timeformat'
# When retrieving lists of people from API, how many should be retrieved in each chunk
PEOPLE_MAX_RESULTS = 'people_max_results'
# Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'print_agu_domains'
# OrgUnits for print cros
PRINT_CROS_OUS = 'print_cros_ous'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'print_cros_ous_and_children'
# Number of seconds to wait for batch/csv processes to complete
PROCESS_WAIT_LIMIT = 'process_wait_limit'
# Use quick method to move Chromebooks to OU
QUICK_CROS_MOVE = 'quick_cros_move'
# Quick info user: nogroups nolicenses noschemas
QUICK_INFO_USER = 'quick_info_user'
# resellerId from gam.cfg or retrieved from Google
RESELLER_ID = 'reseller_id'
# Retry service not available errors on API calls
RETRY_API_SERVICE_NOT_AVAILABLE = 'retry_api_service_not_available'
# Default section to use for processing
SECTION = 'section'
# Show API calls retry data
SHOW_API_CALLS_RETRY_DATA = 'show_api_calls_retry_data'
# Show commands when processing batch/csv/loop
SHOW_COMMANDS = 'show_commands'
# Convert newlines in text fields to "\n" in show commands
SHOW_CONVERT_CR_NL = 'show_convert_cr_nl'
# Add (n/m) to end of messages if number of items to be processed exceeds this number
SHOW_COUNTS_MIN = 'show_counts_min'
# Enable/disable "Getting ... " messages
SHOW_GETTINGS = 'show_gettings'
# Enable/disable NL at end of "Got ..." messages
SHOW_GETTINGS_GOT_NL = 'show_gettings_got_nl'
# Enable/disable showing multiprocess info in redirected stdout/stderr
SHOW_MULTIPROCESS_INFO = 'show_multiprocess_info'
# SMTP fqdn
SMTP_FQDN = 'smtp_fqdn'
# SMTP host
SMTP_HOST = 'smtp_host'
# SMTP username
SMTP_USERNAME = 'smtp_username'
# SMTP password
SMTP_PASSWORD = 'smtp_password'
## Minimum TLS Version required for HTTPS connections
TLS_MIN_VERSION = 'tls_min_version'
## Maximum TLS Version used for HTTPS connections
TLS_MAX_VERSION = 'tls_max_version'
# Time Zone
TIMEZONE = 'timezone'
# Clear basic filter when updating an existing sheet
TODRIVE_CLEARFILTER = 'todrive_clearfilter'
# Use client access for todrive
TODRIVE_CLIENTACCESS = 'todrive_clientaccess'
# Enable conversion to Google Sheets when uploading todrive files
TODRIVE_CONVERSION = 'todrive_conversion'
# Save local copy of CSV file
TODRIVE_LOCALCOPY = 'todrive_localcopy'
# Specify locale for Google Sheets
TODRIVE_LOCALE = 'todrive_locale'
# Suppress opening browser on todrive upload
TODRIVE_NOBROWSER = 'todrive_nobrowser'
# Suppress sending email on todrive upload
TODRIVE_NOEMAIL = 'todrive_noemail'
# No escape character in CSV output file
TODRIVE_NO_ESCAPE_CHAR = 'todrive_no_escape_char'
# ID/Name of parent folder for todrive files
TODRIVE_PARENT = 'todrive_parent'
# Append timestamp to todrive sheet name
TODRIVE_SHEET_TIMESTAMP = 'todrive_sheet_timestamp'
# Sheet timestamp format, empty defalts to ISOFormat
TODRIVE_SHEET_TIMEFORMAT = 'todrive_sheet_timeformat'
# Append timestamp to todrive file name
TODRIVE_TIMESTAMP = 'todrive_timestamp'
# Timestamp format, empty defalts to ISOFormat
TODRIVE_TIMEFORMAT = 'todrive_timeformat'
# Specify timezone for Google Sheets
TODRIVE_TIMEZONE = 'todrive_timezone'
# Upload data files with no data
TODRIVE_UPLOAD_NODATA = 'todrive_upload_nodata'
# User for todrive files
TODRIVE_USER = 'todrive_user'
# Truncate Client ID
TRUNCATE_CLIENT_ID = 'truncate_client_id'
# Update CrOS org unit with orgUnitId
UPDATE_CROS_OU_WITH_ID = 'update_cros_ou_with_id'
# Use admin access for chat where possible
USE_CHAT_ADMIN_ACCESS = 'use_chat_admin_access'
# Use course owner for course access
USE_COURSE_OWNER_ACCESS = 'use_course_owner_access'
# Use Project ID as Project Name and App Name
USE_PROJECTID_AS_NAME = 'use_projectid_as_name'
# When retrieving lists of Users from API, how many should be retrieved in each chunk
USER_MAX_RESULTS = 'user_max_results'
# User service account access only, no client access
USER_SERVICE_ACCOUNT_ACCESS_ONLY = 'user_service_account_access_only'
CSV_INPUT_ROW_FILTER_ITEMS = {CSV_INPUT_ROW_FILTER, CSV_INPUT_ROW_FILTER_MODE,
CSV_INPUT_ROW_DROP_FILTER, CSV_INPUT_ROW_DROP_FILTER_MODE,
CSV_INPUT_ROW_LIMIT}
CSV_OUTPUT_ROW_FILTER_ITEMS = {CSV_OUTPUT_HEADER_FILTER, CSV_OUTPUT_HEADER_DROP_FILTER,
CSV_OUTPUT_HEADER_FORCE, CSV_OUTPUT_HEADER_ORDER,
CSV_OUTPUT_ROW_FILTER, CSV_OUTPUT_ROW_FILTER_MODE,
CSV_OUTPUT_ROW_DROP_FILTER, CSV_OUTPUT_ROW_DROP_FILTER_MODE,
CSV_OUTPUT_ROW_LIMIT}
Defaults = {
ACTIVITY_MAX_RESULTS: '100',
ADMIN_EMAIL: '',
API_CALLS_RATE_CHECK: FALSE,
API_CALLS_RATE_LIMIT: '100',
API_CALLS_TRIES_LIMIT: '10',
AUTO_BATCH_MIN: '0',
BAIL_ON_INTERNAL_ERROR_TRIES: '2',
BATCH_SIZE: '50',
CACERTS_PEM: '',
CACHE_DIR: '',
CACHE_DISCOVERY_ONLY: TRUE,
CHARSET: DEFAULT_CHARSET,
CHANNEL_CUSTOMER_ID: '',
CLASSROOM_MAX_RESULTS: '0',
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
CLOCK_SKEW_IN_SECONDS: '10',
CMDLOG: '',
CMDLOG_MAX_BACKUPS: 5,
CMDLOG_MAX_KILO_BYTES: 1000,
CONFIG_DIR: '',
CONTACT_MAX_RESULTS: '100',
CSV_INPUT_COLUMN_DELIMITER: ',',
CSV_INPUT_NO_ESCAPE_CHAR: TRUE,
CSV_INPUT_QUOTE_CHAR: '\'"\'',
CSV_INPUT_ROW_FILTER: '',
CSV_INPUT_ROW_FILTER_MODE: 'allmatch',
CSV_INPUT_ROW_DROP_FILTER: '',
CSV_INPUT_ROW_DROP_FILTER_MODE: 'anymatch',
CSV_INPUT_ROW_LIMIT: '0',
CSV_OUTPUT_COLUMN_DELIMITER: ',',
CSV_OUTPUT_CONVERT_CR_NL: FALSE,
CSV_OUTPUT_NO_ESCAPE_CHAR: FALSE,
CSV_OUTPUT_FIELD_DELIMITER: "' '",
CSV_OUTPUT_HEADER_FILTER: '',
CSV_OUTPUT_HEADER_DROP_FILTER: '',
CSV_OUTPUT_HEADER_FORCE: '',
CSV_OUTPUT_HEADER_ORDER: '',
CSV_OUTPUT_LINE_TERMINATOR: 'lf',
CSV_OUTPUT_QUOTE_CHAR: '\'"\'',
CSV_OUTPUT_ROW_FILTER: '',
CSV_OUTPUT_ROW_FILTER_MODE: 'allmatch',
CSV_OUTPUT_ROW_DROP_FILTER: '',
CSV_OUTPUT_ROW_DROP_FILTER_MODE: 'anymatch',
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',
DEVICE_MAX_RESULTS: '200',
DOMAIN: '',
DRIVE_DIR: '',
DRIVE_MAX_RESULTS: '1000',
DRIVE_V3_BETA: FALSE,
DRIVE_V3_NATIVE_NAMES: TRUE,
EMAIL_BATCH_SIZE: '50',
ENABLE_DASA: FALSE,
ENABLE_GCLOUD_REAUTH: FALSE,
EVENT_MAX_RESULTS: '250',
EXTRA_ARGS: '',
GMAIL_CSE_INCERT_DIR: '',
GMAIL_CSE_INKEY_DIR: '',
INTER_BATCH_WAIT: '0',
LICENSE_MAX_RESULTS: '100',
LICENSE_SKUS: '',
MEMBER_MAX_RESULTS: '200',
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,
NO_SHORT_URLS: TRUE,
NO_UPDATE_CHECK: TRUE,
NO_VERIFY_SSL: FALSE,
NUM_TBATCH_THREADS: '2',
NUM_THREADS: '5',
OAUTH2_TXT: FN_OAUTH2_TXT,
OAUTH2SERVICE_JSON: FN_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,
RESELLER_ID: '',
RETRY_API_SERVICE_NOT_AVAILABLE: FALSE,
SECTION: '',
SHOW_API_CALLS_RETRY_DATA: FALSE,
SHOW_COMMANDS: FALSE,
SHOW_CONVERT_CR_NL: FALSE,
SHOW_COUNTS_MIN: '1',
SHOW_GETTINGS: TRUE,
SHOW_GETTINGS_GOT_NL: FALSE,
SHOW_MULTIPROCESS_INFO: FALSE,
SMTP_FQDN: '',
SMTP_HOST: '',
SMTP_USERNAME: '',
SMTP_PASSWORD: '',
TLS_MIN_VERSION: 'TLSv1_3',
TLS_MAX_VERSION: '',
TIMEZONE: 'utc',
TODRIVE_CLEARFILTER: FALSE,
TODRIVE_CLIENTACCESS: FALSE,
TODRIVE_CONVERSION: TRUE,
TODRIVE_LOCALCOPY: FALSE,
TODRIVE_LOCALE: '',
TODRIVE_NOBROWSER: '',
TODRIVE_NOEMAIL: '',
TODRIVE_NO_ESCAPE_CHAR: TRUE,
TODRIVE_PARENT: 'root',
TODRIVE_SHEET_TIMESTAMP: 'copy', # copy from TODRIVE_TIMESTAMP
TODRIVE_SHEET_TIMEFORMAT: 'copy', # copy from TODRIVE_TIMEFORMAT
TODRIVE_TIMESTAMP: FALSE,
TODRIVE_TIMEFORMAT: '',
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,
}
Values = {DEBUG_LEVEL: 0}
TYPE_BOOLEAN = 'bool'
TYPE_CHARACTER = 'char'
TYPE_CHOICE = 'choi'
TYPE_CHOICE_LIST = 'chol'
TYPE_DATETIME = 'datm'
TYPE_DIRECTORY = 'dire'
TYPE_EMAIL = 'emai'
TYPE_EMAIL_OPTIONAL = 'emao'
TYPE_FILE = 'file'
TYPE_FLOAT = 'floa'
TYPE_HEADERFILTER = 'heaf'
TYPE_HEADERFORCE = 'hefo'
TYPE_HEADERORDER = 'heor'
TYPE_INTEGER = 'inte'
TYPE_LANGUAGE = 'lang'
TYPE_LOCALE = 'locl'
TYPE_PASSWORD = 'pass'
TYPE_ROWFILTER = 'rowf'
TYPE_STRING = 'stri'
TYPE_STRINGLIST = 'strl'
TYPE_TIMEZONE = 'tmzn'
VAR_TYPE = 'type'
VAR_ENVVAR = 'enva'
VAR_CHOICES = 'chod'
VAR_LIMITS = 'lmit'
VAR_SFFT = 'sfft'
VAR_SIGFILE = 'sigf'
VAR_ACCESS = 'aces'
VAR_INFO = {
ACTIVITY_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)},
ADMIN_EMAIL: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_ADMIN_EMAIL', VAR_LIMITS: (0, None)},
API_CALLS_RATE_CHECK: {VAR_TYPE: TYPE_BOOLEAN},
API_CALLS_RATE_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (50, None)},
API_CALLS_TRIES_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (3, 30)},
AUTO_BATCH_MIN: {VAR_TYPE: TYPE_INTEGER, VAR_ENVVAR: 'GAM_AUTOBATCH', VAR_LIMITS: (0, 100)},
BAIL_ON_INTERNAL_ERROR_TRIES: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10)},
BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_ENVVAR: 'GAM_BATCH_SIZE', VAR_LIMITS: (1, 1000)},
CACERTS_PEM: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'GAM_CA_FILE', VAR_ACCESS: os.R_OK},
CACHE_DIR: {VAR_TYPE: TYPE_DIRECTORY, VAR_ENVVAR: 'GAMCACHEDIR'},
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},
CMDLOG: {VAR_TYPE: TYPE_FILE, VAR_ACCESS: os.W_OK},
CMDLOG_MAX_BACKUPS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10)},
CMDLOG_MAX_KILO_BYTES: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (100, 10000)},
CONFIG_DIR: {VAR_TYPE: TYPE_DIRECTORY, VAR_ENVVAR: 'GAMUSERCONFIGDIR'},
CONTACT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10000)},
CSV_INPUT_COLUMN_DELIMITER: {VAR_TYPE: TYPE_CHARACTER},
CSV_INPUT_NO_ESCAPE_CHAR: {VAR_TYPE: TYPE_BOOLEAN},
CSV_INPUT_QUOTE_CHAR: {VAR_TYPE: TYPE_CHARACTER},
CSV_INPUT_ROW_FILTER: {VAR_TYPE: TYPE_ROWFILTER},
CSV_INPUT_ROW_FILTER_MODE: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'allmatch': True, 'anymatch': False}},
CSV_INPUT_ROW_DROP_FILTER: {VAR_TYPE: TYPE_ROWFILTER},
CSV_INPUT_ROW_DROP_FILTER_MODE: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'allmatch': True, 'anymatch': False}},
CSV_INPUT_ROW_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)},
CSV_OUTPUT_COLUMN_DELIMITER: {VAR_TYPE: TYPE_CHARACTER},
CSV_OUTPUT_CONVERT_CR_NL: {VAR_TYPE: TYPE_BOOLEAN},
CSV_OUTPUT_NO_ESCAPE_CHAR: {VAR_TYPE: TYPE_BOOLEAN},
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_ORDER: {VAR_TYPE: TYPE_HEADERORDER},
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},
CSV_OUTPUT_ROW_FILTER_MODE: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'allmatch': True, 'anymatch': False}},
CSV_OUTPUT_ROW_DROP_FILTER: {VAR_TYPE: TYPE_ROWFILTER},
CSV_OUTPUT_ROW_DROP_FILTER_MODE: {VAR_TYPE: TYPE_CHOICE, VAR_CHOICES: {'allmatch': True, 'anymatch': False}},
CSV_OUTPUT_ROW_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)},
CSV_OUTPUT_SORT_HEADERS: {VAR_TYPE: TYPE_STRINGLIST},
CSV_OUTPUT_SUBFIELD_DELIMITER: {VAR_TYPE: TYPE_CHARACTER},
CSV_OUTPUT_TIMESTAMP_COLUMN: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
CSV_OUTPUT_USERS_AUDIT: {VAR_TYPE: TYPE_BOOLEAN},
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')},
DEVICE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
DOMAIN: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_DOMAIN', VAR_LIMITS: (0, None)},
DRIVE_DIR: {VAR_TYPE: TYPE_DIRECTORY, VAR_ENVVAR: 'GAMDRIVEDIR'},
DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN},
DRIVE_V3_NATIVE_NAMES: {VAR_TYPE: TYPE_BOOLEAN},
EMAIL_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
ENABLE_DASA: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'enabledasa.txt', VAR_SFFT: (FALSE, TRUE)},
ENABLE_GCLOUD_REAUTH: {VAR_TYPE: TYPE_BOOLEAN},
EVENT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 2500)},
EXTRA_ARGS: {VAR_TYPE: TYPE_FILE, VAR_SIGFILE: FN_EXTRA_ARGS_TXT, VAR_SFFT: ('', FN_EXTRA_ARGS_TXT), VAR_ACCESS: os.R_OK},
GMAIL_CSE_INCERT_DIR: {VAR_TYPE: TYPE_DIRECTORY},
GMAIL_CSE_INKEY_DIR: {VAR_TYPE: TYPE_DIRECTORY},
INTER_BATCH_WAIT: {VAR_TYPE: TYPE_FLOAT, VAR_LIMITS: (0.0, 60.0)},
LICENSE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 1000)},
LICENSE_SKUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
MEMBER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
MESSAGE_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
MESSAGE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10000)},
MOBILE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
MULTIPROCESS_POOL_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (-1, None)},
NEVER_TIME: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
NO_BROWSER: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'nobrowser.txt', VAR_SFFT: (FALSE, TRUE)},
NO_CACHE: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'nocache.txt', VAR_SFFT: (FALSE, TRUE)},
NO_SHORT_URLS: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'noshorturls.txt', VAR_SFFT: (FALSE, TRUE)},
NO_UPDATE_CHECK: {VAR_TYPE: TYPE_BOOLEAN},
NO_VERIFY_SSL: {VAR_TYPE: TYPE_BOOLEAN},
NUM_TBATCH_THREADS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
NUM_THREADS: {VAR_TYPE: TYPE_INTEGER, VAR_ENVVAR: 'GAM_THREADS', VAR_LIMITS: (1, 1000)},
OAUTH2_TXT: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'OAUTHFILE', VAR_ACCESS: os.R_OK | os.W_OK},
OAUTH2SERVICE_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'OAUTHSERVICEFILE', VAR_ACCESS: os.R_OK | os.W_OK},
OUTPUT_DATEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
OUTPUT_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PEOPLE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
PRINT_AGU_DOMAINS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS_AND_CHILDREN: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PROCESS_WAIT_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)},
QUICK_CROS_MOVE: {VAR_TYPE: TYPE_BOOLEAN},
QUICK_INFO_USER: {VAR_TYPE: TYPE_BOOLEAN},
RESELLER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
RETRY_API_SERVICE_NOT_AVAILABLE: {VAR_TYPE: TYPE_BOOLEAN},
SECTION: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SHOW_API_CALLS_RETRY_DATA: {VAR_TYPE: TYPE_BOOLEAN},
SHOW_COMMANDS: {VAR_TYPE: TYPE_BOOLEAN},
SHOW_CONVERT_CR_NL: {VAR_TYPE: TYPE_BOOLEAN},
SHOW_COUNTS_MIN: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 100)},
SHOW_GETTINGS: {VAR_TYPE: TYPE_BOOLEAN},
SHOW_GETTINGS_GOT_NL: {VAR_TYPE: TYPE_BOOLEAN},
SHOW_MULTIPROCESS_INFO: {VAR_TYPE: TYPE_BOOLEAN},
SMTP_FQDN: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SMTP_HOST: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SMTP_USERNAME: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
SMTP_PASSWORD: {VAR_TYPE: TYPE_PASSWORD, VAR_LIMITS: (0, None)},
TLS_MIN_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MIN_VERSION', VAR_CHOICES: TLS_CHOICE_MAP},
TLS_MAX_VERSION: {VAR_TYPE: TYPE_CHOICE, VAR_ENVVAR: 'GAM_TLS_MAX_VERSION', VAR_CHOICES: TLS_CHOICE_MAP},
TIMEZONE: {VAR_TYPE: TYPE_TIMEZONE},
TODRIVE_CLEARFILTER: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_CLIENTACCESS: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_CONVERSION: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_LOCALCOPY: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_LOCALE: {VAR_TYPE: TYPE_LOCALE},
TODRIVE_NOBROWSER: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'nobrowser.txt', VAR_SFFT: (FALSE, TRUE)},
TODRIVE_NOEMAIL: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'notdemail.txt', VAR_SFFT: (FALSE, TRUE)},
TODRIVE_NO_ESCAPE_CHAR: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_PARENT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
TODRIVE_SHEET_TIMESTAMP: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_SHEET_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
TODRIVE_TIMESTAMP: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
TODRIVE_TIMEZONE: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
TODRIVE_UPLOAD_NODATA: {VAR_TYPE: TYPE_BOOLEAN},
TODRIVE_USER: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
TRUNCATE_CLIENT_ID: {VAR_TYPE: TYPE_BOOLEAN},
UPDATE_CROS_OU_WITH_ID: {VAR_TYPE: TYPE_BOOLEAN},
USE_CHAT_ADMIN_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
USE_COURSE_OWNER_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
USE_PROJECTID_AS_NAME: {VAR_TYPE: TYPE_BOOLEAN},
USER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)},
USER_SERVICE_ACCOUNT_ACCESS_ONLY: {VAR_TYPE: TYPE_BOOLEAN},
}

1184
src/gam/gamlib/glclargs.py Normal file

File diff suppressed because it is too large Load Diff

831
src/gam/gamlib/glentity.py Normal file
View File

@@ -0,0 +1,831 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM entity processing
"""
class GamEntity():
ROLE_MANAGER = 'MANAGER'
ROLE_MEMBER = 'MEMBER'
ROLE_OWNER = 'OWNER'
ROLE_LIST = [ROLE_MANAGER, ROLE_MEMBER, ROLE_OWNER]
ROLE_USER = 'USER'
ROLE_MANAGER_MEMBER = ','.join([ROLE_MANAGER, ROLE_MEMBER])
ROLE_MANAGER_OWNER = ','.join([ROLE_MANAGER, ROLE_OWNER])
ROLE_MEMBER_OWNER = ','.join([ROLE_MEMBER, ROLE_OWNER])
ROLE_MANAGER_MEMBER_OWNER = ','.join(ROLE_LIST)
ROLE_PUBLIC = 'PUBLIC'
ROLE_ALL = ROLE_MANAGER_MEMBER_OWNER
TYPE_CBCM_BROWSER = 'CBCM_BROWSER'
TYPE_CUSTOMER = 'CUSTOMER'
TYPE_EXTERNAL = 'EXTERNAL'
TYPE_OTHER = 'OTHER'
TYPE_GROUP = 'GROUP'
TYPE_SERVICE_ACCOUNT = 'SERVICE_ACCOUNT'
TYPE_USER = 'USER'
# Keys into NAMES; arbitrary values but must be unique
ACCESS_TOKEN = 'atok'
ACCOUNT = 'acct'
ACTION = 'actn'
ACTIVITY = 'actv'
ADMINISTRATOR = 'admi'
ADMIN_ROLE = 'adro'
ADMIN_ROLE_ASSIGNMENT = 'adra'
ALERT = 'alrt'
ALERT_ID = 'alri'
ALERT_FEEDBACK = 'alfb'
ALERT_FEEDBACK_ID = 'alfi'
ALIAS = 'alia'
ALIAS_EMAIL = 'alie'
ALIAS_TARGET = 'alit'
ANALYTIC_ACCOUNT = 'anac'
ANALYTIC_ACCOUNT_SUMMARY = 'anas'
ANALYTIC_DATASTREAM = 'anad'
ANALYTIC_PROPERTY = 'anap'
ANALYTIC_UA_PROPERTY = 'anau'
API = 'api '
APP_ACCESS_SETTINGS = 'apps'
APP_ID = 'appi'
APP_NAME = 'appn'
APPLICATION_SPECIFIC_PASSWORD = 'aspa'
ARROWS_ENABLED = 'arro'
ATTACHMENT = 'atta'
ATTENDEE = 'atnd'
AUDIT_ACTIVITY_REQUEST = 'auda'
AUDIT_EXPORT_REQUEST = 'audx'
AUDIT_MONITOR_REQUEST = 'audm'
BACKUP_VERIFICATION_CODES = 'buvc'
BUILDING = 'bldg'
BUILDING_ID = 'bldi'
CAA_LEVEL = 'calv'
CALENDAR = 'cale'
CALENDAR_ACL = 'cacl'
CALENDAR_SETTINGS = 'cset'
CHANNEL_CUSTOMER = 'chcu'
CHANNEL_CUSTOMER_ENTITLEMENT = 'chce'
CHANNEL_OFFER = 'chof'
CHANNEL_PRODUCT = 'chpr'
CHANNEL_SKU = 'chsk'
CHAT_BOT = 'chbo'
CHAT_ADMIN = 'chad'
CHAT_EVENT = 'chev'
CHAT_MANAGER_USER = 'chgu'
CHAT_MEMBER = 'chme'
CHAT_MEMBER_GROUP = 'chmg'
CHAT_MEMBER_USER = 'chmu'
CHAT_MESSAGE = 'chms'
CHAT_MESSAGE_ID = 'chmi'
CHAT_SPACE = 'chsp'
CHAT_THREAD = 'chth'
CHILD_ORGANIZATIONAL_UNIT = 'corg'
CHROME_APP = 'capp'
CHROME_APP_DEVICE = 'capd'
CHROME_BROWSER = 'chbr'
CHROME_BROWSER_ENROLLMENT_TOKEN = 'cbet'
CHROME_CHANNEL = 'chan'
CHROME_DEVICE = 'chdv'
CHROME_MODEL = 'chmo'
CHROME_NETWORK_ID = 'chni'
CHROME_NETWORK_NAME = 'chnn'
CHROME_PLATFORM = 'cpla'
CHROME_POLICY = 'cpol'
CHROME_POLICY_IMAGE = 'cpim'
CHROME_POLICY_SCHEMA = 'cpsc'
CHROME_PROFILE = 'cpro'
CHROME_RELEASE = 'crel'
CHROME_VERSION = 'cver'
CLASSIFICATION_LABEL = 'dlab'
CLASSIFICATION_LABEL_FIELD_ID = 'dlfi'
CLASSIFICATION_LABEL_ID = 'dlid'
CLASSIFICATION_LABEL_NAME = 'dlna'
CLASSIFICATION_LABEL_PERMISSION = 'dlpe'
CLASSIFICATION_LABEL_PERMISSION_NAME = 'dlpn'
CLASSROOM_INVITATION = 'clai'
CLASSROOM_INVITATION_OWNER = 'clio'
CLASSROOM_INVITATION_STUDENT = 'clis'
CLASSROOM_INVITATION_TEACHER = 'clit'
CLASSROOM_OAUTH2_TXT_FILE = 'coa'
CLASSROOM_USER_PROFILE = 'clup'
CLIENT_ID = 'clid'
CLIENT_SECRETS_JSON_FILE = 'csjf'
CLOUD_IDENTITY_GROUP = 'cidg'
CLOUD_STORAGE_BUCKET = 'clsb'
CLOUD_STORAGE_FILE = 'clsf'
COLLABORATOR = 'cola'
COMMAND_ID = 'cmdi'
COMPANY_DEVICE = 'codv'
CONFIG_FILE = 'conf'
CONTACT = 'cont'
CONTACT_DELEGATE = 'cond'
CONTACT_GROUP = 'cogr'
CONTACT_GROUP_NAME = 'cogn'
COPYFROM_COURSE = 'cfco'
COPYFROM_GROUP = 'cfgr'
COURSE = 'cour'
COURSE_ALIAS = 'coal'
COURSE_ANNOUNCEMENT = 'cann'
COURSE_ANNOUNCEMENT_ID = 'caid'
COURSE_ANNOUNCEMENT_STATE = 'cast'
COURSE_MATERIAL_DRIVEFILE = 'comd'
COURSE_MATERIAL_FORM = 'comf'
COURSE_MATERIAL = 'cmtl'
COURSE_MATERIAL_ID = 'cmid'
COURSE_MATERIAL_STATE = 'cmst'
COURSE_NAME = 'cona'
COURSE_STATE = 'cost'
COURSE_SUBMISSION_ID = 'csid'
COURSE_SUBMISSION_STATE = 'csst'
COURSE_TOPIC = 'ctop'
COURSE_TOPIC_ID = 'ctoi'
COURSE_WORK = 'cwrk'
COURSE_WORK_ID = 'cwid'
COURSE_WORK_STATE = 'cwst'
CREATOR_ID = 'crid'
CREDENTIALS = 'cred'
CRITERIA = 'crit'
CROS_DEVICE = 'cros'
CROS_SERIAL_NUMBER = 'crsn'
CSE_IDENTITY = 'csei'
CSE_KEYPAIR = 'csek'
CUSTOMER_DOMAIN = 'cudo'
CUSTOMER_ID = 'cuid'
DATE = 'date'
DEFAULT_LANGUAGE = 'dfla'
DELEGATE = 'dele'
DELETED_USER = 'delu'
DELIVERY = 'deli'
DEVICE = 'devi'
DEVICE_FILE = 'devf'
DIRECTORY = 'drct'
DEVICE_USER = 'devu'
DEVICE_USER_CLIENT_STATE = 'ducs'
DISCOVERY_JSON_FILE = 'disc'
DOCUMENT = 'docu'
DOMAIN = 'doma'
DOMAIN_ALIAS = 'doal'
DOMAIN_CONTACT = 'doco'
DOMAIN_PEOPLE_CONTACT = 'dopc'
DOMAIN_PROFILE = 'dopr'
DRIVE_DISK_USAGE = 'drdu'
DRIVE_FILE = 'dfil'
DRIVE_FILE_COMMENT = 'filc'
DRIVE_FILE_ID = 'fili'
DRIVE_FILE_NAME = 'filn'
DRIVE_FILE_RENAMED = 'firn'
DRIVE_FILE_REVISION = 'filr'
DRIVE_FILE_SHORTCUT = 'fils'
DRIVE_FILE_OR_FOLDER = 'fifo'
DRIVE_FILE_OR_FOLDER_ACL = 'fiac'
DRIVE_FILE_OR_FOLDER_ID = 'fifi'
DRIVE_FOLDER = 'fold'
DRIVE_FOLDER_ID = 'foli'
DRIVE_FOLDER_NAME = 'foln'
DRIVE_FOLDER_PATH = 'folp'
DRIVE_FOLDER_RENAMED = 'forn'
DRIVE_FOLDER_SHORTCUT = 'fols'
DRIVE_ORPHAN_FILE_OR_FOLDER = 'orph'
DRIVE_PARENT_FOLDER = 'fipf'
DRIVE_PARENT_FOLDER_ID = 'fipi'
DRIVE_PARENT_FOLDER_REFERENCE = 'pfrf'
DRIVE_PATH = 'drvp'
DRIVE_SETTINGS = 'drvs'
DRIVE_SHORTCUT = 'drsc'
DRIVE_SHORTCUT_ID = 'dsci'
DRIVE_3PSHORTCUT = 'dr3s'
DRIVE_TRASH = 'drvt'
EMAIL = 'emai'
EMAIL_ALIAS = 'emal'
EMAIL_SETTINGS = 'emse'
END_TIME = 'endt'
ENTITY = 'enti'
EVENT = 'evnt'
EVENT_BIRTHDAY = 'evbd'
EVENT_FOCUSTIME = 'evft'
EVENT_OUTOFOFFICE = 'evoo'
EVENT_WORKINGLOCATION = 'evwl'
FEATURE = 'feat'
FIELD = 'fiel'
FILE = 'file'
FILE_PARENT_TREE = 'fptr'
FILTER = 'filt'
FORM = 'form'
FORM_RESPONSE = 'frmr'
FORWARD_ENABLED = 'fwde'
FORWARDING_ADDRESS = 'fwda'
GCP_FOLDER = 'gcpf'
GCP_FOLDER_NAME = 'gcpn'
GMAIL_PROFILE = 'gmpr'
GROUP = 'grou'
GROUP_ALIAS = 'gali'
GROUP_EMAIL = 'gale'
GROUP_MEMBERSHIP = 'gmem'
GROUP_MEMBERSHIP_TREE = 'gmtr'
GROUP_SETTINGS = 'gset'
GROUP_TREE = 'gtre'
GUARDIAN = 'guar'
GUARDIAN_INVITATION = 'gari'
GUARDIAN_AND_INVITATION = 'gani'
IAM_POLICY = 'iamp'
IMAP_ENABLED = 'imap'
INBOUND_SSO_ASSIGNMENT = 'insa'
INBOUND_SSO_CREDENTIALS = 'insc'
INBOUND_SSO_PROFILE = 'insp'
INSTANCE = 'inst'
ITEM = 'item'
ISSUER_CN = 'iscn'
KEYBOARD_SHORTCUTS_ENABLED = 'kbsc'
LABEL = 'labe'
LABEL_ID = 'labi'
LANGUAGE = 'lang'
LICENSE = 'lice'
LOCATION = 'loca'
LOOKERSTUDIO_ASSET = 'lsas'
LOOKERSTUDIO_ASSET_DATASOURCE = 'lsad'
LOOKERSTUDIO_ASSETID = 'lsai'
LOOKERSTUDIO_ASSET_REPORT = 'lsar'
LOOKERSTUDIO_PERMISSION = 'lspe'
MD5HASH = 'md5h'
MEET_SPACE = 'mesp'
MEET_CONFERENCE = 'msco'
MEET_PARTICIPANT = 'msps'
MEET_RECORDING = 'msre'
MEET_TRANSCRIPT = 'mstr'
MEMBER = 'memb'
MEMBER_NOT_ARCHIVED = 'mena'
MEMBER_ARCHIVED = 'mear'
MEMBER_NOT_SUSPENDED = 'mens'
MEMBER_SUSPENDED = 'mesu'
MEMBER_NOT_SUSPENDED_NOT_ARCHIVED = 'nsna'
MEMBER_SUSPENDED_ARCHIVED = 'suar'
MEMBER_RESTRICTION = 'memr'
MEMBER_URI = 'memu'
MEMBERSHIP_TREE = 'metr'
MESSAGE = 'mesg'
MIMETYPE = 'mime'
MOBILE_DEVICE = 'mobi'
NAME = 'name'
NOTE = 'note'
NOTE_ACL = 'nota'
NOTES_ACLS = 'naac'
NONEDITABLE_ALIAS = 'neal'
OAUTH2_TXT_FILE = 'oaut'
OAUTH2SERVICE_JSON_FILE = 'oau2'
ORGANIZATIONAL_UNIT = 'orgu'
OTHER_CONTACT = 'otco'
OWNER = 'ownr'
OWNER_ID = 'owid'
PAGE_SIZE = 'page'
PARENT_ORGANIZATIONAL_UNIT = 'porg'
PARTICIPANT = 'part'
PEOPLE_CONTACT = 'peco'
PEOPLE_CONTACT_GROUP = 'pecg'
PEOPLE_PHOTO = 'peph'
PEOPLE_PROFILE = 'pepr'
PERMISSION = 'perm'
PERMISSION_ID = 'peid'
PERMITTEE = 'prmt'
PERSONAL_DEVICE = 'pedv'
PHOTO = 'phot'
POLICY = 'poli'
POP_ENABLED = 'popa'
PRESENTATION = 'pres'
PRINTER = 'prin'
PRINTER_ID = 'prid'
PRINTER_MODEL = 'prmd'
PRIVILEGE = 'priv'
PRODUCT = 'prod'
PROFILE_SHARING_ENABLED = 'prof'
PROJECT = 'proj'
PROJECT_FOLDER = 'prjf'
PROJECT_ID = 'prji'
PUBLIC_KEY = 'pubk'
QUERY = 'quer'
RECIPIENT = 'recp'
RECIPIENT_BCC = 'rebc'
RECIPIENT_CC = 'recc'
REPORT = 'rept'
REQUEST_ID = 'reqi'
RESOURCE_CALENDAR = 'resc'
RESOURCE_ID = 'resi'
ROLE = 'role'
ROW = 'row '
SCOPE = 'scop'
SECTION = 'sect'
SENDAS_ADDRESS = 'sasa'
SENDER = 'send'
SERVICE = 'serv'
SHAREDDRIVE = 'tdrv'
SHAREDDRIVE_ACL = 'tdac'
SHAREDDRIVE_FOLDER = 'tdfo'
SHAREDDRIVE_ID = 'tdid'
SHAREDDRIVE_NAME = 'tdna'
SHAREDDRIVE_THEME = 'tdth'
SHEET = 'shet'
SHEET_ID = 'shti'
SIGNATURE = 'sign'
SITE = 'site'
SITE_ACL = 'sacl'
SIZE = 'size'
SKU = 'sku '
SMIME_ID = 'smid'
SNIPPETS_ENABLED = 'snip'
SSO_KEY = 'ssok'
SSO_SETTINGS = 'ssos'
SOURCE_USER = 'src'
SPREADSHEET = 'sprd'
SPREADSHEET_RANGE = 'ssrn'
START_TIME = 'strt'
STATUS = 'stat'
STUDENT = 'stud'
SUBSCRIPTION = 'subs'
SVCACCT = 'svac'
SVCACCT_KEY = 'svky'
TARGET_USER = 'tgt'
TASK = 'task'
TASKLIST = 'tali'
TEACHER = 'teac'
THREAD = 'thre'
TRANSFER_APPLICATION = 'trap'
TRANSFER_ID = 'trid'
TRANSFER_REQUEST = 'trnr'
TRASHED_EVENT = 'trev'
TRUSTED_APPLICATION = 'trus'
TYPE = 'type'
UNICODE_ENCODING_ENABLED = 'unic'
UNIQUE_ID = 'uniq'
URL = 'url '
USER = 'user'
USER_ALIAS = 'uali'
USER_EMAIL = 'uema'
USER_INVITATION = 'uinv'
USER_NOT_SUSPENDED = 'uns'
USER_SCHEMA = 'usch'
USER_SUSPENDED = 'usup'
VACATION = 'vaca'
VACATION_ENABLED = 'vace'
VALUE = 'val'
VAULT_EXPORT = 'vlte'
VAULT_HOLD = 'vlth'
VAULT_MATTER = 'vltm'
VAULT_MATTER_ARTIFACT = 'vlma'
VAULT_MATTER_ID = 'vlmi'
VAULT_OPERATION = 'vlto'
VAULT_QUERY = 'vltq'
WEBCLIPS_ENABLED = 'webc'
YOUTUBE_CHANNEL = 'ytch'
# _NAMES[0] is plural, _NAMES[1] is singular unless the item name is explicitly plural (Calendar Settings)
# For items with Boolean values, both entries are singular (Forward, POP)
# These values can be translated into other languages
_NAMES = {
ACCESS_TOKEN: ['Access Tokens', 'Access Token'],
ACCOUNT: ['Google Workspace Accounts', 'Google Workspace Account'],
ACTION: ['Actions', 'Action'],
ACTIVITY: ['Activities', 'Activity'],
ADMINISTRATOR: ['Administrators', 'Administrator'],
ADMIN_ROLE: ['Admin Roles', 'Admin Role'],
ADMIN_ROLE_ASSIGNMENT: ['Admin Role Assignments', 'Admin Role Assignment'],
ALERT: ['Alerts', 'Alert'],
ALERT_ID: ['Alert IDs', 'Alert ID'],
ALERT_FEEDBACK: ['Alert Feedbacks', 'Alert Feedback'],
ALERT_FEEDBACK_ID: ['Alert Feedback IDs', 'Alert Feedback ID'],
ALIAS: ['Aliases', 'Alias'],
ALIAS_EMAIL: ['Alias Emails', 'Alias Email'],
ALIAS_TARGET: ['Alias Targets', 'Alias Target'],
ANALYTIC_ACCOUNT: ['Analytic Accounts', 'Analytic Account'],
ANALYTIC_ACCOUNT_SUMMARY: ['Analytic Account Summaries', 'Analytic Account Summary'],
ANALYTIC_DATASTREAM: ['Analytic Datastreams', 'Analytic Datastream'],
ANALYTIC_PROPERTY: ['Analytic GA4 Properties', 'Analytic GA4 Property'],
ANALYTIC_UA_PROPERTY: ['Analytic UA Properties', 'Analytic UA Property'],
API: ['APIs', 'API'],
APP_ACCESS_SETTINGS: ['Application Access Settings', 'Application Access Settings'],
APP_ID: ['Application IDs', 'Application ID'],
APP_NAME: ['Application Names', 'Application Name'],
APPLICATION_SPECIFIC_PASSWORD: ['Application Specific Password IDs', 'Application Specific Password ID'],
ARROWS_ENABLED: ['Personal Indicator Arrows Enabled', 'Personal Indicator Arrows Enabled'],
ATTACHMENT: ['Attachments', 'Attachment'],
ATTENDEE: ['Attendees', 'Attendee'],
AUDIT_ACTIVITY_REQUEST: ['Audit Activity Requests', 'Audit Activity Request'],
AUDIT_EXPORT_REQUEST: ['Audit Export Requests', 'Audit Export Request'],
AUDIT_MONITOR_REQUEST: ['Audit Monitor Requests', 'Audit Monitor Request'],
BACKUP_VERIFICATION_CODES: ['Backup Verification Codes', 'Backup Verification Codes'],
BUILDING: ['Buildings', 'Building'],
BUILDING_ID: ['Building IDs', 'Building ID'],
CAA_LEVEL: ['CAA Levels', 'CAA Level'],
CALENDAR: ['Calendars', 'Calendar'],
CALENDAR_ACL: ['Calendar ACLs', 'Calendar ACL'],
CALENDAR_SETTINGS: ['Calendar Settings', 'Calendar Settings'],
CHANNEL_CUSTOMER: ['Channel Customers', 'Channel Customer'],
CHANNEL_CUSTOMER_ENTITLEMENT: ['Channel Customer Entitlements', 'Channel Customer Entitlement'],
CHANNEL_OFFER: ['Channel Offers', 'Channel Offer'],
CHANNEL_PRODUCT: ['Channel Products', 'Channel Product'],
CHANNEL_SKU: ['Channel SKUs', 'Channel SKU'],
CHAT_BOT: ['Chat BOTs', 'Chat BOT'],
CHAT_ADMIN: ['Chat Admins', 'Chat Admin'],
CHAT_EVENT: ['Chat Events', 'Chat Event'],
CHAT_MANAGER_USER: ['Chat User Managers', 'Chat User Manager'],
CHAT_MESSAGE: ['Chat Messages', 'Chat Message'],
CHAT_MESSAGE_ID: ['Chat Message IDs', 'Chat Message ID'],
CHAT_MEMBER: ['Chat Members', 'Chat Member'],
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],
CHROME_APP: ['Chrome Applications', 'Chrome Application'],
CHROME_APP_DEVICE: ['Chrome Application Devices', 'Chrome Application Device'],
CHROME_BROWSER: ['Chrome Browsers', 'Chrome Browser'],
CHROME_BROWSER_ENROLLMENT_TOKEN: ['Chrome Browser Enrollment Tokens', 'Chrome Browser Enrollment Token'],
CHROME_CHANNEL: ['Chrome Channels', 'Chrome Channel'],
CHROME_DEVICE: ['Chrome Devices', 'Chrome Device'],
CHROME_MODEL: ['Chrome Models', 'Chrome Model'],
CHROME_NETWORK_ID: ['Chrome Network IDs', 'Chrome Network ID'],
CHROME_NETWORK_NAME: ['Chrome Network Names', 'Chrome Network Name'],
CHROME_PLATFORM: ['Chrome Platforms', 'Chrome Platform'],
CHROME_POLICY: ['Chrome Policies', 'Chrome Policy'],
CHROME_POLICY_IMAGE: ['Chrome Policy Images', 'Chrome Policy Image'],
CHROME_POLICY_SCHEMA: ['Chrome Policy Schemas', 'Chrome Policy Schema'],
CHROME_PROFILE: ['Chrome Profiles', 'Chrome Profile'],
CHROME_RELEASE: ['Chrome Releases', 'Chrome Release'],
CHROME_VERSION: ['Chrome Versions', 'Chrome Version'],
CLASSIFICATION_LABEL: ['Classification Labels', 'Classification Label'],
CLASSIFICATION_LABEL_FIELD_ID: ['Classification Label Field IDs', 'Classification Label Field ID'],
CLASSIFICATION_LABEL_ID: ['Classification Label IDs', 'Classification Label ID'],
CLASSIFICATION_LABEL_NAME: ['Classification Label Names', 'Classification Label Name'],
CLASSIFICATION_LABEL_PERMISSION: ['Classification Label Permissions', 'Classification Label Permission'],
CLASSIFICATION_LABEL_PERMISSION_NAME: ['Classification Label Permission Names', 'Classification Label Permission Name'],
CLASSROOM_INVITATION: ['Classroom Invitations', 'Classroom Invitation'],
CLASSROOM_INVITATION_OWNER: ['Classroom Owner Invitations', 'Classroom Owner Invitation'],
CLASSROOM_INVITATION_STUDENT: ['Classroom Student Invitations', 'Classroom Student Invitation'],
CLASSROOM_INVITATION_TEACHER: ['Classroom Teacher Invitations', 'Classroom Teacher Invitation'],
CLASSROOM_OAUTH2_TXT_FILE: ['Classroom OAuth2 File', 'Classroom OAuth2 File'],
CLASSROOM_USER_PROFILE: ['Classroom User Profile', 'Classroom User Profile'],
CLIENT_ID: ['Client IDs', 'Client ID'],
CLIENT_SECRETS_JSON_FILE: ['Client Secrets File', 'Client Secrets File'],
CLOUD_IDENTITY_GROUP: ['Cloud Identity Groups', 'Cloud Identity Group'],
CLOUD_STORAGE_BUCKET: ['Cloud Storage Buckets', 'Cloud Storage Bucket'],
CLOUD_STORAGE_FILE: ['Cloud Storage Files', 'Cloud Storage File'],
COLLABORATOR: ['Collaborators', 'Collaborator'],
COMMAND_ID: ['Command IDs', 'Command ID'],
COMPANY_DEVICE: ['Company Devices', 'Company Device'],
CONFIG_FILE: ['Config File', 'Config File'],
CONTACT: ['Contacts', 'Contact'],
CONTACT_DELEGATE: ['Contact Delegates', 'Contact Delegate'],
CONTACT_GROUP: ['Contact Groups', 'Contact Group'],
CONTACT_GROUP_NAME: ['Contact Group Names', 'Contact Group Name'],
COPYFROM_COURSE: ['Copy From Courses', 'CopyFrom Course'],
COPYFROM_GROUP: ['Copy From Groups', 'CopyFrom Group'],
COURSE: ['Courses', 'Course'],
COURSE_ALIAS: ['Course Aliases', 'Course Alias'],
COURSE_ANNOUNCEMENT: ['Course Announcements', 'Course Announcement'],
COURSE_ANNOUNCEMENT_ID: ['Course Announcement IDs', 'Course Announcement ID'],
COURSE_ANNOUNCEMENT_STATE: ['Course Announcement States', 'Course Announcement State'],
COURSE_MATERIAL_DRIVEFILE: ['Course Material Drive Files', 'Course Material Drive File'],
COURSE_MATERIAL_FORM: ['Course Material Forms', 'Course Material Form'],
COURSE_MATERIAL: ['Course Materials', 'Course Material'],
COURSE_MATERIAL_ID: ['Course Material IDs', 'Course Material ID'],
COURSE_MATERIAL_STATE: ['Course Material States', 'Course Material State'],
COURSE_NAME: ['Course Names', 'Course Name'],
COURSE_STATE: ['Course States', 'Course State'],
COURSE_SUBMISSION_ID: ['Course Submission IDs', 'Course Submission ID'],
COURSE_SUBMISSION_STATE: ['Course Submission States', 'Course Submission State'],
COURSE_TOPIC: ['Course Topics', 'Course Topic'],
COURSE_TOPIC_ID: ['Course Topic IDs', 'Course Topic ID'],
COURSE_WORK: ['Course Works', 'Course Work'],
COURSE_WORK_ID: ['Course Work IDs', 'Course Work ID'],
COURSE_WORK_STATE: ['Course Work States', 'Course Work State'],
CREATOR_ID: ['Creator IDs', 'Creator ID'],
CREDENTIALS: ['Credentials', 'Credentials'],
CRITERIA: ['Criteria', 'Criteria'],
CROS_DEVICE: ['CrOS Devices', 'CrOS Device'],
CROS_SERIAL_NUMBER: ['CrOS Serial Numbers', 'CrOS Serial Numbers'],
CSE_IDENTITY: ['CSE Identities', 'CSE Identity'],
CSE_KEYPAIR: ['CSE KeyPairs', 'CSE KeyPair'],
CUSTOMER_DOMAIN: ['Customer Domains', 'Customer Domain'],
CUSTOMER_ID: ['Customer IDs', 'Customer ID'],
DATE: ['Dates', 'Date'],
DEFAULT_LANGUAGE: ['Default Language', 'Default Language'],
DELEGATE: ['Delegates', 'Delegate'],
DELETED_USER: ['Deleted Users', 'Deleted User'],
DELIVERY: ['Delivery', 'Delivery'],
DEVICE: ['Devices', 'Device'],
DEVICE_FILE: ['Device Files', 'Device File'],
DEVICE_USER: ['Device Users', 'Device User'],
DEVICE_USER_CLIENT_STATE: ['Device Users Client States', 'Device User Client State'],
DIRECTORY: ['Directories', 'Directory'],
DISCOVERY_JSON_FILE: ['Discovery File', 'Discovery File'],
DOCUMENT: ['Documents', 'Document'],
DOMAIN: ['Domains', 'Domain'],
DOMAIN_ALIAS: ['Domain Aliases', 'Domain Alias'],
DOMAIN_CONTACT: ['Domain Contacts', 'Domain Contact'],
DOMAIN_PEOPLE_CONTACT: ['Domain People Contacts', 'Domain People Contact'],
DOMAIN_PROFILE: ['Domain Profiles', 'Domain Profile'],
DRIVE_DISK_USAGE: ['Drive Disk Usages', 'Drive Disk Usage'],
DRIVE_FILE: ['Drive Files', 'Drive File'],
DRIVE_FILE_COMMENT: ['Drive File Comments', 'Drive File Comment'],
DRIVE_FILE_ID: ['Drive File IDs', 'Drive File ID'],
DRIVE_FILE_NAME: ['Drive File Names', 'Drive File Name'],
DRIVE_FILE_REVISION: ['Drive File Revisions', 'Drive File Revision'],
DRIVE_FILE_RENAMED: ['Drive Files Renamed', 'Drive File Renamed'],
DRIVE_FILE_SHORTCUT: ['Drive File Shortcuts', 'Drive File Shortcut'],
DRIVE_FILE_OR_FOLDER: ['Drive Files/Folders', 'Drive File/Folder'],
DRIVE_FILE_OR_FOLDER_ACL: ['Drive File/Folder ACLs', 'Drive File/Folder ACL'],
DRIVE_FILE_OR_FOLDER_ID: ['Drive File/Folder IDs', 'Drive File/Folder ID'],
DRIVE_FOLDER: ['Drive Folders', 'Drive Folder'],
DRIVE_FOLDER_ID: ['Drive Folder IDs', 'Drive Folder ID'],
DRIVE_FOLDER_NAME: ['Drive Folder Names', 'Drive Folder Name'],
DRIVE_FOLDER_PATH: ['Drive Folder Paths', 'Drive Folder Path'],
DRIVE_FOLDER_RENAMED: ['Drive Folders Renamed', 'Drive Folder Renamed'],
DRIVE_FOLDER_SHORTCUT: ['Drive Folder Shortcuts', 'Drive Folder Shortcut'],
DRIVE_ORPHAN_FILE_OR_FOLDER: ['Drive Orphan Files/Folders', 'Drive Orphan File/Folder'],
DRIVE_PARENT_FOLDER: ['Drive Parent Folders', 'Drive Parent Folder'],
DRIVE_PARENT_FOLDER_ID: ['Drive Parent Folder IDs', 'Drive Parent Folder ID'],
DRIVE_PARENT_FOLDER_REFERENCE: ['Drive Parent Folder References', 'Drive Parent Folder Reference'],
DRIVE_PATH: ['Drive Paths', 'Drive Path'],
DRIVE_SETTINGS: ['Drive Settings', 'Drive Settings'],
DRIVE_SHORTCUT: ['Drive Shortcuts', 'Drive Shortcut'],
DRIVE_SHORTCUT_ID: ['Drive Shortcut IDs', 'Drive Shortcut ID'],
DRIVE_3PSHORTCUT: ['Drive 3rd Party Shortcuts', 'Drive 3rd Party Shortcut'],
DRIVE_TRASH: ['Drive Trash', 'Drive Trash'],
EMAIL: ['Email Addresses', 'Email Address'],
EMAIL_ALIAS: ['Email Aliases', 'Email Alias'],
EMAIL_SETTINGS: ['Email Settings', 'Email Settings'],
END_TIME: ['End Times', 'End Time'],
ENTITY: ['Entities', 'Entity'],
EVENT: ['Events', 'Event'],
EVENT_BIRTHDAY: ['Borthday Events', 'Birthday Event'],
EVENT_FOCUSTIME: ['Focus Time Events', 'Focus Time Event'],
EVENT_OUTOFOFFICE: ['Out of Office Events', 'Out of Office Event'],
EVENT_WORKINGLOCATION: ['Working Location Events', 'Working Location Event'],
FEATURE: ['Features', 'Feature'],
FIELD: ['Fields', 'Field'],
FILE: ['Files', 'File'],
FILE_PARENT_TREE: ['File Parent Trees', 'File Parent Tree'],
FILTER: ['Filters', 'Filter'],
FORM: ['Forms', 'Form'],
FORM_RESPONSE: ['Form Responses', 'Form Response'],
FORWARD_ENABLED: ['Forward Enabled', 'Forward Enabled'],
FORWARDING_ADDRESS: ['Forwarding Addresses', 'Forwarding Address'],
GCP_FOLDER: ['GCP Folders', 'GCP Folder'],
GCP_FOLDER_NAME: ['GCP Folder Names', 'GCP Folder Name'],
GMAIL_PROFILE: ['Gmail Profile', 'Gmail Profile'],
GROUP: ['Groups', 'Group'],
GROUP_ALIAS: ['Group Aliases', 'Group Alias'],
GROUP_EMAIL: ['Group Emails', 'Group Email'],
GROUP_MEMBERSHIP: ['Group Memberships', 'Group Membership'],
GROUP_MEMBERSHIP_TREE: ['Group Membership Trees', 'Group Membership Tree'],
GROUP_SETTINGS: ['Group Settings', 'Group Settings'],
GROUP_TREE: ['Group Trees', 'Group Tree'],
GUARDIAN: ['Guardians', 'Guardian'],
GUARDIAN_INVITATION: ['Guardian Invitations', 'Guardian Invitation'],
GUARDIAN_AND_INVITATION: ['Guardians and Invitations', 'Guardian and Invitation'],
IAM_POLICY: ['IAM Policies', 'IAM Policy'],
IMAP_ENABLED: ['IMAP Enabled', 'IMAP Enabled'],
INBOUND_SSO_ASSIGNMENT: ['Inbound SSO Assignments', 'Inbound SSO Assignment'],
INBOUND_SSO_CREDENTIALS: ['Inbound SSO Credentials', 'Inbound SSO Credential'],
INBOUND_SSO_PROFILE: ['Inbound SSO Profiles', 'Inbound SSO Profile'],
INSTANCE: ['Instances', 'Instance'],
ISSUER_CN: ['Issuer CNs', 'Issuer CN'],
ITEM: ['Items', 'Item'],
KEYBOARD_SHORTCUTS_ENABLED: ['Keyboard Shortcuts Enabled', 'Keyboard Shortcuts Enabled'],
LABEL: ['Labels', 'Label'],
LABEL_ID: ['Label IDs', 'Label ID'],
LANGUAGE: ['Languages', 'Language'],
LICENSE: ['Licenses', 'License'],
LOCATION: ['Locations', 'Location'],
LOOKERSTUDIO_ASSET: ['Looker Studio Assets', 'Looker Studio Asset'],
LOOKERSTUDIO_ASSET_DATASOURCE: ['Looker Studio DATA_SOURCE Assets', 'Looker Studio DATA_SOURCE Asset'],
LOOKERSTUDIO_ASSETID: ['Looker Studio Asset IDs', 'Looker Studio Asset ID'],
LOOKERSTUDIO_ASSET_REPORT: ['Looker Studio REPORT Assets', 'Looker Studio REPORT Asset'],
LOOKERSTUDIO_PERMISSION: ['Looker Studio Permissions', 'Looker Studio Permission'],
MD5HASH: ['MD5 hash', 'MD5 Hash'],
MEET_SPACE: ['Meet Spaces', 'Meet Space'],
MEET_CONFERENCE: ['Meet Conferences', 'Meet Conference'],
MEET_PARTICIPANT: ['Meet Participants', 'Meet Participant'],
MEET_RECORDING: ['Meet Recordings', 'Meet Recording'],
MEET_TRANSCRIPT: ['Meet Transcripts', 'Meet Transcript'],
MEMBER: ['Members', 'Member'],
MEMBER_NOT_ARCHIVED: ['Members (Not Archived)', 'Member (Not Archived)'],
MEMBER_ARCHIVED: ['Members (Archived)', 'Member (Archived)'],
MEMBER_NOT_SUSPENDED: ['Members (Not Suspended)', 'Member (Not Suspended)'],
MEMBER_SUSPENDED: ['Members (Suspended)', 'Member (Suspended)'],
MEMBER_NOT_SUSPENDED_NOT_ARCHIVED: ['Members (Not Suspended & Not Archived)', 'Member (Not Suspended & Not Archived)'],
MEMBER_SUSPENDED_ARCHIVED: ['Members (Suspended & Archived)', 'Member (Suspended & Archived)'],
MEMBER_RESTRICTION: ['Member Restrictions', 'Member Restriction'],
MEMBER_URI: ['Member URIs', 'Member URI'],
MEMBERSHIP_TREE: ['Membership Trees', 'Membership Tree'],
MESSAGE: ['Messages', 'Message'],
MIMETYPE: ['MIME Types', 'MIME Type'],
MOBILE_DEVICE: ['Mobile Devices', 'Mobile Device'],
NAME: ['Names', 'Name'],
NOTE: ['Notes', 'Note'],
NOTE_ACL: ['Note ACLs', 'Note ACL'],
NOTES_ACLS: ["'Note's ACLs", "Note's ACLs"],
NONEDITABLE_ALIAS: ['Non-Editable Aliases', 'Non-Editable Alias'],
OAUTH2_TXT_FILE: ['Client OAuth2 File', 'Client OAuth2 File'],
OAUTH2SERVICE_JSON_FILE: ['Service Account OAuth2 File', 'Service Account OAuth2 File'],
ORGANIZATIONAL_UNIT: ['Organizational Units', 'Organizational Unit'],
OTHER_CONTACT: ['Other Contacts', 'Other Contact'],
OWNER: ['Owners', 'Owner'],
OWNER_ID: ['Owner IDs', 'Owner ID'],
PAGE_SIZE: ['Page Size', 'Page Size'],
PARENT_ORGANIZATIONAL_UNIT: ['Parent Organizational Units', 'Parent Organizational Unit'],
PARTICIPANT: ['Participants', 'Participant'],
PEOPLE_CONTACT: ['People Contacts', 'Person Contact'],
PEOPLE_CONTACT_GROUP: ['People Contact Groups', 'People Contact Group'],
PEOPLE_PHOTO: ['People Photos', 'Person Photo'],
PEOPLE_PROFILE: ['People Profiles', 'People Profile'],
PERMISSION: ['Permissions', 'Permission'],
PERMISSION_ID: ['Permission IDs', 'Permission ID'],
PERMITTEE: ['Permittees', 'Permittee'],
PERSONAL_DEVICE: ['Personal Devices', 'Personal Device'],
PHOTO: ['Photos', 'Photo'],
POLICY: ['Policies', 'Policy'],
POP_ENABLED: ['POP Enabled', 'POP Enabled'],
PRESENTATION: ['Presentations', 'Presentation'],
PRINTER: ['Printers', 'Printer'],
PRINTER_ID: ['Printer IDs', 'Printer ID'],
PRINTER_MODEL: ['Printer Models', 'Printer Model'],
PRIVILEGE: ['Privileges', 'Privilege'],
PRODUCT: ['Products', 'Product'],
PROFILE_SHARING_ENABLED: ['Profile Sharing Enabled', 'Profile Sharing Enabled'],
PROJECT: ['Projects', 'Project'],
PROJECT_FOLDER: ['Project Folders', 'Project Folder'],
PROJECT_ID: ['Project IDs', 'Project ID'],
PUBLIC_KEY: ['Public Key', 'Public Key'],
QUERY: ['Queries', 'Query'],
RECIPIENT: ['Recipients', 'Recipient'],
RECIPIENT_BCC: ['Recipients (BCC)', 'Recipient (BCC)'],
RECIPIENT_CC: ['Recipients (CC)', 'Recipient (CC)'],
REPORT: ['Reports', 'Report'],
REQUEST_ID: ['Request IDs', 'Request ID'],
RESOURCE_CALENDAR: ['Resource Calendars', 'Resource Calendar'],
RESOURCE_ID: ['Resource IDs', 'Resource ID'],
ROLE: ['Roles', 'Role'],
ROW: ['Rows', 'Row'],
SCOPE: ['Scopes', 'Scope'],
SECTION: ['Sections', 'Section'],
SENDAS_ADDRESS: ['SendAs Addresses', 'SendAs Address'],
SENDER: ['Senders', 'Sender'],
SERVICE: ['Services', 'Service'],
SHAREDDRIVE: ['Shared Drives', 'Shared Drive'],
SHAREDDRIVE_ACL: ['Shared Drive ACLs', 'Shared Drive ACL'],
SHAREDDRIVE_FOLDER: ['Shared Drive Folders', 'Shared Drive Folder'],
SHAREDDRIVE_ID: ['Shared Drive IDs', 'Shared Drive ID'],
SHAREDDRIVE_NAME: ['Shared Drive Names', 'Shared Drive Name'],
SHAREDDRIVE_THEME: ['Shared Drive Themes', 'Shared Drive Theme'],
SHEET: ['Sheets', 'Sheet'],
SHEET_ID: ['Sheet IDs', 'Sheet ID'],
SIGNATURE: ['Signatures', 'Signature'],
SITE: ['Sites', 'Site'],
SITE_ACL: ['Site ACLs', 'Site ACL'],
SIZE: ['Sizes', 'Size'],
SKU: ['SKUs', 'SKU'],
SMIME_ID: ['S/MIME Certificate IDs', 'S/MIME Certificate ID'],
SNIPPETS_ENABLED: ['Preview Snippets Enabled', 'Preview Snippets Enabled'],
SSO_KEY: ['SSO Key', 'SSO Key'],
SSO_SETTINGS: ['SSO Settings', 'SSO Settings'],
SOURCE_USER: ['Source Users', 'Source User'],
SPREADSHEET: ['Spreadsheets', 'Spreadsheet'],
SPREADSHEET_RANGE: ['Spreadsheet Ranges', 'Spreadsheet Range'],
START_TIME: ['Start Times', 'Start Time'],
STATUS: ['Status', 'Status'],
STUDENT: ['Students', 'Student'],
SUBSCRIPTION: ['Subscriptions', 'Subscription'],
SVCACCT: ['Service Accounts', 'Service Account'],
SVCACCT_KEY: ['Service Account Keys', 'Service Account Key'],
TARGET_USER: ['Target Users', 'Target User'],
TASK: ['Tasks', 'Task'],
TASKLIST: ['Tasklists', 'Tasklist'],
TEACHER: ['Teachers', 'Teacher'],
THREAD: ['Threads', 'Thread'],
TRANSFER_APPLICATION: ['Transfer Applications', 'Transfer Application'],
TRANSFER_ID: ['Transfer IDs', 'Transfer ID'],
TRANSFER_REQUEST: ['Transfer Requests', 'Transfer Request'],
TRASHED_EVENT: ['Trashed Events', 'Trashed Event'],
TRUSTED_APPLICATION: ['Trusted Applications', 'Trusted Application'],
TYPE: ['Types', 'Type'],
UNICODE_ENCODING_ENABLED: ['UTF-8 Encoding Enabled', 'UTF-8 Encoding Enabled'],
UNIQUE_ID: ['Unique IDs', 'Unique ID'],
URL: ['URLs', 'URL'],
USER: ['Users', 'User'],
USER_ALIAS: ['User Aliases', 'User Alias'],
USER_EMAIL: ['User Emails', 'User Email'],
USER_INVITATION: ['User Invitations', 'User Invitation'],
USER_NOT_SUSPENDED: ['Users (Not suspended)', 'User (Not suspended)'],
USER_SCHEMA: ['Schemas', 'Schema'],
USER_SUSPENDED: ['Users (Suspended)', 'User (Suspended)'],
VACATION: ['Vacation', 'Vacation'],
VACATION_ENABLED: ['Vacation Enabled', 'Vacation Enabled'],
VALUE: ['Values', 'Value'],
VAULT_EXPORT: ['Vault Exports', 'Vault Export'],
VAULT_HOLD: ['Vault Holds', 'Vault Hold'],
VAULT_MATTER: ['Vault Matters', 'Vault Matter'],
VAULT_MATTER_ARTIFACT: ['Vault Matter Artifacts', 'Vault Matter Artifact'],
VAULT_MATTER_ID: ['Vault Matter IDs', 'Vault Matter ID'],
VAULT_OPERATION: ['Vault Operations', 'Vault Operation'],
VAULT_QUERY: ['Vault Queries', 'Vault Query'],
WEBCLIPS_ENABLED: ['Web Clips Enabled', 'Web Clips Enabled'],
YOUTUBE_CHANNEL: ['YouTube Channels', 'YouTube Channel'],
ROLE_MANAGER: ['Managers', 'Manager'],
ROLE_MEMBER: ['Members', 'Member'],
ROLE_OWNER: ['Owners', 'Owner'],
ROLE_ALL: ['Members, Managers, Owners', 'Member, Manager, Owner'],
ROLE_USER: ['Users', 'User'],
ROLE_MANAGER_MEMBER: ['Members, Managers', 'Member, Manager'],
ROLE_MANAGER_OWNER: ['Managers, Owners', 'Manager, Owner'],
ROLE_MEMBER_OWNER: ['Members, Owners', 'Member, Owner'],
ROLE_MANAGER_MEMBER_OWNER: ['Members, Managers, Owners', 'Member, Manager, Owner'],
ROLE_PUBLIC: ['Public', 'Public'],
}
def __init__(self):
self.entityType = None
self.forWhom = None
self.preQualifier = ''
self.postQualifier = ''
def SetGetting(self, entityType):
self.entityType = entityType
self.preQualifier = self.postQualifier = ''
def SetGettingQuery(self, entityType, query):
self.entityType = entityType
self.preQualifier = f' that match query ({query})'
self.postQualifier = f' that matched query ({query})'
def SetGettingQualifier(self, entityType, qualifier):
self.entityType = entityType
self.preQualifier = self.postQualifier = qualifier
def Getting(self):
return self.entityType
def GettingPreQualifier(self):
return self.preQualifier
def GettingPostQualifier(self):
return self.postQualifier
def SetGettingForWhom(self, forWhom):
self.forWhom = forWhom
def GettingForWhom(self):
return self.forWhom
def Choose(self, entityType, count):
return self._NAMES[entityType][[0, 1][count == 1]]
def ChooseGetting(self, count):
return self._NAMES[self.entityType][[0, 1][count == 1]]
def Plural(self, entityType):
return self._NAMES[entityType][0]
def PluralGetting(self):
return self._NAMES[self.entityType][0]
def Singular(self, entityType):
return self._NAMES[entityType][1]
def SingularGetting(self):
return self._NAMES[self.entityType][1]
def MayTakeTime(self, entityType):
if entityType:
return f', may take some time on a large {self.Singular(entityType)}...'
return ''
def FormatEntityValueList(self, entityValueList):
evList = []
for j in range(0, len(entityValueList), 2):
evList.append(self.Singular(entityValueList[j]))
evList.append(entityValueList[j+1])
return evList
def TypeMessage(self, entityType, message):
return f'{self.Singular(entityType)}: {message}'
def TypeName(self, entityType, entityName):
return f'{self.Singular(entityType)}: {entityName}'
def TypeNameMessage(self, entityType, entityName, message):
return f'{self.Singular(entityType)}: {entityName} {message}'

817
src/gam/gamlib/glgapi.py Normal file
View File

@@ -0,0 +1,817 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM GAPI resources
"""
# callGAPI throw reasons
ABORTED = 'aborted'
ABUSIVE_CONTENT_RESTRICTION = 'abusiveContentRestriction'
ACCESS_NOT_CONFIGURED = 'accessNotConfigured'
ALREADY_EXISTS = 'alreadyExists'
APPLY_LABEL_FORBIDDEN = 'applyLabelForbidden'
AUTH_ERROR = 'authError'
BACKEND_ERROR = 'backendError'
BAD_GATEWAY = 'badGateway'
BAD_REQUEST = 'badRequest'
CANNOT_ADD_PARENT = 'cannotAddParent'
CANNOT_CHANGE_ORGANIZER = 'cannotChangeOrganizer'
CANNOT_CHANGE_ORGANIZER_OF_INSTANCE = 'cannotChangeOrganizerOfInstance'
CANNOT_CHANGE_OWN_ACL = 'cannotChangeOwnAcl'
CANNOT_CHANGE_OWNER_ACL = 'cannotChangeOwnerAcl'
CANNOT_CHANGE_OWN_PRIMARY_SUBSCRIPTION = 'cannotChangeOwnPrimarySubscription'
CANNOT_COPY_FILE = 'cannotCopyFile'
CANNOT_DELETE_ONLY_REVISION = 'cannotDeleteOnlyRevision'
CANNOT_DELETE_PRIMARY_CALENDAR = 'cannotDeletePrimaryCalendar'
CANNOT_DELETE_PRIMARY_SENDAS = 'cannotDeletePrimarySendAs'
CANNOT_DELETE_RESOURCE_WITH_CHILDREN = 'cannotDeleteResourceWithChildren'
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION = 'cannotModifyInheritedTeamDrivePermission'
CANNOT_MODIFY_RESTRICTED_LABEL = 'cannotModifyRestrictedLabel'
CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT = 'cannotModifyViewersCanCopyContent'
CANNOT_MOVE_TRASHED_ITEM_INTO_TEAMDRIVE = 'cannotMoveTrashedItemIntoTeamDrive'
CANNOT_MOVE_TRASHED_ITEM_OUT_OF_TEAMDRIVE = 'cannotMoveTrashedItemOutOfTeamDrive'
CANNOT_REMOVE_OWNER = 'cannotRemoveOwner'
CANNOT_SET_EXPIRATION = 'cannotSetExpiration'
CANNOT_SHARE_GROUPS_WITHLINK = 'cannotShareGroupsWithLink'
CANNOT_SHARE_USERS_WITHLINK = 'cannotShareUsersWithLink'
CANNOT_SHARE_TEAMDRIVE_TOPFOLDER_WITH_ANYONEORDOMAINS = 'cannotShareTeamDriveTopFolderWithAnyoneOrDomains'
CANNOT_SHARE_TEAMDRIVE_WITH_NONGOOGLE_ACCOUNTS = 'cannotShareTeamDriveWithNonGoogleAccounts'
CANNOT_UPDATE_PERMISSION = 'cannotUpdatePermission'
CONDITION_NOT_MET = 'conditionNotMet'
CONFLICT = 'conflict'
CONTENT_OWNER_ACCOUNT_NOT_FOUND = 'contentOwnerAccountNotFound'
CROSS_DOMAIN_MOVE_RESTRICTION = 'crossDomainMoveRestriction'
CUSTOMER_EXCEEDED_ROLE_ASSIGNMENTS_LIMIT = 'CUSTOMER_EXCEEDED_ROLE_ASSIGNMENTS_LIMIT'
CUSTOMER_NOT_FOUND = 'customerNotFound'
CYCLIC_MEMBERSHIPS_NOT_ALLOWED = 'cyclicMembershipsNotAllowed'
DAILY_LIMIT_EXCEEDED = 'dailyLimitExceeded'
DELETED = 'deleted'
DELETED_USER_NOT_FOUND = 'deletedUserNotFound'
DOMAIN_ALIAS_NOT_FOUND = 'domainAliasNotFound'
DOMAIN_CANNOT_USE_APIS = 'domainCannotUseApis'
DOMAIN_NOT_FOUND = 'domainNotFound'
DOMAIN_NOT_VERIFIED_SECONDARY = 'domainNotVerifiedSecondary'
DOMAIN_POLICY = 'domainPolicy'
DOWNLOAD_QUOTA_EXCEEDED = 'downloadQuotaExceeded'
DUPLICATE = 'duplicate'
EVENT_DURATION_EXCEEDS_LIMIT = 'eventDurationExceedsLimit'
EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS = 'expirationDateNotAllowedForSharedDriveMembers'
FAILED_PRECONDITION = 'failedPrecondition'
FIELD_IN_USE = 'fieldInUse'
FIELD_NOT_WRITABLE = 'fieldNotWritable'
FILE_NEVER_WRITABLE = 'fileNeverWritable'
FILE_NOT_FOUND = 'fileNotFound'
FILE_ORGANIZER_NOT_YET_ENABLED_FOR_THIS_TEAMDRIVE = 'fileOrganizerNotYetEnabledForThisTeamDrive'
FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY = 'fileOrganizerOnFoldersInSharedDriveOnly'
FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED = 'fileOrganizerOnNonTeamDriveNotSupported'
FILE_OWNER_NOT_MEMBER_OF_TEAMDRIVE = 'fileOwnerNotMemberOfTeamDrive'
FILE_OWNER_NOT_MEMBER_OF_WRITER_DOMAIN = 'fileOwnerNotMemberOfWriterDomain'
FILE_WRITER_TEAMDRIVE_MOVE_IN_DISABLED = 'fileWriterTeamDriveMoveInDisabled'
FORBIDDEN = 'forbidden'
GATEWAY_TIMEOUT = 'gatewayTimeout'
GROUP_NOT_FOUND = 'groupNotFound'
ILLEGAL_ACCESS_ROLE_FOR_DEFAULT = 'illegalAccessRoleForDefault'
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES = 'insufficientAdministratorPrivileges'
INSUFFICIENT_ARCHIVED_USER_LICENSES = 'insufficientArchivedUserLicenses'
INSUFFICIENT_FILE_PERMISSIONS = 'insufficientFilePermissions'
INSUFFICIENT_PARENT_PERMISSIONS = 'insufficientParentPermissions'
INSUFFICIENT_PERMISSIONS = 'insufficientPermissions'
INTERNAL_ERROR = 'internalError'
INVALID = 'invalid'
INVALID_ARGUMENT = 'invalidArgument'
INVALID_ATTRIBUTE_VALUE = 'invalidAttributeValue'
INVALID_CUSTOMER_ID = 'invalidCustomerId'
INVALID_INPUT = 'invalidInput'
INVALID_LINK_VISIBILITY = 'invalidLinkVisibility'
INVALID_MEMBER = 'invalidMember'
INVALID_MESSAGE_ID = 'invalidMessageId'
INVALID_ORGUNIT = 'invalidOrgunit'
INVALID_ORGUNIT_NAME = 'invalidOrgunitName'
INVALID_OWNERSHIP_TRANSFER = 'invalidOwnershipTransfer'
INVALID_PARAMETER = 'invalidParameter'
INVALID_PARENT_ORGUNIT = 'invalidParentOrgunit'
INVALID_QUERY = 'invalidQuery'
INVALID_RESOURCE = 'invalidResource'
INVALID_SCHEMA_VALUE = 'invalidSchemaValue'
INVALID_SCOPE_VALUE = 'invalidScopeValue'
INVALID_SHARING_REQUEST = 'invalidSharingRequest'
LABEL_MULTIPLE_VALUES_FOR_SINGULAR_FIELD = 'labelMultipleValuesForSingularField'
LABEL_MUTATION_FORBIDDEN = 'labelMutationForbidden'
LABEL_MUTATION_ILLEGAL_SELECTION = 'labelMutationIllegalSelection'
LABEL_MUTATION_UNKNOWN_FIELD = 'labelMutationUnknownField'
LIMIT_EXCEEDED = 'limitExceeded'
LOGIN_REQUIRED = 'loginRequired'
MALFORMED_WORKING_LOCATION_EVENT = 'malformedWorkingLocationEvent'
MEMBER_NOT_FOUND = 'memberNotFound'
MYDRIVE_HIERARCHY_DEPTH_LIMIT_EXCEEDED = 'myDriveHierarchyDepthLimitExceeded'
NO_LIST_TEAMDRIVES_ADMINISTRATOR_PRIVILEGE = 'noListTeamDrivesAdministratorPrivilege'
NO_MANAGE_TEAMDRIVE_ADMINISTRATOR_PRIVILEGE = 'noManageTeamDriveAdministratorPrivilege'
NOT_A_CALENDAR_USER = 'notACalendarUser'
NOT_FOUND = 'notFound'
NOT_IMPLEMENTED = 'notImplemented'
NUM_CHILDREN_IN_NON_ROOT_LIMIT_EXCEEDED = 'numChildrenInNonRootLimitExceeded'
OPERATION_NOT_SUPPORTED = 'operationNotSupported'
ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED = 'organizerOnNonTeamDriveNotSupported'
ORGANIZER_ON_NON_TEAMDRIVE_ITEM_NOT_SUPPORTED = 'organizerOnNonTeamDriveItemNotSupported'
ORGUNIT_NOT_FOUND = 'orgunitNotFound'
OWNER_ON_TEAMDRIVE_ITEM_NOT_SUPPORTED = 'ownerOnTeamDriveItemNotSupported'
OWNERSHIP_CHANGE_ACROSS_DOMAIN_NOT_PERMITTED = 'ownershipChangeAcrossDomainNotPermitted'
PARTICIPANT_IS_NEITHER_ORGANIZER_NOR_ATTENDEE = 'participantIsNeitherOrganizerNorAttendee'
PERMISSION_DENIED = 'permissionDenied'
PERMISSION_NOT_FOUND = 'permissionNotFound'
PHOTO_NOT_FOUND = 'photoNotFound'
PUBLISH_OUT_NOT_PERMITTED = 'publishOutNotPermitted'
QUERY_REQUIRES_ADMIN_CREDENTIALS = 'queryRequiresAdminCredentials'
QUOTA_EXCEEDED = 'quotaExceeded'
RATE_LIMIT_EXCEEDED = 'rateLimitExceeded'
REQUIRED = 'required'
REQUIRED_ACCESS_LEVEL = 'requiredAccessLevel'
RESOURCE_EXHAUSTED = 'resourceExhausted'
RESOURCE_ID_NOT_FOUND = 'resourceIdNotFound'
RESOURCE_NOT_FOUND = 'resourceNotFound'
RESPONSE_PREPARATION_FAILURE = 'responsePreparationFailure'
REVISION_DELETION_NOT_SUPPORTED = 'revisionDeletionNotSupported'
REVISION_NOT_FOUND = 'revisionNotFound'
REVISIONS_NOT_SUPPORTED = 'revisionsNotSupported'
SERVICE_LIMIT = 'serviceLimit'
SERVICE_NOT_AVAILABLE = 'serviceNotAvailable'
SHARE_IN_NOT_PERMITTED = 'shareInNotPermitted'
SHARE_OUT_NOT_PERMITTED = 'shareOutNotPermitted'
SHARE_OUT_NOT_PERMITTED_TO_USER = 'shareOutNotPermittedToUser'
SHARING_RATE_LIMIT_EXCEEDED = 'sharingRateLimitExceeded'
SHORTCUT_TARGET_INVALID = 'shortcutTargetInvalid'
STORAGE_QUOTA_EXCEEDED = 'storageQuotaExceeded'
SYSTEM_ERROR = 'systemError'
TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION = 'targetUserRoleLimitedByLicenseRestriction'
TEAMDRIVE_ALREADY_EXISTS = 'teamDriveAlreadyExists'
TEAMDRIVE_DOMAIN_USERS_ONLY_RESTRICTION = 'teamDriveDomainUsersOnlyRestriction'
TEAMDRIVE_TEAM_MEMBERS_ONLY_RESTRICTION = 'teamDriveTeamMembersOnlyRestriction'
TEAMDRIVE_FILE_LIMIT_EXCEEDED = 'teamDriveFileLimitExceeded'
TEAMDRIVE_HIERARCHY_TOO_DEEP = 'teamDriveHierarchyTooDeep'
TEAMDRIVE_MEMBERSHIP_REQUIRED = 'teamDriveMembershipRequired'
TEAMDRIVES_FOLDER_MOVE_IN_NOT_SUPPORTED = 'teamDrivesFolderMoveInNotSupported'
TEAMDRIVES_FOLDER_SHARING_NOT_SUPPORTED = 'teamDrivesFolderSharingNotSupported'
TEAMDRIVES_PARENT_LIMIT = 'teamDrivesParentLimit'
TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED = 'teamDrivesSharingRestrictionNotAllowed'
TEAMDRIVES_SHORTCUT_FILE_NOT_SUPPORTED = 'teamDrivesShortcutFileNotSupported'
TIME_RANGE_EMPTY = 'timeRangeEmpty'
TRANSIENT_ERROR = 'transientError'
UNKNOWN_ERROR = 'unknownError'
UNSUPPORTED_LANGUAGE_CODE = 'unsupportedLanguageCode'
UNSUPPORTED_SUPERVISED_ACCOUNT = 'unsupportedSupervisedAccount'
UPLOAD_TOO_LARGE = 'uploadTooLarge'
USER_CANNOT_CREATE_TEAMDRIVES = 'userCannotCreateTeamDrives'
USER_ACCESS = 'userAccess'
USER_NOT_FOUND = 'userNotFound'
USER_RATE_LIMIT_EXCEEDED = 'userRateLimitExceeded'
#
DEFAULT_RETRY_REASONS = [QUOTA_EXCEEDED, RATE_LIMIT_EXCEEDED, SHARING_RATE_LIMIT_EXCEEDED, USER_RATE_LIMIT_EXCEEDED,
BACKEND_ERROR, BAD_GATEWAY, GATEWAY_TIMEOUT, INTERNAL_ERROR, TRANSIENT_ERROR]
SERVICE_NOT_AVAILABLE_RETRY_REASONS = [SERVICE_NOT_AVAILABLE]
ACTIVITY_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST]
ALERT_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, PERMISSION_DENIED]
CALENDAR_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, NOT_A_CALENDAR_USER]
CIGROUP_CREATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, ALREADY_EXISTS, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, INVALID, INVALID_ARGUMENT, PERMISSION_DENIED, FAILED_PRECONDITION]
CIGROUP_GET_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, INVALID, SYSTEM_ERROR, PERMISSION_DENIED]
CIGROUP_LIST_THROW_REASONS = [SERVICE_NOT_AVAILABLE, RESOURCE_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, INVALID, INVALID_ARGUMENT, SYSTEM_ERROR, PERMISSION_DENIED]
CIGROUP_LIST_USERKEY_THROW_REASONS = CIGROUP_LIST_THROW_REASONS+[INVALID_ARGUMENT]
CIGROUP_UPDATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS,
FORBIDDEN, BAD_REQUEST, INVALID, INVALID_INPUT, INVALID_ARGUMENT,
SYSTEM_ERROR, PERMISSION_DENIED, FAILED_PRECONDITION]
CIGROUP_RETRY_REASONS = [INVALID, SYSTEM_ERROR, SERVICE_NOT_AVAILABLE]
CIMEMBERS_THROW_REASONS = [SERVICE_NOT_AVAILABLE, MEMBER_NOT_FOUND, INVALID_MEMBER]
CISSO_CREATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, FAILED_PRECONDITION, NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, INVALID, INVALID_ARGUMENT, PERMISSION_DENIED, INTERNAL_ERROR]
CISSO_GET_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, INVALID, SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR]
CISSO_LIST_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, INVALID, SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR]
CISSO_UPDATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, FAILED_PRECONDITION, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS,
FORBIDDEN, BAD_REQUEST, INVALID, INVALID_INPUT, INVALID_ARGUMENT,
SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR]
CONTACT_DELEGATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, FAILED_PRECONDITION, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
COURSE_ACCESS_THROW_REASONS = [NOT_FOUND, INSUFFICIENT_PERMISSIONS, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
DRIVE_USER_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, DOMAIN_POLICY]
DRIVE_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS, UNKNOWN_ERROR, INVALID]
DRIVE_COPY_THROW_REASONS = DRIVE_ACCESS_THROW_REASONS+[CANNOT_COPY_FILE, BAD_REQUEST, RESPONSE_PREPARATION_FAILURE, TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
FIELD_NOT_WRITABLE, RATE_LIMIT_EXCEEDED, USER_RATE_LIMIT_EXCEEDED,
STORAGE_QUOTA_EXCEEDED, TEAMDRIVE_FILE_LIMIT_EXCEEDED, TEAMDRIVE_HIERARCHY_TOO_DEEP]
DRIVE_GET_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, DOWNLOAD_QUOTA_EXCEEDED]
DRIVE3_CREATE_ACL_THROW_REASONS = [BAD_REQUEST, INVALID, INVALID_SHARING_REQUEST, OWNERSHIP_CHANGE_ACROSS_DOMAIN_NOT_PERMITTED,
CANNOT_SET_EXPIRATION, EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS,
NOT_FOUND, TEAMDRIVE_DOMAIN_USERS_ONLY_RESTRICTION, TEAMDRIVE_TEAM_MEMBERS_ONLY_RESTRICTION,
TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION, INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED,
PUBLISH_OUT_NOT_PERMITTED, SHARE_IN_NOT_PERMITTED, SHARE_OUT_NOT_PERMITTED, SHARE_OUT_NOT_PERMITTED_TO_USER,
CANNOT_SHARE_TEAMDRIVE_TOPFOLDER_WITH_ANYONEORDOMAINS,
CANNOT_SHARE_TEAMDRIVE_WITH_NONGOOGLE_ACCOUNTS,
OWNER_ON_TEAMDRIVE_ITEM_NOT_SUPPORTED,
ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED,
ORGANIZER_ON_NON_TEAMDRIVE_ITEM_NOT_SUPPORTED,
FILE_ORGANIZER_NOT_YET_ENABLED_FOR_THIS_TEAMDRIVE,
FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY,
FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED,
TEAMDRIVES_FOLDER_SHARING_NOT_SUPPORTED, INVALID_LINK_VISIBILITY, ABUSIVE_CONTENT_RESTRICTION]
DRIVE3_GET_ACL_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, FORBIDDEN, INTERNAL_ERROR,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, INSUFFICIENT_FILE_PERMISSIONS,
UNKNOWN_ERROR, INVALID]
DRIVE3_UPDATE_ACL_THROW_REASONS = [BAD_REQUEST, INVALID_OWNERSHIP_TRANSFER, CANNOT_REMOVE_OWNER,
CANNOT_SET_EXPIRATION, EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS,
OWNERSHIP_CHANGE_ACROSS_DOMAIN_NOT_PERMITTED,
NOT_FOUND, TEAMDRIVE_DOMAIN_USERS_ONLY_RESTRICTION, TEAMDRIVE_TEAM_MEMBERS_ONLY_RESTRICTION,
TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION, INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED,
PUBLISH_OUT_NOT_PERMITTED, SHARE_IN_NOT_PERMITTED, SHARE_OUT_NOT_PERMITTED, SHARE_OUT_NOT_PERMITTED_TO_USER,
CANNOT_SHARE_TEAMDRIVE_TOPFOLDER_WITH_ANYONEORDOMAINS,
CANNOT_SHARE_TEAMDRIVE_WITH_NONGOOGLE_ACCOUNTS,
OWNER_ON_TEAMDRIVE_ITEM_NOT_SUPPORTED,
ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED,
ORGANIZER_ON_NON_TEAMDRIVE_ITEM_NOT_SUPPORTED,
FILE_ORGANIZER_NOT_YET_ENABLED_FOR_THIS_TEAMDRIVE,
FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY,
FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED,
CANNOT_UPDATE_PERMISSION,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION,
FIELD_NOT_WRITABLE, PERMISSION_NOT_FOUND]
DRIVE3_DELETE_ACL_THROW_REASONS = [BAD_REQUEST, CANNOT_REMOVE_OWNER,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED,
NOT_FOUND, PERMISSION_NOT_FOUND]
DRIVE3_MODIFY_LABEL_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, NOT_FOUND, FORBIDDEN, INTERNAL_ERROR,
FILE_NEVER_WRITABLE, APPLY_LABEL_FORBIDDEN,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, INSUFFICIENT_FILE_PERMISSIONS,
UNKNOWN_ERROR, INVALID_INPUT, BAD_REQUEST,
LABEL_MULTIPLE_VALUES_FOR_SINGULAR_FIELD, LABEL_MUTATION_FORBIDDEN,
LABEL_MUTATION_ILLEGAL_SELECTION, LABEL_MUTATION_UNKNOWN_FIELD]
DOCS_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[NOT_FOUND, PERMISSION_DENIED, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS,
BAD_REQUEST, INVALID, INVALID_ARGUMENT, FAILED_PRECONDITION]
GMAIL_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST]
GMAIL_LIST_THROW_REASONS = [FAILED_PRECONDITION, PERMISSION_DENIED, INVALID, INVALID_ARGUMENT]
GMAIL_SMIME_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, INVALID_ARGUMENT, FORBIDDEN, NOT_FOUND, PERMISSION_DENIED]
GROUP_GET_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, INVALID, SYSTEM_ERROR]
GROUP_GET_RETRY_REASONS = [INVALID, SYSTEM_ERROR, SERVICE_NOT_AVAILABLE]
GROUP_CREATE_THROW_REASONS = [DUPLICATE, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, INVALID, INVALID_INPUT]
GROUP_UPDATE_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, INVALID, INVALID_INPUT]
GROUP_SETTINGS_THROW_REASONS = [NOT_FOUND, GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, SYSTEM_ERROR, PERMISSION_DENIED,
INVALID, INVALID_ARGUMENT, INVALID_PARAMETER, INVALID_ATTRIBUTE_VALUE, INVALID_INPUT,
SERVICE_LIMIT, SERVICE_NOT_AVAILABLE, AUTH_ERROR, REQUIRED]
GROUP_SETTINGS_RETRY_REASONS = [INVALID, SERVICE_LIMIT, SERVICE_NOT_AVAILABLE]
GROUP_LIST_THROW_REASONS = [RESOURCE_NOT_FOUND, DOMAIN_NOT_FOUND, FORBIDDEN, BAD_REQUEST]
GROUP_LIST_USERKEY_THROW_REASONS = GROUP_LIST_THROW_REASONS+[INVALID_MEMBER, INVALID_INPUT]
KEEP_THROW_REASONS = [AUTH_ERROR, BAD_REQUEST, PERMISSION_DENIED, INVALID_ARGUMENT, NOT_FOUND]
LOOKERSTUDIO_THROW_REASONS = [INVALID_ARGUMENT, SERVICE_NOT_AVAILABLE, BAD_REQUEST, NOT_FOUND, PERMISSION_DENIED, INTERNAL_ERROR]
MEMBERS_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, INVALID, FORBIDDEN, SERVICE_NOT_AVAILABLE]
MEMBERS_RETRY_REASONS = [SYSTEM_ERROR, SERVICE_NOT_AVAILABLE]
ORGUNIT_GET_THROW_REASONS = [INVALID_ORGUNIT, ORGUNIT_NOT_FOUND, BACKEND_ERROR, BAD_REQUEST, INVALID_CUSTOMER_ID, LOGIN_REQUIRED]
PEOPLE_ACCESS_THROW_REASONS = [SERVICE_NOT_AVAILABLE, FORBIDDEN, PERMISSION_DENIED]
RESELLER_THROW_REASONS = [BAD_REQUEST, RESOURCE_NOT_FOUND, FORBIDDEN, INVALID]
SHEETS_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[NOT_FOUND, PERMISSION_DENIED, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS,
BAD_REQUEST, INVALID, INVALID_ARGUMENT, FAILED_PRECONDITION]
TASK_THROW_REASONS = [BAD_REQUEST, PERMISSION_DENIED, INVALID, NOT_FOUND, ACCESS_NOT_CONFIGURED]
TASKLIST_THROW_REASONS = [BAD_REQUEST, PERMISSION_DENIED, INVALID, NOT_FOUND, ACCESS_NOT_CONFIGURED]
USER_GET_THROW_REASONS = [USER_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, FORBIDDEN, BAD_REQUEST, SYSTEM_ERROR]
YOUTUBE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, UNSUPPORTED_SUPERVISED_ACCOUNT, UNSUPPORTED_LANGUAGE_CODE, CONTENT_OWNER_ACCOUNT_NOT_FOUND]
REASON_MESSAGE_MAP = {
ABORTED: [
('Label name exists or conflicts', DUPLICATE),
('The operation was aborted', ABORTED),
],
CONDITION_NOT_MET: [
('Cyclic memberships not allowed', CYCLIC_MEMBERSHIPS_NOT_ALLOWED),
('undelete', DELETED_USER_NOT_FOUND),
],
FAILED_PRECONDITION: [
('Bad Request', BAD_REQUEST),
('Mail service not enabled', SERVICE_NOT_AVAILABLE),
],
INVALID: [
('userId', USER_NOT_FOUND),
('memberKey', INVALID_MEMBER),
('A system error has occurred', SYSTEM_ERROR),
('Invalid attribute value', INVALID_ATTRIBUTE_VALUE),
('Invalid Customer Id', INVALID_CUSTOMER_ID),
('Invalid Input: INVALID_OU_ID', INVALID_ORGUNIT),
('Invalid Input: custom_schema', INVALID_SCHEMA_VALUE),
('Invalid Input: groupKey', INVALID_INPUT),
('Invalid Input: resource', INVALID_RESOURCE),
('Invalid Input:', INVALID_INPUT),
('Invalid Input', INVALID_INPUT),
('Invalid Org Unit', INVALID_ORGUNIT),
('Invalid Ou Id', INVALID_ORGUNIT),
('Invalid Ou Name', INVALID_ORGUNIT_NAME),
('Invalid Parent Orgunit Id', INVALID_PARENT_ORGUNIT),
('Invalid query', INVALID_QUERY),
('Invalid scope value', INVALID_SCOPE_VALUE),
('Invalid value', INVALID_INPUT),
('New domain name is not a verified secondary domain', DOMAIN_NOT_VERIFIED_SECONDARY),
('PermissionDenied', PERMISSION_DENIED),
],
INVALID_ARGUMENT: [
('Cannot delete primary send-as', CANNOT_DELETE_PRIMARY_SENDAS),
('Invalid id value', INVALID_MESSAGE_ID),
('Invalid ids value', INVALID_MESSAGE_ID),
],
NOT_FOUND: [
('userKey', USER_NOT_FOUND),
('groupKey', GROUP_NOT_FOUND),
('memberKey', MEMBER_NOT_FOUND),
('photo', PHOTO_NOT_FOUND),
('resource_id', RESOURCE_ID_NOT_FOUND),
('resourceId', RESOURCE_ID_NOT_FOUND),
('Customer doesn\'t exist', CUSTOMER_NOT_FOUND),
('Domain alias does not exist', DOMAIN_ALIAS_NOT_FOUND),
('Domain not found', DOMAIN_NOT_FOUND),
('domain', DOMAIN_NOT_FOUND),
('File not found', FILE_NOT_FOUND),
('Org unit not found', ORGUNIT_NOT_FOUND),
('Permission not found', PERMISSION_NOT_FOUND),
('Resource Not Found', RESOURCE_NOT_FOUND),
('Revision not found', REVISION_NOT_FOUND),
('Shared Drive not found', NOT_FOUND),
('Not Found', NOT_FOUND),
],
REQUIRED: [
('Login Required', LOGIN_REQUIRED),
('memberKey', MEMBER_NOT_FOUND),
],
RESOURCE_NOT_FOUND: [
('resourceId', RESOURCE_ID_NOT_FOUND),
],
}
class aborted(Exception):
pass
class abusiveContentRestriction(Exception):
pass
class accessNotConfigured(Exception):
pass
class alreadyExists(Exception):
pass
class applyLabelForbidden(Exception):
pass
class authError(Exception):
pass
class backendError(Exception):
pass
class badRequest(Exception):
pass
class cannotAddParent(Exception):
pass
class cannotChangeOrganizer(Exception):
pass
class cannotChangeOrganizerOfInstance(Exception):
pass
class cannotChangeOwnAcl(Exception):
pass
class cannotChangeOwnerAcl(Exception):
pass
class cannotChangeOwnPrimarySubscription(Exception):
pass
class cannotCopyFile(Exception):
pass
class cannotDeleteOnlyRevision(Exception):
pass
class cannotDeletePrimaryCalendar(Exception):
pass
class cannotDeletePrimarySendAs(Exception):
pass
class cannotDeleteResourceWithChildren(Exception):
pass
class cannotModifyInheritedTeamDrivePermission(Exception):
pass
class cannotModifyRestrictedLabel(Exception):
pass
class cannotModifyViewersCanCopyContent(Exception):
pass
class cannotMoveTrashedItemIntoTeamDrive(Exception):
pass
class cannotMoveTrashedItemOutOfTeamDrive(Exception):
pass
class cannotRemoveOwner(Exception):
pass
class cannotSetExpiration(Exception):
pass
class cannotShareGroupsWithLink(Exception):
pass
class cannotShareUsersWithLink(Exception):
pass
class cannotShareTeamDriveTopFolderWithAnyoneOrDomains(Exception):
pass
class cannotShareTeamDriveWithNonGoogleAccounts(Exception):
pass
class cannotUpdatePermission(Exception):
pass
class conditionNotMet(Exception):
pass
class conflict(Exception):
pass
class contentOwnerAccountNotFound(Exception):
pass
class crossDomainMoveRestriction(Exception):
pass
class customerExceededRoleAssignmentsLimit(Exception):
pass
class customerNotFound(Exception):
pass
class cyclicMembershipsNotAllowed(Exception):
pass
class deleted(Exception):
pass
class deletedUserNotFound(Exception):
pass
class domainAliasNotFound(Exception):
pass
class domainCannotUseApis(Exception):
pass
class domainNotFound(Exception):
pass
class domainNotVerifiedSecondary(Exception):
pass
class domainPolicy(Exception):
pass
class downloadQuotaExceeded(Exception):
pass
class duplicate(Exception):
pass
class eventDurationExceedsLimit(Exception):
pass
class expirationDateNotAllowedForSharedDriveMembers(Exception):
pass
class failedPrecondition(Exception):
pass
class fieldInUse(Exception):
pass
class fieldNotWritable(Exception):
pass
class fileNeverWritable(Exception):
pass
class fileNotFound(Exception):
pass
class fileOrganizerNotYetEnabledForThisTeamDrive(Exception):
pass
class fileOrganizerOnFoldersInSharedDriveOnly(Exception):
pass
class fileOrganizerOnNonTeamDriveNotSupported(Exception):
pass
class fileOwnerNotMemberOfTeamDrive(Exception):
pass
class fileOwnerNotMemberOfWriterDomain(Exception):
pass
class fileWriterTeamDriveMoveInDisabled(Exception):
pass
class forbidden(Exception):
pass
class groupNotFound(Exception):
pass
class illegalAccessRoleForDefault(Exception):
pass
class insufficientAdministratorPrivileges(Exception):
pass
class insufficientArchivedUserLicenses(Exception):
pass
class insufficientFilePermissions(Exception):
pass
class insufficientParentPermissions(Exception):
pass
class insufficientPermissions(Exception):
pass
class internalError(Exception):
pass
class invalid(Exception):
pass
class invalidArgument(Exception):
pass
class invalidAttributeValue(Exception):
pass
class invalidCustomerId(Exception):
pass
class invalidInput(Exception):
pass
class invalidLinkVisibility(Exception):
pass
class invalidMember(Exception):
pass
class invalidMessageId(Exception):
pass
class invalidOrgunit(Exception):
pass
class invalidOrgunitName(Exception):
pass
class invalidOwnershipTransfer(Exception):
pass
class invalidParameter(Exception):
pass
class invalidParentOrgunit(Exception):
pass
class invalidQuery(Exception):
pass
class invalidResource(Exception):
pass
class invalidSchemaValue(Exception):
pass
class invalidScopeValue(Exception):
pass
class invalidSharingRequest(Exception):
pass
class labelMultipleValuesForSingularField(Exception):
pass
class labelMutationForbidden(Exception):
pass
class labelMutationIllegalSelection(Exception):
pass
class labelMutationUnknownField(Exception):
pass
class limitExceeded(Exception):
pass
class loginRequired(Exception):
pass
class malformedWorkingLocationEvent(Exception):
pass
class memberNotFound(Exception):
pass
class noListTeamDrivesAdministratorPrivilege(Exception):
pass
class noManageTeamDriveAdministratorPrivilege(Exception):
pass
class notACalendarUser(Exception):
pass
class notFound(Exception):
pass
class notImplemented(Exception):
pass
class operationNotSupported(Exception):
pass
class organizerOnNonTeamDriveNotSupported(Exception):
pass
class organizerOnNonTeamDriveItemNotSupported(Exception):
pass
class orgunitNotFound(Exception):
pass
class ownerOnTeamDriveItemNotSupported(Exception):
pass
class ownershipChangeAcrossDomainNotPermitted(Exception):
pass
class participantIsNeitherOrganizerNorAttendee(Exception):
pass
class permissionDenied(Exception):
pass
class permissionNotFound(Exception):
pass
class photoNotFound(Exception):
pass
class publishOutNotPermitted(Exception):
pass
class queryRequiresAdminCredentials(Exception):
pass
class quotaExceeded(Exception):
pass
class rateLimitExceeded(Exception):
pass
class required(Exception):
pass
class requiredAccessLevel(Exception):
pass
class resourceExhausted(Exception):
pass
class resourceIdNotFound(Exception):
pass
class resourceNotFound(Exception):
pass
class responsePreparationFailure(Exception):
pass
class revisionDeletionNotSupported(Exception):
pass
class revisionNotFound(Exception):
pass
class revisionsNotSupported(Exception):
pass
class serviceLimit(Exception):
pass
class serviceNotAvailable(Exception):
pass
class shareInNotPermitted(Exception):
pass
class shareOutNotPermitted(Exception):
pass
class shareOutNotPermittedToUser(Exception):
pass
class sharingRateLimitExceeded(Exception):
pass
class shortcutTargetInvalid(Exception):
pass
class storageQuotaExceeded(Exception):
pass
class systemError(Exception):
pass
class targetUserRoleLimitedByLicenseRestriction(Exception):
pass
class teamDriveAlreadyExists(Exception):
pass
class teamDriveDomainUsersOnlyRestriction(Exception):
pass
class teamDriveTeamMembersOnlyRestriction(Exception):
pass
class teamDriveFileLimitExceeded(Exception):
pass
class teamDriveHierarchyTooDeep(Exception):
pass
class teamDriveMembershipRequired(Exception):
pass
class teamDrivesFolderMoveInNotSupported(Exception):
pass
class teamDrivesFolderSharingNotSupported(Exception):
pass
class teamDrivesParentLimit(Exception):
pass
class teamDrivesSharingRestrictionNotAllowed(Exception):
pass
class teamDrivesShortcutFileNotSupported(Exception):
pass
class timeRangeEmpty(Exception):
pass
class transientError(Exception):
pass
class unknownError(Exception):
pass
class unsupportedLanguageCode(Exception):
pass
class unsupportedSupervisedAccount(Exception):
pass
class uploadTooLarge(Exception):
pass
class userCannotCreateTeamDrives(Exception):
pass
class userAccess(Exception):
pass
class userNotFound(Exception):
pass
class userRateLimitExceeded(Exception):
pass
REASON_EXCEPTION_MAP = {
ABORTED: aborted,
ABUSIVE_CONTENT_RESTRICTION: abusiveContentRestriction,
ACCESS_NOT_CONFIGURED: accessNotConfigured,
ALREADY_EXISTS: alreadyExists,
APPLY_LABEL_FORBIDDEN: applyLabelForbidden,
AUTH_ERROR: authError,
BACKEND_ERROR: backendError,
BAD_REQUEST: badRequest,
CANNOT_ADD_PARENT: cannotAddParent,
CANNOT_CHANGE_ORGANIZER: cannotChangeOrganizer,
CANNOT_CHANGE_ORGANIZER_OF_INSTANCE: cannotChangeOrganizerOfInstance,
CANNOT_CHANGE_OWN_ACL: cannotChangeOwnAcl,
CANNOT_CHANGE_OWNER_ACL: cannotChangeOwnerAcl,
CANNOT_CHANGE_OWN_PRIMARY_SUBSCRIPTION: cannotChangeOwnPrimarySubscription,
CANNOT_COPY_FILE: cannotCopyFile,
CANNOT_DELETE_ONLY_REVISION: cannotDeleteOnlyRevision,
CANNOT_DELETE_PRIMARY_CALENDAR: cannotDeletePrimaryCalendar,
CANNOT_DELETE_PRIMARY_SENDAS: cannotDeletePrimarySendAs,
CANNOT_DELETE_RESOURCE_WITH_CHILDREN: cannotDeleteResourceWithChildren,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION: cannotModifyInheritedTeamDrivePermission,
CANNOT_MODIFY_RESTRICTED_LABEL: cannotModifyRestrictedLabel,
CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT: cannotModifyViewersCanCopyContent,
CANNOT_MOVE_TRASHED_ITEM_INTO_TEAMDRIVE: cannotMoveTrashedItemIntoTeamDrive,
CANNOT_MOVE_TRASHED_ITEM_OUT_OF_TEAMDRIVE: cannotMoveTrashedItemOutOfTeamDrive,
CANNOT_REMOVE_OWNER: cannotRemoveOwner,
CANNOT_SET_EXPIRATION: cannotSetExpiration,
CANNOT_SHARE_GROUPS_WITHLINK: cannotShareGroupsWithLink,
CANNOT_SHARE_USERS_WITHLINK: cannotShareUsersWithLink,
CANNOT_SHARE_TEAMDRIVE_TOPFOLDER_WITH_ANYONEORDOMAINS: cannotShareTeamDriveTopFolderWithAnyoneOrDomains,
CANNOT_SHARE_TEAMDRIVE_WITH_NONGOOGLE_ACCOUNTS: cannotShareTeamDriveWithNonGoogleAccounts,
CANNOT_UPDATE_PERMISSION: cannotUpdatePermission,
CONDITION_NOT_MET: conditionNotMet,
CONFLICT: conflict,
CONTENT_OWNER_ACCOUNT_NOT_FOUND: contentOwnerAccountNotFound,
CROSS_DOMAIN_MOVE_RESTRICTION: crossDomainMoveRestriction,
CUSTOMER_EXCEEDED_ROLE_ASSIGNMENTS_LIMIT: customerExceededRoleAssignmentsLimit,
CUSTOMER_NOT_FOUND: customerNotFound,
CYCLIC_MEMBERSHIPS_NOT_ALLOWED: cyclicMembershipsNotAllowed,
DELETED: deleted,
DELETED_USER_NOT_FOUND: deletedUserNotFound,
DOMAIN_ALIAS_NOT_FOUND: domainAliasNotFound,
DOMAIN_CANNOT_USE_APIS: domainCannotUseApis,
DOMAIN_NOT_FOUND: domainNotFound,
DOMAIN_NOT_VERIFIED_SECONDARY: domainNotVerifiedSecondary,
DOMAIN_POLICY: domainPolicy,
DOWNLOAD_QUOTA_EXCEEDED: downloadQuotaExceeded,
DUPLICATE: duplicate,
EVENT_DURATION_EXCEEDS_LIMIT: eventDurationExceedsLimit,
EXPIRATION_DATE_NOT_ALLOWED_FOR_SHARED_DRIVE_MEMBERS: expirationDateNotAllowedForSharedDriveMembers,
FAILED_PRECONDITION: failedPrecondition,
FIELD_IN_USE: fieldInUse,
FIELD_NOT_WRITABLE: fieldNotWritable,
FILE_NEVER_WRITABLE: fileNeverWritable,
FILE_NOT_FOUND: fileNotFound,
FILE_ORGANIZER_NOT_YET_ENABLED_FOR_THIS_TEAMDRIVE: fileOrganizerNotYetEnabledForThisTeamDrive,
FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY: fileOrganizerOnFoldersInSharedDriveOnly,
FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED: fileOrganizerOnNonTeamDriveNotSupported,
FILE_OWNER_NOT_MEMBER_OF_TEAMDRIVE: fileOwnerNotMemberOfTeamDrive,
FILE_OWNER_NOT_MEMBER_OF_WRITER_DOMAIN: fileOwnerNotMemberOfWriterDomain,
FILE_WRITER_TEAMDRIVE_MOVE_IN_DISABLED: fileWriterTeamDriveMoveInDisabled,
FORBIDDEN: forbidden,
GROUP_NOT_FOUND: groupNotFound,
ILLEGAL_ACCESS_ROLE_FOR_DEFAULT: illegalAccessRoleForDefault,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES: insufficientAdministratorPrivileges,
INSUFFICIENT_ARCHIVED_USER_LICENSES: insufficientArchivedUserLicenses,
INSUFFICIENT_FILE_PERMISSIONS: insufficientFilePermissions,
INSUFFICIENT_PARENT_PERMISSIONS: insufficientParentPermissions,
INSUFFICIENT_PERMISSIONS: insufficientPermissions,
INTERNAL_ERROR: internalError,
INVALID: invalid,
INVALID_ARGUMENT: invalidArgument,
INVALID_ATTRIBUTE_VALUE: invalidAttributeValue,
INVALID_CUSTOMER_ID: invalidCustomerId,
INVALID_INPUT: invalidInput,
INVALID_LINK_VISIBILITY: invalidLinkVisibility,
INVALID_MEMBER: invalidMember,
INVALID_MESSAGE_ID: invalidMessageId,
INVALID_ORGUNIT: invalidOrgunit,
INVALID_ORGUNIT_NAME: invalidOrgunitName,
INVALID_OWNERSHIP_TRANSFER: invalidOwnershipTransfer,
INVALID_PARAMETER: invalidParameter,
INVALID_PARENT_ORGUNIT: invalidParentOrgunit,
INVALID_QUERY: invalidQuery,
INVALID_RESOURCE: invalidResource,
INVALID_SCHEMA_VALUE: invalidSchemaValue,
INVALID_SCOPE_VALUE: invalidScopeValue,
INVALID_SHARING_REQUEST: invalidSharingRequest,
LABEL_MULTIPLE_VALUES_FOR_SINGULAR_FIELD: labelMultipleValuesForSingularField,
LABEL_MUTATION_FORBIDDEN: labelMutationForbidden,
LABEL_MUTATION_ILLEGAL_SELECTION: labelMutationIllegalSelection,
LABEL_MUTATION_UNKNOWN_FIELD: labelMutationUnknownField,
LIMIT_EXCEEDED: limitExceeded,
LOGIN_REQUIRED: loginRequired,
MALFORMED_WORKING_LOCATION_EVENT: malformedWorkingLocationEvent,
MEMBER_NOT_FOUND: memberNotFound,
NO_LIST_TEAMDRIVES_ADMINISTRATOR_PRIVILEGE: noListTeamDrivesAdministratorPrivilege,
NO_MANAGE_TEAMDRIVE_ADMINISTRATOR_PRIVILEGE: noManageTeamDriveAdministratorPrivilege,
NOT_A_CALENDAR_USER: notACalendarUser,
NOT_FOUND: notFound,
NOT_IMPLEMENTED: notImplemented,
OPERATION_NOT_SUPPORTED: operationNotSupported,
ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED: organizerOnNonTeamDriveNotSupported,
ORGANIZER_ON_NON_TEAMDRIVE_ITEM_NOT_SUPPORTED: organizerOnNonTeamDriveItemNotSupported,
ORGUNIT_NOT_FOUND: orgunitNotFound,
OWNER_ON_TEAMDRIVE_ITEM_NOT_SUPPORTED: ownerOnTeamDriveItemNotSupported,
OWNERSHIP_CHANGE_ACROSS_DOMAIN_NOT_PERMITTED: ownershipChangeAcrossDomainNotPermitted,
PARTICIPANT_IS_NEITHER_ORGANIZER_NOR_ATTENDEE: participantIsNeitherOrganizerNorAttendee,
PERMISSION_DENIED: permissionDenied,
PERMISSION_NOT_FOUND: permissionNotFound,
PHOTO_NOT_FOUND: photoNotFound,
PUBLISH_OUT_NOT_PERMITTED: publishOutNotPermitted,
QUERY_REQUIRES_ADMIN_CREDENTIALS: queryRequiresAdminCredentials,
QUOTA_EXCEEDED: quotaExceeded,
RATE_LIMIT_EXCEEDED: rateLimitExceeded,
REQUIRED: required,
REQUIRED_ACCESS_LEVEL: requiredAccessLevel,
RESOURCE_EXHAUSTED: resourceExhausted,
RESOURCE_ID_NOT_FOUND: resourceIdNotFound,
RESOURCE_NOT_FOUND: resourceNotFound,
RESPONSE_PREPARATION_FAILURE: responsePreparationFailure,
REVISION_DELETION_NOT_SUPPORTED: revisionDeletionNotSupported,
REVISION_NOT_FOUND: revisionNotFound,
REVISIONS_NOT_SUPPORTED: revisionsNotSupported,
SERVICE_LIMIT: serviceLimit,
SERVICE_NOT_AVAILABLE: serviceNotAvailable,
SHARE_IN_NOT_PERMITTED: shareInNotPermitted,
SHARE_OUT_NOT_PERMITTED: shareOutNotPermitted,
SHARE_OUT_NOT_PERMITTED_TO_USER: shareOutNotPermittedToUser,
SHARING_RATE_LIMIT_EXCEEDED: sharingRateLimitExceeded,
SHORTCUT_TARGET_INVALID: shortcutTargetInvalid,
STORAGE_QUOTA_EXCEEDED: storageQuotaExceeded,
SYSTEM_ERROR: systemError,
TARGET_USER_ROLE_LIMITED_BY_LICENSE_RESTRICTION: targetUserRoleLimitedByLicenseRestriction,
TEAMDRIVE_ALREADY_EXISTS: teamDriveAlreadyExists,
TEAMDRIVE_DOMAIN_USERS_ONLY_RESTRICTION: teamDriveDomainUsersOnlyRestriction,
TEAMDRIVE_TEAM_MEMBERS_ONLY_RESTRICTION: teamDriveTeamMembersOnlyRestriction,
TEAMDRIVE_FILE_LIMIT_EXCEEDED: teamDriveFileLimitExceeded,
TEAMDRIVE_HIERARCHY_TOO_DEEP: teamDriveHierarchyTooDeep,
TEAMDRIVE_MEMBERSHIP_REQUIRED: teamDriveMembershipRequired,
TEAMDRIVES_FOLDER_MOVE_IN_NOT_SUPPORTED: teamDrivesFolderMoveInNotSupported,
TEAMDRIVES_FOLDER_SHARING_NOT_SUPPORTED: teamDrivesFolderSharingNotSupported,
TEAMDRIVES_PARENT_LIMIT: teamDrivesParentLimit,
TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED: teamDrivesSharingRestrictionNotAllowed,
TEAMDRIVES_SHORTCUT_FILE_NOT_SUPPORTED: teamDrivesShortcutFileNotSupported,
TIME_RANGE_EMPTY: timeRangeEmpty,
TRANSIENT_ERROR: transientError,
UNKNOWN_ERROR: unknownError,
UNSUPPORTED_LANGUAGE_CODE: unsupportedLanguageCode,
UNSUPPORTED_SUPERVISED_ACCOUNT: unsupportedSupervisedAccount,
UPLOAD_TOO_LARGE: uploadTooLarge,
USER_CANNOT_CREATE_TEAMDRIVES: userCannotCreateTeamDrives,
USER_ACCESS: userAccess,
USER_NOT_FOUND: userNotFound,
USER_RATE_LIMIT_EXCEEDED: userRateLimitExceeded,
}

98
src/gam/gamlib/glgdata.py Normal file
View File

@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM GData resources
"""
API_DEPRECATED_MSG = 'Contacts API is being deprecated.'
# callGData throw errors
API_DEPRECATED = 612
BAD_GATEWAY = 601
BAD_REQUEST = 602
DOES_NOT_EXIST = 1301
ENTITY_EXISTS = 1300
FORBIDDEN = 603
GATEWAY_TIMEOUT = 612
INSUFFICIENT_PERMISSIONS = 604
INTERNAL_SERVER_ERROR = 1000
INVALID_DOMAIN = 605
INVALID_INPUT = 1317
INVALID_VALUE = 1801
NAME_NOT_VALID = 1303
NOT_FOUND = 606
NOT_IMPLEMENTED = 607
PRECONDITION_FAILED = 608
QUOTA_EXCEEDED = 609
SERVICE_NOT_APPLICABLE = 1410
SERVICE_UNAVAILABLE = 610
TOKEN_EXPIRED = 611
TOKEN_INVALID = 403
UNKNOWN_ERROR = 600
#
NON_TERMINATING_ERRORS = [API_DEPRECATED, BAD_GATEWAY, GATEWAY_TIMEOUT, QUOTA_EXCEEDED, SERVICE_UNAVAILABLE, TOKEN_EXPIRED]
EMAILSETTINGS_THROW_LIST = [INVALID_DOMAIN, DOES_NOT_EXIST, SERVICE_NOT_APPLICABLE, BAD_REQUEST, NAME_NOT_VALID, INTERNAL_SERVER_ERROR, INVALID_VALUE]
#
class apiDeprecated(Exception):
pass
class badRequest(Exception):
pass
class doesNotExist(Exception):
pass
class entityExists(Exception):
pass
class forbidden(Exception):
pass
class insufficientPermissions(Exception):
pass
class internalServerError(Exception):
pass
class invalidDomain(Exception):
pass
class invalidInput(Exception):
pass
class invalidValue(Exception):
pass
class nameNotValid(Exception):
pass
class notFound(Exception):
pass
class notImplemented(Exception):
pass
class preconditionFailed(Exception):
pass
class serviceNotApplicable(Exception):
pass
ERROR_CODE_EXCEPTION_MAP = {
API_DEPRECATED: apiDeprecated,
BAD_REQUEST: badRequest,
DOES_NOT_EXIST: doesNotExist,
ENTITY_EXISTS: entityExists,
FORBIDDEN: forbidden,
INSUFFICIENT_PERMISSIONS: insufficientPermissions,
INTERNAL_SERVER_ERROR: internalServerError,
INVALID_DOMAIN: invalidDomain,
INVALID_INPUT: invalidInput,
INVALID_VALUE: invalidValue,
NAME_NOT_VALID: nameNotValid,
NOT_FOUND: notFound,
NOT_IMPLEMENTED: notImplemented,
PRECONDITION_FAILED: preconditionFailed,
SERVICE_NOT_APPLICABLE: serviceNotApplicable,
}

307
src/gam/gamlib/glglobals.py Normal file
View File

@@ -0,0 +1,307 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM global variables
"""
# The following GM_XXX constants are arbitrary but must be unique
# Most errors print a message and bail out with a return code
# Some commands want to set a non-zero return code but not bail
# GAM admin user
ADMIN = 'admin'
# Number/length of API call retries
API_CALLS_RETRY_DATA = 'rtry'
# GAM cache directory. If no_cache is True, this variable will be set to None
CACHE_DIR = 'gacd'
# Reset GAM cache directory after discovery
CACHE_DISCOVERY_ONLY = 'gcdo'
# Classroom service not available
CLASSROOM_SERVICE_NOT_AVAILABLE = 'csna'
# Command logging
CMDLOG_HANDLER = 'clha'
CMDLOG_LOGGER = 'cllo'
# Convert to local time
CONVERT_TO_LOCAL_TIME = 'ctlt'
# Credentials scopes
CREDENTIALS_SCOPES = 'crsc'
# csvfile keyfield <FieldName> [delimiter <Character>] (matchfield <FieldName> <MatchPattern>)* [datafield <FieldName>(:<FieldName>*) [delimiter <String>]]
CSVFILE = 'csvf'
# { key: [datafieldvalues]}
CSV_DATA_DICT = 'csdd'
CSV_KEY_FIELD = 'cskf'
CSV_SUBKEY_FIELD = 'cssk'
CSV_DATA_FIELD = 'csdf'
# Filter for input column drop values
CSV_INPUT_ROW_DROP_FILTER = 'cird'
# Mode (and|or) for input column drop values
CSV_INPUT_ROW_DROP_FILTER_MODE = 'cidm'
# Filter for input column values
CSV_INPUT_ROW_FILTER = 'cirf'
# Mode (and|or) for input column values
CSV_INPUT_ROW_FILTER_MODE = 'cirm'
# Limit number of input rows
CSV_INPUT_ROW_LIMIT = 'cirl'
# Column delimiter in CSV output file
CSV_OUTPUT_COLUMN_DELIMITER = 'codl'
# Filter for output column headers to drop
CSV_OUTPUT_HEADER_DROP_FILTER = 'cohd'
# Filter for output column headers
CSV_OUTPUT_HEADER_FILTER = 'cohf'
# Force output column headers
CSV_OUTPUT_HEADER_FORCE = 'cofh'
# Order output column headers
CSV_OUTPUT_HEADER_ORDER = 'coho'
# No escape character in CSV output file
CSV_OUTPUT_NO_ESCAPE_CHAR = 'cone'
# Quote character in CSV output file
CSV_OUTPUT_QUOTE_CHAR = 'coqc'
# Filter for output column drop values
CSV_OUTPUT_ROW_DROP_FILTER = 'cord'
# Mode (and|or) for output column drop values
CSV_OUTPUT_ROW_DROP_FILTER_MODE = 'codm'
# Filter for output column values
CSV_OUTPUT_ROW_FILTER = 'corf'
# Mode (and|or) for output column values
CSV_OUTPUT_ROW_FILTER_MODE = 'corm'
# Limit number of output rows
CSV_OUTPUT_ROW_LIMIT = 'corl'
# Add timestamp column to CSV output file
CSV_OUTPUT_TIMESTAMP_COLUMN = 'cotc'
# Output sort headers
CSV_OUTPUT_SORT_HEADERS = 'cosh'
# CSV todrive options
CSV_TODRIVE = 'todr'
# Current API services
CURRENT_API_SERVICES = 'caps'
# Current Client API
CURRENT_CLIENT_API = 'ccap'
# Current Client API scopes
CURRENT_CLIENT_API_SCOPES = 'ccas'
# Current Service Account API
CURRENT_SVCACCT_API = 'csap'
# Current Service Account API scopes
CURRENT_SVCACCT_API_SCOPES = 'csas'
# Current Service Account user
CURRENT_SVCACCT_USER = 'csa'
# datetime.datetime.now
DATETIME_NOW = 'dtno'
# If debug_level > 0: extra_args['prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
DEBUG_LEVEL = 'dbgl'
# Decoded ID token
DECODED_ID_TOKEN = 'didt'
# Index of start of <UserTypeEntity> in command line
ENTITY_CL_DELAY_START = 'ecld'
ENTITY_CL_START = 'ecls'
# Extra arguments to pass to GAPI functions
EXTRA_ARGS_LIST = 'exad'
# gam.cfg file
GAM_CFG_FILE = 'gcfi'
GAM_CFG_PATH = 'gcpa'
GAM_CFG_SECTION = 'gcse'
GAM_CFG_SECTION_NAME = 'gcsn'
# Path to gam
GAM_PATH = 'gpth'
# Python source, PyInstaller or StaticX?
GAM_TYPE = 'gtyp'
# Length of last Got message
LAST_GOT_MSG_LEN = 'lgml'
# License SKUs
LICENSE_SKUS = 'lsku'
# Make Building ID/Name map
MAKE_BUILDING_ID_NAME_MAP = 'mkbm'
# Dictionary mapping Building ID to Name
MAP_BUILDING_ID_TO_NAME = 'bi2n'
# Dictionary mapping Building Name to ID
MAP_BUILDING_NAME_TO_ID = 'bn2i'
# Dictionary mapping OrgUnit ID to Name
MAP_ORGUNIT_ID_TO_NAME = 'oi2n'
# Dictionary mapping Shared Drive ID to Name
MAP_SHAREDDRIVE_ID_TO_NAME = 'si2n'
# Make Role ID/Name map
MAKE_ROLE_ID_NAME_MAP = 'mkrm'
# Dictionary mapping Role ID to Name
MAP_ROLE_ID_TO_NAME = 'ri2n'
# Dictionary mapping Role Name to ID
MAP_ROLE_NAME_TO_ID = 'rn2i'
# Dictionary mapping User ID to Name
MAP_USER_ID_TO_NAME = 'ui2n'
# Multiprocess exit condition
MULTIPROCESS_EXIT_CONDITION = 'mpec'
# Multiprocess exit processing
MULTIPROCESS_EXIT_PROCESSING = 'mpep'
# Number of batch items
NUM_BATCH_ITEMS = 'nbat'
# Values retrieved from oauth2service.json
OAUTH2SERVICE_CLIENT_ID = 'osci'
OAUTH2SERVICE_JSON_DATA = 'osjd'
# Values retrieved from oauth2.txt
OAUTH2_CLIENT_ID = 'oaci'
# oauth2.txt lock file
OAUTH2_TXT_LOCK = 'oatl'
# Output date format, empty defalts to ISOFormat
OUTPUT_DATEFORMAT = 'oudf'
# Output time format, empty defalts to ISOFormat
OUTPUT_TIMEFORMAT = 'outf'
# gam.cfg parser
PARSER = 'pars'
# Process ID
PID = 'pid '
# Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'pagu'
# OrgUnits for print cros
PRINT_CROS_OUS = 'pcou'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'pcoc'
# Check API calls rate
RATE_CHECK_COUNT = 'rccn'
RATE_CHECK_START = 'rcst'
# Section name from outer gam, passed to inner gams
SECTION = 'sect'
# Enable/disable "Getting ... " messages
SHOW_GETTINGS = 'shog'
# Enable/disable NL at end of "Got ..." messages
SHOW_GETTINGS_GOT_NL = 'shgn'
# redirected files
SAVED_STDOUT = 'svso'
STDERR = 'stde'
STDOUT = 'stdo'
# Scopes values retrieved from oauth2service.json
SVCACCT_SCOPES = 'sasc'
# Were scopes values retrieved from oauth2service.json
SVCACCT_SCOPES_DEFINED = 'sasd'
# Most errors print a message and bail out with a return code
# Some commands want to set a non-zero return code but not bail
SYSEXITRC = 'sxrc'
# Encodings
SYS_ENCODING = 'syen'
# Shared by threadBatchWorker and threadBatchGAMCommands
TBATCH_QUEUE = 'batq'
# redirected file fields: name, mode, encoding, write header, multiproces, queue
REDIRECT_NAME = 'rdfn'
REDIRECT_MODE = 'rdmo'
REDIRECT_FD = 'rdfd'
REDIRECT_MULTI_FD = 'rdmf'
REDIRECT_STD = 'rdst'
REDIRECT_ENCODING = 'rden'
REDIRECT_WRITE_HEADER = 'rdwh'
REDIRECT_MULTIPROCESS = 'rdmp'
REDIRECT_QUEUE = 'rdq'
REDIRECT_QUEUE_NAME = 'name'
REDIRECT_QUEUE_TODRIVE = 'todrive'
REDIRECT_QUEUE_CSVPF = 'csvpf'
REDIRECT_QUEUE_DATA = 'rows'
REDIRECT_QUEUE_ARGS = 'args'
REDIRECT_QUEUE_GLOBALS = 'globals'
REDIRECT_QUEUE_VALUES = 'values'
REDIRECT_QUEUE_START = 'start'
REDIRECT_QUEUE_END = 'end'
REDIRECT_QUEUE_EOF = 'eof'
#
Globals = {
ADMIN: None,
API_CALLS_RETRY_DATA: {},
CACHE_DIR: None,
CACHE_DISCOVERY_ONLY: True,
CLASSROOM_SERVICE_NOT_AVAILABLE: False,
CMDLOG_HANDLER: None,
CMDLOG_LOGGER: None,
CONVERT_TO_LOCAL_TIME: False,
CREDENTIALS_SCOPES: set(),
CSVFILE: {},
CSV_DATA_DICT: {},
CSV_KEY_FIELD: None,
CSV_SUBKEY_FIELD: None,
CSV_DATA_FIELD: None,
CSV_INPUT_ROW_DROP_FILTER: [],
CSV_INPUT_ROW_DROP_FILTER_MODE: False,
CSV_INPUT_ROW_FILTER: [],
CSV_INPUT_ROW_FILTER_MODE: True,
CSV_INPUT_ROW_LIMIT: 0,
CSV_OUTPUT_COLUMN_DELIMITER: None,
CSV_OUTPUT_HEADER_DROP_FILTER: [],
CSV_OUTPUT_HEADER_FILTER: [],
CSV_OUTPUT_HEADER_FORCE: [],
CSV_OUTPUT_HEADER_ORDER: [],
CSV_OUTPUT_NO_ESCAPE_CHAR: None,
CSV_OUTPUT_QUOTE_CHAR: None,
CSV_OUTPUT_ROW_DROP_FILTER: [],
CSV_OUTPUT_ROW_DROP_FILTER_MODE: False,
CSV_OUTPUT_ROW_FILTER: [],
CSV_OUTPUT_ROW_FILTER_MODE: True,
CSV_OUTPUT_ROW_LIMIT: 0,
CSV_OUTPUT_SORT_HEADERS: [],
CSV_OUTPUT_TIMESTAMP_COLUMN: None,
CSV_TODRIVE: {},
CURRENT_API_SERVICES: {},
CURRENT_CLIENT_API: None,
CURRENT_CLIENT_API_SCOPES: set(),
CURRENT_SVCACCT_API: None,
CURRENT_SVCACCT_API_SCOPES: set(),
CURRENT_SVCACCT_USER: None,
DATETIME_NOW: None,
DEBUG_LEVEL: 0,
DECODED_ID_TOKEN: None,
ENTITY_CL_DELAY_START: 1,
ENTITY_CL_START: 1,
EXTRA_ARGS_LIST: [],
GAM_CFG_FILE: '',
GAM_CFG_PATH: '',
GAM_CFG_SECTION: '',
GAM_CFG_SECTION_NAME: '',
GAM_PATH: '.',
GAM_TYPE: '',
LAST_GOT_MSG_LEN: 0,
LICENSE_SKUS: [],
MAKE_BUILDING_ID_NAME_MAP: True,
MAKE_ROLE_ID_NAME_MAP: True,
MAP_BUILDING_ID_TO_NAME: {},
MAP_BUILDING_NAME_TO_ID: {},
MAP_ORGUNIT_ID_TO_NAME: {},
MAP_SHAREDDRIVE_ID_TO_NAME: {},
MAP_ROLE_ID_TO_NAME: {},
MAP_ROLE_NAME_TO_ID: {},
MAP_USER_ID_TO_NAME: {},
MULTIPROCESS_EXIT_CONDITION: None,
MULTIPROCESS_EXIT_PROCESSING: False,
NUM_BATCH_ITEMS: 0,
OAUTH2SERVICE_CLIENT_ID: None,
OAUTH2SERVICE_JSON_DATA: {},
OAUTH2_CLIENT_ID: None,
OAUTH2_TXT_LOCK: None,
OUTPUT_DATEFORMAT: '',
OUTPUT_TIMEFORMAT: '',
PARSER: None,
PID: 0,
PRINT_AGU_DOMAINS: '',
PRINT_CROS_OUS: '',
PRINT_CROS_OUS_AND_CHILDREN: '',
RATE_CHECK_COUNT: 0,
RATE_CHECK_START: 0,
SECTION: None,
SHOW_GETTINGS: True,
SHOW_GETTINGS_GOT_NL: False,
SAVED_STDOUT: None,
STDERR: {},
STDOUT: {},
SVCACCT_SCOPES: {},
SVCACCT_SCOPES_DEFINED: False,
SYSEXITRC: 0,
SYS_ENCODING: 'utf-8',
TBATCH_QUEUE: None
}

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM indent processing
"""
class GamIndent():
INDENT_SPACES_PER_LEVEL = ' '
def __init__(self):
self.indent = 0
def Reset(self):
self.indent = 0
def Increment(self):
self.indent += 1
def Decrement(self):
self.indent -= 1
def Spaces(self):
return self.INDENT_SPACES_PER_LEVEL*self.indent
def SpacesSub1(self):
return self.INDENT_SPACES_PER_LEVEL*(self.indent-1)
def MultiLineText(self, message, n=0):
return message.replace('\n', f'\n{self.INDENT_SPACES_PER_LEVEL*(self.indent+n)}').rstrip()

547
src/gam/gamlib/glmsgs.py Normal file
View File

@@ -0,0 +1,547 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2024 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM messages
"""
# These values can be translated into other languages
# Project creation messages in order of appearance
CREATING_PROJECT = 'Creating project "{0}"...\n'
CHECK_INTERRUPTED = 'Check interrupted'
CHECKING_PROJECT_CREATION_STATUS = 'Checking project creation status...\n'
NO_RIGHTS_GOOGLE_CLOUD_ORGANIZATION = 'Looks like you have no rights to your Google Cloud Organization.\nAttempting to fix that...\n'
YOUR_ORGANIZATION_NAME_IS = 'Your organization name is {0}\n'
YOU_HAVE_NO_RIGHTS_TO_CREATE_PROJECTS_AND_YOU_ARE_NOT_A_SUPER_ADMIN = 'You have no rights to create projects for your organization and you don\'t seem to be a super admin! Sorry, there\'s nothing more I can do.'
LOOKS_LIKE_NO_ONE_HAS_RIGHTS_TO_YOUR_GOOGLE_CLOUD_ORGANIZATION_ATTEMPTING_TO_GIVE_YOU_CREATE_RIGHTS = 'Looks like no one has rights to your Google Cloud Organization. Attempting to give you create rights...\n'
THE_FOLLOWING_RIGHTS_SEEM_TO_EXIST = 'The following rights seem to exist:\n'
GIVING_LOGIN_HINT_THE_CREATOR_ROLE = 'Giving {0} the role of {1}...\n'
ACCEPT_CLOUD_TOS = '''
Please go to:
https://console.cloud.google.com/projectselector2/home/dashboard?supportedpurview=project
sign in as {0} and accept the Terms of Service (ToS). As soon as you've accepted the ToS popup, you can return here and press enter.\n'''
PROJECT_STILL_BEING_CREATED_SLEEPING = 'Project still being created. Sleeping {0} seconds\n'
FAILED_TO_CREATE_PROJECT = 'Failed to create project: {0}\n'
SETTING_GAM_PROJECT_CONSENT_SCREEN_CREATING_CLIENT = 'Setting GAM project consent screen, creating client...\n'
CREATE_CLIENT_INSTRUCTIONS = '''
Please go to:
{0}
1. If "+ CREATE CLIENT" is on the screen, skip to step 14
2. Click "GET STARTED"
3. Under "App Information", enter {1} or another value in "App name *"
4. Under "App Information", enter {2} in "User support email *"
5. Click "NEXT"
6. Under "Audience", choose INTERNAL
7. Click "NEXT"
8. Under, "Contact Information", enter an email address in "Email addresses *"
9. Click "NEXT"
10. Under "Finish", click "I agree to the Google API Services: User Data Policy."
11. Click "CONTINUE"
12. Click "CREATE"
13. Click "Clients" in the left-hand column
14. Click "+ CREATE CLIENT"
15. Choose "Desktop App" for "Application type"
16. Enter {1} or another value in "Name *"
17. Click "Create"
18. Under "Name", click your client name
19. Copy the "Client ID" value under "Additional information"
20. Paste it at the "Enter your Client ID: " prompt in your terminal
21. Press return/enter in your terminal
22. Switch back to the browser
23. Copy the "Client secret" value under "Client Secrets"
24. Paste it at the "Enter your Client Secret: " prompt in your terminal
25. Press return/enter in your terminal
26. Switch back to the browser
27. Click "CANCEL"
28. These steps are complete
'''
ENTER_YOUR_CLIENT_ID = '\nEnter your Client ID: '
ENTER_YOUR_CLIENT_SECRET = '\nEnter your Client Secret: '
IS_NOT_A_VALID_CLIENT_ID = '''
{0}
Is not a valid Client ID.
Please make sure you are following the directions exactly and that there are no extra spaces in your Client ID.
'''
IS_NOT_A_VALID_CLIENT_SECRET = '''
{0}
Is not a valid Client Secret.
Please make sure you are following the directions exactly and that there are no extra spaces in your Client Secret.
'''
TRUST_GAM_CLIENT_ID = '''
It's important to mark the {0} Client ID as trusted by your Workspace instance.
Please go to:
https://admin.google.com/ac/owl/list?tab=configuredApps
1. Click on: Configure new app
2. Enter the following Client ID value in Search for app:
{1}
3. Press Search, select the {0} app, click
4. Keep the default scope or select a preferred scope that includes your GAM admin.
5. Press Continue
6. Select Trusted radio button, press Continue and Finish.
7. Press Confirm if Confirm parental consent pops up
8. Press enter here on the terminal once trust is complete.
'''
ENABLE_SERVICE_ACCOUNT_PRIVATE_KEY_UPLOAD = '''
Your workspace is configured to disable service account private key uploads.
Please go to:
https://github.com/taers232c/GAMADV-XTD3/wiki/Authorization#authorize-service-account-key-uploads
Follow the steps to allow a service account private key upload for the project ({0}) just created.
Once those steps are completed, you can continue with your project authentication.
'''
YOUR_GAM_PROJECT_IS_CREATED_AND_READY_TO_USE = '''
That\'s it! Your GAM Project is created and ready to use.
Proceed to the authentication steps.
'''
# check|update service messages in order of appearance
SYSTEM_TIME_STATUS = 'System time status'
YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE = 'Your system time differs from {0} by {1}'
PRESS_ENTER_ONCE_AUTHORIZATION_IS_COMPLETE = 'Press enter once authorization is complete.'
SERVICE_ACCOUNT_API_DISABLED = '{0} not enabled. Please run "gam update project" and "gam user user@domain.com update serviceaccount"'
SERVICE_ACCOUNT_PRIVATE_KEY_AUTHENTICATION = 'Service Account Private Key Authentication'
SERVICE_ACCOUNT_CHECK_PRIVATE_KEY_AGE = 'Service Account Private Key age; Google recommends rotating keys on a routine basis'
SERVICE_ACCOUNT_PRIVATE_KEY_AGE = 'Service Account Private Key age: {0} days'
SERVICE_ACCOUNT_SKIPPING_KEY_AGE_CHECK = 'Skipping Private Key age check: {0} rotation not necessary'
UPDATE_PROJECT_TO_VIEW_MANAGE_SAKEYS = 'Please run "gam update project" to view/manage service account keys'
DOMAIN_WIDE_DELEGATION_AUTHENTICATION = 'Domain-wide Delegation authentication'
SCOPE_AUTHORIZATION_PASSED = '''All scopes PASSED!
Service Account Client name: {0} is fully authorized.
'''
SCOPE_AUTHORIZATION_UPDATE_PASSED = '''All scopes PASSED!
To authorize them (in case some scopes were unselected), please go to the following link in your browser:
{0}
{1}
You will be directed to the Google Workspace admin console Security > API Controls > Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
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.
'''
SCOPE_AUTHORIZATION_FAILED = '''Some scopes FAILED!
To authorize them, please go to the following link in your browser:
{0}
{1}
You will be directed to the Google Workspace admin console Security > API Controls > Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
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.
'''
# General messages
ACCESS_FORBIDDEN = 'Access Forbidden'
ACTION_APPLIED = 'Action Applied'
ACTION_IN_PROGRESS = 'Action {0} in progress'
ACTION_MAY_BE_DELAYED = 'Action may be delayed'
ADMIN_STATUS_CHANGED_TO = 'Admin Status Changed to'
ALL = 'All'
ALL_FOLDER_NAMES_MUST_BE_NON_BLANK = 'All folder names must be non-blank: {0}'
ALL_SKU_PRODUCTIDS_MUST_MATCH = 'All SKU productIds must match, {0} != {1}'
ALREADY_WAS_OWNER = 'Already was owner'
ALREADY_EXISTS = 'Already exists'
ALREADY_EXISTS_IN_TARGET_FOLDER = 'Already exists in {0}: {1}'
ALREADY_EXISTS_USE_MERGE_ARGUMENT = 'Already exists; use the "merge" argument to merge the labels'
API_ACCESS_DENIED = 'API access Denied'
API_CALLS_RETRY_DATA = 'API calls retry data\n'
API_CHECK_CLIENT_AUTHORIZATION = 'Please make sure the Client ID: {0} is authorized for the appropriate API or scopes:\n{1}\n\nRun: gam oauth create\n'
API_CHECK_SVCACCT_AUTHORIZATION = 'Please make sure the Service Account Client ID: {0} is authorized for the appropriate API or scopes:\n{1}\n\nRun: gam user {2} update serviceaccount\n'
API_ERROR_SETTINGS = 'API error, some settings not set'
ARE_BOTH_REQUIRED = 'Arguments {0} and {1} are both required'
ARE_MUTUALLY_EXCLUSIVE = 'Arguments {0} and {1} are mutually exclusive'
AS = 'as'
ATTENDEES_ADD = 'Add Attendees'
ATTENDEES_ADD_REMOVE = 'Add/Remove Attendees'
ATTENDEES_REMOVE = 'Remove Attendees'
AUTHORIZATION_FILE_ALREADY_EXISTS = '{0} already exists. Please delete or rename it before attempting to {1} project.'
AUTHENTICATION_FLOW_COMPLETE = '\nThe authentication flow has completed.'
AUTHENTICATION_FLOW_COMPLETE_CLOSE_BROWSER = 'The authentication flow has completed. You may close this browser window and return to {0}.'
AUTHENTICATION_FLOW_FAILED = 'The authentication flow failed, reissue command'
BAD_ENTITIES_IN_SOURCE = '{0} {1} {2} in source marked >>> <<< above'
BAD_REQUEST = 'Bad Request'
BATCH = 'Batch'
BATCH_CSV_LOOP_DASH_DEBUG_INCOMPATIBLE = '"gam {0} - ..." is not compatible with debugging. Disable debugging by setting debug_level = 0 in gam.cfg'
BATCH_CSV_PROCESSING_COMPLETE = '{0},0/{1},Processing complete\n'
BATCH_CSV_TERMINATE_N_PROCESSES = '{0},0/{1},Terminating {2} running {3}\n'
BATCH_CSV_WAIT_LIMIT = ', wait limit {0} seconds'
BATCH_CSV_WAIT_N_PROCESSES = '{0},0/{1},Waiting for {2} running {3} to finish before terminating{4}\n'
BATCH_NOT_PROCESSED_ERRORS = '{0}batch file: {1}, not processed, {2} {3}\n'
CALLING_GCLOUD_FOR_REAUTH = 'Calling gcloud for reauth credentials..."\n'
CAN_NOT_DELETE_USER_WITH_VAULT_HOLD = '{0}: The user may be (or have recently been) on Google Vault Hold and thus not eligible for deletion. You can check holds with "gam user {1} show vaultholds".'
CAN_NOT_BE_SPECIFIED_MORE_THAN_ONCE = 'Argument {0} can not be specified more than once'
CHAT_ADMIN_ACCESS_LIMITED_TO_ONE_USER = 'Chat adminaccess|asadmin limited to one user, {0} specified'
CHROME_TARGET_VERSION_FORMAT = r'^([a-z]+)-(\d+)$ or ^(\d{1,4}\.){1,4}$'
COLUMN_DOES_NOT_MATCH_ANY_INPUT_COLUMNS = '{0} column "{1}" does not match any input columns'
COLUMN_DOES_NOT_MATCH_ANY_OUTPUT_COLUMNS = '{0} column "{1}" does not match any output columns'
COMMAND_NOT_COMPATIBLE_WITH_ENABLE_DASA = 'gam {0} {1} is not compatible with enable_dasa = true in gam.cfg'
COMMIT_BATCH_COMPLETE = '{0},0/{1},commit-batch - running {2} finished, proceeding\n'
COMMIT_BATCH_WAIT_N_PROCESSES = '{0},0/{1},commit-batch - waiting for {2} running {3} to finish before proceeding\n'
CONFIRM_WIPE_YUBIKEY_PIV = 'This will wipe all YubiKey PIV keys and configuration from your YubiKey. Are you sure? (y/N) '
CONTACT_ADMINISTRATOR_FOR_PASSWORD = 'Contact administrator for password'
CONTACT_PHOTO_NOT_FOUND = 'Contact photo not found'
CONTAINS_AT_LEAST_1_ITEM = 'Contains at least 1 item'
COUNT_N_EXCEEDS_MAX_TO_PROCESS_M = 'Count {0} exceeds maximum to {1} {2}'
CORRUPT_FILE = 'Corrupt file'
COULD_NOT_FIND_ANY_YUBIKEY = 'Could not find any YubiKey\n'
COULD_NOT_FIND_YUBIKEY_WITH_SERIAL = 'Could not find YubiKey with serial number {0}\n'
CREATE_USER_NOTIFY_MESSAGE = 'Hello #givenname# #familyname#,\n\nYou have a new account at #domain#\nAccount details:\nUsername: #user#\nPassword: #password#\nStart using your new account by signing in at\nhttps://www.google.com/accounts/AccountChooser?Email=#user#&continue=https://workspace.google.com/dashboard\n'
CREATE_USER_NOTIFY_SUBJECT = 'Welcome to #domain#'
CSV_DATA_ALREADY_SAVED = 'CSV data already saved'
CSV_FILE_HEADERS = 'The CSV file ({0}) has the following headers:\n'
CSV_SAMPLE_COMMANDS = 'Here are the first {0} commands {1} will run\n'
DATA_FIELD_MISMATCH = 'datafield {0} does not match saved datafield {1}'
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'
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'
DIRECTLY_IN_THE = ' directly in the {0}'
DISABLE_TLS_MIN_MAX = 'Execute: gam select default config tls_max_version "" tls_min_version "" save\n'
DISPLAYNAME_NOT_ALLOWED_WHEN_UPDATING_MULTIPLE_SCHEMAS = 'displayname not allowed when updating multiple schemas'
DOES_NOT_EXIST = 'Does not exist'
DOES_NOT_EXIST_OR_HAS_INVALID_FORMAT = '{0}: {1}, Does not exist or has invalid format, {2}'
DOES_NOT_MATCH = 'Does not match {0}'
DOMAIN_NOT_FOUND_IN_DNS = 'Domain not found in DNS!'
DOMAIN_NOT_VERIFIED_SECONDARY = 'Domain is not a verified secondary domain'
DONE_GENERATING_PRIVATE_KEY_AND_PUBLIC_CERTIFICATE = 'Done generating private key and public certificate'
DO_NOT_EXIST = 'Do not exist'
DOWNLOADING_AGAIN_AND_OVER_WRITING = 'Downloading again and over-writing...'
DUPLICATE = 'Duplicate'
DUPLICATE_ALREADY_A_ROLE = 'Duplicate, already a {0}'
DYNAMIC_GROUP_MEMBERSHIP_CANNOT_BE_MODIFIED = 'Dynamic group membership cannot be modified'
EITHER = 'Either'
EMAIL_ADDRESS_IS_UNMANAGED_ACCOUNT = 'The email address is an unmanaged account'
ENABLE_PROJECT_APIS_AUTOMATICALLY_OR_MANUALLY = 'Do you want to enable project APIs [a]utomatically or [m]anually? (a/m): '
ENTER_GSUITE_ADMIN_EMAIL_ADDRESS = '\nEnter your Google Workspace admin email address? '
ENTER_MANAGE_GCP_PROJECT_EMAIL_ADDRESS = '\nEnter your Google Workspace admin or GCP project manager email address authorized to manage project(s): {0}? '
ENTER_VERIFICATION_CODE_OR_URL = 'Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required): '
ENTITY_DOES_NOT_EXIST = '{0} does not exist'
ENTITY_NAME_NOT_VALID = 'Entity Name Not Valid'
ERROR = 'error'
ERRORS = 'errors'
EVENT_IS_CANCELED = 'Event is canceled'
EXECUTE_GAM_OAUTH_CREATE = '\nPlease run\n\ngam oauth delete\ngam oauth create\n\n'
EXISTS = 'Exists'
EXPECTED = 'Expected'
EXPORT_NOT_COMPLETE = 'Export needs to be complete before downloading, current status is: {0}'
EXTRACTING_PUBLIC_CERTIFICATE = 'Extracting public certificate'
FAILED_PRECONDITION = 'Failed precondition'
FAILED_TO_PARSE_AS_JSON = 'Failed to parse as JSON'
FAILED_TO_PARSE_AS_LIST = 'Failed to parse as list'
FIELD_NOT_FOUND_IN_SCHEMA = 'Field {0} not found in schema {1}'
FILE_NOT_FOUND = 'File {0} not found'
FINISHED = 'Finished'
FILTER_CAN_ONLY_CONTAIN_ONE_CATEGORY_LABEL = 'Filter can only contain one CATEGORY label'
FILTER_CAN_ONLY_CONTAIN_ONE_USER_LABEL = 'Filter can only contain one USER label'
FOR = 'for'
FORBIDDEN = 'Forbidden'
FORMAT_NOT_AVAILABLE = 'Format ({0}) not available'
FORMAT_NOT_DOWNLOADABLE = 'Format not downloadable'
FROM = 'From'
FROM_LC = 'from'
FULL_PATH_MUST_START_WITH_DRIVE = 'fullpath must start with {0} or {1}'
GAM_BATCH_FILE_WRITTEN = 'GAM batch file {0} written\n'
GAM_LATEST_VERSION_NOT_AVAILABLE = 'GAM Latest Version information not available'
GAM_OUT_OF_MEMORY = 'GAM has run out of memory. If this is a large Google Workspace instance, you should use a 64-bit version of GAM on Windows or a 64-bit version of Python on other systems.'
GENERATING_NEW_PRIVATE_KEY = 'Generating new private key'
GETTING = 'Getting'
GETTING_ALL = 'Getting all'
GOOGLE_DELEGATION_ERROR = 'Google delegation error, delegator and delegate both exist and are valid for delegation'
GOT = 'Got'
GROUP_MAPS_TO_MULTIPLE_OUS = 'File: {0}, Group: {1} references multiple OUs: {2}'
GROUP_MAPS_TO_OU_INVALID_ROW = 'File: {0}, Invalid row, must contain non-blank <EmailAddress> and <OrgUnitPath>: <{1}> <{2}>'
GUARDIAN_INVITATION_STATUS_NOT_PENDING = 'Guardian invitation status is not PENDING'
HAS_CHILD_ORGS = 'Has child {0}'
HAS_INVALID_FORMAT = '{0}: {1}, Has invalid format'
HAS_RIGHTS_TO_ROTATE_OWN_PRIVATE_KEY = 'Giving account {0} rights to rotate {1} private key'
HEADER_NOT_FOUND_IN_CSV_HEADERS = 'Header "{0}" not found in CSV headers of "{1}".'
HELP_SYNTAX = 'Help: Syntax in file {0}\n'
HELP_WIKI = 'Help: Documentation is at {0}\n'
IGNORED = 'Ignored'
INSTRUCTIONS_CLIENT_SECRETS_JSON = 'Please run\n\ngam create|use project\ngam oauth create\n\nto create and authorize a Client account.\n'
INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create|use project\ngam user <user> check serviceaccount\n\nto create and authorize a Service account.\n'
INSUFFICIENT_PERMISSIONS_TO_PERFORM_TASK = 'Insufficient permissions to perform this task'
INTER_BATCH_WAIT_INCREASED = 'inter_batch_wait increased to {0:.2f}'
INVALID = 'Invalid'
INVALID_ALIAS = 'Invalid Alias'
INVALID_ATTENDEE_CHANGE = 'Invalid attendee change "{0}"'
INVALID_CHARSET = 'Invalid charset "{0}"'
INVALID_DATE_TIME_RANGE = '{0} {1} must be greater than/equal to {2} {3}'
INVALID_ENTITY = 'Invalid {0}, {1}'
INVALID_FILE_SELECTION_WITH_ADMIN_ACCESS = 'Invalid file selection with adminaccess|asadmin'
INVALID_GROUP = 'Invalid Group'
INVALID_HTTP_HEADER = 'Invalid http header data: {0}'
INVALID_JSON_INFORMATION = 'Google API reported Invalid JSON Information'
INVALID_JSON_SETTING = 'Invalid JSON setting'
INVALID_LIST = 'Invalid list'
INVALID_MEMBER = 'Invalid Member address'
INVALID_MESSAGE_ID = 'Invalid message id(s)'
INVALID_MIMETYPE = 'Invalid mimeType {0}, must be {1}'
INVALID_NUMBER_OF_CHAT_SPACE_MEMBERS = '{0} type {1} number of members, {2}, must be in range {3} to {4}'
INVALID_ORGUNIT = 'Invalid Organizational Unit'
INVALID_PATH = 'Invalid Path'
INVALID_PERMISSION_ATTRIBUTE_TYPE = 'permission attribute {0} not allowed with type {1}'
INVALID_REGION = 'See: https://github.com/taers232c/GAMADV-XTD3/wiki/Context-Aware-Access-Levels#caa-region-codes'
INVALID_QUERY = 'Invalid Query'
INVALID_RE = 'Invalid RE'
INVALID_REQUEST = 'Invalid Request'
INVALID_RESELLER_CUSTOMER_NAME = 'name must be: accounts/<ResellerID>/customers/<ChannelCustomerID>'
INVALID_ROLE = 'Invalid subkeyfield Role, must be one of: {0}'
INVALID_SCHEMA_VALUE = 'Invalid Schema Value'
INVALID_SCOPE = 'Invalid Scope'
INVALID_SITE = 'Invalid Site ({0}), must match pattern ({1})'
INVALID_TAG_SPECIFICATION = 'Invalid tag, expected field.subfield or field.subfield.subfield.string'
INVALID_TIMEOFDAY_RANGE = '{0} must be less than/equal to {1}'
IN_SKIPIDS = 'In skipids'
IN_THE = ' in the {0}'
IN_TRASH_AND_EXCLUDE_TRASHED = 'In Trash and excludeTrashed'
IS_EXPIRED_OR_REVOKED = '{0}: {1}, Is expired or has been revoked'
IS_NOT_DONE_CHECKING_IN_SECONDS = 'Is not done, checking again in {0} seconds'
IS_NOT_UNIQUE = 'Is not unique, {0}: {1}'
IS_REQD_TO_CHG_PWD_NO_DELEGATION = 'Is required to change password at next login. You must change password or clear changepassword flag for delegation.'
IS_SUSPENDED_NO_BACKUPCODES = 'User is suspended. You must unsuspend to process backupcodes'
IS_SUSPENDED_NO_DELEGATION = 'Is suspended. You must unsuspend for delegation.'
IS_YUBIKEY_INSERTED = 'Is YubiKey inserted?'
JSON_ERROR = 'JSON error "{0}" in file {1}'
JSON_KEY_NOT_FOUND = 'JSON key "{0}" not found in file {1}'
KIOSK_MODE_REQUIRED = ' This command ({0}) requires that the ChromeOS device be in Kiosk mode.'
LESS_THAN_1_SECOND = 'less than 1 second'
LIST_CHROMEOS_INVALID_INPUT_PAGE_TOKEN_RETRY = 'List ChromeOSdevices Invalid Input: pageToken retry'
LOGGING_INITIALIZATION_ERROR = 'Logging initialization error: {0}'
LOOKING_UP_GOOGLE_UNIQUE_ID = 'Looking up Google Unique ID'
MARKED_AS = 'Marked as'
MATCHED_THE_FOLLOWING = 'Matched the following'
MATTER_NOT_OPEN = 'Matter needs to be open, current state is: {0}'
MAXIMUM_OF = 'maximum of'
MEMBERSHIP_IS_PENDING_WILL_DELETE_ADD_TO_ACCEPT = 'Membership is pending, will delete and add to accept'
MIMETYPE_MISMATCH = 'Shortcut target mimeType {0} does not match actual target mimeType {1}'
MIMETYPE_NOT_PRESENT_IN_ATTACHMENT = 'MIME type not present in attachment'
MISMATCH_RE_SEARCH_REPLACE_SUBFIELDS = 'The subfield ({2}) in replace "{3}" exceeds the number of subfields ({0}) in search "{1}"'
MISMATCH_SEARCH_REPLACE_SUBFIELDS = 'The number of subfields ({0}) in search "{1}" does not match the number of subfields ({2}) in replace "{3}"'
MISSING_FIELDS = 'Missing fields: {0}\n'
MULTIPLE_BUILDINGS_SAME_NAME = '{0} {1} with the same (case-insensitive) name exist'
MULTIPLE_ENTITIES_FOUND = 'Multiple {0} ({1}) found, {2}'
MULTIPLE_ITEMS_SPECIFIED = 'Multiple {0} are specfied, only one is allowed'
MULTIPLE_ITEMS_MARKED_PRIMARY = 'Multiple {0} are marked primary, only one can be primary'
MULTIPLE_PARENTS_SPECIFIED = 'Multiple parents ({0}) specified, only one is allowed'
MULTIPLE_SEARCH_METHODS_SPECIFIED = 'Multiple search methods ({0}) specified, only one is allowed'
MULTIPLE_SSO_PROFILES_MATCH = 'Multiple SSO profiles match display name {0}:\n'
MULTIPLE_YUBIKEYS_CONNECTED = 'Multiple YubiKeys connected. Specify yubikey_serial_number and one of {0}\n'
MUST_BE_NUMERIC = 'Must be numeric'
NEED_READ_ACCESS = 'Need Read access'
NEED_READ_WRITE_ACCESS = 'Need Read/Write access'
NEED_WRITE_ACCESS = 'Need Write access'
NESTED_LOOP_CMD_NOT_ALLOWED = 'Command can not be nested.'
NEWUSER_REQUIREMENTS = 'newuser option requires: at least 1 recipient and givenname, familyname and password options'
NEW_OWNER_MUST_DIFFER_FROM_OLD_OWNER = 'New owner must differ from old owner'
NO_DATA = 'No data'
NON_BLANK = 'Non-blank'
NON_EMPTY = 'Non-empty'
NOT_A = 'Not a'
NOT_A_PRIMARY_EMAIL_ADDRESS = 'Not a primary email address'
NOT_A_MEMBER = 'Not a member'
NOT_ACTIVE = 'Not Active'
NOT_ALLOWED = 'Not Allowed'
NOT_AN_ENTITY = 'Not a {0}'
NOT_APPROPRIATE = 'Not Appropriate'
NOT_COMPATIBLE = 'Not Compatible'
NOT_COPYABLE = 'Not Copyable'
NOT_COPYABLE_INTO_ITSELF = 'Not copyable into itself'
NOT_COPYABLE_SAME_NAME_CURRENT_FOLDER_MERGE = 'Not copyable with same name into current folder with duplicatefolders merge'
NOT_COPYABLE_SAME_NAME_CURRENT_FOLDER_OVERWRITE = 'Not copyable with same name into current folder with duplicatefiles overwriteall|overwriteolder'
NOT_DELETABLE = 'Not Deletable'
NOT_FOUND = 'Not Found'
NOT_MOVABLE = 'Not Movable'
NOT_MOVABLE_IN_TRASH = 'Not Movable, in Trash'
NOT_MOVABLE_INTO_ITSELF = 'Not movable into itself'
NOT_MOVABLE_SAME_NAME_CURRENT_FOLDER_MERGE = 'Not movable with same name into current folder with duplicatefolders merge'
NOT_MOVABLE_SAME_NAME_CURRENT_FOLDER_OVERWRITE = 'Not movable with same name into current folder with duplicatefiles overwriteall|overwriteolder'
NOT_OWNED_BY = 'Not owned by {0}'
NOT_SELECTED = 'Not Selected'
NOT_WRITABLE = 'Not Writable'
NOW_THE_PRIMARY_DOMAIN = 'Now the primary domain'
NO_ACTION_SPECIFIED = 'No action specified'
NO_AVAILABLE_LICENSES = "There aren't enough available licenses for the specified product-SKU pair(s)"
NO_CHANGES = 'No changes'
NO_CLIENT_ACCESS_ALLOWED = 'No Client Access allowed'
NO_CLIENT_ACCESS_CREATE_UPDATE_ALLOWED = 'No Client Access create/update allowed'
NO_COLUMNS_SELECTED_WITH_CSV_OUTPUT_HEADER_FILTER = 'No columns selected with {0} and {1}'
NO_CREDENTIALS_REPLACEMENT = '{0}: {1} has {2} {3}. We only replace if there are 2.\n'
NO_CSV_DATA_TO_UPLOAD = 'No CSV data to upload'
NO_CSV_FILE_DATA_FOUND = 'No CSV file data found'
NO_CSV_FILE_DATA_SAVED = 'No CSV file data saved'
NO_CSV_FILE_SUBKEYS_SAVED = 'No CSV file subkeys saved'
NO_DATA_TRANSFER_APP_FOR_PARAMETER = 'No data transfer application for key {0}'
NO_ENTITIES_FOUND = 'No {0} found'
NO_ENTITIES_MATCHED = 'No {0} matched'
NO_FILTER_ACTIONS = 'No {0} actions specified'
NO_FILTER_CRITERIA = 'No {0} criteria specified'
NO_LABELS_MATCH = 'No Labels match'
NO_LABELS_TO_PROCESS = 'No Labels to process'
NO_MESSAGES_WITH_LABEL = 'No Messages with Label'
NO_PARENTS_TO_CONVERT_TO_SHORTCUTS = 'No parents to convert to shortcuts'
NO_REPORT_AVAILABLE = 'No {0} report available.'
NO_SCOPES_FOR_API = 'There are no scopes authorized for the {0}'
NO_SERIAL_NUMBERS_SPECIFIED = 'No serial numbers specified'
NO_SSO_PROFILE_MATCHES = 'No SSO profile matches display name {0}'
NO_SSO_PROFILE_ASSIGNED = 'No SSO profile assigned to {0} {1}'
NO_SVCACCT_ACCESS_ALLOWED = 'No Service Account Access allowed'
NO_TRANSFER_LACK_OF_DISK_SPACE = 'Transfer not performed due to lack of target drive space.'
NO_USAGE_PARAMETERS_DATA_AVAILABLE = 'No usage parameters data available.'
NO_USER_COUNTS_DATA_AVAILABLE = 'No User counts data available.'
OAUTH2_GO_TO_LINK_MESSAGE = """
Go to the following link in a browser on this computer or on another computer:
{url}
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
"""
ON_CURRENT_PRIVATE_KEY = ' on current key'
ON_VAULT_HOLD = 'On Google Vault Hold'
ONLY_ADMINISTRATORS_CAN_PERFORM_SHARED_DRIVE_QUERIES = 'Only administrators can perform Shared Drive queries'
ONLY_ADMINISTRATORS_CAN_SPECIFY_SHARED_DRIVE_ORGUNIT = 'Only administrators can specify Shared Drive Org Unit'
ONLY_ONE_DEVICE_SELECTION_ALLOWED = 'Only one device selection allowed, filter = "{0}"'
ONLY_ONE_JSON_RANGE_ALLOWED = 'Only one range/json allowed'
ONLY_ONE_OWNER_ALLOWED = 'Only one owner allowed'
OR = 'or'
OU_AND_MOVETOOU_CANNOT_BE_IDENTICAL = 'ou {0} can not be be identical to movetoou {1}'
OU_SUBOUS_CANNOT_BE_MOVED_TO_MOVETOOU = 'ou {0} sub OUs can not be be moved to movetoou {1}'
PERMISSION_DENIED = 'The caller does not have permission'
PLEASE_CORRECT_YOUR_SYSTEM_TIME = 'Please correct your system time.'
PLEASE_ENTER_A_OR_M = 'Please enter a or m ...\n'
PLEASE_SELECT_ENTITY_TO_PROCESS = '{0} {1} found, please select the correct one to {2} and specify with {3}'
PLEASE_SPECIFY_BUILDING_EXACT_CASE_NAME_OR_ID = 'Please specify building by exact case name or ID.'
PREVIEW_ONLY = 'Preview Only'
PRIMARY_EMAIL_DID_NOT_MATCH_PATTERN = 'primaryEmail address did not match pattern: {0}'
PROCESS = 'process'
PROCESSES = 'processes'
PROCESSING_ITEM_N = '{0},0,Processing item {1}\n'
PROCESSING_ITEM_N_OF_M = '{0},0,Processing item {1}/{2}\n'
PROFILE_PHOTO_NOT_FOUND = 'Profile photo not found'
PROFILE_PHOTO_IS_DEFAULT = 'Profile photo is default'
REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE = 'reason only valid with contentrestrictions readonly true'
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.'
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'
RESOURCE_CAPACITY_FLOOR_REQUIRED = 'Options "capacity <Number>" (<Number> > 0) and "floor <String>" required'
RESOURCE_FLOOR_REQUIRED = 'Option "floor <String>" required'
RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.'
RETRIES_EXHAUSTED = 'Retries {0} exhausted'
RETRYING_GOOGLE_SHEET_EXPORT_SLEEPING = 'Retrying Google Sheet export {0}/{1}. Sleeping {2} seconds\n'
ROLE_MUST_BE_ORGANIZER = 'Role must be organizer'
ROLE_NOT_IN_SET = 'Role not in set: {0})'
SCHEMA_WOULD_HAVE_NO_FIELDS = '{0} would have no {1}'
SELECTED = 'Selected'
SERVICE_NOT_APPLICABLE = 'Service not applicable/Does not exist'
SERVICE_NOT_APPLICABLE_THIS_ADDRESS = 'Service not applicable for this address: {0}'
SERVICE_NOT_ENABLED = '{0} Service/App not enabled'
SHORTCUT_TARGET_CAPABILITY_IS_FALSE = '{0} capability {1} is False'
SKU_HAS_NO_MATCHING_ARCHIVED_USER_SKU = 'SKU {0} has no matching Archived User SKU'
STARTING_THREAD = 'Starting thread'
STATISTICS_COPY_FILE = 'Total: {0}, Copied: {1}, Shortcut created {2}, Shortcut exists {3}, Duplicate: {4}, Copy Failed: {5}, Not copyable: {6}, In skipids: {7}, Permissions Failed: {8}, Protected Ranges Failed: {9}'
STATISTICS_COPY_FOLDER = 'Total: {0}, Copied: {1}, Shortcut created {2}, Shortcut exists {3}, Duplicate: {4}, Merged: {5}, Copy Failed: {6}, Not writable: {7}, Permissions Failed: {8}'
STATISTICS_MOVE_FILE = 'Total: {0}, Moved: {1}, Shortcut created {2}, Shortcut exists {3}, Duplicate: {4}, Move Failed: {5}, Not movable: {6}'
STATISTICS_MOVE_FOLDER = 'Total: {0}, Moved: {1}, Shortcut created {2}, Shortcut exists {3}, Duplicate: {4}, Merged: {5}, Move Failed: {6}, Not writable: {7}'
STATISTICS_USER_NOT_ORGANIZER = 'User not organizer: {0}'
STRING_LENGTH = 'string length'
SUBKEY_FIELD_MISMATCH = 'subkeyfield {0} does not match saved subkeyfield {1}'
SUBSCRIPTION_NOT_FOUND = 'Could not find subscription'
SUFFIX_NOT_ALLOWED_WITH_CUSTOMLANGUAGE = 'Suffix {0} not allowed with customLanguage {1}'
TASKLIST_TITLE_NOT_FOUND = 'Task list title not found'
THREAD = 'thread'
THREADS = 'threads'
TO = 'To'
TO_LC = 'to'
TO_MAXIMUM_OF = 'to maximum of'
TO_SET_UP_GOOGLE_CHAT = """
To set up Google Chat for your API project, please go to:
{0}
and complete all fields.
"""
TOTAL_ITEMS_IN_ENTITY = 'Total {0} in {1}'
TRIMMED_MESSAGE_FROM_LENGTH_TO_MAXIMUM = 'Trimmed message of length {0} to maximum length {1}'
UNABLE_TO_GET_PERMISSION_ID = 'Unable to get Permission ID for <{0}>'
UNABLE_TO_CREATE_NOT_FOUND_USER = 'Unable to create not found user, some required field (givenName, familyName, password/notfoundpassword) not present'
UNAVAILABLE = 'Unavailable'
UNKNOWN = 'Unknown'
UNKNOWN_API_OR_VERSION = 'Unknown Google API or version: ({0}), contact {1}'
UNRECOVERABLE_ERROR = 'Unrecoverable error'
UPDATE_ATTENDEE_CHANGES = 'Update attendee changes'
UPDATE_GAM_TO_64BIT = "You're running a 32-bit version of GAM on a 64-bit version of Windows, upgrade to a windows-x86_64 version of GAM"
UPDATE_USER_PASSWORD_CHANGE_NOTIFY_MESSAGE = 'The account password for #givenname# #familyname#, #user# has been changed to: #password#\n'
UPDATE_USER_PASSWORD_CHANGE_NOTIFY_SUBJECT = 'Account #user# password has been changed'
UPLOAD_CSV_FILE_INTERNAL_ERROR = 'Google reported "{0}" but the file was probably uploaded, check that it has {1} rows'
UPLOADING_NEW_PUBLIC_CERTIFICATE_TO_GOOGLE = 'Uploading new public certificate to Google...\n'
URL_ERROR = 'URL error: {0}'
USE_MIMETYPE_TO_SPECIFY_GOOGLE_FORMAT = 'Use "mimetype <MimeType>" to specify Google file format\n'
USED = 'Used'
USER_BELONGS_TO_N_GROUPS_THAT_MAP_TO_ORGUNITS = 'User belongs to {0} groups ({1}) that map to OUs'
USER_CANCELLED = 'User cancelled'
USER_HAS_MULTIPLE_DIRECT_OR_INHERITED_MEMBERSHIPS_IN_GROUP = 'User has multiple direct or inherited memberships in group'
USER_IN_OTHER_DOMAIN = '{0}: {1} in other domain.'
USER_IS_NOT_ORGANIZER = 'User is not organizer, use anyorganizer option to override'
USER_NOT_IN_MATCHUSERS = 'User not in matchusers'
USER_SUBS_NOT_ALLOWED_TAG_REPLACEMENT = 'user substitutions not allowed in replace <Tag> <String>'
USE_DOIT_ARGUMENT_TO_PERFORM_ACTION = 'Use the "doit" argument to perform action'
USING_N_PROCESSES = '{0},0/{1},Using {2} {3}...\n'
VALUES_ARE_NOT_CONSISTENT = 'Values are not consistent'
VERSION_UPDATE_AVAILABLE = 'Version update available'
WAITING_FOR_DATA_TRANSFER_TO_COMPLETE_SLEEPING = 'Waiting for Data Transfer to complete. Sleeping {0} seconds\n'
WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for {0} creation to complete. Sleeping {1} seconds\n'
WHAT_IS_YOUR_PROJECT_ID = '\nWhat is your project ID? '
WILL_RERUN_WITH_NO_BROWSER_TRUE = 'Will re-run command with no_browser true\n'
WITH = 'with'
WOULD_MAKE_MEMBERSHIP_CYCLE = 'Would make membership cycle'
WRITER_ACCESS_REQUIRED_TO_BOTH_CALENDARS = 'Writer access required to both calendars'
WROTE_PRIVATE_KEY_DATA = 'Wrote private key data to {0}\n'
WROTE_PUBLIC_CERTIFICATE = 'Wrote public certificate to {0}\n'
YOU_CAN_ADD_DOMAIN_TO_ACCOUNT = 'You can now add: {0} or its subdomains as secondary or domain aliases of the Google Workspace Account: {1}'
YUBIKEY_GENERATING_NONEXPORTABLE_PRIVATE_KEY = 'YubiKey is generating a non-exportable private key...\n'
YUBIKEY_PIN_SET_TO = 'YubiKey PIN set to: {0}\n'

246
src/gam/gamlib/glskus.py Normal file
View File

@@ -0,0 +1,246 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Google SKUs
"""
# Products/SKUs
_PRODUCTS = {
'101001': 'Cloud Identity Free',
'101005': 'Cloud Identity Premium',
'101031': 'Google Workspace for Education',
'101033': 'Google Voice',
'101034': 'Google Workspace Archived User',
'101035': 'Cloud Search',
'101036': 'Google Meet Global Dialing',
'101037': 'Google Workspace for Education',
'101038': 'AppSheet',
'101039': 'Assured Controls',
'101040': 'Chrome Enterprise',
'101043': 'Google Workspace Additional Storage',
'101047': 'Gemini',
'101049': 'Education Endpoint Management',
'101050': 'Colab',
'Google-Apps': 'Google Workspace',
'Google-Chrome-Device-Management': 'Google Chrome Device Management',
'Google-Drive-storage': 'Google Drive Storage',
'Google-Vault': 'Google Vault',
}
_SKUS = {
'1010010001': {
'product': '101001', 'aliases': ['identity', 'cloudidentity'], 'displayName': 'Cloud Identity'},
'1010050001': {
'product': '101005', 'aliases': ['identitypremium', 'cloudidentitypremium'], 'displayName': 'Cloud Identity Premium'},
'1010310002': {
'product': '101031', 'aliases': ['gsefe', 'e4e', 'gsuiteenterpriseeducation'], 'displayName': 'Google Workspace for Education Plus - Legacy'},
'1010310003': {
'product': '101031', 'aliases': ['gsefes', 'e4es', 'gsuiteenterpriseeducationstudent'], 'displayName': 'Google Workspace for Education Plus - Legacy (Student)'},
'1010310005': {
'product': '101031', 'aliases': ['gwes', 'workspaceeducationstandard'], 'displayName': 'Google Workspace for Education Standard'},
'1010310006': {
'product': '101031', 'aliases': ['gwesstaff', 'workspaceeducationstandardstaff'], 'displayName': 'Google Workspace for Education Standard (Staff)'},
'1010310007': {
'product': '101031', 'aliases': ['gwesstudent', 'workspaceeducationstandardstudent'], 'displayName': 'Google Workspace for Education Standard (Extra Student)'},
'1010310008': {
'product': '101031', 'aliases': ['gwep', 'workspaceeducationplus'], 'displayName': 'Google Workspace for Education Plus'},
'1010310009': {
'product': '101031', 'aliases': ['gwepstaff', 'workspaceeducationplusstaff'], 'displayName': 'Google Workspace for Education Plus (Staff)'},
'1010310010': {
'product': '101031', 'aliases': ['gwepstudent', 'workspaceeducationplusstudent'], 'displayName': 'Google Workspace for Education Plus (Extra Student)'},
'1010330002': {
'product': '101033', 'aliases': ['gvpremier', 'voicepremier', 'googlevoicepremier'], 'displayName': 'Google Voice Premier'},
'1010330003': {
'product': '101033', 'aliases': ['gvstarter', 'voicestarter', 'googlevoicestarter'], 'displayName': 'Google Voice Starter'},
'1010330004': {
'product': '101033', 'aliases': ['gvstandard', 'voicestandard', 'googlevoicestandard'], 'displayName': 'Google Voice Standard'},
'1010350001': {
'product': '101035', 'aliases': ['cloudsearch'], 'displayName': 'Cloud Search'},
'1010360001': {
'product': '101036', 'aliases': ['meetdialing','googlemeetglobaldialing'], 'displayName': 'Google Meet Global Dialing'},
'1010370001': {
'product': '101037', 'aliases': ['gwetlu', 'workspaceeducationupgrade'], 'displayName': 'Google Workspace for Education: Teaching and Learning Upgrade'},
'1010380001': {
'product': '101038', 'aliases': ['appsheetcore'], 'displayName': 'AppSheet Core'},
'1010380002': {
'product': '101038', 'aliases': ['appsheetstandard', 'appsheetenterprisestandard'], 'displayName': 'AppSheet Enterprise Standard'},
'1010380003': {
'product': '101038', 'aliases': ['appsheetplus', 'appsheetenterpriseplus'], 'displayName': 'AppSheet Enterprise Plus'},
'1010390001': {
'product': '101039', 'aliases': ['assuredcontrols'], 'displayName': 'Assured Controls'},
'1010400001': {
'product': '101040', 'aliases': ['beyondcorp', 'beyondcorpenterprise', 'bce', 'cep', 'chromeenterprisepremium'], 'displayName': 'Chrome Enterprise Premium'},
'1010430001': {
'product': '101043', 'aliases': ['gwas', 'plusstorage'], 'displayName': 'Google Workspace Additional Storage'},
'1010470001': {
'product': '101047', 'aliases': ['geminient', 'duetai'], 'displayName': 'Gemini Enterprise'},
'1010470002': {
'product': '101047', 'aliases': ['gwlabs', 'workspacelabs'], 'displayName': 'Google Workspace Labs'},
'1010470003': {
'product': '101047', 'aliases': ['geminibiz'], 'displayName': 'Gemini Business'},
'1010470004': {
'product': '101047', 'aliases': ['geminiedu'], 'displayName': 'Gemini Education'},
'1010470005': {
'product': '101047', 'aliases': ['geminiedupremium'], 'displayName': 'Gemini Education Premium'},
'1010470006': {
'product': '101047', 'aliases': ['aisecurity'], 'displayName': 'AI Security'},
'1010470007': {
'product': '101047', 'aliases': ['aimeetingsandmessaging'], 'displayName': 'AI Meetings and Messaging'},
'1010490001': {
'product': '101049', 'aliases': ['eeu'], 'displayName': 'Endpoint Education Upgrade'},
'1010500001': {
'product': '101050', 'aliases': ['colabpro'], 'displayName': 'Colab Pro'},
'1010500002': {
'product': '101050', 'aliases': ['colabpro+', 'colabproplus'], 'displayName': 'Colab Pro+'},
'Google-Apps': {
'product': 'Google-Apps', 'aliases': ['standard', 'free'], 'displayName': 'G Suite Legacy'},
'Google-Apps-For-Business': {
'product': 'Google-Apps', 'aliases': ['gafb', 'gafw', 'basic', 'gsuitebasic'], 'displayName': 'G Suite Basic'},
'Google-Apps-For-Government': {
'product': 'Google-Apps', 'aliases': ['gafg', 'gsuitegovernment', 'gsuitegov'], 'displayName': 'Google Workspace Government'},
'Google-Apps-For-Postini': {
'product': 'Google-Apps', 'aliases': ['gams', 'postini', 'gsuitegams', 'gsuitepostini', 'gsuitemessagesecurity'], 'displayName': 'Google Apps Message Security'},
'Google-Apps-Lite': {
'product': 'Google-Apps', 'aliases': ['gal', 'gsl', 'lite', 'gsuitelite'], 'displayName': 'G Suite Lite'},
'Google-Apps-Unlimited': {
'product': 'Google-Apps', 'aliases': ['gau', 'gsb', 'unlimited', 'gsuitebusiness'], 'displayName': 'G Suite Business'},
'1010020020': {
'product': 'Google-Apps', 'aliases': ['gae', 'gse', 'enterprise', 'gsuiteenterprise',
'wsentplus', 'workspaceenterpriseplus'], 'displayName': 'Google Workspace Enterprise Plus'},
'1010020025': {
'product': 'Google-Apps', 'aliases': ['wsbizplus', 'workspacebusinessplus'], 'displayName': 'Google Workspace Business Plus'},
'1010020026': {
'product': 'Google-Apps', 'aliases': ['wsentstan', 'workspaceenterprisestandard'], 'displayName': 'Google Workspace Enterprise Standard'},
'1010020027': {
'product': 'Google-Apps', 'aliases': ['wsbizstart', 'wsbizstarter', 'workspacebusinessstarter'], 'displayName': 'Google Workspace Business Starter'},
'1010020028': {
'product': 'Google-Apps', 'aliases': ['wsbizstan', 'workspacebusinessstandard'], 'displayName': 'Google Workspace Business Standard'},
'1010020029': {
'product': 'Google-Apps', 'aliases': ['wes', 'wsentstarter', 'workspaceenterprisestarter'], 'displayName': 'Workspace Enterprise Starter'},
'1010020030': {
'product': 'Google-Apps', 'aliases': ['wsflw', 'workspacefrontline', 'workspacefrontlineworker'], 'displayName': 'Google Workspace Frontline Starter'},
'1010020031': {
'product': 'Google-Apps', 'aliases': ['wsflwstan', 'workspacefrontlinestan', 'workspacefrontlineworkerstan'], 'displayName': 'Google Workspace Frontline Standard'},
'1010340001': {
'product': '101034', 'aliases': ['gseau', 'enterprisearchived', 'gsuiteenterprisearchived'], 'displayName': 'Google Workspace Enterprise Plus - Archived User'},
'1010340002': {
'product': '101034', 'aliases': ['gsbau', 'businessarchived', 'gsuitebusinessarchived'], 'displayName': 'Google Workspace Business - Archived User'},
'1010340003': {
'product': '101034', 'aliases': ['wsbizplusarchived', 'workspacebusinessplusarchived'], 'displayName': 'Google Workspace Business Plus - Archived User'},
'1010340004': {
'product': '101034', 'aliases': ['wsentstanarchived', 'workspaceenterprisestandardarchived'], 'displayName': 'Google Workspace Enterprise Standard - Archived User'},
'1010340005': {
'product': '101034', 'aliases': ['wsbizstarterarchived', 'workspacebusinessstarterarchived'], 'displayName': 'Google Workspace Business Starter - Archived User'},
'1010340006': {
'product': '101034', 'aliases': ['wsbizstanarchived', 'workspacebusinessstanarchived'], 'displayName': 'Google Workspace Business Standard - Archived User'},
'1010060001': {
'product': '101006', 'aliases': ['gsuiteessentials', 'essentials',
'd4e', 'driveenterprise', 'drive4enterprise',
'wsess', 'workspaceesentials'], 'displayName': 'Google Workspace Essentials'},
'1010060003': {
'product': 'Google-Apps', 'aliases': ['wsentess', 'workspaceenterpriseessentials'], 'displayName': 'Google Workspace Enterprise Essentials'},
'1010060005': {
'product': 'Google-Apps', 'aliases': ['wsessplus', 'workspaceessentialsplus'], 'displayName': 'Google Workspace Essentials Plus'},
'Google-Drive-storage-20GB': {
'product': 'Google-Drive-storage', 'aliases': ['drive20gb', '20gb', 'googledrivestorage20gb'], 'displayName': 'Google Drive Storage 20GB'},
'Google-Drive-storage-50GB': {
'product': 'Google-Drive-storage', 'aliases': ['drive50gb', '50gb', 'googledrivestorage50gb'], 'displayName': 'Google Drive Storage 50GB'},
'Google-Drive-storage-200GB': {
'product': 'Google-Drive-storage', 'aliases': ['drive200gb', '200gb', 'googledrivestorage200gb'], 'displayName': 'Google Drive Storage 200GB'},
'Google-Drive-storage-400GB': {
'product': 'Google-Drive-storage', 'aliases': ['drive400gb', '400gb', 'googledrivestorage400gb'], 'displayName': 'Google Drive Storage 400GB'},
'Google-Drive-storage-1TB': {
'product': 'Google-Drive-storage', 'aliases': ['drive1tb', '1tb', 'googledrivestorage1tb'], 'displayName': 'Google Drive Storage 1TB'},
'Google-Drive-storage-2TB': {
'product': 'Google-Drive-storage', 'aliases': ['drive2tb', '2tb', 'googledrivestorage2tb'], 'displayName': 'Google Drive Storage 2TB'},
'Google-Drive-storage-4TB': {
'product': 'Google-Drive-storage', 'aliases': ['drive4tb', '4tb', 'googledrivestorage4tb'], 'displayName': 'Google Drive Storage 4TB'},
'Google-Drive-storage-8TB': {
'product': 'Google-Drive-storage', 'aliases': ['drive8tb', '8tb', 'googledrivestorage8tb'], 'displayName': 'Google Drive Storage 8TB'},
'Google-Drive-storage-16TB': {
'product': 'Google-Drive-storage', 'aliases': ['drive16tb', '16tb', 'googledrivestorage16tb'], 'displayName': 'Google Drive Storage 16TB'},
'Google-Vault': {
'product': 'Google-Vault', 'aliases': ['vault', 'googlevault'], 'displayName': 'Google Vault'},
'Google-Vault-Former-Employee': {
'product': 'Google-Vault', 'aliases': ['vfe', 'googlevaultformeremployee'], 'displayName': 'Google Vault - Former Employee'},
'Google-Chrome-Device-Management': {
'product': 'Google-Chrome-Device-Management', 'aliases': ['chrome', 'cdm', 'googlechromedevicemanagement'], 'displayName': 'Google Chrome Device Management'}
}
ARCHIVABLE_SKUS = {'1010020020', '1010020025', '1010020026', '1010020027', '1010020028', 'Google-Apps-Unlimited'}
def getProductAndSKU(sku):
l_sku = sku.lower().replace('-', '').replace(' ', '').replace('"', '').replace("'", '').strip()
if l_sku.startswith('nv:'):
if ':' in sku[3:]:
return sku[3:].split(':', 1)
return (None, sku)
for a_sku, sku_values in list(_SKUS.items()):
if ((l_sku == a_sku.lower().replace('-', '')) or
(l_sku in sku_values['aliases']) or
(l_sku == sku_values['displayName'].lower().replace(' ', ''))):
return (sku_values['product'], a_sku)
return (None, sku)
def productIdToDisplayName(productId):
return _PRODUCTS.get(productId, productId)
def formatProductIdDisplayName(productId):
productIdDisplay = productIdToDisplayName(productId)
if productId == productIdDisplay:
return productId
return f'{productId} ({productIdDisplay})'
def normalizeProductId(product):
l_product = product.lower().replace('-', '').replace(' ', '').strip()
if l_product.startswith('nv:'):
return (True, product[3:])
for a_sku, sku_values in list(_SKUS.items()):
if ((l_product == sku_values['product'].lower().replace('-', '')) or
(l_product == a_sku.lower().replace('-', '')) or
(l_product in sku_values['aliases']) or
(l_product == sku_values['displayName'].lower().replace(' ', ''))):
return (True, sku_values['product'])
return (False, product)
def getSortedProductList():
return sorted(_PRODUCTS)
def skuIdToDisplayName(skuId):
return _SKUS[skuId]['displayName'] if skuId in _SKUS else skuId
def formatSKUIdDisplayName(skuId):
skuIdDisplay = skuIdToDisplayName(skuId)
if skuId == skuIdDisplay:
return skuId
return f'{skuId} ({skuIdDisplay})'
def getSortedSKUList():
return sorted(_SKUS)
def convertProductListToSKUList(productList):
skuList = []
for productId in productList:
skuList += [(productId, skuId) for skuId in _SKUS if _SKUS[skuId]['product'] == productId]
return skuList
def getAllSKUs():
return convertProductListToSKUList(sorted(_PRODUCTS))
def getGSuiteSKUs():
return convertProductListToSKUList(['Google-Apps', '101031'])

279
src/gam/gamlib/gluprop.py Normal file
View File

@@ -0,0 +1,279 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM user properties
"""
# notes
# a|b|c
# getKeywordAttribute(CUSTOM_TYPE_NOCUSTOM, attrdict)
#CUSTOM_TYPE_NOCUSTOM = {
# PTKW_CL_TYPE_KEYWORD: 'type',
# PTKW_CL_CUSTOM_KEYWORD: None,
# PTKW_ATTR_TYPE_KEYWORD: 'type',
# PTKW_ATTR_TYPE_CUSTOM_VALUE: None,
# PTKW_ATTR_CUSTOMTYPE_KEYWORD: None,
# PTKW_KEYWORD_LIST: ['a', 'b', 'c']
# }
# addresses, ims
# type a|b|c|([custom] <String>)
# getChoice([CUSTOM_TYPE_CUSTOM[PTKW_CL_TYPE_KEYWORD]])
# getKeywordAttribute(CUSTOM_TYPE_CUSTOM, attrdict)
# emails, externalids, relations, websites
# [type] a|b|c|([custom] <String>)
# getChoice([CUSTOM_TYPE_CUSTOM[PTKW_CL_TYPE_KEYWORD]], defaultChoice=None)
# getKeywordAttribute(CUSTOM_TYPE_IMPLICIT, attrdict)
# locations, phones
# type a|b|c|([custom] <String>)
# if argument == CUSTOM_TYPE_CUSTOM[PTKW_CL_TYPE_KEYWORD]:
# getKeywordAttribute(CUSTOM_TYPE_CUSTOM, attrdict)
#CUSTOM_TYPE_CUSTOM = {
# PTKW_CL_TYPE_KEYWORD: 'type',
# PTKW_CL_CUSTOM_KEYWORD: 'custom',
# PTKW_ATTR_TYPE_KEYWORD: 'type',
# PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom',
# PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
# PTKW_KEYWORD_LIST: ['custom', 'a', 'b', 'c']
# }
# organizations
# (type a|b|c|([custom] <String>)) | (custom_type <String>)
# if argument == CUSTOM_TYPE_DIFFERENT_KEYWORD[PTKW_CL_TYPE_KEYWORD]:
# getKeywordAttribute(CUSTOM_TYPE_DIFFERENT_KEYWORD, attrdict)
# elif argument == CUSTOM_TYPE_DIFFERENT_KEYWORD[PTKW_CL_CUSTOM_KEYWORD]:
# attrdict[CUSTOM_TYPE_DIFFERENT_KEYWORD[PTKW_ATTR_CUSTOMTYPE_KEYWORD]] = getValue()
#CUSTOM_TYPE_DIFFERENT_KEYWORD = {
# PTKW_CL_TYPE_KEYWORD: 'type',
# PTKW_CL_CUSTOM_KEYWORD: 'custom',
# PTKW_CL_CUSTOMTYPE_KEYWORD: 'custom_type',
# PTKW_ATTR_TYPE_KEYWORD: 'type',
# PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom',
# PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
# PTKW_KEYWORD_LIST: ['custom', 'a', 'b', 'c']
# }
# Keys into USER_PROPERTIES
CLASS = 'clas'
TITLE = 'titl'
TYPE_KEYWORDS = 'tykw'
PTKW_CL_TYPE_KEYWORD = 'ctkw'
PTKW_CL_CUSTOM_KEYWORD = 'ccuk'
PTKW_CL_CUSTOMTYPE_KEYWORD = 'cctk'
PTKW_ATTR_TYPE_KEYWORD = 'atkw'
PTKW_ATTR_TYPE_CUSTOM_VALUE = 'atcv'
PTKW_ATTR_CUSTOMTYPE_KEYWORD = 'actk'
PTKW_KEYWORD_LIST = 'kwli'
#
PC_ADDRESSES = 'addr'
PC_ALIASES = 'alia'
PC_ARRAY = 'arry'
PC_BOOLEAN = 'bool'
PC_EMAILS = 'emai'
PC_GENDER = 'gndr'
PC_IMS = 'ims '
PC_LANGUAGES = 'lang'
PC_LOCATIONS = 'loca'
PC_NAME = 'name'
PC_NOTES = 'note'
PC_ORGANIZATIONS = 'orga'
PC_POSIX = 'posi'
PC_SCHEMAS = 'schm'
PC_SSH = 'ssh '
PC_STRING = 'stri'
PC_TIME = 'time'
PROPERTIES = {
'primaryEmail':
{CLASS: PC_STRING, TITLE: 'User',},
'name':
{CLASS: PC_NAME, TITLE: 'Name',},
'givenName':
{CLASS: PC_STRING, TITLE: 'First Name',},
'familyName':
{CLASS: PC_STRING, TITLE: 'Last Name',},
'fullName':
{CLASS: PC_STRING, TITLE: 'Full Name',},
'displayName':
{CLASS: PC_STRING, TITLE: 'Display Name',},
'languages':
{CLASS: PC_LANGUAGES, TITLE: 'Languages',},
'languageCode':
{CLASS: PC_LANGUAGES, TITLE: 'Languages',},
'customLanguage':
{CLASS: PC_LANGUAGES, TITLE: 'Custom Languages',},
'password':
{CLASS: PC_STRING, TITLE: 'Password',},
'hashFunction':
{CLASS: PC_STRING, TITLE: 'Hash Function',},
'isAdmin':
{CLASS: PC_BOOLEAN, TITLE: 'Is a Super Admin',},
'isDelegatedAdmin':
{CLASS: PC_BOOLEAN, TITLE: 'Is Delegated Admin',},
'isEnrolledIn2Sv':
{CLASS: PC_BOOLEAN, TITLE: '2-step enrolled',},
'isEnforcedIn2Sv':
{CLASS: PC_BOOLEAN, TITLE: '2-step enforced',},
'agreedToTerms':
{CLASS: PC_BOOLEAN, TITLE: 'Has Agreed to Terms',},
'ipWhitelisted':
{CLASS: PC_BOOLEAN, TITLE: 'IP Whitelisted',},
'archived':
{CLASS: PC_BOOLEAN, TITLE: 'Is Archived',},
'suspended':
{CLASS: PC_BOOLEAN, TITLE: 'Account Suspended',},
'suspensionReason':
{CLASS: PC_STRING, TITLE: 'Suspension Reason',},
'changePasswordAtNextLogin':
{CLASS: PC_BOOLEAN, TITLE: 'Must Change Password',},
'recoveryEmail':
{CLASS: PC_STRING, TITLE: 'Recovery Email',},
'recoveryPhone':
{CLASS: PC_STRING, TITLE: 'Recovery Phone',},
'id':
{CLASS: PC_STRING, TITLE: 'Google Unique ID',},
'customerId':
{CLASS: PC_STRING, TITLE: 'Customer ID',},
'isMailboxSetup':
{CLASS: PC_BOOLEAN, TITLE: 'Mailbox is setup',},
'includeInGlobalAddressList':
{CLASS: PC_BOOLEAN, TITLE: 'Included in GAL',},
'creationTime':
{CLASS: PC_TIME, TITLE: 'Creation Time',},
'lastLoginTime':
{CLASS: PC_TIME, TITLE: 'Last login time',},
'deletionTime':
{CLASS: PC_TIME, TITLE: 'Deletion Time',},
'orgUnitPath':
{CLASS: PC_STRING, TITLE: 'Google Org Unit Path',},
'thumbnailPhotoUrl':
{CLASS: PC_STRING, TITLE: 'Photo URL',},
'addresses':
{CLASS: PC_ADDRESSES, TITLE: 'Addresses',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'other', 'work'],},},
'emails':
{CLASS: PC_EMAILS, TITLE: 'Other Emails',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'other', 'work'],},},
'externalIds':
{CLASS: PC_ARRAY, TITLE: 'External IDs',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'account', 'customer', 'login_id', 'network', 'organization'],},},
'gender':
{CLASS: PC_GENDER, TITLE: 'Gender',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'other',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'other', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customGender',
PTKW_KEYWORD_LIST: ['male', 'female', 'other', 'unknown'],},},
'ims':
{CLASS: PC_IMS, TITLE: 'IMs',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'other', 'work'],},},
'keywords':
{CLASS: PC_ARRAY, TITLE: 'Keywords',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'mission', 'occupation', 'outlook'],},},
'locations':
{CLASS: PC_LOCATIONS, TITLE: 'Locations',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'default', 'desk'],},},
'notes':
{CLASS: PC_NOTES, TITLE: 'Notes',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: None,
PTKW_ATTR_TYPE_KEYWORD: 'contentType', PTKW_ATTR_TYPE_CUSTOM_VALUE: None, PTKW_ATTR_CUSTOMTYPE_KEYWORD: None,
PTKW_KEYWORD_LIST: ['text_plain', 'text_html'],},},
'organizations':
{CLASS: PC_ORGANIZATIONS, TITLE: 'Organizations',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom', PTKW_CL_CUSTOMTYPE_KEYWORD: 'customtype',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: None, PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'domain_only', 'school', 'unknown', 'work'],},},
'phones':
{CLASS: PC_ARRAY, TITLE: 'Phones',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'work', 'other',
'home_fax', 'work_fax', 'other_fax',
'mobile', 'pager',
'company_main', 'assistant',
'car', 'radio', 'isdn', 'callback',
'telex', 'tty_tdd', 'work_mobile',
'work_pager', 'main', 'grand_central'],},},
'posixAccounts':
{CLASS: PC_POSIX, TITLE: 'Posix Accounts',},
'relations':
{CLASS: PC_ARRAY, TITLE: 'Relations',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'spouse', 'child', 'mother',
'father', 'parent', 'brother',
'sister', 'friend', 'relative',
'domestic_partner', 'partner',
'manager', 'dotted_line_manager',
'assistant', 'admin_assistant', 'exec_assistant',
'referred_by'],},},
'sshPublicKeys':
{CLASS: PC_SSH, TITLE: 'SSH Public Keys',},
'websites':
{CLASS: PC_ARRAY, TITLE: 'Websites',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'work',
'home_page', 'ftp', 'blog',
'profile', 'other', 'reservations',
'app_install_page', 'resume'],},},
'customSchemas':
{CLASS: PC_SCHEMAS, TITLE: 'Custom Schemas',
TYPE_KEYWORDS:
{PTKW_CL_TYPE_KEYWORD: 'type', PTKW_CL_CUSTOM_KEYWORD: 'custom',
PTKW_ATTR_TYPE_KEYWORD: 'type', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customType',
PTKW_KEYWORD_LIST: ['custom', 'home', 'other', 'work'],},},
'aliases': {
CLASS: PC_ALIASES, TITLE: 'Email Aliases',},
'nonEditableAliases': {
CLASS: PC_ALIASES, TITLE: 'NonEditable Aliases',},
}
#
IM_PROTOCOLS = {
PTKW_CL_TYPE_KEYWORD: 'protocol', PTKW_CL_CUSTOM_KEYWORD: 'custom_protocol',
PTKW_ATTR_TYPE_KEYWORD: 'protocol', PTKW_ATTR_TYPE_CUSTOM_VALUE: 'custom_protocol', PTKW_ATTR_CUSTOMTYPE_KEYWORD: 'customProtocol',
PTKW_KEYWORD_LIST: ['custom_protocol', 'aim', 'gtalk', 'icq', 'jabber', 'msn', 'net_meeting', 'qq', 'skype', 'xmpp', 'yahoo']
}

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""GAM extended library versions
"""
GAM_VER_LIBS = ['cryptography',
'filelock',
'google-api-python-client',
'google-auth-httplib2',
'google-auth-oauthlib',
'google-auth',
'httplib2',
'passlib',
'python-dateutil',
'yubikey-manager',
]

202
src/gam/gamlib/yubikey.py Normal file
View File

@@ -0,0 +1,202 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""YubiKey"""
import base64
import datetime
from secrets import SystemRandom
import string
import sys
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from smartcard.Exceptions import CardConnectionException
from ykman.device import list_all_devices
from ykman.piv import generate_self_signed_certificate, generate_chuid
from yubikit.piv import DEFAULT_MANAGEMENT_KEY, \
InvalidPinError, \
KEY_TYPE, \
MANAGEMENT_KEY_TYPE, \
PIN_POLICY, \
PivSession, \
OBJECT_ID, \
SLOT, \
TOUCH_POLICY
from yubikit.core.smartcard import ApduError, SmartCardConnection
YUBIKEY_CONNECTION_ERROR_RC = 80
YUBIKEY_INVALID_KEY_TYPE_RC = 81
YUBIKEY_INVALID_SLOT_RC = 82
YUBIKEY_INVALID_PIN_RC = 83
YUBIKEY_APDU_ERROR_RC = 84
YUBIKEY_VALUE_ERROR_RC = 85
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
YUBIKEY_NOT_FOUND_RC = 87
from gam import mplock
from gam import systemErrorExit
from gam import readStdin
from gam import writeStdout
from gam.gamlib import glmsgs as Msg
PIN_PUK_CHARS = string.ascii_letters+string.digits+string.punctuation
class YubiKey():
def __init__(self, service_account_info=None):
self.key_type = None
self.slot = None
self.serial_number = None
self.pin = None
self.key_id = None
if service_account_info:
key_type = service_account_info.get('yubikey_key_type', 'RSA2048')
try:
self.key_type = getattr(KEY_TYPE, key_type.upper())
except AttributeError:
systemErrorExit(YUBIKEY_INVALID_KEY_TYPE_RC, f'{key_type} is not a valid value for yubikey_key_type')
slot = service_account_info.get('yubikey_slot', 'AUTHENTICATION')
try:
self.slot = getattr(SLOT, slot.upper())
except AttributeError:
systemErrorExit(YUBIKEY_INVALID_SLOT_RC, f'{slot} is not a valid value for yubikey_slot')
self.serial_number = service_account_info.get('yubikey_serial_number')
self.pin = service_account_info.get('yubikey_pin')
self.key_id = service_account_info.get('private_key_id')
def _connect(self):
try:
devices = list_all_devices()
for (device, info) in devices:
if info.serial == self.serial_number:
return device.open_connection(SmartCardConnection)
except CardConnectionException as err:
systemErrorExit(YUBIKEY_CONNECTION_ERROR_RC, f'YubiKey - {err}')
def get_certificate(self):
try:
conn = self._connect()
with conn:
session = PivSession(conn)
if self.pin:
try:
session.verify_pin(self.pin)
except InvalidPinError as err:
systemErrorExit(YUBIKEY_INVALID_PIN_RC, f'YubiKey - {err}')
try:
cert = session.get_certificate(self.slot)
except ApduError as err:
systemErrorExit(YUBIKEY_APDU_ERROR_RC, f'YubiKey - {err}')
cert_pem = cert.public_bytes(serialization.Encoding.PEM).decode()
publicKeyData = base64.b64encode(cert_pem.encode())
if isinstance(publicKeyData, bytes):
publicKeyData = publicKeyData.decode()
return publicKeyData
except ValueError as err:
systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
except TypeError as err:
systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
def get_serial_number(self):
try:
devices = list_all_devices()
if not devices:
systemErrorExit(YUBIKEY_NOT_FOUND_RC, Msg.COULD_NOT_FIND_ANY_YUBIKEY)
if self.serial_number:
for (_, info) in devices:
if info.serial == self.serial_number:
return info.serial
systemErrorExit(YUBIKEY_NOT_FOUND_RC, Msg.COULD_NOT_FIND_YUBIKEY_WITH_SERIAL.format(self.serial_number))
if len(devices) > 1:
serials = ', '.join([str(info.serial) for (_, info) in devices])
systemErrorExit(YUBIKEY_MULTIPLE_CONNECTED_RC, Msg.MULTIPLE_YUBIKEYS_CONNECTED.format(serials))
return devices[0][1].serial
except ValueError as err:
systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
def reset_piv(self):
'''Resets YubiKey PIV app and generates new key for GAM to use.'''
reply = str(readStdin(Msg.CONFIRM_WIPE_YUBIKEY_PIV).lower().strip())
if reply != 'y':
sys.exit(1)
try:
conn = self._connect()
with conn:
piv = PivSession(conn)
piv.reset()
rnd = SystemRandom()
new_puk = ''.join(rnd.choice(PIN_PUK_CHARS) for _ in range(8))
new_pin = ''.join(rnd.choice(PIN_PUK_CHARS) for _ in range(8))
piv.change_puk('12345678', new_puk)
piv.change_pin('123456', new_pin)
writeStdout(Msg.YUBIKEY_PIN_SET_TO.format(new_pin))
piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
piv.verify_pin(new_pin)
writeStdout(Msg.YUBIKEY_GENERATING_NONEXPORTABLE_PRIVATE_KEY)
pubkey = piv.generate_key(SLOT.AUTHENTICATION,
KEY_TYPE.RSA2048,
PIN_POLICY.ALWAYS,
TOUCH_POLICY.NEVER)
now = datetime.datetime.utcnow()
valid_to = now + datetime.timedelta(days=36500)
subject = 'CN=GAM Created Key'
piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
piv.verify_pin(new_pin)
cert = generate_self_signed_certificate(piv,
SLOT.AUTHENTICATION,
pubkey,
subject,
now,
valid_to)
piv.put_certificate(SLOT.AUTHENTICATION, cert)
piv.put_object(OBJECT_ID.CHUID, generate_chuid())
except ValueError as err:
systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
except TypeError as err:
systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
def sign(self, message):
if mplock is not None:
mplock.acquire()
try:
conn = self._connect()
with conn:
session = PivSession(conn)
if self.pin:
try:
session.verify_pin(self.pin)
except InvalidPinError as err:
systemErrorExit(YUBIKEY_INVALID_PIN_RC, f'YubiKey - {err}')
try:
signed = session.sign(slot=self.slot,
key_type=self.key_type,
message=message,
hash_algorithm=hashes.SHA256(),
padding=padding.PKCS1v15())
except ApduError as err:
systemErrorExit(YUBIKEY_APDU_ERROR_RC, f'YubiKey - {err}')
except ValueError as err:
systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
except TypeError as err:
systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
if mplock is not None:
mplock.release()
return signed

825
src/gam/gdata/__init__.py Normal file
View File

@@ -0,0 +1,825 @@
#!/usr/bin/python
#
# Copyright (C) 2006 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Contains classes representing Google Data elements.
Extends Atom classes to add Google Data specific elements.
"""
__author__ = 'j.s@google.com (Jeffrey Scudder)'
import os
import atom
import lxml.etree as ElementTree
# XML namespaces which are often used in GData entities.
GDATA_NAMESPACE = 'http://schemas.google.com/g/2005'
GDATA_TEMPLATE = '{http://schemas.google.com/g/2005}%s'
OPENSEARCH_NAMESPACE = 'http://a9.com/-/spec/opensearchrss/1.0/'
OPENSEARCH_TEMPLATE = '{http://a9.com/-/spec/opensearchrss/1.0/}%s'
BATCH_NAMESPACE = 'http://schemas.google.com/gdata/batch'
GACL_NAMESPACE = 'http://schemas.google.com/acl/2007'
GACL_TEMPLATE = '{http://schemas.google.com/acl/2007}%s'
# Labels used in batch request entries to specify the desired CRUD operation.
BATCH_INSERT = 'insert'
BATCH_UPDATE = 'update'
BATCH_DELETE = 'delete'
BATCH_QUERY = 'query'
class Error(Exception):
pass
class MissingRequiredParameters(Error):
pass
class MediaSource(object):
"""GData Entries can refer to media sources, so this class provides a
place to store references to these objects along with some metadata.
"""
def __init__(self, file_handle=None, content_type=None, content_length=None,
file_path=None, file_name=None):
"""Creates an object of type MediaSource.
Args:
file_handle: A file handle pointing to the file to be encapsulated in the
MediaSource
content_type: string The MIME type of the file. Required if a file_handle
is given.
content_length: int The size of the file. Required if a file_handle is
given.
file_path: string (optional) A full path name to the file. Used in
place of a file_handle.
file_name: string The name of the file without any path information.
Required if a file_handle is given.
"""
self.file_handle = file_handle
self.content_type = content_type
self.content_length = content_length
self.file_name = file_name
if (file_handle is None and content_type is not None and
file_path is not None):
self.setFile(file_path, content_type)
def setFile(self, file_name, content_type):
"""A helper function which can create a file handle from a given filename
and set the content type and length all at once.
Args:
file_name: string The path and file name to the file containing the media
content_type: string A MIME type representing the type of the media
"""
self.file_handle = open(file_name, 'rb')
self.content_type = content_type
self.content_length = os.path.getsize(file_name)
self.file_name = os.path.basename(file_name)
class LinkFinder(atom.LinkFinder):
"""An "interface" providing methods to find link elements
GData Entry elements often contain multiple links which differ in the rel
attribute or content type. Often, developers are interested in a specific
type of link so this class provides methods to find specific classes of
links.
This class is used as a mixin in GData entries.
"""
def GetSelfLink(self):
"""Find the first link with rel set to 'self'
Returns:
An atom.Link or none if none of the links had rel equal to 'self'
"""
for a_link in self.link:
if a_link.rel == 'self':
return a_link
return None
def GetEditLink(self):
for a_link in self.link:
if a_link.rel == 'edit':
return a_link
return None
def GetEditMediaLink(self):
"""The Picasa API mistakenly returns media-edit rather than edit-media, but
this may change soon.
"""
for a_link in self.link:
if a_link.rel == 'edit-media':
return a_link
if a_link.rel == 'media-edit':
return a_link
return None
def GetHtmlLink(self):
"""Find the first link with rel of alternate and type of text/html
Returns:
An atom.Link or None if no links matched
"""
for a_link in self.link:
if a_link.rel == 'alternate' and a_link.type == 'text/html':
return a_link
return None
def GetPostLink(self):
"""Get a link containing the POST target URL.
The POST target URL is used to insert new entries.
Returns:
A link object with a rel matching the POST type.
"""
for a_link in self.link:
if a_link.rel == 'http://schemas.google.com/g/2005#post':
return a_link
return None
def GetAclLink(self):
for a_link in self.link:
if a_link.rel == 'http://schemas.google.com/acl/2007#accessControlList':
return a_link
return None
def GetFeedLink(self):
for a_link in self.link:
if a_link.rel == 'http://schemas.google.com/g/2005#feed':
return a_link
return None
def GetNextLink(self):
for a_link in self.link:
if a_link.rel == 'next':
return a_link
return None
def GetPrevLink(self):
for a_link in self.link:
if a_link.rel == 'previous':
return a_link
return None
class TotalResults(atom.AtomBase):
"""opensearch:TotalResults for a GData feed"""
_tag = 'totalResults'
_namespace = OPENSEARCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def __init__(self, extension_elements=None,
extension_attributes=None, text=None):
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def TotalResultsFromString(xml_string):
return atom.CreateClassFromXMLString(TotalResults, xml_string)
class StartIndex(atom.AtomBase):
"""The opensearch:startIndex element in GData feed"""
_tag = 'startIndex'
_namespace = OPENSEARCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def __init__(self, extension_elements=None,
extension_attributes=None, text=None):
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def StartIndexFromString(xml_string):
return atom.CreateClassFromXMLString(StartIndex, xml_string)
class ItemsPerPage(atom.AtomBase):
"""The opensearch:itemsPerPage element in GData feed"""
_tag = 'itemsPerPage'
_namespace = OPENSEARCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def __init__(self, extension_elements=None,
extension_attributes=None, text=None):
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def ItemsPerPageFromString(xml_string):
return atom.CreateClassFromXMLString(ItemsPerPage, xml_string)
class ExtendedProperty(atom.AtomBase):
"""The Google Data extendedProperty element.
Used to store arbitrary key-value information specific to your
application. The value can either be a text string stored as an XML
attribute (.value), or an XML node (XmlBlob) as a child element.
This element is used in the Google Calendar data API and the Google
Contacts data API.
"""
_tag = 'extendedProperty'
_namespace = GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['name'] = 'name'
_attributes['value'] = 'value'
def __init__(self, name=None, value=None, extension_elements=None,
extension_attributes=None, text=None):
self.name = name
self.value = value
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def GetXmlBlobExtensionElement(self):
"""Returns the XML blob as an atom.ExtensionElement.
Returns:
An atom.ExtensionElement representing the blob's XML, or None if no
blob was set.
"""
if len(self.extension_elements) < 1:
return None
else:
return self.extension_elements[0]
def GetXmlBlobString(self):
"""Returns the XML blob as a string.
Returns:
A string containing the blob's XML, or None if no blob was set.
"""
blob = self.GetXmlBlobExtensionElement()
if blob:
return blob.ToString()
return None
def SetXmlBlob(self, blob):
"""Sets the contents of the extendedProperty to XML as a child node.
Since the extendedProperty is only allowed one child element as an XML
blob, setting the XML blob will erase any preexisting extension elements
in this object.
Args:
blob: str, ElementTree Element or atom.ExtensionElement representing
the XML blob stored in the extendedProperty.
"""
# Erase any existing extension_elements, clears the child nodes from the
# extendedProperty.
self.extension_elements = []
if isinstance(blob, atom.ExtensionElement):
self.extension_elements.append(blob)
elif ElementTree.iselement(blob):
self.extension_elements.append(atom._ExtensionElementFromElementTree(
blob))
else:
self.extension_elements.append(atom.ExtensionElementFromString(blob))
def ExtendedPropertyFromString(xml_string):
return atom.CreateClassFromXMLString(ExtendedProperty, xml_string)
class GDataEntry(atom.Entry, LinkFinder):
"""Extends Atom Entry to provide data processing"""
_tag = atom.Entry._tag
_namespace = atom.Entry._namespace
_children = atom.Entry._children.copy()
_attributes = atom.Entry._attributes.copy()
def __GetId(self):
return self.__id
# This method was created to strip the unwanted whitespace from the id's
# text node.
def __SetId(self, id):
self.__id = id
if id is not None and id.text is not None:
self.__id.text = id.text.strip()
id = property(__GetId, __SetId)
def IsMedia(self):
"""Determines whether or not an entry is a GData Media entry.
"""
if (self.GetEditMediaLink()):
return True
else:
return False
def GetMediaURL(self):
"""Returns the URL to the media content, if the entry is a media entry.
Otherwise returns None.
"""
if not self.IsMedia():
return None
else:
return self.content.src
def GDataEntryFromString(xml_string):
"""Creates a new GDataEntry instance given a string of XML."""
return atom.CreateClassFromXMLString(GDataEntry, xml_string)
class GDataFeed(atom.Feed, LinkFinder):
"""A Feed from a GData service"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = atom.Feed._children.copy()
_attributes = atom.Feed._attributes.copy()
_children['{%s}totalResults' % OPENSEARCH_NAMESPACE] = ('total_results',
TotalResults)
_children['{%s}startIndex' % OPENSEARCH_NAMESPACE] = ('start_index',
StartIndex)
_children['{%s}itemsPerPage' % OPENSEARCH_NAMESPACE] = ('items_per_page',
ItemsPerPage)
# Add a conversion rule for atom:entry to make it into a GData
# Entry.
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [GDataEntry])
def __GetId(self):
return self.__id
def __SetId(self, id):
self.__id = id
if id is not None and id.text is not None:
self.__id.text = id.text.strip()
id = property(__GetId, __SetId)
def __GetGenerator(self):
return self.__generator
def __SetGenerator(self, generator):
self.__generator = generator
if generator is not None:
self.__generator.text = generator.text.strip()
generator = property(__GetGenerator, __SetGenerator)
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None, entry=None,
total_results=None, start_index=None, items_per_page=None,
extension_elements=None, extension_attributes=None, text=None):
"""Constructor for Source
Args:
author: list (optional) A list of Author instances which belong to this
class.
category: list (optional) A list of Category instances
contributor: list (optional) A list on Contributor instances
generator: Generator (optional)
icon: Icon (optional)
id: Id (optional) The entry's Id element
link: list (optional) A list of Link instances
logo: Logo (optional)
rights: Rights (optional) The entry's Rights element
subtitle: Subtitle (optional) The entry's subtitle element
title: Title (optional) the entry's title element
updated: Updated (optional) the entry's updated element
entry: list (optional) A list of the Entry instances contained in the
feed.
text: String (optional) The text contents of the element. This is the
contents of the Entry's XML text node.
(Example: <foo>This is the text</foo>)
extension_elements: list (optional) A list of ExtensionElement instances
which are children of this element.
extension_attributes: dict (optional) A dictionary of strings which are
the values for additional XML attributes of this element.
"""
self.author = author or []
self.category = category or []
self.contributor = contributor or []
self.generator = generator
self.icon = icon
self.id = atom_id
self.link = link or []
self.logo = logo
self.rights = rights
self.subtitle = subtitle
self.title = title
self.updated = updated
self.entry = entry or []
self.total_results = total_results
self.start_index = start_index
self.items_per_page = items_per_page
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def GDataFeedFromString(xml_string):
return atom.CreateClassFromXMLString(GDataFeed, xml_string)
class BatchId(atom.AtomBase):
_tag = 'id'
_namespace = BATCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def BatchIdFromString(xml_string):
return atom.CreateClassFromXMLString(BatchId, xml_string)
class BatchOperation(atom.AtomBase):
_tag = 'operation'
_namespace = BATCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['type'] = 'type'
def __init__(self, op_type=None, extension_elements=None,
extension_attributes=None,
text=None):
self.type = op_type
atom.AtomBase.__init__(self,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def BatchOperationFromString(xml_string):
return atom.CreateClassFromXMLString(BatchOperation, xml_string)
class BatchStatus(atom.AtomBase):
"""The batch:status element present in a batch response entry.
A status element contains the code (HTTP response code) and
reason as elements. In a single request these fields would
be part of the HTTP response, but in a batch request each
Entry operation has a corresponding Entry in the response
feed which includes status information.
See http://code.google.com/apis/gdata/batch.html#Handling_Errors
"""
_tag = 'status'
_namespace = BATCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['code'] = 'code'
_attributes['reason'] = 'reason'
_attributes['content-type'] = 'content_type'
def __init__(self, code=None, reason=None, content_type=None,
extension_elements=None, extension_attributes=None, text=None):
self.code = code
self.reason = reason
self.content_type = content_type
atom.AtomBase.__init__(self, extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def BatchStatusFromString(xml_string):
return atom.CreateClassFromXMLString(BatchStatus, xml_string)
class BatchEntry(GDataEntry):
"""An atom:entry for use in batch requests.
The BatchEntry contains additional members to specify the operation to be
performed on this entry and a batch ID so that the server can reference
individual operations in the response feed. For more information, see:
http://code.google.com/apis/gdata/batch.html
"""
_tag = GDataEntry._tag
_namespace = GDataEntry._namespace
_children = GDataEntry._children.copy()
_children['{%s}operation' % BATCH_NAMESPACE] = ('batch_operation', BatchOperation)
_children['{%s}id' % BATCH_NAMESPACE] = ('batch_id', BatchId)
_children['{%s}status' % BATCH_NAMESPACE] = ('batch_status', BatchStatus)
_attributes = GDataEntry._attributes.copy()
def __init__(self, author=None, category=None, content=None,
contributor=None, atom_id=None, link=None, published=None, rights=None,
source=None, summary=None, control=None, title=None, updated=None,
batch_operation=None, batch_id=None, batch_status=None,
extension_elements=None, extension_attributes=None, text=None):
self.batch_operation = batch_operation
self.batch_id = batch_id
self.batch_status = batch_status
GDataEntry.__init__(self, author=author, category=category,
content=content, contributor=contributor, atom_id=atom_id, link=link,
published=published, rights=rights, source=source, summary=summary,
control=control, title=title, updated=updated,
extension_elements=extension_elements,
extension_attributes=extension_attributes, text=text)
def BatchEntryFromString(xml_string):
return atom.CreateClassFromXMLString(BatchEntry, xml_string)
class BatchInterrupted(atom.AtomBase):
"""The batch:interrupted element sent if batch request was interrupted.
Only appears in a feed if some of the batch entries could not be processed.
See: http://code.google.com/apis/gdata/batch.html#Handling_Errors
"""
_tag = 'interrupted'
_namespace = BATCH_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['reason'] = 'reason'
_attributes['success'] = 'success'
_attributes['failures'] = 'failures'
_attributes['parsed'] = 'parsed'
def __init__(self, reason=None, success=None, failures=None, parsed=None,
extension_elements=None, extension_attributes=None, text=None):
self.reason = reason
self.success = success
self.failures = failures
self.parsed = parsed
atom.AtomBase.__init__(self, extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def BatchInterruptedFromString(xml_string):
return atom.CreateClassFromXMLString(BatchInterrupted, xml_string)
class BatchFeed(GDataFeed):
"""A feed containing a list of batch request entries."""
_tag = GDataFeed._tag
_namespace = GDataFeed._namespace
_children = GDataFeed._children.copy()
_attributes = GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [BatchEntry])
_children['{%s}interrupted' % BATCH_NAMESPACE] = ('interrupted', BatchInterrupted)
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None, entry=None,
total_results=None, start_index=None, items_per_page=None,
interrupted=None,
extension_elements=None, extension_attributes=None, text=None):
self.interrupted = interrupted
GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results, start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def AddBatchEntry(self, entry=None, id_url_string=None,
batch_id_string=None, operation_string=None):
"""Logic for populating members of a BatchEntry and adding to the feed.
If the entry is not a BatchEntry, it is converted to a BatchEntry so
that the batch specific members will be present.
The id_url_string can be used in place of an entry if the batch operation
applies to a URL. For example query and delete operations require just
the URL of an entry, no body is sent in the HTTP request. If an
id_url_string is sent instead of an entry, a BatchEntry is created and
added to the feed.
This method also assigns the desired batch id to the entry so that it
can be referenced in the server's response. If the batch_id_string is
None, this method will assign a batch_id to be the index at which this
entry will be in the feed's entry list.
Args:
entry: BatchEntry, atom.Entry, or another Entry flavor (optional) The
entry which will be sent to the server as part of the batch request.
The item must have a valid atom id so that the server knows which
entry this request references.
id_url_string: str (optional) The URL of the entry to be acted on. You
can find this URL in the text member of the atom id for an entry.
If an entry is not sent, this id will be used to construct a new
BatchEntry which will be added to the request feed.
batch_id_string: str (optional) The batch ID to be used to reference
this batch operation in the results feed. If this parameter is None,
the current length of the feed's entry array will be used as a
count. Note that batch_ids should either always be specified or
never, mixing could potentially result in duplicate batch ids.
operation_string: str (optional) The desired batch operation which will
set the batch_operation.type member of the entry. Options are
'insert', 'update', 'delete', and 'query'
Raises:
MissingRequiredParameters: Raised if neither an id_ url_string nor an
entry are provided in the request.
Returns:
The added entry.
"""
if entry is None and id_url_string is None:
raise MissingRequiredParameters('supply either an entry or URL string')
if entry is None and id_url_string is not None:
entry = BatchEntry(atom_id=atom.Id(text=id_url_string))
# TODO: handle cases in which the entry lacks batch_... members.
#if not isinstance(entry, BatchEntry):
# Convert the entry to a batch entry.
if batch_id_string is not None:
entry.batch_id = BatchId(text=batch_id_string)
elif entry.batch_id is None or entry.batch_id.text is None:
entry.batch_id = BatchId(text=str(len(self.entry)))
if operation_string is not None:
entry.batch_operation = BatchOperation(op_type=operation_string)
self.entry.append(entry)
return entry
def AddInsert(self, entry, batch_id_string=None):
"""Add an insert request to the operations in this batch request feed.
If the entry doesn't yet have an operation or a batch id, these will
be set to the insert operation and a batch_id specified as a parameter.
Args:
entry: BatchEntry The entry which will be sent in the batch feed as an
insert request.
batch_id_string: str (optional) The batch ID to be used to reference
this batch operation in the results feed. If this parameter is None,
the current length of the feed's entry array will be used as a
count. Note that batch_ids should either always be specified or
never, mixing could potentially result in duplicate batch ids.
"""
entry = self.AddBatchEntry(entry=entry, batch_id_string=batch_id_string,
operation_string=BATCH_INSERT)
def AddUpdate(self, entry, batch_id_string=None):
"""Add an update request to the list of batch operations in this feed.
Sets the operation type of the entry to insert if it is not already set
and assigns the desired batch id to the entry so that it can be
referenced in the server's response.
Args:
entry: BatchEntry The entry which will be sent to the server as an
update (HTTP PUT) request. The item must have a valid atom id
so that the server knows which entry to replace.
batch_id_string: str (optional) The batch ID to be used to reference
this batch operation in the results feed. If this parameter is None,
the current length of the feed's entry array will be used as a
count. See also comments for AddInsert.
"""
entry = self.AddBatchEntry(entry=entry, batch_id_string=batch_id_string,
operation_string=BATCH_UPDATE)
def AddDelete(self, url_string=None, entry=None, batch_id_string=None):
"""Adds a delete request to the batch request feed.
This method takes either the url_string which is the atom id of the item
to be deleted, or the entry itself. The atom id of the entry must be
present so that the server knows which entry should be deleted.
Args:
url_string: str (optional) The URL of the entry to be deleted. You can
find this URL in the text member of the atom id for an entry.
entry: BatchEntry (optional) The entry to be deleted.
batch_id_string: str (optional)
Raises:
MissingRequiredParameters: Raised if neither a url_string nor an entry
are provided in the request.
"""
entry = self.AddBatchEntry(entry=entry, id_url_string=url_string,
batch_id_string=batch_id_string,
operation_string=BATCH_DELETE)
def AddQuery(self, url_string=None, entry=None, batch_id_string=None):
"""Adds a query request to the batch request feed.
This method takes either the url_string which is the query URL
whose results will be added to the result feed. The query URL will
be encapsulated in a BatchEntry, and you may pass in the BatchEntry
with a query URL instead of sending a url_string.
Args:
url_string: str (optional)
entry: BatchEntry (optional)
batch_id_string: str (optional)
Raises:
MissingRequiredParameters
"""
entry = self.AddBatchEntry(entry=entry, id_url_string=url_string,
batch_id_string=batch_id_string,
operation_string=BATCH_QUERY)
def GetBatchLink(self):
for link in self.link:
if link.rel == 'http://schemas.google.com/g/2005#batch':
return link
return None
def BatchFeedFromString(xml_string):
return atom.CreateClassFromXMLString(BatchFeed, xml_string)
class EntryLink(atom.AtomBase):
"""The gd:entryLink element"""
_tag = 'entryLink'
_namespace = GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
# The entry used to be an atom.Entry, now it is a GDataEntry.
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', GDataEntry)
_attributes['rel'] = 'rel'
_attributes['readOnly'] = 'read_only'
_attributes['href'] = 'href'
def __init__(self, href=None, read_only=None, rel=None,
entry=None, extension_elements=None,
extension_attributes=None, text=None):
self.href = href
self.read_only = read_only
self.rel = rel
self.entry = entry
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def EntryLinkFromString(xml_string):
return atom.CreateClassFromXMLString(EntryLink, xml_string)
class FeedLink(atom.AtomBase):
"""The gd:feedLink element"""
_tag = 'feedLink'
_namespace = GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_children['{%s}feed' % atom.ATOM_NAMESPACE] = ('feed', GDataFeed)
_attributes['rel'] = 'rel'
_attributes['readOnly'] = 'read_only'
_attributes['countHint'] = 'count_hint'
_attributes['href'] = 'href'
def __init__(self, count_hint=None, href=None, read_only=None, rel=None,
feed=None, extension_elements=None, extension_attributes=None,
text=None):
self.count_hint = count_hint
self.href = href
self.read_only = read_only
self.rel = rel
self.feed = feed
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def FeedLinkFromString(xml_string):
return atom.CreateClassFromXMLString(FeedLink, xml_string)

View File

@@ -0,0 +1,20 @@
#!/usr/bin/python
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This package's modules adapt the gdata library to run in other environments
The first example is the appengine module which contains functions and
classes which modify a GDataService object to run on Google App Engine.
"""

View File

@@ -0,0 +1,101 @@
#!/usr/bin/python
#
# Copyright (C) 2009 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides functions to persist serialized auth tokens in the datastore.
The get_token and set_token functions should be used in conjunction with
gdata.gauth's token_from_blob and token_to_blob to allow auth token objects
to be reused across requests. It is up to your own code to ensure that the
token key's are unique.
"""
__author__ = 'j.s@google.com (Jeff Scudder)'
from google.appengine.ext import db
from google.appengine.api import memcache
class Token(db.Model):
"""Datastore Model which stores a serialized auth token."""
t = db.BlobProperty()
def get_token(unique_key):
"""Searches for a stored token with the desired key.
Checks memcache and then the datastore if required.
Args:
unique_key: str which uniquely identifies the desired auth token.
Returns:
A string encoding the auth token data. Use gdata.gauth.token_from_blob to
convert back into a usable token object. None if the token was not found
in memcache or the datastore.
"""
token_string = memcache.get(unique_key)
if token_string is None:
# The token wasn't in memcache, so look in the datastore.
token = Token.get_by_key_name(unique_key)
if token is None:
return None
return token.t
return token_string
def set_token(unique_key, token_str):
"""Saves the serialized auth token in the datastore.
The token is also stored in memcache to speed up retrieval on a cache hit.
Args:
unique_key: The unique name for this token as a string. It is up to your
code to ensure that this token value is unique in your application.
Previous values will be silently overwitten.
token_str: A serialized auth token as a string. I expect that this string
will be generated by gdata.gauth.token_to_blob.
Returns:
True if the token was stored sucessfully, False if the token could not be
safely cached (if an old value could not be cleared). If the token was
set in memcache, but not in the datastore, this function will return None.
However, in that situation an exception will likely be raised.
Raises:
Datastore exceptions may be raised from the App Engine SDK in the event of
failure.
"""
# First try to save in memcache.
result = memcache.set(unique_key, token_str)
# If memcache fails to save the value, clear the cached value.
if not result:
result = memcache.delete(unique_key)
# If we could not clear the cached value for this token, refuse to save.
if result == 0:
return False
# Save to the datastore.
if Token(key_name=unique_key, t=token_str).put():
return True
return None
def delete_token(unique_key):
# Clear from memcache.
memcache.delete(unique_key)
# Clear from the datastore.
Token(key_name=unique_key).delete()

View File

@@ -0,0 +1,321 @@
#!/usr/bin/python
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides HTTP functions for gdata.service to use on Google App Engine
AppEngineHttpClient: Provides an HTTP request method which uses App Engine's
urlfetch API. Set the http_client member of a GDataService object to an
instance of an AppEngineHttpClient to allow the gdata library to run on
Google App Engine.
run_on_appengine: Function which will modify an existing GDataService object
to allow it to run on App Engine. It works by creating a new instance of
the AppEngineHttpClient and replacing the GDataService object's
http_client.
"""
__author__ = 'api.jscudder (Jeff Scudder)'
import StringIO
import pickle
import atom.http_interface
import atom.token_store
from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.api import memcache
def run_on_appengine(gdata_service, store_tokens=True,
single_user_mode=False, deadline=None):
"""Modifies a GDataService object to allow it to run on App Engine.
Args:
gdata_service: An instance of AtomService, GDataService, or any
of their subclasses which has an http_client member and a
token_store member.
store_tokens: Boolean, defaults to True. If True, the gdata_service
will attempt to add each token to it's token_store when
SetClientLoginToken or SetAuthSubToken is called. If False
the tokens will not automatically be added to the
token_store.
single_user_mode: Boolean, defaults to False. If True, the current_token
member of gdata_service will be set when
SetClientLoginToken or SetAuthTubToken is called. If set
to True, the current_token is set in the gdata_service
and anyone who accesses the object will use the same
token.
Note: If store_tokens is set to False and
single_user_mode is set to False, all tokens will be
ignored, since the library assumes: the tokens should not
be stored in the datastore and they should not be stored
in the gdata_service object. This will make it
impossible to make requests which require authorization.
deadline: int (optional) The number of seconds to wait for a response
before timing out on the HTTP request. If no deadline is
specified, the deafault deadline for HTTP requests from App
Engine is used. The maximum is currently 10 (for 10 seconds).
The default deadline for App Engine is 5 seconds.
"""
gdata_service.http_client = AppEngineHttpClient(deadline=deadline)
gdata_service.token_store = AppEngineTokenStore()
gdata_service.auto_store_tokens = store_tokens
gdata_service.auto_set_current_token = single_user_mode
return gdata_service
class AppEngineHttpClient(atom.http_interface.GenericHttpClient):
def __init__(self, headers=None, deadline=None):
self.debug = False
self.headers = headers or {}
self.deadline = deadline
def request(self, operation, url, data=None, headers=None):
"""Performs an HTTP call to the server, supports GET, POST, PUT, and
DELETE.
Usage example, perform and HTTP GET on http://www.google.com/:
import atom.http
client = atom.http.HttpClient()
http_response = client.request('GET', 'http://www.google.com/')
Args:
operation: str The HTTP operation to be performed. This is usually one
of 'GET', 'POST', 'PUT', or 'DELETE'
data: filestream, list of parts, or other object which can be converted
to a string. Should be set to None when performing a GET or DELETE.
If data is a file-like object which can be read, this method will
read a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be
evaluated and sent.
url: The full URL to which the request should be sent. Can be a string
or atom.url.Url.
headers: dict of strings. HTTP headers which should be sent
in the request.
"""
all_headers = self.headers.copy()
if headers:
all_headers.update(headers)
# Construct the full payload.
# Assume that data is None or a string.
data_str = data
if data:
if isinstance(data, list):
# If data is a list of different objects, convert them all to strings
# and join them together.
converted_parts = [_convert_data_part(x) for x in data]
data_str = ''.join(converted_parts)
else:
data_str = _convert_data_part(data)
# If the list of headers does not include a Content-Length, attempt to
# calculate it based on the data object.
if data and 'Content-Length' not in all_headers:
all_headers['Content-Length'] = str(len(data_str))
# Set the content type to the default value if none was set.
if 'Content-Type' not in all_headers:
all_headers['Content-Type'] = 'application/atom+xml'
# Lookup the urlfetch operation which corresponds to the desired HTTP verb.
if operation == 'GET':
method = urlfetch.GET
elif operation == 'POST':
method = urlfetch.POST
elif operation == 'PUT':
method = urlfetch.PUT
elif operation == 'DELETE':
method = urlfetch.DELETE
else:
method = None
if self.deadline is None:
return HttpResponse(urlfetch.Fetch(url=str(url), payload=data_str,
method=method, headers=all_headers, follow_redirects=False))
return HttpResponse(urlfetch.Fetch(url=str(url), payload=data_str,
method=method, headers=all_headers, follow_redirects=False,
deadline=self.deadline))
def _convert_data_part(data):
if not data or isinstance(data, str):
return data
elif hasattr(data, 'read'):
# data is a file like object, so read it completely.
return data.read()
# The data object was not a file.
# Try to convert to a string and send the data.
return str(data)
class HttpResponse(object):
"""Translates a urlfetch resoinse to look like an hhtplib resoinse.
Used to allow the resoinse from HttpRequest to be usable by gdata.service
methods.
"""
def __init__(self, urlfetch_response):
self.body = StringIO.StringIO(urlfetch_response.content)
self.headers = urlfetch_response.headers
self.status = urlfetch_response.status_code
self.reason = ''
def read(self, length=None):
if not length:
return self.body.read()
else:
return self.body.read(length)
def getheader(self, name):
if not self.headers.has_key(name):
return self.headers[name.lower()]
return self.headers[name]
class TokenCollection(db.Model):
"""Datastore Model which associates auth tokens with the current user."""
user = db.UserProperty()
pickled_tokens = db.BlobProperty()
class AppEngineTokenStore(atom.token_store.TokenStore):
"""Stores the user's auth tokens in the App Engine datastore.
Tokens are only written to the datastore if a user is signed in (if
users.get_current_user() returns a user object).
"""
def __init__(self):
self.user = None
def add_token(self, token):
"""Associates the token with the current user and stores it.
If there is no current user, the token will not be stored.
Returns:
False if the token was not stored.
"""
tokens = load_auth_tokens(self.user)
if not hasattr(token, 'scopes') or not token.scopes:
return False
for scope in token.scopes:
tokens[str(scope)] = token
key = save_auth_tokens(tokens, self.user)
if key:
return True
return False
def find_token(self, url):
"""Searches the current user's collection of token for a token which can
be used for a request to the url.
Returns:
The stored token which belongs to the current user and is valid for the
desired URL. If there is no current user, or there is no valid user
token in the datastore, a atom.http_interface.GenericToken is returned.
"""
if url is None:
return None
if isinstance(url, (str, unicode)):
url = atom.url.parse_url(url)
tokens = load_auth_tokens(self.user)
if url in tokens:
token = tokens[url]
if token.valid_for_scope(url):
return token
else:
del tokens[url]
save_auth_tokens(tokens, self.user)
for scope, token in tokens.iteritems():
if token.valid_for_scope(url):
return token
return atom.http_interface.GenericToken()
def remove_token(self, token):
"""Removes the token from the current user's collection in the datastore.
Returns:
False if the token was not removed, this could be because the token was
not in the datastore, or because there is no current user.
"""
token_found = False
scopes_to_delete = []
tokens = load_auth_tokens(self.user)
for scope, stored_token in tokens.iteritems():
if stored_token == token:
scopes_to_delete.append(scope)
token_found = True
for scope in scopes_to_delete:
del tokens[scope]
if token_found:
save_auth_tokens(tokens, self.user)
return token_found
def remove_all_tokens(self):
"""Removes all of the current user's tokens from the datastore."""
save_auth_tokens({}, self.user)
def save_auth_tokens(token_dict, user=None):
"""Associates the tokens with the current user and writes to the datastore.
If there us no current user, the tokens are not written and this function
returns None.
Returns:
The key of the datastore entity containing the user's tokens, or None if
there was no current user.
"""
if user is None:
user = users.get_current_user()
if user is None:
return None
memcache.set('gdata_pickled_tokens:%s' % user, pickle.dumps(token_dict))
user_tokens = TokenCollection.all().filter('user =', user).get()
if user_tokens:
user_tokens.pickled_tokens = pickle.dumps(token_dict)
return user_tokens.put()
else:
user_tokens = TokenCollection(
user=user,
pickled_tokens=pickle.dumps(token_dict))
return user_tokens.put()
def load_auth_tokens(user=None):
"""Reads a dictionary of the current user's tokens from the datastore.
If there is no current user (a user is not signed in to the app) or the user
does not have any tokens, an empty dictionary is returned.
"""
if user is None:
user = users.get_current_user()
if user is None:
return {}
pickled_tokens = memcache.get('gdata_pickled_tokens:%s' % user)
if pickled_tokens:
return pickle.loads(pickled_tokens)
user_tokens = TokenCollection.all().filter('user =', user).get()
if user_tokens:
memcache.set('gdata_pickled_tokens:%s' % user, user_tokens.pickled_tokens)
return pickle.loads(user_tokens.pickled_tokens)
return {}

View File

@@ -0,0 +1,526 @@
#!/usr/bin/python
#
# Copyright (C) 2007 SIOS Technology, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Contains objects used with Google Apps."""
__author__ = 'tmatsuo@sios.com (Takashi MATSUO)'
import atom
import gdata
# XML namespaces which are often used in Google Apps entity.
APPS_NAMESPACE = 'http://schemas.google.com/apps/2006'
APPS_TEMPLATE = '{http://schemas.google.com/apps/2006}%s'
class EmailList(atom.AtomBase):
"""The Google Apps EmailList element"""
_tag = 'emailList'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['name'] = 'name'
def __init__(self, name=None, extension_elements=None,
extension_attributes=None, text=None):
self.name = name
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def EmailListFromString(xml_string):
return atom.CreateClassFromXMLString(EmailList, xml_string)
class Who(atom.AtomBase):
"""The Google Apps Who element"""
_tag = 'who'
_namespace = gdata.GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['rel'] = 'rel'
_attributes['email'] = 'email'
def __init__(self, rel=None, email=None, extension_elements=None,
extension_attributes=None, text=None):
self.rel = rel
self.email = email
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def WhoFromString(xml_string):
return atom.CreateClassFromXMLString(Who, xml_string)
class Login(atom.AtomBase):
"""The Google Apps Login element"""
_tag = 'login'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['userName'] = 'user_name'
_attributes['password'] = 'password'
_attributes['suspended'] = 'suspended'
_attributes['admin'] = 'admin'
_attributes['changePasswordAtNextLogin'] = 'change_password'
_attributes['agreedToTerms'] = 'agreed_to_terms'
_attributes['ipWhitelisted'] = 'ip_whitelisted'
_attributes['hashFunctionName'] = 'hash_function_name'
def __init__(self, user_name=None, password=None, suspended=None,
ip_whitelisted=None, hash_function_name=None,
admin=None, change_password=None, agreed_to_terms=None,
extension_elements=None, extension_attributes=None,
text=None):
self.user_name = user_name
self.password = password
self.suspended = suspended
self.admin = admin
self.change_password = change_password
self.agreed_to_terms = agreed_to_terms
self.ip_whitelisted = ip_whitelisted
self.hash_function_name = hash_function_name
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def LoginFromString(xml_string):
return atom.CreateClassFromXMLString(Login, xml_string)
class Quota(atom.AtomBase):
"""The Google Apps Quota element"""
_tag = 'quota'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['limit'] = 'limit'
def __init__(self, limit=None, extension_elements=None,
extension_attributes=None, text=None):
self.limit = limit
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def QuotaFromString(xml_string):
return atom.CreateClassFromXMLString(Quota, xml_string)
class Name(atom.AtomBase):
"""The Google Apps Name element"""
_tag = 'name'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['familyName'] = 'family_name'
_attributes['givenName'] = 'given_name'
def __init__(self, family_name=None, given_name=None,
extension_elements=None, extension_attributes=None, text=None):
self.family_name = family_name
self.given_name = given_name
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def NameFromString(xml_string):
return atom.CreateClassFromXMLString(Name, xml_string)
class Nickname(atom.AtomBase):
"""The Google Apps Nickname element"""
_tag = 'nickname'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['name'] = 'name'
def __init__(self, name=None,
extension_elements=None, extension_attributes=None, text=None):
self.name = name
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def NicknameFromString(xml_string):
return atom.CreateClassFromXMLString(Nickname, xml_string)
class NicknameEntry(gdata.GDataEntry):
"""A Google Apps flavor of an Atom Entry for Nickname"""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataEntry._children.copy()
_attributes = gdata.GDataEntry._attributes.copy()
_children['{%s}login' % APPS_NAMESPACE] = ('login', Login)
_children['{%s}nickname' % APPS_NAMESPACE] = ('nickname', Nickname)
def __init__(self, author=None, category=None, content=None,
atom_id=None, link=None, published=None,
title=None, updated=None,
login=None, nickname=None,
extended_property=None,
extension_elements=None, extension_attributes=None, text=None):
gdata.GDataEntry.__init__(self, author=author, category=category,
content=content,
atom_id=atom_id, link=link, published=published,
title=title, updated=updated)
self.login = login
self.nickname = nickname
self.extended_property = extended_property or []
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def NicknameEntryFromString(xml_string):
return atom.CreateClassFromXMLString(NicknameEntry, xml_string)
class NicknameFeed(gdata.GDataFeed, gdata.LinkFinder):
"""A Google Apps Nickname feed flavor of an Atom Feed"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataFeed._children.copy()
_attributes = gdata.GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [NicknameEntry])
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None,
entry=None, total_results=None, start_index=None,
items_per_page=None, extension_elements=None,
extension_attributes=None, text=None):
gdata.GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results,
start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def NicknameFeedFromString(xml_string):
return atom.CreateClassFromXMLString(NicknameFeed, xml_string)
class UserEntry(gdata.GDataEntry):
"""A Google Apps flavor of an Atom Entry"""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataEntry._children.copy()
_attributes = gdata.GDataEntry._attributes.copy()
_children['{%s}login' % APPS_NAMESPACE] = ('login', Login)
_children['{%s}name' % APPS_NAMESPACE] = ('name', Name)
_children['{%s}quota' % APPS_NAMESPACE] = ('quota', Quota)
# This child may already be defined in GDataEntry, confirm before removing.
_children['{%s}feedLink' % gdata.GDATA_NAMESPACE] = ('feed_link',
[gdata.FeedLink])
_children['{%s}who' % gdata.GDATA_NAMESPACE] = ('who', Who)
def __init__(self, author=None, category=None, content=None,
atom_id=None, link=None, published=None,
title=None, updated=None,
login=None, name=None, quota=None, who=None, feed_link=None,
extended_property=None,
extension_elements=None, extension_attributes=None, text=None):
gdata.GDataEntry.__init__(self, author=author, category=category,
content=content,
atom_id=atom_id, link=link, published=published,
title=title, updated=updated)
self.login = login
self.name = name
self.quota = quota
self.who = who
self.feed_link = feed_link or []
self.extended_property = extended_property or []
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def UserEntryFromString(xml_string):
return atom.CreateClassFromXMLString(UserEntry, xml_string)
class UserFeed(gdata.GDataFeed, gdata.LinkFinder):
"""A Google Apps User feed flavor of an Atom Feed"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataFeed._children.copy()
_attributes = gdata.GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [UserEntry])
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None,
entry=None, total_results=None, start_index=None,
items_per_page=None, extension_elements=None,
extension_attributes=None, text=None):
gdata.GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results,
start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def UserFeedFromString(xml_string):
return atom.CreateClassFromXMLString(UserFeed, xml_string)
class EmailListEntry(gdata.GDataEntry):
"""A Google Apps EmailList flavor of an Atom Entry"""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataEntry._children.copy()
_attributes = gdata.GDataEntry._attributes.copy()
_children['{%s}emailList' % APPS_NAMESPACE] = ('email_list', EmailList)
# Might be able to remove this _children entry.
_children['{%s}feedLink' % gdata.GDATA_NAMESPACE] = ('feed_link',
[gdata.FeedLink])
def __init__(self, author=None, category=None, content=None,
atom_id=None, link=None, published=None,
title=None, updated=None,
email_list=None, feed_link=None,
extended_property=None,
extension_elements=None, extension_attributes=None, text=None):
gdata.GDataEntry.__init__(self, author=author, category=category,
content=content,
atom_id=atom_id, link=link, published=published,
title=title, updated=updated)
self.email_list = email_list
self.feed_link = feed_link or []
self.extended_property = extended_property or []
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def EmailListEntryFromString(xml_string):
return atom.CreateClassFromXMLString(EmailListEntry, xml_string)
class EmailListFeed(gdata.GDataFeed, gdata.LinkFinder):
"""A Google Apps EmailList feed flavor of an Atom Feed"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataFeed._children.copy()
_attributes = gdata.GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [EmailListEntry])
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None,
entry=None, total_results=None, start_index=None,
items_per_page=None, extension_elements=None,
extension_attributes=None, text=None):
gdata.GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results,
start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def EmailListFeedFromString(xml_string):
return atom.CreateClassFromXMLString(EmailListFeed, xml_string)
class EmailListRecipientEntry(gdata.GDataEntry):
"""A Google Apps EmailListRecipient flavor of an Atom Entry"""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataEntry._children.copy()
_attributes = gdata.GDataEntry._attributes.copy()
_children['{%s}who' % gdata.GDATA_NAMESPACE] = ('who', Who)
def __init__(self, author=None, category=None, content=None,
atom_id=None, link=None, published=None,
title=None, updated=None,
who=None,
extended_property=None,
extension_elements=None, extension_attributes=None, text=None):
gdata.GDataEntry.__init__(self, author=author, category=category,
content=content,
atom_id=atom_id, link=link, published=published,
title=title, updated=updated)
self.who = who
self.extended_property = extended_property or []
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def EmailListRecipientEntryFromString(xml_string):
return atom.CreateClassFromXMLString(EmailListRecipientEntry, xml_string)
class EmailListRecipientFeed(gdata.GDataFeed, gdata.LinkFinder):
"""A Google Apps EmailListRecipient feed flavor of an Atom Feed"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataFeed._children.copy()
_attributes = gdata.GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry',
[EmailListRecipientEntry])
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None,
entry=None, total_results=None, start_index=None,
items_per_page=None, extension_elements=None,
extension_attributes=None, text=None):
gdata.GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results,
start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def EmailListRecipientFeedFromString(xml_string):
return atom.CreateClassFromXMLString(EmailListRecipientFeed, xml_string)
class Property(atom.AtomBase):
"""The Google Apps Property element"""
_tag = 'property'
_namespace = APPS_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
_attributes['name'] = 'name'
_attributes['value'] = 'value'
def __init__(self, name=None, value=None, extension_elements=None,
extension_attributes=None, text=None):
self.name = name
self.value = value
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def PropertyFromString(xml_string):
return atom.CreateClassFromXMLString(Property, xml_string)
class PropertyEntry(gdata.GDataEntry):
"""A Google Apps Property flavor of an Atom Entry"""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataEntry._children.copy()
_attributes = gdata.GDataEntry._attributes.copy()
_children['{%s}property' % APPS_NAMESPACE] = ('property', [Property])
def __init__(self, author=None, category=None, content=None,
atom_id=None, link=None, published=None,
title=None, updated=None,
property=None,
extended_property=None,
extension_elements=None, extension_attributes=None, text=None):
gdata.GDataEntry.__init__(self, author=author, category=category,
content=content,
atom_id=atom_id, link=link, published=published,
title=title, updated=updated)
self.property = property
self.extended_property = extended_property or []
self.text = text
self.extension_elements = extension_elements or []
self.extension_attributes = extension_attributes or {}
def PropertyEntryFromString(xml_string):
return atom.CreateClassFromXMLString(PropertyEntry, xml_string)
class PropertyFeed(gdata.GDataFeed, gdata.LinkFinder):
"""A Google Apps Property feed flavor of an Atom Feed"""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.GDataFeed._children.copy()
_attributes = gdata.GDataFeed._attributes.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PropertyEntry])
def __init__(self, author=None, category=None, contributor=None,
generator=None, icon=None, atom_id=None, link=None, logo=None,
rights=None, subtitle=None, title=None, updated=None,
entry=None, total_results=None, start_index=None,
items_per_page=None, extension_elements=None,
extension_attributes=None, text=None):
gdata.GDataFeed.__init__(self, author=author, category=category,
contributor=contributor, generator=generator,
icon=icon, atom_id=atom_id, link=link,
logo=logo, rights=rights, subtitle=subtitle,
title=title, updated=updated, entry=entry,
total_results=total_results,
start_index=start_index,
items_per_page=items_per_page,
extension_elements=extension_elements,
extension_attributes=extension_attributes,
text=text)
def PropertyFeedFromString(xml_string):
return atom.CreateClassFromXMLString(PropertyFeed, xml_string)

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,278 @@
#!/usr/bin/env python
# Copyright (C) 2008 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Allow Google Apps domain administrators to audit user data.
AuditService: Set auditing."""
__author__ = 'jlee@pbu.edu'
from base64 import b64encode
import gdata.apps
import gdata.apps.service
import gdata.service
class AuditService(gdata.apps.service.PropertyService):
"""Client for the Google Apps Audit service."""
def _serviceUrl(self, setting_id, domain=None, user=None):
if domain is None:
domain = self.domain
if user is None:
return '/a/feeds/compliance/audit/%s/%s' % (setting_id, domain)
else:
return '/a/feeds/compliance/audit/%s/%s/%s' % (setting_id, domain, user)
def updatePGPKey(self, pgpkey):
"""Updates Public PGP Key Google uses to encrypt audit data
Args:
pgpkey: string, ASCII text of PGP Public Key to be used
Returns:
A dict containing the result of the POST operation."""
uri = self._serviceUrl('publickey')
b64pgpkey = b64encode(pgpkey)
properties = {}
properties['publicKey'] = b64pgpkey
return self._PostProperties(uri, properties)
def createEmailMonitor(self, source_user, destination_user, end_date,
begin_date=None, incoming_headers_only=False,
outgoing_headers_only=False, drafts=False,
drafts_headers_only=False, chats=False,
chats_headers_only=False):
"""Creates a email monitor, forwarding the source_users emails/chats
Args:
source_user: string, the user whose email will be audited
destination_user: string, the user to receive the audited email
end_date: string, the date the audit will end in
"yyyy-MM-dd HH:mm" format, required
begin_date: string, the date the audit will start in
"yyyy-MM-dd HH:mm" format, leave blank to use current time
incoming_headers_only: boolean, whether to audit only the headers of
mail delivered to source user
outgoing_headers_only: boolean, whether to audit only the headers of
mail sent from the source user
drafts: boolean, whether to audit draft messages of the source user
drafts_headers_only: boolean, whether to audit only the headers of
mail drafts saved by the user
chats: boolean, whether to audit archived chats of the source user
chats_headers_only: boolean, whether to audit only the headers of
archived chats of the source user
Returns:
A dict containing the result of the POST operation."""
uri = self._serviceUrl('mail/monitor', user=source_user)
properties = {}
properties['destUserName'] = destination_user
if begin_date is not None:
properties['beginDate'] = begin_date
properties['endDate'] = end_date
if incoming_headers_only:
properties['incomingEmailMonitorLevel'] = 'HEADER_ONLY'
else:
properties['incomingEmailMonitorLevel'] = 'FULL_MESSAGE'
if outgoing_headers_only:
properties['outgoingEmailMonitorLevel'] = 'HEADER_ONLY'
else:
properties['outgoingEmailMonitorLevel'] = 'FULL_MESSAGE'
if drafts:
if drafts_headers_only:
properties['draftMonitorLevel'] = 'HEADER_ONLY'
else:
properties['draftMonitorLevel'] = 'FULL_MESSAGE'
if chats:
if chats_headers_only:
properties['chatMonitorLevel'] = 'HEADER_ONLY'
else:
properties['chatMonitorLevel'] = 'FULL_MESSAGE'
return self._PostProperties(uri, properties)
def getEmailMonitors(self, user):
""""Gets the email monitors for the given user
Args:
user: string, the user to retrieve email monitors for
Returns:
list results of the POST operation
"""
uri = self._serviceUrl('mail/monitor', user=user)
return self._GetPropertiesList(uri)
def deleteEmailMonitor(self, source_user, destination_user):
"""Deletes the email monitor for the given user
Args:
source_user: string, the user who is being monitored
destination_user: string, theuser who recieves the monitored emails
Returns:
Nothing
"""
uri = self._serviceUrl('mail/monitor', user=source_user+'/'+destination_user)
try:
return self._DeleteProperties(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def createAccountInformationRequest(self, user):
"""Creates a request for account auditing details
Args:
user: string, the user to request account information for
Returns:
A dict containing the result of the post operation."""
uri = self._serviceUrl('account', user=user)
properties = {}
#XML Body is left empty
try:
return self._PostProperties(uri, properties)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def getAccountInformationRequestStatus(self, user, request_id):
"""Gets the status of an account auditing request
Args:
user: string, the user whose account auditing details were requested
request_id: string, the request_id
Returns:
A dict containing the result of the get operation."""
uri = self._serviceUrl('account', user=user+'/'+request_id)
try:
return self._GetProperties(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def getAllAccountInformationRequestsStatus(self):
"""Gets the status of all account auditing requests for the domain
Args:
None
Returns:
list results of the POST operation
"""
uri = self._serviceUrl('account')
return self._GetPropertiesList(uri)
def deleteAccountInformationRequest(self, user, request_id):
"""Deletes the request for account auditing information
Args:
user: string, the user whose account auditing details were requested
request_id: string, the request_id
Returns:
Nothing
"""
uri = self._serviceUrl('account', user=user+'/'+request_id)
try:
return self._DeleteProperties(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def createMailboxExportRequest(self, user, begin_date=None, end_date=None, include_deleted=False, search_query=None, headers_only=False):
"""Creates a mailbox export request
Args:
user: string, the user whose mailbox export is being requested
begin_date: string, date of earliest emails to export, optional, defaults to date of account creation
format is 'yyyy-MM-dd HH:mm'
end_date: string, date of latest emails to export, optional, defaults to current date
format is 'yyyy-MM-dd HH:mm'
include_deleted: boolean, whether to include deleted emails in export, mutually exclusive with search_query
search_query: string, gmail style search query, matched emails will be exported, mutually exclusive with include_deleted
Returns:
A dict containing the result of the post operation."""
uri = self._serviceUrl('mail/export', user=user)
properties = {}
if begin_date is not None:
properties['beginDate'] = begin_date
if end_date is not None:
properties['endDate'] = end_date
if include_deleted is not None:
properties['includeDeleted'] = gdata.apps.service._bool2str(include_deleted)
if search_query is not None:
properties['searchQuery'] = search_query
if headers_only is True:
properties['packageContent'] = 'HEADER_ONLY'
else:
properties['packageContent'] = 'FULL_MESSAGE'
return self._PostProperties(uri, properties)
def getMailboxExportRequestStatus(self, user, request_id):
"""Gets the status of an mailbox export request
Args:
user: string, the user whose mailbox were requested
request_id: string, the request_id
Returns:
A dict containing the result of the get operation."""
uri = self._serviceUrl('mail/export', user=user+'/'+request_id)
try:
return self._GetProperties(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def getAllMailboxExportRequestsStatus(self):
"""Gets the status of all mailbox export requests for the domain
Args:
None
Returns:
list results of the POST operation
"""
uri = self._serviceUrl('mail/export')
return self._GetPropertiesList(uri)
def deleteMailboxExportRequest(self, user, request_id):
"""Deletes the request for mailbox export
Args:
user: string, the user whose mailbox were requested
request_id: string, the request_id
Returns:
Nothing
"""
uri = self._serviceUrl('mail/export', user=user+'/'+request_id)
try:
return self._DeleteProperties(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])

View File

@@ -0,0 +1,874 @@
#!/usr/bin/env python
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Data model classes for parsing and generating XML for the Contacts API."""
import atom
import gdata
## Constants from http://code.google.com/apis/gdata/elements.html ##
REL_HOME = 'http://schemas.google.com/g/2005#home'
REL_WORK = 'http://schemas.google.com/g/2005#work'
REL_OTHER = 'http://schemas.google.com/g/2005#other'
IM_AIM = 'http://schemas.google.com/g/2005#AIM' # AOL Instant Messenger protocol
IM_MSN = 'http://schemas.google.com/g/2005#MSN' # MSN Messenger protocol
IM_YAHOO = 'http://schemas.google.com/g/2005#YAHOO' # Yahoo Messenger protocol
IM_SKYPE = 'http://schemas.google.com/g/2005#SKYPE' # Skype protocol
IM_QQ = 'http://schemas.google.com/g/2005#QQ' # QQ protocol
IM_GOOGLE_TALK = 'http://schemas.google.com/g/2005#GOOGLE_TALK' # Google Talk protocol
IM_ICQ = 'http://schemas.google.com/g/2005#ICQ' # ICQ protocol
IM_JABBER = 'http://schemas.google.com/g/2005#JABBER' # Jabber protocol
IM_NETMEETING = 'http://schemas.google.com/g/2005#NETMEETING' # NetMeeting
PHOTO_LINK_REL = 'http://schemas.google.com/contacts/2008/rel#photo'
PHOTO_EDIT_LINK_REL = 'http://schemas.google.com/contacts/2008/rel#edit-photo'
# Different phone types, for more info see:
# http://code.google.com/apis/gdata/docs/2.0/elements.html#gdPhoneNumber
PHONE_ASSISTANT = 'http://schemas.google.com/g/2005#assistant'
PHONE_CALLBACK = 'http://schemas.google.com/g/2005#callback'
PHONE_CAR = 'http://schemas.google.com/g/2005#car'
PHONE_COMPANY_MAIN = 'http://schemas.google.com/g/2005#company_main'
PHONE_FAX = 'http://schemas.google.com/g/2005#fax'
PHONE_GENERAL = 'http://schemas.google.com/g/2005#general'
PHONE_HOME = REL_HOME
PHONE_HOME_FAX = 'http://schemas.google.com/g/2005#home_fax'
PHONE_INTERNAL = 'http://schemas.google.com/g/2005#internal-extension'
PHONE_ISDN = 'http://schemas.google.com/g/2005#isdn'
PHONE_MAIN = 'http://schemas.google.com/g/2005#main'
PHONE_MOBILE = 'http://schemas.google.com/g/2005#mobile'
PHONE_OTHER = REL_OTHER
PHONE_OTHER_FAX = 'http://schemas.google.com/g/2005#other_fax'
PHONE_PAGER = 'http://schemas.google.com/g/2005#pager'
PHONE_RADIO = 'http://schemas.google.com/g/2005#radio'
PHONE_SATELLITE = 'http://schemas.google.com/g/2005#satellite'
PHONE_TELEX = 'http://schemas.google.com/g/2005#telex'
PHONE_TTY_TDD = 'http://schemas.google.com/g/2005#tty_tdd'
PHONE_VOIP = 'http://schemas.google.com/g/2005#voip'
PHONE_WORK = REL_WORK
PHONE_WORK_FAX = 'http://schemas.google.com/g/2005#work_fax'
PHONE_WORK_MOBILE = 'http://schemas.google.com/g/2005#work_mobile'
PHONE_WORK_PAGER = 'http://schemas.google.com/g/2005#work_pager'
MAIL_BOTH = 'http://schemas.google.com/g/2005#both'
MAIL_LETTERS = 'http://schemas.google.com/g/2005#letters'
MAIL_PARCELS = 'http://schemas.google.com/g/2005#parcels'
MAIL_NEITHER = 'http://schemas.google.com/g/2005#neither'
GENERAL_ADDRESS = 'http://schemas.google.com/g/2005#general'
LOCAL_ADDRESS = 'http://schemas.google.com/g/2005#local'
EXTERNAL_ID_ORGANIZATION = 'organization'
RELATION_MANAGER = 'manager'
CONTACTS_NAMESPACE = 'http://schemas.google.com/contact/2008'
class GDataBase(atom.AtomBase):
"""The Google Contacts intermediate class from atom.AtomBase."""
_namespace = gdata.GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def __init__(self, text=None):
atom.AtomBase.__init__(self, text=text)
class ContactsBase(GDataBase):
"""The Google Contacts intermediate class for Contacts namespace."""
_namespace = CONTACTS_NAMESPACE
class BillingInformation(ContactsBase):
"""The gContact:billingInformation element."""
_tag = 'billingInformation'
class Birthday(ContactsBase):
"""The gContact:birthday element."""
_tag = 'birthday'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['when'] = 'when'
def __init__(self, when=None):
ContactsBase.__init__(self)
self.when = when
class CalendarLink(ContactsBase):
"""The gContact:calendarLink element."""
_tag = 'calendarLink'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['href'] = 'href'
_attributes['label'] = 'label'
_attributes['primary'] = 'primary'
_attributes['rel'] = 'rel'
def __init__(self, href=None, label=None, primary='false', rel=None):
ContactsBase.__init__(self)
self.href = href
self.label = label
self.primary = primary
self.rel = rel
class Content(atom.AtomBase):
"""The Google Contacts Content element."""
_tag = 'content'
_namespace = atom.ATOM_NAMESPACE
def __init__(self, text=None):
atom.AtomBase.__init__(self, text=text)
class DirectoryServer(ContactsBase):
"""The gContact:directoryServer element."""
_tag = 'directoryServer'
class Email(GDataBase):
"""The gd:email element."""
_tag = 'email'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['address'] = 'address'
_attributes['primary'] = 'primary'
_attributes['rel'] = 'rel'
_attributes['label'] = 'label'
def __init__(self, label=None, rel=None, address=None, primary='false'):
GDataBase.__init__(self)
self.label = label
self.rel = rel
self.address = address
self.primary = primary
class When(GDataBase):
"""The Google Contacts when element."""
_tag = 'when'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['startTime'] = 'startTime'
_attributes['label'] = 'label'
def __init__(self, startTime=None, label=None):
GDataBase.__init__(self)
self.startTime = startTime
self.label = label
class Event(ContactsBase):
"""The gContact:event element."""
_tag = 'event'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_children['{%s}when' % GDataBase._namespace] = ('when', When)
def __init__(self, label=None, rel=None, when=None):
ContactsBase.__init__(self)
self.label = label
self.rel = rel
self.when = when
def EventFromString(xml_string):
return atom.CreateClassFromXMLString(Event, xml_string)
class ExternalId(ContactsBase):
"""The gContact:externalId element."""
_tag = 'externalId'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_attributes['value'] = 'value'
def __init__(self, label=None, rel=None, value=None):
ContactsBase.__init__(self)
self.label = label
self.rel = rel
self.value = value
def ExternalIdFromString(xml_string):
return atom.CreateClassFromXMLString(ExternalId, xml_string)
class Gender(ContactsBase):
"""The gContact:gender element."""
_tag = 'gender'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['value'] = 'value'
def __init__(self, value=None):
ContactsBase.__init__(self)
self.value = value
class Hobby(ContactsBase):
"""The gContact:hobby element."""
_tag = 'hobby'
class IM(GDataBase):
"""The gd:im element."""
_tag = 'im'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['address'] = 'address'
_attributes['primary'] = 'primary'
_attributes['protocol'] = 'protocol'
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
def __init__(self, primary='false', rel=None, address=None, protocol=None, label=None):
GDataBase.__init__(self)
self.protocol = protocol
self.address = address
self.primary = primary
self.rel = rel
self.label = label
class Initials(ContactsBase):
"""The gContact:initials element."""
_tag = 'initials'
class Jot(ContactsBase):
"""The gContact:jot element."""
_tag = 'jot'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['rel'] = 'rel'
def __init__(self, rel=None, text=None):
ContactsBase.__init__(self, text=text)
self.rel = rel
class Language(ContactsBase):
"""The gContact:language element."""
_tag = 'language'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['code'] = 'code'
_attributes['label'] = 'label'
def __init__(self, code=None, label=None):
ContactsBase.__init__(self)
self.code = code
self.label = label
class MaidenName(ContactsBase):
"""The gContact:maidenName element."""
_tag = 'maidenName'
class Mileage(ContactsBase):
"""The gContact:mileage element."""
_tag = 'mileage'
class NamePrefix(GDataBase):
"""The gd:namePrefix element."""
_tag = 'namePrefix'
class GivenName(GDataBase):
"""The gd:givenName element."""
_tag = 'givenName'
class AdditionalName(GDataBase):
"""The gd:additionalName element."""
_tag = 'additionalName'
class FamilyName(GDataBase):
"""The gd:familyName element."""
_tag = 'familyName'
class NameSuffix(GDataBase):
"""The gd:nameSuffix element."""
_tag = 'nameSuffix'
class FullName(GDataBase):
"""The gd:fullName element."""
_tag = 'fullName'
class Name(GDataBase):
"""The gd:name element."""
_tag = 'name'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_children['{%s}namePrefix' % GDataBase._namespace] = ('name_prefix', NamePrefix)
_children['{%s}givenName' % GDataBase._namespace] = ('given_name', GivenName)
_children['{%s}additionalName' % GDataBase._namespace] = ('additional_name', AdditionalName)
_children['{%s}familyName' % GDataBase._namespace] = ('family_name', FamilyName)
_children['{%s}nameSuffix' % GDataBase._namespace] = ('name_suffix', NameSuffix)
_children['{%s}fullName' % GDataBase._namespace] = ('full_name', FullName)
def __init__(self, given_name=None, additional_name=None, family_name=None,
name_prefix=None, name_suffix=None, full_name=None,):
GDataBase.__init__(self)
self.given_name = given_name
self.additional_name = additional_name
self.family_name = family_name
self.name_prefix = name_prefix
self.name_suffix = name_suffix
self.full_name = full_name
class Nickname(ContactsBase):
"""The gContact:nickname element."""
_tag = 'nickname'
class Occupation(ContactsBase):
"""The gContact:occupation element."""
_tag = 'occupation'
class PhoneNumber(GDataBase):
"""The gd:phoneNumber element."""
_tag = 'phoneNumber'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_attributes['uri'] = 'uri'
_attributes['primary'] = 'primary'
def __init__(self, label=None, rel=None, uri=None, primary='false', text=None):
GDataBase.__init__(self, text=text)
self.label = label
self.rel = rel
self.uri = uri
self.primary = primary
class OrgName(GDataBase):
"""The gd:orgName element."""
_tag = 'orgName'
class OrgTitle(GDataBase):
"""The gd:orgTitle element."""
_tag = 'orgTitle'
class OrgSymbol(GDataBase):
"""The gd:orgSymbol element."""
_tag = 'orgSymbol'
class OrgDepartment(GDataBase):
"""The gd:orgDepartment element."""
_tag = 'orgDepartment'
class OrgJobDescription(GDataBase):
"""The gd:orgJobDescription element."""
_tag = 'orgJobDescription'
class Where(GDataBase):
"""The gd:where element."""
_tag = 'where'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['valueString'] = 'value_string'
def __init__(self, value_string=None):
GDataBase.__init__(self)
self.value_string = value_string
class Organization(GDataBase):
"""The gd:organization element."""
_tag = 'organization'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_attributes['primary'] = 'primary'
_children['{%s}orgName' % GDataBase._namespace] = ('name', OrgName)
_children['{%s}orgSymbol' % GDataBase._namespace] = ('symbol', OrgSymbol)
_children['{%s}orgTitle' % GDataBase._namespace] = ('title', OrgTitle)
_children['{%s}orgDepartment' % GDataBase._namespace] = ('department', OrgDepartment)
_children['{%s}orgJobDescription' % GDataBase._namespace] = ('job_description', OrgJobDescription)
_children['{%s}where' % GDataBase._namespace] = ('where', Where)
def __init__(self, label=None, rel=None, primary='false', name=None,
title=None, symbol=None, department=None, job_description=None, where=None,):
GDataBase.__init__(self)
self.label = label
self.rel = rel
self.primary = primary
self.name = name
self.symbol = symbol
self.title = title
self.department = department
self.job_description = job_description
self.where = where
class PostalAddress(GDataBase):
"""The gd:postalAddress element."""
_tag = 'postalAddress'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_attributes['primary'] = 'primary'
def __init__(self, primary=None, rel=None, label=None, text=None):
GDataBase.__init__(self, text=text)
self.label = label
self.rel = rel
self.primary = primary
class Priority(ContactsBase):
"""The gContact:priority element."""
_tag = 'priority'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['rel'] = 'rel'
def __init__(self, rel=None):
ContactsBase.__init__(self)
self.rel = rel
class Relation(ContactsBase):
"""The gContact:relation element."""
_tag = 'relation'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
def __init__(self, label=None, rel=None, text=None):
ContactsBase.__init__(self, text=text)
self.label = label
self.rel = rel
def RelationFromString(xml_string):
return atom.CreateClassFromXMLString(Relation, xml_string)
class Sensitivity(ContactsBase):
"""The gContact:sensitivity element."""
_tag = 'sensitivity'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['rel'] = 'rel'
def __init__(self, rel=None):
ContactsBase.__init__(self)
self.rel = rel
class ShortName(ContactsBase):
"""The gContact:shortName element."""
_tag = 'shortName'
class Street(GDataBase):
"""The gd:street element.
Can be street, avenue, road, etc. This element also includes the
house number and room/apartment/flat/floor number.
"""
_tag = 'street'
class PoBox(GDataBase):
"""The gd:pobox element.
Covers actual P.O. boxes, drawers, locked bags, etc. This is usually
but not always mutually exclusive with street.
"""
_tag = 'pobox'
class Neighborhood(GDataBase):
"""The gd:neighborhood element.
This is used to disambiguate a street address when a city contains more
than one street with the same name, or to specify a small place whose
mail is routed through a larger postal town. In China it could be a
county or a minor city.
"""
_tag = 'neighborhood'
class City(GDataBase):
"""The gd:city element.
Can be city, village, town, borough, etc. This is the postal town and
not necessarily the place of residence or place of business.
"""
_tag = 'city'
class Region(GDataBase):
"""The gd:region element.
A state, province, county (in Ireland), Land (in Germany),
departement (in France), etc.
"""
_tag = 'region'
class Postcode(GDataBase):
"""The gd:postcode element.
Postal code. Usually country-wide, but sometimes specific to the
city (e.g. "2" in "Dublin 2, Ireland" addresses).
"""
_tag = 'postcode'
class Country(GDataBase):
"""The gd:country element.
The name or code of the country.
"""
_tag = 'country'
class FormattedAddress(GDataBase):
"""The gd:formattedAddress element."""
_tag = 'formattedAddress'
class StructuredPostalAddress(GDataBase):
"""The gd:structuredPostalAddress element."""
_tag = 'structuredPostalAddress'
_children = GDataBase._children.copy()
_attributes = GDataBase._attributes.copy()
_attributes['label'] = 'label'
_attributes['rel'] = 'rel'
_attributes['primary'] = 'primary'
_children['{%s}street' % GDataBase._namespace] = ('street', Street)
_children['{%s}pobox' % GDataBase._namespace] = ('pobox', PoBox)
_children['{%s}neighborhood' % GDataBase._namespace] = ('neighborhood', Neighborhood)
_children['{%s}city' % GDataBase._namespace] = ('city', City)
_children['{%s}region' % GDataBase._namespace] = ('region', Region)
_children['{%s}postcode' % GDataBase._namespace] = ('postcode', Postcode)
_children['{%s}country' % GDataBase._namespace] = ('country', Country)
_children['{%s}formattedAddress' % GDataBase._namespace] = ('formatted_address', FormattedAddress)
def __init__(self, rel=None, label=None, primary='false',
street=None,
pobox=None,
neighborhood=None,
city=None,
region=None,
postcode=None,
country=None,
formatted_address=None):
GDataBase.__init__(self)
self.label = label
self.rel = rel
self.primary = primary
self.street = street
self.pobox = pobox
self.neighborhood = neighborhood
self.city = city
self.region = region
self.postcode = postcode
self.country = country
self.formatted_address = formatted_address
class Subject(ContactsBase):
"""The gContact:Subject element."""
_tag = 'subject'
class UserDefinedField(ContactsBase):
"""The gContact:userDefinedField element."""
_tag = 'userDefinedField'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['key'] = 'key'
_attributes['value'] = 'value'
def __init__(self, key=None, value=None):
ContactsBase.__init__(self)
self.key = key
self.value = value
def UserDefinedFieldFromString(xml_string):
return atom.CreateClassFromXMLString(UserDefinedField, xml_string)
class Website(ContactsBase):
"""The gContact:Website element."""
_tag = 'website'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['href'] = 'href'
_attributes['label'] = 'label'
_attributes['primary'] = 'primary'
_attributes['rel'] = 'rel'
def __init__(self, href=None, label=None, primary='false', rel=None):
ContactsBase.__init__(self)
self.href = href
self.label = label
self.primary = primary
self.rel = rel
def WebsiteFromString(xml_string):
return atom.CreateClassFromXMLString(Website, xml_string)
class PersonEntry(gdata.BatchEntry):
"""Base class for ContactEntry and ProfileEntry."""
_children = gdata.BatchEntry._children.copy()
_children['{%s}billingInformation' % CONTACTS_NAMESPACE] = ('billingInformation', BillingInformation)
_children['{%s}birthday' % CONTACTS_NAMESPACE] = ('birthday', Birthday)
_children['{%s}calendarLink' % CONTACTS_NAMESPACE] = ('calendarLink', [CalendarLink])
_children['{%s}content' % atom.ATOM_NAMESPACE] = ('content', Content)
_children['{%s}directoryServer' % CONTACTS_NAMESPACE] = ('directoryServer', DirectoryServer)
_children['{%s}email' % gdata.GDATA_NAMESPACE] = ('email', [Email])
_children['{%s}event' % CONTACTS_NAMESPACE] = ('event', [Event])
_children['{%s}externalId' % CONTACTS_NAMESPACE] = ('externalId', [ExternalId])
_children['{%s}gender' % CONTACTS_NAMESPACE] = ('gender', Gender)
_children['{%s}hobby' % CONTACTS_NAMESPACE] = ('hobby', [Hobby])
_children['{%s}im' % gdata.GDATA_NAMESPACE] = ('im', [IM])
_children['{%s}initials' % CONTACTS_NAMESPACE] = ('initials', Initials)
_children['{%s}jot' % CONTACTS_NAMESPACE] = ('jot', [Jot])
_children['{%s}language' % CONTACTS_NAMESPACE] = ('language', Language)
_children['{%s}maidenName' % CONTACTS_NAMESPACE] = ('maidenName', MaidenName)
_children['{%s}mileage' % CONTACTS_NAMESPACE] = ('mileage', Mileage)
_children['{%s}name' % gdata.GDATA_NAMESPACE] = ('name', Name)
_children['{%s}nickname' % CONTACTS_NAMESPACE] = ('nickname', Nickname)
_children['{%s}occupation' % CONTACTS_NAMESPACE] = ('occupation', Occupation)
_children['{%s}organization' % gdata.GDATA_NAMESPACE] = ('organization', [Organization])
_children['{%s}phoneNumber' % gdata.GDATA_NAMESPACE] = ('phoneNumber', [PhoneNumber])
_children['{%s}postalAddress' % gdata.GDATA_NAMESPACE] = ('postalAddress', [PostalAddress])
_children['{%s}priority' % CONTACTS_NAMESPACE] = ('priority', Priority)
_children['{%s}relation' % CONTACTS_NAMESPACE] = ('relation', [Relation])
_children['{%s}sensitivity' % CONTACTS_NAMESPACE] = ('sensitivity', Sensitivity)
_children['{%s}shortName' % CONTACTS_NAMESPACE] = ('shortName', ShortName)
_children['{%s}structuredPostalAddress' % gdata.GDATA_NAMESPACE] = ('structuredPostalAddress', [StructuredPostalAddress])
_children['{%s}subject' % CONTACTS_NAMESPACE] = ('subject', Subject)
_children['{%s}userDefinedField' % CONTACTS_NAMESPACE] = ('userDefinedField', [UserDefinedField])
_children['{%s}website' % CONTACTS_NAMESPACE] = ('website', [Website])
_children['{%s}where' % gdata.GDATA_NAMESPACE] = ('where', Where)
_attributes = gdata.BatchEntry._attributes.copy()
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
def __init__(self,
billingInformation=None,
birthday=None,
calendarLink=None,
content=None,
directoryServer=None,
email=None,
event=None,
externalId=None,
gender=None,
hobby=None,
im=None,
initials=None,
jot=None,
language=None,
maidenName=None,
mileage=None,
name=None,
nickname=None,
occupation=None,
organization=None,
phoneNumber=None,
postalAddress=None,
priority=None,
relation=None,
sensitivity=None,
shortName=None,
structuredPostalAddress=None,
subject=None,
text=None,
title=None,
userDefinedField=None,
website=None,
where=None,
etag=None):
gdata.BatchEntry.__init__(self)
self.billingInformation = billingInformation
self.birthday = birthday
self.calendarLink = calendarLink or []
self.content = content
self.directoryServer = directoryServer
self.email = email or []
self.event = event or []
self.externalId = externalId or []
self.gender = gender
self.hobby = hobby or []
self.im = im or []
self.initials = initials
self.jot = jot or []
self.language = language
self.maidenName = maidenName
self.mileage = mileage
self.name = name
self.nickname = nickname
self.occupation = occupation
self.organization = organization or []
self.phoneNumber = phoneNumber or []
self.postalAddress = postalAddress or []
self.priority = priority
self.relation = relation or []
self.sensitivity = sensitivity
self.shortName = shortName
self.structuredPostalAddress = structuredPostalAddress or []
self.subject = subject
self.text = text
self.userDefinedField = userDefinedField or []
self.website = website or []
self.where = where
self.extension_attributes = {}
self.extension_elements = []
self.etag = etag
class Deleted(GDataBase):
"""The gd:Deleted element."""
_tag = 'deleted'
class GroupMembershipInfo(ContactsBase):
"""The Google Contacts GroupMembershipInfo element."""
_tag = 'groupMembershipInfo'
_children = ContactsBase._children.copy()
_attributes = ContactsBase._attributes.copy()
_attributes['deleted'] = 'deleted'
_attributes['href'] = 'href'
def __init__(self, deleted=None, href=None, text=None):
ContactsBase.__init__(self, text=text)
self.deleted = deleted
self.href = href
class ContactEntry(PersonEntry):
"""Represents a contact."""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = PersonEntry._children.copy()
_children['{%s}deleted' % gdata.GDATA_NAMESPACE] = ('deleted', Deleted)
_children['{%s}groupMembershipInfo' % CONTACTS_NAMESPACE] = ('groupMembershipInfo', [GroupMembershipInfo])
_children['{%s}extendedProperty' % gdata.GDATA_NAMESPACE] = ('extended_property', [gdata.ExtendedProperty])
# Overwrite the organization rule in PersonEntry so that a ContactEntry
# may only contain one <gd:organization> element.
#_children['{%s}organization' % gdata.GDATA_NAMESPACE] = ('organization', Organization)
def __init__(self,
billingInformation=None,
birthday=None,
calendarLink=None,
content=None,
deleted=None,
directoryServer=None,
email=None,
event=None,
extended_property=None,
externalId=None,
gender=None,
groupMembershipInfo=None,
hobby=None,
im=None,
initials=None,
jot=None,
language=None,
maidenName=None,
mileage=None,
name=None,
nickname=None,
occupation=None,
organization=None,
phoneNumber=None,
postalAddress=None,
priority=None,
relation=None,
sensitivity=None,
shortName=None,
structuredPostalAddress=None,
subject=None,
text=None,
title=None,
userDefinedField=None,
website=None,
where=None,
etag=None):
PersonEntry.__init__(self,
billingInformation=billingInformation,
birthday=birthday,
calendarLink=calendarLink,
content=content,
directoryServer=directoryServer,
email=email,
event=event,
externalId=externalId,
gender=gender,
hobby=hobby,
im=im,
initials=initials,
jot=jot,
language=language,
maidenName=maidenName,
mileage=mileage,
name=name,
nickname=nickname,
occupation=occupation,
organization=organization,
phoneNumber=phoneNumber,
postalAddress=postalAddress,
priority=priority,
relation=relation,
sensitivity=sensitivity,
shortName=shortName,
structuredPostalAddress=structuredPostalAddress,
subject=subject,
text=text,
title=title,
userDefinedField=userDefinedField,
website=website,
where=where,
etag=etag)
self.deleted = deleted
self.extended_property = extended_property or []
self.groupMembershipInfo = groupMembershipInfo or []
def GetPhotoLink(self):
for a_link in self.link:
if a_link.rel == PHOTO_LINK_REL:
return a_link
return None
def GetPhotoEditLink(self):
for a_link in self.link:
if a_link.rel == PHOTO_EDIT_LINK_REL:
return a_link
return None
def ContactEntryFromString(xml_string):
return atom.CreateClassFromXMLString(ContactEntry, xml_string)
class ContactsFeed(gdata.BatchFeed, gdata.LinkFinder):
"""A Google contacts feed flavor of an Atom Feed."""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchFeed._children.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [ContactEntry])
def __init__(self):
gdata.BatchFeed.__init__(self)
def ContactsFeedFromString(xml_string):
return atom.CreateClassFromXMLString(ContactsFeed, xml_string)
class GroupEntry(gdata.BatchEntry):
"""Represents a contact group."""
_children = gdata.BatchEntry._children.copy()
_children['{%s}deleted' % gdata.GDATA_NAMESPACE] = ('deleted', Deleted)
_children['{%s}extendedProperty' % gdata.GDATA_NAMESPACE] = ('extended_property', [gdata.ExtendedProperty])
_attributes = gdata.BatchEntry._attributes.copy()
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
def __init__(self,
title=None,
deleted=None,
extended_property=None,
etag=None):
gdata.BatchEntry.__init__(self)
self.title = title
self.deleted = deleted
self.extended_property = extended_property or []
self.etag = etag
def GroupEntryFromString(xml_string):
return atom.CreateClassFromXMLString(GroupEntry, xml_string)
class GroupsFeed(gdata.BatchFeed):
"""A Google contact groups feed flavor of an Atom Feed."""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchFeed._children.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [GroupEntry])
def __init__(self):
gdata.BatchFeed.__init__(self)
def GroupsFeedFromString(xml_string):
return atom.CreateClassFromXMLString(GroupsFeed, xml_string)

View File

@@ -0,0 +1,355 @@
#!/usr/bin/env python
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""ContactsService extends the GDataService for Google Contacts operations.
ContactsService: Provides methods to query feeds and manipulate items.
Extends GDataService.
"""
import gdata.apps
import gdata.apps.service
import gdata.service
class ContactsService(gdata.service.GDataService):
"""Client for the Google Contacts service."""
def __init__(self, email=None, password=None, source=None,
server='www.google.com', additional_headers=None,
contact_list='default', contactFeed=True, **kwargs):
"""Creates a client for the Contacts service.
Args:
email: string (optional) The user's email address, used for
authentication.
password: string (optional) The user's password.
source: string (optional) The name of the user's application.
server: string (optional) The name of the server to which a connection
will be opened. Default value: 'www.google.com'.
contact_list: string (optional) The name of the default contact list to
use when no URI is specified to the methods of the service.
Default value: 'default' (the logged in user's contact list).
contactFeed: Boolean (optional) Is this contacts feed or a gal feed
Default value: True (the logged in user's contact list).
**kwargs: The other parameters to pass to gdata.service.GDataService
constructor.
"""
self.contact_list = contact_list
self.feed_type = ['gal', 'contacts'][contactFeed]
if additional_headers == None:
additional_headers = {}
additional_headers['GData-Version'] = ['1.1', '3.1'][contactFeed]
gdata.service.GDataService.__init__(self,
email=email, password=password, service='cp', source=source,
server=server, additional_headers=additional_headers, **kwargs)
self.ssl = True
self.port = 443
def _CleanUri(self, uri):
"""Sanitizes a feed URI.
Args:
uri: The URI to sanitize, can be relative or absolute.
Returns:
The given URI without its https://server prefix, if any.
Keeps the leading slash of the URI.
"""
url_prefix = 'https://%s' % self.server
if uri.startswith(url_prefix):
uri = uri[len(url_prefix):]
return uri
def GetContactFeedUri(self, contact_list=None, projection='full', contactId=None):
"""Builds a contact feed URI. """
contact_list = contact_list or self.contact_list
uri = 'https://{0}/m8/feeds/{1}/{2}/{3}'.format(self.server, self.feed_type, contact_list, projection)
if contactId:
uri += '/{0}'.format(contactId)
return uri
def GetContactsFeed(self, uri=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.GetContactFeedUri()
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.contacts.ContactsFeedFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def GetContact(self, uri):
try:
return self.Get(uri, converter=gdata.apps.contacts.ContactEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def CreateContact(self, new_contact, insert_uri=None, url_params=None,
escape_params=True):
"""Adds an new contact to Google Contacts.
Args:
new_contact: atom.Entry or subclass A new contact which is to be added to
Google Contacts.
insert_uri: the URL to post new contacts to the feed
url_params: dict (optional) Additional URL parameters to be included
in the insertion request.
escape_params: boolean (optional) If true, the url_parameters will be
escaped before they are included in the request.
Returns:
On successful insert, an entry containing the contact created
On failure, a RequestError is raised of the form:
{'status': HTTP status code from server,
'reason': HTTP reason from the server,
'body': HTTP body of the server's response}
"""
insert_uri = insert_uri or self.GetContactFeedUri()
try:
return self.Post(new_contact, insert_uri, url_params=url_params,
escape_params=escape_params,
converter=gdata.apps.contacts.ContactEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def UpdateContact(self, edit_uri, updated_contact, extra_headers=None, url_params=None,
escape_params=True):
"""Updates an existing contact.
Args:
edit_uri: string The edit link URI for the element being updated
updated_contact: string, atom.Entry or subclass containing
the Atom Entry which will replace the contact which is
stored at the edit_url
url_params: dict (optional) Additional URL parameters to be included
in the update request.
escape_params: boolean (optional) If true, the url_parameters will be
escaped before they are included in the request.
Returns:
On successful update, a httplib.HTTPResponse containing the server's
response to the PUT request.
On failure, a RequestError is raised of the form:
{'status': HTTP status code from server,
'reason': HTTP reason from the server,
'body': HTTP body of the server's response}
"""
try:
return self.Put(updated_contact, self._CleanUri(edit_uri),
url_params=url_params, extra_headers=extra_headers,
escape_params=escape_params,
converter=gdata.apps.contacts.ContactEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def DeleteContact(self, edit_uri, extra_headers=None,
url_params=None, escape_params=True):
"""Removes an contact with the specified ID from Google Contacts.
Args:
edit_uri: string The edit URL of the entry to be deleted. Example:
'/m8/feeds/contacts/default/full/xxx/yyy'
extra_headers: dict (optional)
url_params: dict (optional) Additional URL parameters to be included
in the deletion request.
escape_params: boolean (optional) If true, the url_parameters will be
escaped before they are included in the request.
Returns:
On successful delete, a httplib.HTTPResponse containing the server's
response to the DELETE request.
On failure, a RequestError is raised of the form:
{'status': HTTP status code from server,
'reason': HTTP reason from the server,
'body': HTTP body of the server's response}
"""
try:
return self.Delete(self._CleanUri(edit_uri),
url_params=url_params, escape_params=escape_params, extra_headers=extra_headers)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def ChangePhoto(self, media, contact_entry_or_url, content_type=None,
content_length=None, extra_headers=None):
"""Change the photo for the contact by uploading a new photo.
Performs a PUT against the photo edit URL to send the binary data for the
photo.
Args:
media: filename, file-like-object, or a gdata.MediaSource object to send.
contact_entry_or_url: ContactEntry or str If it is a ContactEntry, this
method will search for an edit photo link URL and
perform a PUT to the URL.
content_type: str (optional) the mime type for the photo data. This is
necessary if media is a file or file name, but if media
is a MediaSource object then the media object can contain
the mime type. If media_type is set, it will override the
mime type in the media object.
content_length: int or str (optional) Specifying the content length is
only required if media is a file-like object. If media
is a filename, the length is determined using
os.path.getsize. If media is a MediaSource object, it is
assumed that it already contains the content length.
extra_headers: dict (optional)
"""
if isinstance(contact_entry_or_url, gdata.apps.contacts.ContactEntry):
# url = contact_entry_or_url.GetPhotoEditLink().href
url = contact_entry_or_url.GetPhotoLink().href
else:
url = contact_entry_or_url
if isinstance(media, gdata.MediaSource):
payload = media
# If the media object is a file-like object, then use it as the file
# handle in the in the MediaSource.
elif hasattr(media, 'read'):
payload = gdata.MediaSource(file_handle=media,
content_type=content_type, content_length=content_length)
# Assume that the media object is a file name.
else:
payload = gdata.MediaSource(content_type=content_type,
content_length=content_length, file_path=media)
return self.Put(payload, url, extra_headers=extra_headers)
def GetPhoto(self, contact_entry_or_url):
"""Retrives the binary data for the contact's profile photo as a string.
Args:
contact_entry_or_url: a gdata.apps.contacts.ContactEntry object or a string
containing the photo link's URL. If the contact entry does not
contain a photo link, the image will not be fetched and this method
will return None.
"""
# TODO: add the ability to write out the binary image data to a file,
# reading and writing a chunk at a time to avoid potentially using up
# large amounts of memory.
url = None
if isinstance(contact_entry_or_url, gdata.apps.contacts.ContactEntry):
photo_link = contact_entry_or_url.GetPhotoLink()
if photo_link:
url = photo_link.href
else:
url = contact_entry_or_url
if url:
try:
return self.Get(url, converter=str)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
else:
return None
def DeletePhoto(self, contact_entry_or_url, extra_headers=None):
"""Deletes the contact's profile photo.
Args:
contact_entry_or_url: a gdata.apps.contacts.ContactEntry object or a string
containing the photo link's URL.
will return None.
extra_headers: dict (optional)
"""
url = None
if isinstance(contact_entry_or_url, gdata.apps.contacts.ContactEntry):
# url = contact_entry_or_url.GetPhotoEditLink().href
url = contact_entry_or_url.GetPhotoLink().href
else:
url = contact_entry_or_url
if url:
self.Delete(url, extra_headers=extra_headers)
def ExecuteBatch(self, batch_feed, url,
converter=gdata.apps.contacts.ContactsFeedFromString):
"""Sends a batch request feed to the server.
Args:
batch_feed: gdata.apps.contacts.ContactFeed A feed containing batch
request entries. Each entry contains the operation to be performed
on the data contained in the entry. For example an entry with an
operation type of insert will be used as if the individual entry
had been inserted.
url: str The batch URL to which these operations should be applied.
converter: Function (optional) The function used to convert the server's
response to an object. The default value is ContactsFeedFromString.
Returns:
The results of the batch request's execution on the server. If the
default converter is used, this is stored in a ContactsFeed.
"""
return self.Post(batch_feed, url, converter=converter)
def GetContactGroupFeedUri(self, contact_list=None, projection='full', groupId=None):
"""Builds a contact feed URI. """
contact_list = contact_list or self.contact_list
uri = 'https://{0}/m8/feeds/groups/{1}/{2}'.format(self.server, contact_list, projection)
if groupId:
uri += '/{0}'.format(groupId)
return uri
def GetGroupsFeed(self, uri=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.GetContactGroupFeedUri()
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.contacts.GroupsFeedFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def GetGroup(self, uri):
try:
return self.Get(uri, converter=gdata.apps.contacts.GroupEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def CreateGroup(self, new_group, insert_uri=None, url_params=None,
escape_params=True):
insert_uri = insert_uri or self.GetContactGroupFeedUri()
try:
return self.Post(new_group, insert_uri, url_params=url_params,
escape_params=escape_params,
converter=gdata.apps.contacts.GroupEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def UpdateGroup(self, edit_uri, updated_group, extra_headers=None, url_params=None,
escape_params=True):
try:
return self.Put(updated_group, self._CleanUri(edit_uri),
url_params=url_params, extra_headers=extra_headers,
escape_params=escape_params,
converter=gdata.apps.contacts.GroupEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def DeleteGroup(self, edit_uri, extra_headers=None,
url_params=None, escape_params=True):
try:
return self.Delete(self._CleanUri(edit_uri),
url_params=url_params, escape_params=escape_params, extra_headers=extra_headers)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
class ContactsQuery(gdata.service.Query):
def __init__(self, feed=None, text_query=None, params=None,
categories=None, group=None):
self.feed = feed or '/m8/feeds/contacts/default/full'
if group:
self['group'] = group
gdata.service.Query.__init__(self, feed=self.feed, text_query=text_query,
params=params, categories=categories)

View File

@@ -0,0 +1,544 @@
#!/usr/bin/python
#
# Copyright (C) 2007 SIOS Technology, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'tmatsuo@sios.com (Takashi MATSUO)'
import lxml.etree as ElementTree
import urllib.request, urllib.parse, urllib.error
import gdata
import atom.service
import gdata.service
import gdata.apps
import atom
API_VER="2.0"
HTTP_OK=200
UNKOWN_ERROR=1000
USER_DELETED_RECENTLY=1100
USER_SUSPENDED=1101
DOMAIN_USER_LIMIT_EXCEEDED=1200
DOMAIN_ALIAS_LIMIT_EXCEEDED=1201
DOMAIN_SUSPENDED=1202
DOMAIN_FEATURE_UNAVAILABLE=1203
ENTITY_EXISTS=1300
ENTITY_DOES_NOT_EXIST=1301
ENTITY_NAME_IS_RESERVED=1302
ENTITY_NAME_NOT_VALID=1303
INVALID_GIVEN_NAME=1400
INVALID_FAMILY_NAME=1401
INVALID_PASSWORD=1402
INVALID_USERNAME=1403
INVALID_HASH_FUNCTION_NAME=1404
INVALID_HASH_DIGGEST_LENGTH=1405
INVALID_EMAIL_ADDRESS=1406
INVALID_QUERY_PARAMETER_VALUE=1407
TOO_MANY_RECIPIENTS_ON_EMAIL_LIST=1500
DEFAULT_QUOTA_LIMIT='2048'
class Error(Exception):
pass
class AppsForYourDomainException(Error):
def __init__(self, response):
Error.__init__(self, response)
try:
self.element_tree = ElementTree.fromstring(response['body'])
self.error_code = int(self.element_tree[0].attrib['errorCode'])
self.reason = self.element_tree[0].attrib['reason']
self.invalidInput = self.element_tree[0].attrib['invalidInput']
except:
self.error_code = 600
class AppsService(gdata.service.GDataService):
"""Client for the Google Apps Provisioning service."""
def __init__(self, email=None, password=None, domain=None, source=None,
server='apps-apis.google.com', additional_headers=None,
**kwargs):
"""Creates a client for the Google Apps Provisioning service.
Args:
email: string (optional) The user's email address, used for
authentication.
password: string (optional) The user's password.
domain: string (optional) The Google Apps domain name.
source: string (optional) The name of the user's application.
server: string (optional) The name of the server to which a connection
will be opened. Default value: 'apps-apis.google.com'.
**kwargs: The other parameters to pass to gdata.service.GDataService
constructor.
"""
gdata.service.GDataService.__init__(
self, email=email, password=password, service='apps', source=source,
server=server, additional_headers=additional_headers, **kwargs)
self.ssl = True
self.port = 443
self.domain = domain
def _baseURL(self):
return "/a/feeds/%s" % self.domain
def AddAllElementsFromAllPages(self, link_finder, func):
"""retrieve all pages and add all elements"""
next = link_finder.GetNextLink()
while next is not None:
next_feed = self.Get(next.href, converter=func)
for a_entry in next_feed.entry:
link_finder.entry.append(a_entry)
next = next_feed.GetNextLink()
return link_finder
def RetrievePageOfEmailLists(self, start_email_list_name=None,
num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY,
backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve one page of email list"""
uri = "%s/emailList/%s" % (self._baseURL(), API_VER)
if start_email_list_name is not None:
uri += "?startEmailListName=%s" % start_email_list_name
try:
return gdata.apps.EmailListFeedFromString(str(self.GetWithRetries(
uri, num_retries=num_retries, delay=delay, backoff=backoff)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def GetGeneratorForAllEmailLists(
self, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve a generator for all emaillists in this domain."""
first_page = self.RetrievePageOfEmailLists(num_retries=num_retries,
delay=delay,
backoff=backoff)
return self.GetGeneratorFromLinkFinder(
first_page, gdata.apps.EmailListRecipientFeedFromString,
num_retries=num_retries, delay=delay, backoff=backoff)
def RetrieveAllEmailLists(self):
"""Retrieve all email list of a domain."""
ret = self.RetrievePageOfEmailLists()
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.EmailListFeedFromString)
def RetrieveEmailList(self, list_name):
"""Retreive a single email list by the list's name."""
uri = "%s/emailList/%s/%s" % (
self._baseURL(), API_VER, list_name)
try:
return self.Get(uri, converter=gdata.apps.EmailListEntryFromString)
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def RetrieveEmailLists(self, recipient):
"""Retrieve All Email List Subscriptions for an Email Address."""
uri = "%s/emailList/%s?recipient=%s" % (
self._baseURL(), API_VER, recipient)
try:
ret = gdata.apps.EmailListFeedFromString(str(self.Get(uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.EmailListFeedFromString)
def RemoveRecipientFromEmailList(self, recipient, list_name):
"""Remove recipient from email list."""
uri = "%s/emailList/%s/%s/recipient/%s" % (
self._baseURL(), API_VER, list_name, recipient)
try:
self.Delete(uri)
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def RetrievePageOfRecipients(self, list_name, start_recipient=None,
num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY,
backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve one page of recipient of an email list. """
uri = "%s/emailList/%s/%s/recipient" % (
self._baseURL(), API_VER, list_name)
if start_recipient is not None:
uri += "?startRecipient=%s" % start_recipient
try:
return gdata.apps.EmailListRecipientFeedFromString(str(
self.GetWithRetries(
uri, num_retries=num_retries, delay=delay, backoff=backoff)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def GetGeneratorForAllRecipients(
self, list_name, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve a generator for all recipients of a particular emaillist."""
first_page = self.RetrievePageOfRecipients(list_name,
num_retries=num_retries,
delay=delay,
backoff=backoff)
return self.GetGeneratorFromLinkFinder(
first_page, gdata.apps.EmailListRecipientFeedFromString,
num_retries=num_retries, delay=delay, backoff=backoff)
def RetrieveAllRecipients(self, list_name):
"""Retrieve all recipient of an email list."""
ret = self.RetrievePageOfRecipients(list_name)
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.EmailListRecipientFeedFromString)
def AddRecipientToEmailList(self, recipient, list_name):
"""Add a recipient to a email list."""
uri = "%s/emailList/%s/%s/recipient" % (
self._baseURL(), API_VER, list_name)
recipient_entry = gdata.apps.EmailListRecipientEntry()
recipient_entry.who = gdata.apps.Who(email=recipient)
try:
return gdata.apps.EmailListRecipientEntryFromString(
str(self.Post(recipient_entry, uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def DeleteEmailList(self, list_name):
"""Delete a email list"""
uri = "%s/emailList/%s/%s" % (self._baseURL(), API_VER, list_name)
try:
self.Delete(uri)
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def CreateEmailList(self, list_name):
"""Create a email list. """
uri = "%s/emailList/%s" % (self._baseURL(), API_VER)
email_list_entry = gdata.apps.EmailListEntry()
email_list_entry.email_list = gdata.apps.EmailList(name=list_name)
try:
return gdata.apps.EmailListEntryFromString(
str(self.Post(email_list_entry, uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def DeleteNickname(self, nickname):
"""Delete a nickname"""
uri = "%s/nickname/%s/%s" % (self._baseURL(), API_VER, nickname)
try:
self.Delete(uri)
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def RetrievePageOfNicknames(self, start_nickname=None,
num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY,
backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve one page of nicknames in the domain"""
uri = "%s/nickname/%s" % (self._baseURL(), API_VER)
if start_nickname is not None:
uri += "?startNickname=%s" % start_nickname
try:
return gdata.apps.NicknameFeedFromString(str(self.GetWithRetries(
uri, num_retries=num_retries, delay=delay, backoff=backoff)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def GetGeneratorForAllNicknames(
self, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve a generator for all nicknames in this domain."""
first_page = self.RetrievePageOfNicknames(num_retries=num_retries,
delay=delay,
backoff=backoff)
return self.GetGeneratorFromLinkFinder(
first_page, gdata.apps.NicknameFeedFromString, num_retries=num_retries,
delay=delay, backoff=backoff)
def RetrieveAllNicknames(self):
"""Retrieve all nicknames in the domain"""
ret = self.RetrievePageOfNicknames()
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.NicknameFeedFromString)
def GetGeneratorForAllNicknamesOfAUser(
self, user_name, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve a generator for all nicknames of a particular user."""
uri = "%s/nickname/%s?username=%s" % (self._baseURL(), API_VER, user_name)
try:
first_page = gdata.apps.NicknameFeedFromString(str(self.GetWithRetries(
uri, num_retries=num_retries, delay=delay, backoff=backoff)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
return self.GetGeneratorFromLinkFinder(
first_page, gdata.apps.NicknameFeedFromString, num_retries=num_retries,
delay=delay, backoff=backoff)
def RetrieveNicknames(self, user_name):
"""Retrieve nicknames of the user"""
uri = "%s/nickname/%s?username=%s" % (self._baseURL(), API_VER, user_name)
try:
ret = gdata.apps.NicknameFeedFromString(str(self.Get(uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.NicknameFeedFromString)
def RetrieveNickname(self, nickname):
"""Retrieve a nickname.
Args:
nickname: string The nickname to retrieve
Returns:
gdata.apps.NicknameEntry
"""
uri = "%s/nickname/%s/%s" % (self._baseURL(), API_VER, nickname)
try:
return gdata.apps.NicknameEntryFromString(str(self.Get(uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def CreateNickname(self, user_name, nickname):
"""Create a nickname"""
uri = "%s/nickname/%s" % (self._baseURL(), API_VER)
nickname_entry = gdata.apps.NicknameEntry()
nickname_entry.login = gdata.apps.Login(user_name=user_name)
nickname_entry.nickname = gdata.apps.Nickname(name=nickname)
try:
return gdata.apps.NicknameEntryFromString(
str(self.Post(nickname_entry, uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def DeleteUser(self, user_name):
"""Delete a user account"""
uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
try:
return self.Delete(uri)
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def UpdateUser(self, user_name, user_entry):
"""Update a user account."""
uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
try:
return gdata.apps.UserEntryFromString(str(self.Put(user_entry, uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def CreateUser(self, user_name, family_name, given_name, password,
suspended='false', quota_limit=None,
password_hash_function=None,
change_password=None):
"""Create a user account. """
uri = "%s/user/%s" % (self._baseURL(), API_VER)
user_entry = gdata.apps.UserEntry()
user_entry.login = gdata.apps.Login(
user_name=user_name, password=password, suspended=suspended,
hash_function_name=password_hash_function,
change_password=change_password)
user_entry.name = gdata.apps.Name(family_name=family_name,
given_name=given_name)
if quota_limit is not None:
user_entry.quota = gdata.apps.Quota(limit=str(quota_limit))
try:
return gdata.apps.UserEntryFromString(str(self.Post(user_entry, uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def SuspendUser(self, user_name):
user_entry = self.RetrieveUser(user_name)
if user_entry.login.suspended != 'true':
user_entry.login.suspended = 'true'
user_entry = self.UpdateUser(user_name, user_entry)
return user_entry
def RestoreUser(self, user_name):
user_entry = self.RetrieveUser(user_name)
if user_entry.login.suspended != 'false':
user_entry.login.suspended = 'false'
user_entry = self.UpdateUser(user_name, user_entry)
return user_entry
def RetrieveUser(self, user_name):
"""Retrieve an user account.
Args:
user_name: string The user name to retrieve
Returns:
gdata.apps.UserEntry
"""
uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
try:
return gdata.apps.UserEntryFromString(str(self.Get(uri)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def RetrievePageOfUsers(self, start_username=None,
num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY,
backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve one page of users in this domain."""
uri = "%s/user/%s" % (self._baseURL(), API_VER)
if start_username is not None:
uri += "?startUsername=%s" % start_username
try:
return gdata.apps.UserFeedFromString(str(self.GetWithRetries(
uri, num_retries=num_retries, delay=delay, backoff=backoff)))
except gdata.service.RequestError as e:
raise AppsForYourDomainException(e.args[0])
def GetGeneratorForAllUsers(self,
num_retries=gdata.service.DEFAULT_NUM_RETRIES,
delay=gdata.service.DEFAULT_DELAY,
backoff=gdata.service.DEFAULT_BACKOFF):
"""Retrieve a generator for all users in this domain."""
first_page = self.RetrievePageOfUsers(num_retries=num_retries, delay=delay,
backoff=backoff)
return self.GetGeneratorFromLinkFinder(
first_page, gdata.apps.UserFeedFromString, num_retries=num_retries,
delay=delay, backoff=backoff)
def RetrieveAllUsers(self):
"""Retrieve all users in this domain. OBSOLETE"""
ret = self.RetrievePageOfUsers()
# pagination
return self.AddAllElementsFromAllPages(
ret, gdata.apps.UserFeedFromString)
class PropertyService(gdata.service.GDataService):
"""Client for the Google Apps Property service."""
def __init__(self, email=None, password=None, domain=None, source=None,
server='apps-apis.google.com', additional_headers=None):
gdata.service.GDataService.__init__(self, email=email, password=password,
service='apps', source=source,
server=server,
additional_headers=additional_headers)
self.ssl = True
self.port = 443
self.domain = domain
def AddAllElementsFromAllPages(self, link_finder, func):
"""retrieve all pages and add all elements"""
next = link_finder.GetNextLink()
count = 0
while next is not None:
next_feed = self.Get(next.href, converter=func)
count = count + len(next_feed.entry)
for a_entry in next_feed.entry:
link_finder.entry.append(a_entry)
next = next_feed.GetNextLink()
return link_finder
def _GetPropertyEntry(self, properties):
property_entry = gdata.apps.PropertyEntry()
property = []
for name, value in properties.items():
if name is not None and value is not None:
property.append(gdata.apps.Property(name=name, value=value))
property_entry.property = property
return property_entry
def _PropertyEntry2Dict(self, property_entry):
properties = {}
for i, property in enumerate(property_entry.property):
properties[property.name] = property.value
return properties
def _GetPropertyFeed(self, uri):
try:
return gdata.apps.PropertyFeedFromString(str(self.Get(uri)))
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def _GetPropertiesList(self, uri):
property_feed = self._GetPropertyFeed(uri)
# pagination
property_feed = self.AddAllElementsFromAllPages(
property_feed, gdata.apps.PropertyFeedFromString)
properties_list = []
for property_entry in property_feed.entry:
properties_list.append(self._PropertyEntry2Dict(property_entry))
return properties_list
def _GetProperties(self, uri):
try:
return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
str(self.Get(uri))))
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def _PostProperties(self, uri, properties):
property_entry = self._GetPropertyEntry(properties)
try:
return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
str(self.Post(property_entry, uri))))
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def _PutProperties(self, uri, properties):
property_entry = self._GetPropertyEntry(properties)
try:
return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
str(self.Put(property_entry, uri))))
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def _DeleteProperties(self, uri):
try:
self.Delete(uri)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
def _bool2str(b):
if b is None:
return None
return str(b is True).lower()

View File

@@ -0,0 +1,283 @@
#!/usr/bin/env python
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Data model classes for parsing and generating XML for the Sites Data API."""
import atom
import gdata
# XML Namespaces used in Google Sites entities.
SITES_NAMESPACE = 'http://schemas.google.com/sites/2008'
SITES_TEMPLATE = '{http://schemas.google.com/sites/2008}%s'
SPREADSHEETS_NAMESPACE = 'http://schemas.google.com/spreadsheets/2006'
SPREADSHEETS_TEMPLATE = '{http://schemas.google.com/spreadsheets/2006}%s'
GACL_NAMESPACE = 'http://schemas.google.com/acl/2007'
GACL_TEMPLATE = '{http://schemas.google.com/acl/2007}%s'
DC_TERMS_TEMPLATE = '{http://purl.org/dc/terms}%s'
THR_TERMS_TEMPLATE = '{http://purl.org/syndication/thread/1.0}%s'
XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'
XHTML_TEMPLATE = '{http://www.w3.org/1999/xhtml}%s'
SITES_INVITE_LINK_REL = SITES_NAMESPACE + '#invite'
SITES_PARENT_LINK_REL = SITES_NAMESPACE + '#parent'
SITES_REVISION_LINK_REL = SITES_NAMESPACE + '#revision'
SITES_SOURCE_LINK_REL = SITES_NAMESPACE + '#source'
SITES_TEMPLATE_LINK_REL = SITES_NAMESPACE + '#template'
ALTERNATE_REL = 'alternate'
WEB_ADDRESS_MAPPING_REL = 'webAddressMapping'
SITES_KIND_SCHEME = 'http://schemas.google.com/g/2005#kind'
ANNOUNCEMENT_KIND_TERM = SITES_NAMESPACE + '#announcement'
ANNOUNCEMENT_PAGE_KIND_TERM = SITES_NAMESPACE + '#announcementspage'
ATTACHMENT_KIND_TERM = SITES_NAMESPACE + '#attachment'
COMMENT_KIND_TERM = SITES_NAMESPACE + '#comment'
FILECABINET_KIND_TERM = SITES_NAMESPACE + '#filecabinet'
LISTITEM_KIND_TERM = SITES_NAMESPACE + '#listitem'
LISTPAGE_KIND_TERM = SITES_NAMESPACE + '#listpage'
WEBPAGE_KIND_TERM = SITES_NAMESPACE + '#webpage'
WEBATTACHMENT_KIND_TERM = SITES_NAMESPACE + '#webattachment'
FOLDER_KIND_TERM = SITES_NAMESPACE + '#folder'
TAG_KIND_TERM = SITES_NAMESPACE + '#tag'
SUPPORT_KINDS = [
'announcement', 'announcementspage', 'attachment', 'comment', 'filecabinet',
'listitem', 'listpage', 'webpage', 'webattachment', 'tag'
]
class GDataBase(atom.AtomBase):
"""The Google Sites intermediate class from atom.AtomBase."""
_namespace = gdata.GDATA_NAMESPACE
_children = atom.AtomBase._children.copy()
_attributes = atom.AtomBase._attributes.copy()
def __init__(self, text=None):
atom.AtomBase.__init__(self, text=text)
class SitesBase(GDataBase):
_namespace = SITES_NAMESPACE
class SiteName(SitesBase):
"""Google Sites <sites:siteName>."""
_tag = 'siteName'
class Theme(SitesBase):
"""Google Sites <sites:theme>."""
_tag = 'theme'
class SiteEntry(gdata.BatchEntry):
"""Google Sites Site Feed Entry."""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchEntry._children.copy()
_children['{%s}siteName' % SITES_NAMESPACE] = ('siteName', SiteName)
_children['{%s}theme' % SITES_NAMESPACE] = ('theme', Theme)
_attributes = gdata.BatchEntry._attributes.copy()
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
def __init__(self, siteName=None, title=None, summary=None, theme=None, sourceSite=None, category=None, etag=None):
gdata.BatchEntry.__init__(self, category=category)
self.siteName = siteName
self.title = title
self.summary = summary
self.theme = theme
if sourceSite is not None:
sourceLink = atom.Link(href=sourceSite, rel=SITES_SOURCE_LINK_REL, link_type='application/atom+xml')
self.link.append(sourceLink)
self.etag = etag
def find_alternate_link(self):
for link in self.link:
if link.rel == ALTERNATE_REL and link.href:
return link.href
return None
FindAlternateLink = find_alternate_link
def find_source_link(self):
for link in self.link:
if link.rel == SITES_SOURCE_LINK_REL and link.href:
return link.href
return None
FindSourceLink = find_source_link
def find_webaddress_mappings(self):
mappingLinks = []
for link in self.link:
if link.rel == WEB_ADDRESS_MAPPING_REL and link.href:
mappingLinks.append(link.href)
return mappingLinks
FindWebAddressMappings = find_webaddress_mappings
def SiteEntryFromString(xml_string):
return atom.CreateClassFromXMLString(SiteEntry, xml_string)
class SiteFeed(gdata.BatchFeed, gdata.LinkFinder):
"""A Google Sites feed flavor of an Atom Feed."""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchFeed._children.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [SiteEntry])
def __init__(self):
gdata.BatchFeed.__init__(self)
def SiteFeedFromString(xml_string):
return atom.CreateClassFromXMLString(SiteFeed, xml_string)
class AclBase(GDataBase):
_namespace = GACL_NAMESPACE
class AclRole(AclBase):
"""Describes the role of an entry in an access control list."""
_tag = 'role'
_children = AclBase._children.copy()
_attributes = AclBase._attributes.copy()
_attributes['value'] = 'value'
def __init__(self, value=None):
AclBase.__init__(self)
self.value = value
class AclAdditionalRole(AclBase):
"""Describes an additionalRole element."""
_tag = 'additionalRole'
_children = AclBase._children.copy()
_attributes = AclBase._attributes.copy()
_attributes['value'] = 'value'
def __init__(self, value=None):
AclBase.__init__(self)
self.value = value
class AclScope(AclBase):
"""Describes the scope of an entry in an access control list."""
_tag = 'scope'
_children = AclBase._children.copy()
_attributes = AclBase._attributes.copy()
_attributes['type'] = 'type'
_attributes['value'] = 'value'
def __init__(self, stype=None, value=None):
AclBase.__init__(self)
self.type = stype
self.value = value
class AclWithKey(AclBase):
"""Describes a key that can be used to access a document."""
_tag = 'withKey'
_children = AclBase._children.copy()
_children['{%s}role' % GACL_NAMESPACE] = ('role', AclRole)
_children['{%s}additionalRole' % GACL_NAMESPACE] = ('additionalRole', AclAdditionalRole)
_attributes = AclBase._attributes.copy()
_attributes['key'] = 'key'
def __init__(self, key=None, role=None, additionalRole=None):
AclBase.__init__(self)
self.key = key
self.role = role
self.additionalRole = additionalRole
class AclEntry(gdata.BatchEntry):
"""Describes an entry in a feed of an access control list (ACL)."""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchEntry._children.copy()
_children['{%s}role' % GACL_NAMESPACE] = ('role', AclRole)
_children['{%s}additionalRole' % GACL_NAMESPACE] = ('additionalRole', AclAdditionalRole)
_children['{%s}scope' % GACL_NAMESPACE] = ('scope', AclScope)
_children['{%s}withKey' % GACL_NAMESPACE] = ('withKey', AclWithKey)
_attributes = gdata.BatchEntry._attributes.copy()
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
def __init__(self, role=None, additionalRole=None, scope=None, withKey=None, etag=None):
gdata.BatchEntry.__init__(self)
self.role = role
self.additionalRole = additionalRole
self.scope = scope
self.withKey = withKey
self.etag = etag
def find_invite_link(self):
for link in self.link:
if link.rel == SITES_INVITE_LINK_REL and link.href:
return link.href
return None
FindInviteLink = find_invite_link
def AclEntryFromString(xml_string):
return atom.CreateClassFromXMLString(AclEntry, xml_string)
class AclFeed(gdata.BatchFeed, gdata.LinkFinder):
"""Describes a feed of an access control list (ACL)."""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchFeed._children.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [AclEntry])
def __init__(self):
gdata.BatchFeed.__init__(self)
def AclFeedFromString(xml_string):
return atom.CreateClassFromXMLString(AclFeed, xml_string)
class ActivityEntry(gdata.BatchEntry):
"""Describes an entry in a feed of site activity (changes)."""
_tag = 'entry'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchEntry._children.copy()
_attributes = gdata.BatchEntry._attributes.copy()
def __init__(self):
gdata.BatchEntry.__init__(self)
def __find_category_scheme(self, scheme):
for category in self.category:
if category.scheme == scheme:
return category
return None
def kind(self):
kind = self.__find_category_scheme(SITES_KIND_SCHEME)
if kind is not None:
return kind.term[len(SITES_NAMESPACE) + 1:]
else:
return None
Kind = kind
def ActivityEntryFromString(xml_string):
return atom.CreateClassFromXMLString(ActivityEntry, xml_string)
class ActivityFeed(gdata.BatchFeed, gdata.LinkFinder):
"""Describes a feed of site activity (changes)."""
_tag = 'feed'
_namespace = atom.ATOM_NAMESPACE
_children = gdata.BatchFeed._children.copy()
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [ActivityEntry])
def __init__(self):
gdata.BatchFeed.__init__(self)
def ActivityFeedFromString(xml_string):
return atom.CreateClassFromXMLString(ActivityFeed, xml_string)

View File

@@ -0,0 +1,246 @@
#!/usr/bin/python
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""SitesService extends the GDataService for Google Sites API calls."""
import gdata.apps
import gdata.apps.service
import gdata.service
# Feed URI templates
CONTENT_FEED_TEMPLATE = '/feeds/content/%s/%s/'
REVISION_FEED_TEMPLATE = '/feeds/revision/%s/%s/'
ACTIVITY_FEED_TEMPLATE = '/feeds/activity/%s/%s/'
ACTIVITY_ENTRY_TEMPLATE = '/feeds/activity/%s/%s/%s'
SITE_FEED_TEMPLATE = '/feeds/site/%s/'
ACL_FEED_TEMPLATE = '/feeds/acl/site/%s/%s'
ACL_ENTRY_TEMPLATE = '/feeds/acl/site/%s/%s/%s'
class SitesService(gdata.service.GDataService):
"""Client extension for the Google Sites API service."""
def __init__(self,
source=None, server='sites.google.com', additional_headers=None,
**kwargs):
"""Constructs a new client for the Sites API.
Args:
site: string (optional) Name (webspace) of the Google Site
domain: string (optional) Domain of the (Google Apps hosted) Site.
If no domain is given, the Site is assumed to be a consumer Google
Site, in which case the value 'site' is used.
source: string (optional) The name of the user's application.
server: string (optional) The name of the server to which a connection
will be opened. Default value: 'sites..google.com'.
**kwargs: The other parameters to pass to gdata.service.GDataService
constructor.
"""
if additional_headers == None:
additional_headers = {}
additional_headers['GData-Version'] = '1.4'
gdata.service.GDataService.__init__(self,
source=source, server=server, additional_headers=additional_headers,
**kwargs)
self.ssl = True
self.port = 443
def make_site_feed_uri(self, domain=None, site=None):
if not domain:
domain = 'site'
if not site:
return SITE_FEED_TEMPLATE % domain
return (SITE_FEED_TEMPLATE % domain) + site
MakeSiteFeedUri = make_site_feed_uri
def get_site_feed(self, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.SiteFeedFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetSiteFeed = get_site_feed
def create_site(self, siteentry=None, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
if uri is None:
uri = self.make_site_feed_uri(domain=domain, site=site)
try:
return self.Post(siteentry, uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.SiteEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
CreateSite = create_site
def get_site(self, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.SiteEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetSite = get_site
def update_site(self, siteentry=None, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
try:
return self.Put(siteentry, uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.SiteEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
UpdateSite = update_site
def make_acl_feed_uri(self, domain=None, site=None):
return ACL_FEED_TEMPLATE % (domain, site)
MakeAclFeedUri = make_acl_feed_uri
def get_acl_feed(self, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_acl_feed_uri(domain=domain, site=site)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.AclFeedFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetAclFeed = get_acl_feed
def make_acl_entry_uri(self, domain=None, site=None, ruleId=None):
return ACL_ENTRY_TEMPLATE % (domain, site, ruleId)
MakeAclEntryUri = make_acl_entry_uri
def create_acl_entry(self, aclentry=None, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_acl_feed_uri(domain=domain, site=site)
try:
return self.Post(aclentry, uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.AclEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
CreateAclEntry = create_acl_entry
def get_acl_entry(self, uri=None, domain=None, site=None, ruleId=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.AclEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetAclEntry = get_acl_entry
def update_acl_entry(self, aclentry=None, uri=None, domain=None, site=None, ruleId=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
try:
return self.Put(aclentry, uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.AclEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
UpdateAclEntry = update_acl_entry
def delete_acl_entry(self, uri=None, domain=None, site=None, ruleId=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
try:
return self.Delete(uri,
url_params=url_params, escape_params=escape_params, extra_headers=extra_headers)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
DeleteAclEntry = delete_acl_entry
def make_activity_feed_uri(self, domain=None, site=None):
return ACTIVITY_FEED_TEMPLATE % (domain, site)
MakeActivityFeedUri = make_activity_feed_uri
def get_activity_feed(self, uri=None, domain=None, site=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_activity_feed_uri(domain=domain, site=site)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.ActivityFeedFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetActivityFeed = get_activity_feed
def make_activity_entry_uri(self, domain=None, site=None, activityId=None):
return ACTIVITY_ENTRY_TEMPLATE % (domain, site, activityId)
MakeActivityEntryUri = make_activity_entry_uri
def get_activity_entry(self, uri=None, domain=None, site=None, activityId=None,
extra_headers=None, url_params=None, escape_params=True):
uri = uri or self.make_activity_entry_uri(domain=domain, site=site, activityId=activityId)
try:
return self.Get(uri,
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
converter=gdata.apps.sites.ActivityEntryFromString)
except gdata.service.RequestError as e:
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
GetActivityEntry = get_activity_entry
class SitesQuery(gdata.service.Query):
def make_site_feed_uri(self, domain=None, site=None):
if not domain:
domain = 'site'
if not site:
return SITE_FEED_TEMPLATE % domain
return (SITE_FEED_TEMPLATE % domain) + site
def __init__(self, feed=None, domain=None, site=None, params=None):
self.feed = feed or self.make_site_feed_uri(domain=domain, site=site)
gdata.service.Query.__init__(self, feed=self.feed, params=params)

1714
src/gam/gdata/service.py Normal file

File diff suppressed because it is too large Load Diff

247
src/gam/gdata/urlfetch.py Normal file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/python
#
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides HTTP functions for gdata.service to use on Google App Engine
AppEngineHttpClient: Provides an HTTP request method which uses App Engine's
urlfetch API. Set the http_client member of a GDataService object to an
instance of an AppEngineHttpClient to allow the gdata library to run on
Google App Engine.
run_on_appengine: Function which will modify an existing GDataService object
to allow it to run on App Engine. It works by creating a new instance of
the AppEngineHttpClient and replacing the GDataService object's
http_client.
HttpRequest: Function that wraps google.appengine.api.urlfetch.Fetch in a
common interface which is used by gdata.service.GDataService. In other
words, this module can be used as the gdata service request handler so
that all HTTP requests will be performed by the hosting Google App Engine
server.
"""
__author__ = 'api.jscudder (Jeff Scudder)'
import io
import atom.service
import atom.http_interface
from google.appengine.api import urlfetch
def run_on_appengine(gdata_service):
"""Modifies a GDataService object to allow it to run on App Engine.
Args:
gdata_service: An instance of AtomService, GDataService, or any
of their subclasses which has an http_client member.
"""
gdata_service.http_client = AppEngineHttpClient()
class AppEngineHttpClient(atom.http_interface.GenericHttpClient):
def __init__(self, headers=None):
self.debug = False
self.headers = headers or {}
def request(self, operation, url, data=None, headers=None):
"""Performs an HTTP call to the server, supports GET, POST, PUT, and
DELETE.
Usage example, perform and HTTP GET on http://www.google.com/:
import atom.http
client = atom.http.HttpClient()
http_response = client.request('GET', 'http://www.google.com/')
Args:
operation: str The HTTP operation to be performed. This is usually one
of 'GET', 'POST', 'PUT', or 'DELETE'
data: filestream, list of parts, or other object which can be converted
to a string. Should be set to None when performing a GET or DELETE.
If data is a file-like object which can be read, this method will
read a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be
evaluated and sent.
url: The full URL to which the request should be sent. Can be a string
or atom.url.Url.
headers: dict of strings. HTTP headers which should be sent
in the request.
"""
all_headers = self.headers.copy()
if headers:
all_headers.update(headers)
# Construct the full payload.
# Assume that data is None or a string.
data_str = data
if data:
if isinstance(data, list):
# If data is a list of different objects, convert them all to strings
# and join them together.
converted_parts = [__ConvertDataPart(x) for x in data]
data_str = ''.join(converted_parts)
else:
data_str = __ConvertDataPart(data)
# If the list of headers does not include a Content-Length, attempt to
# calculate it based on the data object.
if data and 'Content-Length' not in all_headers:
all_headers['Content-Length'] = len(data_str)
# Set the content type to the default value if none was set.
if 'Content-Type' not in all_headers:
all_headers['Content-Type'] = 'application/atom+xml'
# Lookup the urlfetch operation which corresponds to the desired HTTP verb.
if operation == 'GET':
method = urlfetch.GET
elif operation == 'POST':
method = urlfetch.POST
elif operation == 'PUT':
method = urlfetch.PUT
elif operation == 'DELETE':
method = urlfetch.DELETE
else:
method = None
return HttpResponse(urlfetch.Fetch(url=str(url), payload=data_str,
method=method, headers=all_headers))
def HttpRequest(service, operation, data, uri, extra_headers=None,
url_params=None, escape_params=True, content_type='application/atom+xml'):
"""Performs an HTTP call to the server, supports GET, POST, PUT, and DELETE.
This function is deprecated, use AppEngineHttpClient.request instead.
To use this module with gdata.service, you can set this module to be the
http_request_handler so that HTTP requests use Google App Engine's urlfetch.
import gdata.service
import gdata.urlfetch
gdata.service.http_request_handler = gdata.urlfetch
Args:
service: atom.AtomService object which contains some of the parameters
needed to make the request. The following members are used to
construct the HTTP call: server (str), additional_headers (dict),
port (int), and ssl (bool).
operation: str The HTTP operation to be performed. This is usually one of
'GET', 'POST', 'PUT', or 'DELETE'
data: filestream, list of parts, or other object which can be
converted to a string.
Should be set to None when performing a GET or PUT.
If data is a file-like object which can be read, this method will read
a chunk of 100K bytes at a time and send them.
If the data is a list of parts to be sent, each part will be evaluated
and sent.
uri: The beginning of the URL to which the request should be sent.
Examples: '/', '/base/feeds/snippets',
'/m8/feeds/contacts/default/base'
extra_headers: dict of strings. HTTP headers which should be sent
in the request. These headers are in addition to those stored in
service.additional_headers.
url_params: dict of strings. Key value pairs to be added to the URL as
URL parameters. For example {'foo':'bar', 'test':'param'} will
become ?foo=bar&test=param.
escape_params: bool default True. If true, the keys and values in
url_params will be URL escaped when the form is constructed
(Special characters converted to %XX form.)
content_type: str The MIME type for the data being sent. Defaults to
'application/atom+xml', this is only used if data is set.
"""
full_uri = atom.service.BuildUri(uri, url_params, escape_params)
(server, port, ssl, partial_uri) = atom.service.ProcessUrl(service, full_uri)
# Construct the full URL for the request.
if ssl:
full_url = 'https://%s%s' % (server, partial_uri)
else:
full_url = 'http://%s%s' % (server, partial_uri)
# Construct the full payload.
# Assume that data is None or a string.
data_str = data
if data:
if isinstance(data, list):
# If data is a list of different objects, convert them all to strings
# and join them together.
converted_parts = [__ConvertDataPart(x) for x in data]
data_str = ''.join(converted_parts)
else:
data_str = __ConvertDataPart(data)
# Construct the dictionary of HTTP headers.
headers = {}
if isinstance(service.additional_headers, dict):
headers = service.additional_headers.copy()
if isinstance(extra_headers, dict):
for header, value in extra_headers.items():
headers[header] = value
# Add the content type header (we don't need to calculate content length,
# since urlfetch.Fetch will calculate for us).
if content_type:
headers['Content-Type'] = content_type
# Lookup the urlfetch operation which corresponds to the desired HTTP verb.
if operation == 'GET':
method = urlfetch.GET
elif operation == 'POST':
method = urlfetch.POST
elif operation == 'PUT':
method = urlfetch.PUT
elif operation == 'DELETE':
method = urlfetch.DELETE
else:
method = None
return HttpResponse(urlfetch.Fetch(url=full_url, payload=data_str,
method=method, headers=headers))
def __ConvertDataPart(data):
if not data or isinstance(data, str):
return data
elif hasattr(data, 'read'):
# data is a file like object, so read it completely.
return data.read()
# The data object was not a file.
# Try to convert to a string and send the data.
return str(data)
class HttpResponse(object):
"""Translates a urlfetch resoinse to look like an hhtplib resoinse.
Used to allow the resoinse from HttpRequest to be usable by gdata.service
methods.
"""
def __init__(self, urlfetch_response):
self.body = io.StringIO(urlfetch_response.content)
self.headers = urlfetch_response.headers
self.status = urlfetch_response.status_code
self.reason = ''
def read(self, length=None):
if not length:
return self.body.read()
else:
return self.body.read(length)
def getheader(self, name):
if name not in self.headers:
return self.headers[name.lower()]
return self.headers[name]

View File

@@ -0,0 +1,27 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Set default logging handler to avoid "No handler found" warnings.
import logging
try: # Python 2.7+
from logging import NullHandler
except ImportError:
class NullHandler(logging.Handler):
def emit(self, record):
pass
logging.getLogger(__name__).addHandler(NullHandler())

View File

@@ -0,0 +1,167 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helpers for authentication using oauth2client or google-auth."""
import httplib2
try:
import google.auth
import google.auth.credentials
HAS_GOOGLE_AUTH = True
except ImportError: # pragma: NO COVER
HAS_GOOGLE_AUTH = False
try:
import google_auth_httplib2
except ImportError: # pragma: NO COVER
google_auth_httplib2 = None
try:
import oauth2client
import oauth2client.client
HAS_OAUTH2CLIENT = True
except ImportError: # pragma: NO COVER
HAS_OAUTH2CLIENT = False
def credentials_from_file(filename, scopes=None, quota_project_id=None):
"""Returns credentials loaded from a file."""
if HAS_GOOGLE_AUTH:
credentials, _ = google.auth.load_credentials_from_file(
filename, scopes=scopes, quota_project_id=quota_project_id
)
return credentials
else:
raise EnvironmentError(
"client_options.credentials_file is only supported in google-auth."
)
def default_credentials(scopes=None, quota_project_id=None):
"""Returns Application Default Credentials."""
if HAS_GOOGLE_AUTH:
credentials, _ = google.auth.default(
scopes=scopes, quota_project_id=quota_project_id
)
return credentials
elif HAS_OAUTH2CLIENT:
if scopes is not None or quota_project_id is not None:
raise EnvironmentError(
"client_options.scopes and client_options.quota_project_id are not supported in oauth2client."
"Please install google-auth."
)
return oauth2client.client.GoogleCredentials.get_application_default()
else:
raise EnvironmentError(
"No authentication library is available. Please install either "
"google-auth or oauth2client."
)
def with_scopes(credentials, scopes):
"""Scopes the credentials if necessary.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to scope.
scopes (Sequence[str]): The list of scopes.
Returns:
Union[google.auth.credentials.Credentials,
oauth2client.client.Credentials]: The scoped credentials.
"""
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
return google.auth.credentials.with_scopes_if_required(credentials, scopes)
else:
try:
if credentials.create_scoped_required():
return credentials.create_scoped(scopes)
else:
return credentials
except AttributeError:
return credentials
def authorized_http(credentials):
"""Returns an http client that is authorized with the given credentials.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to use.
Returns:
Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
authorized http client.
"""
from googleapiclient.http import build_http
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
if google_auth_httplib2 is None:
raise ValueError(
"Credentials from google.auth specified, but "
"google-api-python-client is unable to use these credentials "
"unless google-auth-httplib2 is installed. Please install "
"google-auth-httplib2."
)
return google_auth_httplib2.AuthorizedHttp(credentials, http=build_http())
else:
return credentials.authorize(build_http())
def refresh_credentials(credentials):
# Refresh must use a new http instance, as the one associated with the
# credentials could be a AuthorizedHttp or an oauth2client-decorated
# Http instance which would cause a weird recursive loop of refreshing
# and likely tear a hole in spacetime.
refresh_http = httplib2.Http()
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
request = google_auth_httplib2.Request(refresh_http)
return credentials.refresh(request)
else:
return credentials.refresh(refresh_http)
def apply_credentials(credentials, headers):
# oauth2client and google-auth have the same interface for this.
if not is_valid(credentials):
refresh_credentials(credentials)
return credentials.apply(headers)
def is_valid(credentials):
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
return credentials.valid
else:
return (
credentials.access_token is not None
and not credentials.access_token_expired
)
def get_credentials_from_http(http):
if http is None:
return None
elif hasattr(http.request, "credentials"):
return http.request.credentials
elif hasattr(http, "credentials") and not isinstance(
http.credentials, httplib2.Credentials
):
return http.credentials
else:
return None

View File

@@ -0,0 +1,207 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper functions for commonly used utilities."""
import functools
import inspect
import logging
import urllib
logger = logging.getLogger(__name__)
POSITIONAL_WARNING = "WARNING"
POSITIONAL_EXCEPTION = "EXCEPTION"
POSITIONAL_IGNORE = "IGNORE"
POSITIONAL_SET = frozenset(
[POSITIONAL_WARNING, POSITIONAL_EXCEPTION, POSITIONAL_IGNORE]
)
positional_parameters_enforcement = POSITIONAL_WARNING
_SYM_LINK_MESSAGE = "File: {0}: Is a symbolic link."
_IS_DIR_MESSAGE = "{0}: Is a directory"
_MISSING_FILE_MESSAGE = "Cannot access {0}: No such file or directory"
def positional(max_positional_args):
"""A decorator to declare that only the first N arguments may be positional.
This decorator makes it easy to support Python 3 style keyword-only
parameters. For example, in Python 3 it is possible to write::
def fn(pos1, *, kwonly1=None, kwonly2=None):
...
All named parameters after ``*`` must be a keyword::
fn(10, 'kw1', 'kw2') # Raises exception.
fn(10, kwonly1='kw1') # Ok.
Example
^^^^^^^
To define a function like above, do::
@positional(1)
def fn(pos1, kwonly1=None, kwonly2=None):
...
If no default value is provided to a keyword argument, it becomes a
required keyword argument::
@positional(0)
def fn(required_kw):
...
This must be called with the keyword parameter::
fn() # Raises exception.
fn(10) # Raises exception.
fn(required_kw=10) # Ok.
When defining instance or class methods always remember to account for
``self`` and ``cls``::
class MyClass(object):
@positional(2)
def my_method(self, pos1, kwonly1=None):
...
@classmethod
@positional(2)
def my_method(cls, pos1, kwonly1=None):
...
The positional decorator behavior is controlled by
``_helpers.positional_parameters_enforcement``, which may be set to
``POSITIONAL_EXCEPTION``, ``POSITIONAL_WARNING`` or
``POSITIONAL_IGNORE`` to raise an exception, log a warning, or do
nothing, respectively, if a declaration is violated.
Args:
max_positional_arguments: Maximum number of positional arguments. All
parameters after this index must be
keyword only.
Returns:
A decorator that prevents using arguments after max_positional_args
from being used as positional parameters.
Raises:
TypeError: if a keyword-only argument is provided as a positional
parameter, but only if
_helpers.positional_parameters_enforcement is set to
POSITIONAL_EXCEPTION.
"""
def positional_decorator(wrapped):
@functools.wraps(wrapped)
def positional_wrapper(*args, **kwargs):
if len(args) > max_positional_args:
plural_s = ""
if max_positional_args != 1:
plural_s = "s"
message = (
"{function}() takes at most {args_max} positional "
"argument{plural} ({args_given} given)".format(
function=wrapped.__name__,
args_max=max_positional_args,
args_given=len(args),
plural=plural_s,
)
)
if positional_parameters_enforcement == POSITIONAL_EXCEPTION:
raise TypeError(message)
elif positional_parameters_enforcement == POSITIONAL_WARNING:
logger.warning(message)
return wrapped(*args, **kwargs)
return positional_wrapper
if isinstance(max_positional_args, int):
return positional_decorator
else:
args, _, _, defaults, _, _, _ = inspect.getfullargspec(max_positional_args)
return positional(len(args) - len(defaults))(max_positional_args)
def parse_unique_urlencoded(content):
"""Parses unique key-value parameters from urlencoded content.
Args:
content: string, URL-encoded key-value pairs.
Returns:
dict, The key-value pairs from ``content``.
Raises:
ValueError: if one of the keys is repeated.
"""
urlencoded_params = urllib.parse.parse_qs(content)
params = {}
for key, value in urlencoded_params.items():
if len(value) != 1:
msg = "URL-encoded content contains a repeated value:" "%s -> %s" % (
key,
", ".join(value),
)
raise ValueError(msg)
params[key] = value[0]
return params
def update_query_params(uri, params):
"""Updates a URI with new query parameters.
If a given key from ``params`` is repeated in the ``uri``, then
the URI will be considered invalid and an error will occur.
If the URI is valid, then each value from ``params`` will
replace the corresponding value in the query parameters (if
it exists).
Args:
uri: string, A valid URI, with potential existing query parameters.
params: dict, A dictionary of query parameters.
Returns:
The same URI but with the new query parameters added.
"""
parts = urllib.parse.urlparse(uri)
query_params = parse_unique_urlencoded(parts.query)
query_params.update(params)
new_query = urllib.parse.urlencode(query_params)
new_parts = parts._replace(query=new_query)
return urllib.parse.urlunparse(new_parts)
def _add_query_parameter(url, name, value):
"""Adds a query parameter to a url.
Replaces the current value if it already exists in the URL.
Args:
url: string, url to add the query parameter to.
name: string, query parameter name.
value: string, query parameter value.
Returns:
Updated query parameter. Does not update the url if value is None.
"""
if value is None:
return url
else:
return update_query_params(url, {name: value})

View File

@@ -0,0 +1,315 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Channel notifications support.
Classes and functions to support channel subscriptions and notifications
on those channels.
Notes:
- This code is based on experimental APIs and is subject to change.
- Notification does not do deduplication of notification ids, that's up to
the receiver.
- Storing the Channel between calls is up to the caller.
Example setting up a channel:
# Create a new channel that gets notifications via webhook.
channel = new_webhook_channel("https://example.com/my_web_hook")
# Store the channel, keyed by 'channel.id'. Store it before calling the
# watch method because notifications may start arriving before the watch
# method returns.
...
resp = service.objects().watchAll(
bucket="some_bucket_id", body=channel.body()).execute()
channel.update(resp)
# Store the channel, keyed by 'channel.id'. Store it after being updated
# since the resource_id value will now be correct, and that's needed to
# stop a subscription.
...
An example Webhook implementation using webapp2. Note that webapp2 puts
headers in a case insensitive dictionary, as headers aren't guaranteed to
always be upper case.
id = self.request.headers[X_GOOG_CHANNEL_ID]
# Retrieve the channel by id.
channel = ...
# Parse notification from the headers, including validating the id.
n = notification_from_headers(channel, self.request.headers)
# Do app specific stuff with the notification here.
if n.resource_state == 'sync':
# Code to handle sync state.
elif n.resource_state == 'exists':
# Code to handle the exists state.
elif n.resource_state == 'not_exists':
# Code to handle the not exists state.
Example of unsubscribing.
service.channels().stop(channel.body()).execute()
"""
from __future__ import absolute_import
import datetime
import uuid
from googleapiclient import _helpers as util
from googleapiclient import errors
# The unix time epoch starts at midnight 1970.
EPOCH = datetime.datetime(1970, 1, 1)
# Map the names of the parameters in the JSON channel description to
# the parameter names we use in the Channel class.
CHANNEL_PARAMS = {
"address": "address",
"id": "id",
"expiration": "expiration",
"params": "params",
"resourceId": "resource_id",
"resourceUri": "resource_uri",
"type": "type",
"token": "token",
}
X_GOOG_CHANNEL_ID = "X-GOOG-CHANNEL-ID"
X_GOOG_MESSAGE_NUMBER = "X-GOOG-MESSAGE-NUMBER"
X_GOOG_RESOURCE_STATE = "X-GOOG-RESOURCE-STATE"
X_GOOG_RESOURCE_URI = "X-GOOG-RESOURCE-URI"
X_GOOG_RESOURCE_ID = "X-GOOG-RESOURCE-ID"
def _upper_header_keys(headers):
new_headers = {}
for k, v in headers.items():
new_headers[k.upper()] = v
return new_headers
class Notification(object):
"""A Notification from a Channel.
Notifications are not usually constructed directly, but are returned
from functions like notification_from_headers().
Attributes:
message_number: int, The unique id number of this notification.
state: str, The state of the resource being monitored.
uri: str, The address of the resource being monitored.
resource_id: str, The unique identifier of the version of the resource at
this event.
"""
@util.positional(5)
def __init__(self, message_number, state, resource_uri, resource_id):
"""Notification constructor.
Args:
message_number: int, The unique id number of this notification.
state: str, The state of the resource being monitored. Can be one
of "exists", "not_exists", or "sync".
resource_uri: str, The address of the resource being monitored.
resource_id: str, The identifier of the watched resource.
"""
self.message_number = message_number
self.state = state
self.resource_uri = resource_uri
self.resource_id = resource_id
class Channel(object):
"""A Channel for notifications.
Usually not constructed directly, instead it is returned from helper
functions like new_webhook_channel().
Attributes:
type: str, The type of delivery mechanism used by this channel. For
example, 'web_hook'.
id: str, A UUID for the channel.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each event delivered
over this channel.
address: str, The address of the receiving entity where events are
delivered. Specific to the channel type.
expiration: int, The time, in milliseconds from the epoch, when this
channel will expire.
params: dict, A dictionary of string to string, with additional parameters
controlling delivery channel behavior.
resource_id: str, An opaque id that identifies the resource that is
being watched. Stable across different API versions.
resource_uri: str, The canonicalized ID of the watched resource.
"""
@util.positional(5)
def __init__(
self,
type,
id,
token,
address,
expiration=None,
params=None,
resource_id="",
resource_uri="",
):
"""Create a new Channel.
In user code, this Channel constructor will not typically be called
manually since there are functions for creating channels for each specific
type with a more customized set of arguments to pass.
Args:
type: str, The type of delivery mechanism used by this channel. For
example, 'web_hook'.
id: str, A UUID for the channel.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each event delivered
over this channel.
address: str, The address of the receiving entity where events are
delivered. Specific to the channel type.
expiration: int, The time, in milliseconds from the epoch, when this
channel will expire.
params: dict, A dictionary of string to string, with additional parameters
controlling delivery channel behavior.
resource_id: str, An opaque id that identifies the resource that is
being watched. Stable across different API versions.
resource_uri: str, The canonicalized ID of the watched resource.
"""
self.type = type
self.id = id
self.token = token
self.address = address
self.expiration = expiration
self.params = params
self.resource_id = resource_id
self.resource_uri = resource_uri
def body(self):
"""Build a body from the Channel.
Constructs a dictionary that's appropriate for passing into watch()
methods as the value of body argument.
Returns:
A dictionary representation of the channel.
"""
result = {
"id": self.id,
"token": self.token,
"type": self.type,
"address": self.address,
}
if self.params:
result["params"] = self.params
if self.resource_id:
result["resourceId"] = self.resource_id
if self.resource_uri:
result["resourceUri"] = self.resource_uri
if self.expiration:
result["expiration"] = self.expiration
return result
def update(self, resp):
"""Update a channel with information from the response of watch().
When a request is sent to watch() a resource, the response returned
from the watch() request is a dictionary with updated channel information,
such as the resource_id, which is needed when stopping a subscription.
Args:
resp: dict, The response from a watch() method.
"""
for json_name, param_name in CHANNEL_PARAMS.items():
value = resp.get(json_name)
if value is not None:
setattr(self, param_name, value)
def notification_from_headers(channel, headers):
"""Parse a notification from the webhook request headers, validate
the notification, and return a Notification object.
Args:
channel: Channel, The channel that the notification is associated with.
headers: dict, A dictionary like object that contains the request headers
from the webhook HTTP request.
Returns:
A Notification object.
Raises:
errors.InvalidNotificationError if the notification is invalid.
ValueError if the X-GOOG-MESSAGE-NUMBER can't be converted to an int.
"""
headers = _upper_header_keys(headers)
channel_id = headers[X_GOOG_CHANNEL_ID]
if channel.id != channel_id:
raise errors.InvalidNotificationError(
"Channel id mismatch: %s != %s" % (channel.id, channel_id)
)
else:
message_number = int(headers[X_GOOG_MESSAGE_NUMBER])
state = headers[X_GOOG_RESOURCE_STATE]
resource_uri = headers[X_GOOG_RESOURCE_URI]
resource_id = headers[X_GOOG_RESOURCE_ID]
return Notification(message_number, state, resource_uri, resource_id)
@util.positional(2)
def new_webhook_channel(url, token=None, expiration=None, params=None):
"""Create a new webhook Channel.
Args:
url: str, URL to post notifications to.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each notification delivered
over this channel.
expiration: datetime.datetime, A time in the future when the channel
should expire. Can also be None if the subscription should use the
default expiration. Note that different services may have different
limits on how long a subscription lasts. Check the response from the
watch() method to see the value the service has set for an expiration
time.
params: dict, Extra parameters to pass on channel creation. Currently
not used for webhook channels.
"""
expiration_ms = 0
if expiration:
delta = expiration - EPOCH
expiration_ms = (
delta.microseconds / 1000 + (delta.seconds + delta.days * 24 * 3600) * 1000
)
if expiration_ms < 0:
expiration_ms = 0
return Channel(
"web_hook",
str(uuid.uuid4()),
token,
url,
expiration=expiration_ms,
params=params,
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Caching utility for the discovery document."""
from __future__ import absolute_import
import logging
import os
LOGGER = logging.getLogger(__name__)
DISCOVERY_DOC_MAX_AGE = 60 * 60 * 24 # 1 day
DISCOVERY_DOC_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "documents"
)
def autodetect():
"""Detects an appropriate cache module and returns it.
Returns:
googleapiclient.discovery_cache.base.Cache, a cache object which
is auto detected, or None if no cache object is available.
"""
if "GAE_ENV" in os.environ:
try:
from . import appengine_memcache
return appengine_memcache.cache
except Exception:
pass
try:
from . import file_cache
return file_cache.cache
except Exception:
LOGGER.info(
"file_cache is only supported with oauth2client<4.0.0", exc_info=False
)
return None
def get_static_doc(serviceName, version):
"""Retrieves the discovery document from the directory defined in
DISCOVERY_DOC_DIR corresponding to the serviceName and version provided.
Args:
serviceName: string, name of the service.
version: string, the version of the service.
Returns:
A string containing the contents of the JSON discovery document,
otherwise None if the JSON discovery document was not found.
"""
content = None
doc_name = "{}.{}.json".format(serviceName, version)
try:
with open(os.path.join(DISCOVERY_DOC_DIR, doc_name), "r") as f:
content = f.read()
except FileNotFoundError:
# File does not exist. Nothing to do here.
pass
return content

View File

@@ -0,0 +1,55 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""App Engine memcache based cache for the discovery document."""
import logging
# This is only an optional dependency because we only import this
# module when google.appengine.api.memcache is available.
from google.appengine.api import memcache
from . import base
from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
LOGGER = logging.getLogger(__name__)
NAMESPACE = "google-api-client"
class Cache(base.Cache):
"""A cache with app engine memcache API."""
def __init__(self, max_age):
"""Constructor.
Args:
max_age: Cache expiration in seconds.
"""
self._max_age = max_age
def get(self, url):
try:
return memcache.get(url, namespace=NAMESPACE)
except Exception as e:
LOGGER.warning(e, exc_info=True)
def set(self, url, content):
try:
memcache.set(url, content, time=int(self._max_age), namespace=NAMESPACE)
except Exception as e:
LOGGER.warning(e, exc_info=True)
cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)

View File

@@ -0,0 +1,46 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""An abstract class for caching the discovery document."""
import abc
class Cache(object):
"""A base abstract cache class."""
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get(self, url):
"""Gets the content from the memcache with a given key.
Args:
url: string, the key for the cache.
Returns:
object, the value in the cache for the given key, or None if the key is
not in the cache.
"""
raise NotImplementedError()
@abc.abstractmethod
def set(self, url, content):
"""Sets the given key and content in the cache.
Args:
url: string, the key for the cache.
content: string, the discovery document.
"""
raise NotImplementedError()

View File

@@ -0,0 +1,145 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""File based cache for the discovery document.
The cache is stored in a single file so that multiple processes can
share the same cache. It locks the file whenever accessing to the
file. When the cache content is corrupted, it will be initialized with
an empty cache.
"""
from __future__ import division
import datetime
import json
import logging
import os
import tempfile
try:
from oauth2client.contrib.locked_file import LockedFile
except ImportError:
# oauth2client < 2.0.0
try:
from oauth2client.locked_file import LockedFile
except ImportError:
# oauth2client > 4.0.0 or google-auth
raise ImportError(
"file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth"
)
from . import base
from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
LOGGER = logging.getLogger(__name__)
FILENAME = "google-api-python-client-discovery-doc.cache"
EPOCH = datetime.datetime(1970, 1, 1)
def _to_timestamp(date):
try:
return (date - EPOCH).total_seconds()
except AttributeError:
# The following is the equivalent of total_seconds() in Python2.6.
# See also: https://docs.python.org/2/library/datetime.html
delta = date - EPOCH
return (
delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10**6
) / 10**6
def _read_or_initialize_cache(f):
f.file_handle().seek(0)
try:
cache = json.load(f.file_handle())
except Exception:
# This means it opens the file for the first time, or the cache is
# corrupted, so initializing the file with an empty dict.
cache = {}
f.file_handle().truncate(0)
f.file_handle().seek(0)
json.dump(cache, f.file_handle())
return cache
class Cache(base.Cache):
"""A file based cache for the discovery documents."""
def __init__(self, max_age):
"""Constructor.
Args:
max_age: Cache expiration in seconds.
"""
self._max_age = max_age
self._file = os.path.join(tempfile.gettempdir(), FILENAME)
f = LockedFile(self._file, "a+", "r")
try:
f.open_and_lock()
if f.is_locked():
_read_or_initialize_cache(f)
# If we can not obtain the lock, other process or thread must
# have initialized the file.
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
def get(self, url):
f = LockedFile(self._file, "r+", "r")
try:
f.open_and_lock()
if f.is_locked():
cache = _read_or_initialize_cache(f)
if url in cache:
content, t = cache.get(url, (None, 0))
if _to_timestamp(datetime.datetime.now()) < t + self._max_age:
return content
return None
else:
LOGGER.debug("Could not obtain a lock for the cache file.")
return None
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
def set(self, url, content):
f = LockedFile(self._file, "r+", "r")
try:
f.open_and_lock()
if f.is_locked():
cache = _read_or_initialize_cache(f)
cache[url] = (content, _to_timestamp(datetime.datetime.now()))
# Remove stale cache.
for k, (_, timestamp) in list(cache.items()):
if (
_to_timestamp(datetime.datetime.now())
>= timestamp + self._max_age
):
del cache[k]
f.file_handle().truncate(0)
f.file_handle().seek(0)
json.dump(cache, f.file_handle())
else:
LOGGER.debug("Could not obtain a lock for the cache file.")
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)

View File

@@ -0,0 +1,197 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Errors for the library.
All exceptions defined by the library
should be defined in this file.
"""
from __future__ import absolute_import
__author__ = "jcgregorio@google.com (Joe Gregorio)"
import json
from googleapiclient import _helpers as util
class Error(Exception):
"""Base error for this module."""
pass
class HttpError(Error):
"""HTTP data was invalid or unexpected."""
@util.positional(3)
def __init__(self, resp, content, uri=None):
self.resp = resp
if not isinstance(content, bytes):
raise TypeError("HTTP content should be bytes")
self.content = content
self.uri = uri
self.error_details = ""
self.reason = self._get_reason()
@property
def status_code(self):
"""Return the HTTP status code from the response content."""
return self.resp.status
def _get_reason(self):
"""Calculate the reason for the error from the response content."""
reason = self.resp.reason
try:
try:
data = json.loads(self.content.decode("utf-8"))
except json.JSONDecodeError:
# In case it is not json
data = self.content.decode("utf-8")
if isinstance(data, dict):
reason = data["error"]["message"]
error_detail_keyword = next(
(
kw
for kw in ["detail", "details", "errors", "message"]
if kw in data["error"]
),
"",
)
if error_detail_keyword:
self.error_details = data["error"][error_detail_keyword]
elif isinstance(data, list) and len(data) > 0:
first_error = data[0]
reason = first_error["error"]["message"]
if "details" in first_error["error"]:
self.error_details = first_error["error"]["details"]
else:
self.error_details = data
except (ValueError, KeyError, TypeError):
pass
if reason is None:
reason = ""
return reason.strip()
def __repr__(self):
if self.error_details:
return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % (
self.resp.status,
self.uri,
self.reason,
self.error_details,
)
elif self.uri:
return '<HttpError %s when requesting %s returned "%s">' % (
self.resp.status,
self.uri,
self.reason,
)
else:
return '<HttpError %s "%s">' % (self.resp.status, self.reason)
__str__ = __repr__
class InvalidJsonError(Error):
"""The JSON returned could not be parsed."""
pass
class UnknownFileType(Error):
"""File type unknown or unexpected."""
pass
class UnknownLinkType(Error):
"""Link type unknown or unexpected."""
pass
class UnknownApiNameOrVersion(Error):
"""No API with that name and version exists."""
pass
class UnacceptableMimeTypeError(Error):
"""That is an unacceptable mimetype for this operation."""
pass
class MediaUploadSizeError(Error):
"""Media is larger than the method can accept."""
pass
class ResumableUploadError(HttpError):
"""Error occurred during resumable upload."""
pass
class InvalidChunkSizeError(Error):
"""The given chunksize is not valid."""
pass
class InvalidNotificationError(Error):
"""The channel Notification is invalid."""
pass
class BatchError(HttpError):
"""Error occurred during batch operations."""
@util.positional(2)
def __init__(self, reason, resp=None, content=None):
self.resp = resp
self.content = content
self.reason = reason
def __repr__(self):
if getattr(self.resp, "status", None) is None:
return '<BatchError "%s">' % (self.reason)
else:
return '<BatchError %s "%s">' % (self.resp.status, self.reason)
__str__ = __repr__
class UnexpectedMethodError(Error):
"""Exception raised by RequestMockBuilder on unexpected calls."""
@util.positional(1)
def __init__(self, methodId=None):
"""Constructor for an UnexpectedMethodError."""
super(UnexpectedMethodError, self).__init__(
"Received unexpected call %s" % methodId
)
class UnexpectedBodyError(Error):
"""Exception raised by RequestMockBuilder on unexpected bodies."""
def __init__(self, expected, provided):
"""Constructor for an UnexpectedMethodError."""
super(UnexpectedBodyError, self).__init__(
"Expected: [%s] - Provided: [%s]" % (expected, provided)
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
# Copyright 2014 Joe Gregorio
#
# Licensed under the MIT License
"""MIME-Type Parser
This module provides basic functions for handling mime-types. It can handle
matching mime-types against a list of media-ranges. See section 14.1 of the
HTTP specification [RFC 2616] for a complete explanation.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
Contents:
- parse_mime_type(): Parses a mime-type into its component parts.
- parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q'
quality parameter.
- quality(): Determines the quality ('q') of a mime-type when
compared against a list of media-ranges.
- quality_parsed(): Just like quality() except the second parameter must be
pre-parsed.
- best_match(): Choose the mime-type with the highest quality ('q')
from a list of candidates.
"""
from __future__ import absolute_import
from functools import reduce
__version__ = "0.1.3"
__author__ = "Joe Gregorio"
__email__ = "joe@bitworking.org"
__license__ = "MIT License"
__credits__ = ""
def parse_mime_type(mime_type):
"""Parses a mime-type into its component parts.
Carves up a mime-type and returns a tuple of the (type, subtype, params)
where 'params' is a dictionary of all the parameters for the media range.
For example, the media range 'application/xhtml;q=0.5' would get parsed
into:
('application', 'xhtml', {'q', '0.5'})
"""
parts = mime_type.split(";")
params = dict(
[tuple([s.strip() for s in param.split("=", 1)]) for param in parts[1:]]
)
full_type = parts[0].strip()
# Java URLConnection class sends an Accept header that includes a
# single '*'. Turn it into a legal wildcard.
if full_type == "*":
full_type = "*/*"
(type, subtype) = full_type.split("/")
return (type.strip(), subtype.strip(), params)
def parse_media_range(range):
"""Parse a media-range into its component parts.
Carves up a media range and returns a tuple of the (type, subtype,
params) where 'params' is a dictionary of all the parameters for the media
range. For example, the media range 'application/*;q=0.5' would get parsed
into:
('application', '*', {'q', '0.5'})
In addition this function also guarantees that there is a value for 'q'
in the params dictionary, filling it in with a proper default if
necessary.
"""
(type, subtype, params) = parse_mime_type(range)
if (
"q" not in params
or not params["q"]
or not float(params["q"])
or float(params["q"]) > 1
or float(params["q"]) < 0
):
params["q"] = "1"
return (type, subtype, params)
def fitness_and_quality_parsed(mime_type, parsed_ranges):
"""Find the best match for a mime-type amongst parsed media-ranges.
Find the best match for a given mime-type against a list of media_ranges
that have already been parsed by parse_media_range(). Returns a tuple of
the fitness value and the value of the 'q' quality parameter of the best
match, or (-1, 0) if no match was found. Just as for quality_parsed(),
'parsed_ranges' must be a list of parsed media ranges.
"""
best_fitness = -1
best_fit_q = 0
(target_type, target_subtype, target_params) = parse_media_range(mime_type)
for (type, subtype, params) in parsed_ranges:
type_match = type == target_type or type == "*" or target_type == "*"
subtype_match = (
subtype == target_subtype or subtype == "*" or target_subtype == "*"
)
if type_match and subtype_match:
param_matches = reduce(
lambda x, y: x + y,
[
1
for (key, value) in target_params.items()
if key != "q" and key in params and value == params[key]
],
0,
)
fitness = (type == target_type) and 100 or 0
fitness += (subtype == target_subtype) and 10 or 0
fitness += param_matches
if fitness > best_fitness:
best_fitness = fitness
best_fit_q = params["q"]
return best_fitness, float(best_fit_q)
def quality_parsed(mime_type, parsed_ranges):
"""Find the best match for a mime-type amongst parsed media-ranges.
Find the best match for a given mime-type against a list of media_ranges
that have already been parsed by parse_media_range(). Returns the 'q'
quality parameter of the best match, 0 if no match was found. This function
bahaves the same as quality() except that 'parsed_ranges' must be a list of
parsed media ranges.
"""
return fitness_and_quality_parsed(mime_type, parsed_ranges)[1]
def quality(mime_type, ranges):
"""Return the quality ('q') of a mime-type against a list of media-ranges.
Returns the quality 'q' of a mime-type when compared against the
media-ranges in ranges. For example:
>>> quality('text/html','text/*;q=0.3, text/html;q=0.7,
text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5')
0.7
"""
parsed_ranges = [parse_media_range(r) for r in ranges.split(",")]
return quality_parsed(mime_type, parsed_ranges)
def best_match(supported, header):
"""Return mime-type with the highest quality ('q') from list of candidates.
Takes a list of supported mime-types and finds the best match for all the
media-ranges listed in header. The value of header must be a string that
conforms to the format of the HTTP Accept: header. The value of 'supported'
is a list of mime-types. The list of supported mime-types should be sorted
in order of increasing desirability, in case of a situation where there is
a tie.
>>> best_match(['application/xbel+xml', 'text/xml'],
'text/*;q=0.5,*/*; q=0.1')
'text/xml'
"""
split_header = _filter_blank(header.split(","))
parsed_header = [parse_media_range(r) for r in split_header]
weighted_matches = []
pos = 0
for mime_type in supported:
weighted_matches.append(
(fitness_and_quality_parsed(mime_type, parsed_header), pos, mime_type)
)
pos += 1
weighted_matches.sort()
return weighted_matches[-1][0][1] and weighted_matches[-1][2] or ""
def _filter_blank(i):
for s in i:
if s.strip():
yield s

View File

@@ -0,0 +1,429 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Model objects for requests and responses.
Each API may support one or more serializations, such
as JSON, Atom, etc. The model classes are responsible
for converting between the wire format and the Python
object representation.
"""
from __future__ import absolute_import
__author__ = "jcgregorio@google.com (Joe Gregorio)"
import json
import logging
import platform
import urllib
import warnings
from googleapiclient import version as googleapiclient_version
from googleapiclient.errors import HttpError
try:
from google.api_core.version_header import API_VERSION_METADATA_KEY
HAS_API_VERSION = True
except ImportError:
HAS_API_VERSION = False
_LIBRARY_VERSION = googleapiclient_version.__version__
_PY_VERSION = platform.python_version()
LOGGER = logging.getLogger(__name__)
dump_request_response = False
def _abstract():
raise NotImplementedError("You need to override this function")
class Model(object):
"""Model base class.
All Model classes should implement this interface.
The Model serializes and de-serializes between a wire
format such as JSON and a Python object representation.
"""
def request(self, headers, path_params, query_params, body_value):
"""Updates outgoing requests with a serialized body.
Args:
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query_params: dict, parameters that appear in the query
body_value: object, the request body as a Python object, which must be
serializable.
Returns:
A tuple of (headers, path_params, query, body)
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query: string, query part of the request URI
body: string, the body serialized in the desired wire format.
"""
_abstract()
def response(self, resp, content):
"""Convert the response wire format into a Python object.
Args:
resp: httplib2.Response, the HTTP response headers and status
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
Raises:
googleapiclient.errors.HttpError if a non 2xx response is received.
"""
_abstract()
class BaseModel(Model):
"""Base model class.
Subclasses should provide implementations for the "serialize" and
"deserialize" methods, as well as values for the following class attributes.
Attributes:
accept: The value to use for the HTTP Accept header.
content_type: The value to use for the HTTP Content-type header.
no_content_response: The value to return when deserializing a 204 "No
Content" response.
alt_param: The value to supply as the "alt" query parameter for requests.
"""
accept = None
content_type = None
no_content_response = None
alt_param = None
def _log_request(self, headers, path_params, query, body):
"""Logs debugging information about the request if requested."""
if dump_request_response:
LOGGER.info("--request-start--")
LOGGER.info("-headers-start-")
for h, v in headers.items():
LOGGER.info("%s: %s", h, v)
LOGGER.info("-headers-end-")
LOGGER.info("-path-parameters-start-")
for h, v in path_params.items():
LOGGER.info("%s: %s", h, v)
LOGGER.info("-path-parameters-end-")
LOGGER.info("body: %s", body)
LOGGER.info("query: %s", query)
LOGGER.info("--request-end--")
def request(self, headers, path_params, query_params, body_value, api_version=None):
"""Updates outgoing requests with a serialized body.
Args:
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query_params: dict, parameters that appear in the query
body_value: object, the request body as a Python object, which must be
serializable by json.
api_version: str, The precise API version represented by this request,
which will result in an API Version header being sent along with the
HTTP request.
Returns:
A tuple of (headers, path_params, query, body)
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query: string, query part of the request URI
body: string, the body serialized as JSON
"""
query = self._build_query(query_params)
headers["accept"] = self.accept
headers["accept-encoding"] = "gzip, deflate"
if "user-agent" in headers:
headers["user-agent"] += " "
else:
headers["user-agent"] = ""
headers["user-agent"] += "(gzip)"
if "x-goog-api-client" in headers:
headers["x-goog-api-client"] += " "
else:
headers["x-goog-api-client"] = ""
headers["x-goog-api-client"] += "gdcl/%s gl-python/%s" % (
_LIBRARY_VERSION,
_PY_VERSION,
)
if api_version and HAS_API_VERSION:
headers[API_VERSION_METADATA_KEY] = api_version
elif api_version:
warnings.warn(
"The `api_version` argument is ignored as a newer version of "
"`google-api-core` is required to use this feature."
"Please upgrade `google-api-core` to 2.19.0 or newer."
)
if body_value is not None:
headers["content-type"] = self.content_type
body_value = self.serialize(body_value)
self._log_request(headers, path_params, query, body_value)
return (headers, path_params, query, body_value)
def _build_query(self, params):
"""Builds a query string.
Args:
params: dict, the query parameters
Returns:
The query parameters properly encoded into an HTTP URI query string.
"""
if self.alt_param is not None:
params.update({"alt": self.alt_param})
astuples = []
for key, value in params.items():
if type(value) == type([]):
for x in value:
x = x.encode("utf-8")
astuples.append((key, x))
else:
if isinstance(value, str) and callable(value.encode):
value = value.encode("utf-8")
astuples.append((key, value))
return "?" + urllib.parse.urlencode(astuples)
def _log_response(self, resp, content):
"""Logs debugging information about the response if requested."""
if dump_request_response:
LOGGER.info("--response-start--")
for h, v in resp.items():
LOGGER.info("%s: %s", h, v)
if content:
LOGGER.info(content)
LOGGER.info("--response-end--")
def response(self, resp, content):
"""Convert the response wire format into a Python object.
Args:
resp: httplib2.Response, the HTTP response headers and status
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
Raises:
googleapiclient.errors.HttpError if a non 2xx response is received.
"""
self._log_response(resp, content)
# Error handling is TBD, for example, do we retry
# for some operation/error combinations?
if resp.status < 300:
if resp.status == 204:
# A 204: No Content response should be treated differently
# to all the other success states
return self.no_content_response
return self.deserialize(content)
else:
LOGGER.debug("Content from bad request was: %r" % content)
raise HttpError(resp, content)
def serialize(self, body_value):
"""Perform the actual Python object serialization.
Args:
body_value: object, the request body as a Python object.
Returns:
string, the body in serialized form.
"""
_abstract()
def deserialize(self, content):
"""Perform the actual deserialization from response string to Python
object.
Args:
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
"""
_abstract()
class JsonModel(BaseModel):
"""Model class for JSON.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request and response bodies.
"""
accept = "application/json"
content_type = "application/json"
alt_param = "json"
def __init__(self, data_wrapper=False):
"""Construct a JsonModel.
Args:
data_wrapper: boolean, wrap requests and responses in a data wrapper
"""
self._data_wrapper = data_wrapper
def serialize(self, body_value):
if (
isinstance(body_value, dict)
and "data" not in body_value
and self._data_wrapper
):
body_value = {"data": body_value}
return json.dumps(body_value)
def deserialize(self, content):
try:
content = content.decode("utf-8")
except AttributeError:
pass
try:
body = json.loads(content)
except json.decoder.JSONDecodeError:
body = content
else:
if self._data_wrapper and "data" in body:
body = body["data"]
return body
@property
def no_content_response(self):
return {}
class RawModel(JsonModel):
"""Model class for requests that don't return JSON.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request, and returns the raw bytes
of the response body.
"""
accept = "*/*"
content_type = "application/json"
alt_param = None
def deserialize(self, content):
return content
@property
def no_content_response(self):
return ""
class MediaModel(JsonModel):
"""Model class for requests that return Media.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request, and returns the raw bytes
of the response body.
"""
accept = "*/*"
content_type = "application/json"
alt_param = "media"
def deserialize(self, content):
return content
@property
def no_content_response(self):
return ""
class ProtocolBufferModel(BaseModel):
"""Model class for protocol buffers.
Serializes and de-serializes the binary protocol buffer sent in the HTTP
request and response bodies.
"""
accept = "application/x-protobuf"
content_type = "application/x-protobuf"
alt_param = "proto"
def __init__(self, protocol_buffer):
"""Constructs a ProtocolBufferModel.
The serialized protocol buffer returned in an HTTP response will be
de-serialized using the given protocol buffer class.
Args:
protocol_buffer: The protocol buffer class used to de-serialize a
response from the API.
"""
self._protocol_buffer = protocol_buffer
def serialize(self, body_value):
return body_value.SerializeToString()
def deserialize(self, content):
return self._protocol_buffer.FromString(content)
@property
def no_content_response(self):
return self._protocol_buffer()
def makepatch(original, modified):
"""Create a patch object.
Some methods support PATCH, an efficient way to send updates to a resource.
This method allows the easy construction of patch bodies by looking at the
differences between a resource before and after it was modified.
Args:
original: object, the original deserialized resource
modified: object, the modified deserialized resource
Returns:
An object that contains only the changes from original to modified, in a
form suitable to pass to a PATCH method.
Example usage:
item = service.activities().get(postid=postid, userid=userid).execute()
original = copy.deepcopy(item)
item['object']['content'] = 'This is updated.'
service.activities.patch(postid=postid, userid=userid,
body=makepatch(original, item)).execute()
"""
patch = {}
for key, original_value in original.items():
modified_value = modified.get(key, None)
if modified_value is None:
# Use None to signal that the element is deleted
patch[key] = None
elif original_value != modified_value:
if type(original_value) == type({}):
# Recursively descend objects
patch[key] = makepatch(original_value, modified_value)
else:
# In the case of simple types or arrays we just replace
patch[key] = modified_value
else:
# Don't add anything to patch if there's no change
pass
for key in modified:
if key not in original:
patch[key] = modified[key]
return patch

View File

@@ -0,0 +1,317 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Schema processing for discovery based APIs
Schemas holds an APIs discovery schemas. It can return those schema as
deserialized JSON objects, or pretty print them as prototype objects that
conform to the schema.
For example, given the schema:
schema = \"\"\"{
"Foo": {
"type": "object",
"properties": {
"etag": {
"type": "string",
"description": "ETag of the collection."
},
"kind": {
"type": "string",
"description": "Type of the collection ('calendar#acl').",
"default": "calendar#acl"
},
"nextPageToken": {
"type": "string",
"description": "Token used to access the next
page of this result. Omitted if no further results are available."
}
}
}
}\"\"\"
s = Schemas(schema)
print s.prettyPrintByName('Foo')
Produces the following output:
{
"nextPageToken": "A String", # Token used to access the
# next page of this result. Omitted if no further results are available.
"kind": "A String", # Type of the collection ('calendar#acl').
"etag": "A String", # ETag of the collection.
},
The constructor takes a discovery document in which to look up named schema.
"""
from __future__ import absolute_import
# TODO(jcgregorio) support format, enum, minimum, maximum
__author__ = "jcgregorio@google.com (Joe Gregorio)"
from collections import OrderedDict
from googleapiclient import _helpers as util
class Schemas(object):
"""Schemas for an API."""
def __init__(self, discovery):
"""Constructor.
Args:
discovery: object, Deserialized discovery document from which we pull
out the named schema.
"""
self.schemas = discovery.get("schemas", {})
# Cache of pretty printed schemas.
self.pretty = {}
@util.positional(2)
def _prettyPrintByName(self, name, seen=None, dent=0):
"""Get pretty printed object prototype from the schema name.
Args:
name: string, Name of schema in the discovery document.
seen: list of string, Names of schema already seen. Used to handle
recursive definitions.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
if seen is None:
seen = []
if name in seen:
# Do not fall into an infinite loop over recursive definitions.
return "# Object with schema name: %s" % name
seen.append(name)
if name not in self.pretty:
self.pretty[name] = _SchemaToStruct(
self.schemas[name], seen, dent=dent
).to_str(self._prettyPrintByName)
seen.pop()
return self.pretty[name]
def prettyPrintByName(self, name):
"""Get pretty printed object prototype from the schema name.
Args:
name: string, Name of schema in the discovery document.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
# Return with trailing comma and newline removed.
return self._prettyPrintByName(name, seen=[], dent=0)[:-2]
@util.positional(2)
def _prettyPrintSchema(self, schema, seen=None, dent=0):
"""Get pretty printed object prototype of schema.
Args:
schema: object, Parsed JSON schema.
seen: list of string, Names of schema already seen. Used to handle
recursive definitions.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
if seen is None:
seen = []
return _SchemaToStruct(schema, seen, dent=dent).to_str(self._prettyPrintByName)
def prettyPrintSchema(self, schema):
"""Get pretty printed object prototype of schema.
Args:
schema: object, Parsed JSON schema.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
# Return with trailing comma and newline removed.
return self._prettyPrintSchema(schema, dent=0)[:-2]
def get(self, name, default=None):
"""Get deserialized JSON schema from the schema name.
Args:
name: string, Schema name.
default: object, return value if name not found.
"""
return self.schemas.get(name, default)
class _SchemaToStruct(object):
"""Convert schema to a prototype object."""
@util.positional(3)
def __init__(self, schema, seen, dent=0):
"""Constructor.
Args:
schema: object, Parsed JSON schema.
seen: list, List of names of schema already seen while parsing. Used to
handle recursive definitions.
dent: int, Initial indentation depth.
"""
# The result of this parsing kept as list of strings.
self.value = []
# The final value of the parsing.
self.string = None
# The parsed JSON schema.
self.schema = schema
# Indentation level.
self.dent = dent
# Method that when called returns a prototype object for the schema with
# the given name.
self.from_cache = None
# List of names of schema already seen while parsing.
self.seen = seen
def emit(self, text):
"""Add text as a line to the output.
Args:
text: string, Text to output.
"""
self.value.extend([" " * self.dent, text, "\n"])
def emitBegin(self, text):
"""Add text to the output, but with no line terminator.
Args:
text: string, Text to output.
"""
self.value.extend([" " * self.dent, text])
def emitEnd(self, text, comment):
"""Add text and comment to the output with line terminator.
Args:
text: string, Text to output.
comment: string, Python comment.
"""
if comment:
divider = "\n" + " " * (self.dent + 2) + "# "
lines = comment.splitlines()
lines = [x.rstrip() for x in lines]
comment = divider.join(lines)
self.value.extend([text, " # ", comment, "\n"])
else:
self.value.extend([text, "\n"])
def indent(self):
"""Increase indentation level."""
self.dent += 1
def undent(self):
"""Decrease indentation level."""
self.dent -= 1
def _to_str_impl(self, schema):
"""Prototype object based on the schema, in Python code with comments.
Args:
schema: object, Parsed JSON schema file.
Returns:
Prototype object based on the schema, in Python code with comments.
"""
stype = schema.get("type")
if stype == "object":
self.emitEnd("{", schema.get("description", ""))
self.indent()
if "properties" in schema:
properties = schema.get("properties", {})
sorted_properties = OrderedDict(sorted(properties.items()))
for pname, pschema in sorted_properties.items():
self.emitBegin('"%s": ' % pname)
self._to_str_impl(pschema)
elif "additionalProperties" in schema:
self.emitBegin('"a_key": ')
self._to_str_impl(schema["additionalProperties"])
self.undent()
self.emit("},")
elif "$ref" in schema:
schemaName = schema["$ref"]
description = schema.get("description", "")
s = self.from_cache(schemaName, seen=self.seen)
parts = s.splitlines()
self.emitEnd(parts[0], description)
for line in parts[1:]:
self.emit(line.rstrip())
elif stype == "boolean":
value = schema.get("default", "True or False")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "string":
value = schema.get("default", "A String")
self.emitEnd('"%s",' % str(value), schema.get("description", ""))
elif stype == "integer":
value = schema.get("default", "42")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "number":
value = schema.get("default", "3.14")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "null":
self.emitEnd("None,", schema.get("description", ""))
elif stype == "any":
self.emitEnd('"",', schema.get("description", ""))
elif stype == "array":
self.emitEnd("[", schema.get("description"))
self.indent()
self.emitBegin("")
self._to_str_impl(schema["items"])
self.undent()
self.emit("],")
else:
self.emit("Unknown type! %s" % stype)
self.emitEnd("", "")
self.string = "".join(self.value)
return self.string
def to_str(self, from_cache):
"""Prototype object based on the schema, in Python code with comments.
Args:
from_cache: callable(name, seen), Callable that retrieves an object
prototype for a schema with the given name. Seen is a list of schema
names already seen as we recursively descend the schema definition.
Returns:
Prototype object based on the schema, in Python code with comments.
The lines of the code will all be properly indented.
"""
self.from_cache = from_cache
return self._to_str_impl(self.schema)

View File

@@ -0,0 +1,15 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__version__ = "2.156.0"

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2007 - 2015 Michael Twomey
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""ISO 8601 date time string parsing
"""
__all__ = ["parse_date", "ParseError", "UTC"]

160
src/gam/iso8601/iso8601.py Normal file
View File

@@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
"""ISO 8601 date time string parsing
"""
from datetime import (datetime, timedelta, tzinfo)
import time as _time
import re
ISO8601_REGEX = re.compile(r'^(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})(?P<separator>[ T])(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2}):(?P<second>[0-9]{2})([.,](?P<second_fraction>[0-9]+)){0,1}(?P<timezone>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9]{2}):(?P<tz_minute>[0-9]{2}))$')
ISO8601_TZ_REGEX = re.compile(r'^(?P<timezone>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9]{2}):(?P<tz_minute>[0-9]{2}))$')
class ParseError(Exception):
"""Raised when there is a problem parsing a date string"""
# Yoinked from python docs
ZERO = timedelta(0)
class Utc(tzinfo):
"""UTC Timezone
"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
def __repr__(self):
return "<iso8601.Utc>"
UTC = Utc()
class FixedOffset(tzinfo):
"""Fixed offset in hours and minutes from UTC
"""
def __init__(self, offset_hours, offset_minutes, name):
self.__offset_hours = offset_hours # Keep for later __getinitargs__
self.__offset_minutes = offset_minutes # Keep for later __getinitargs__
self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
self.__name = name
def __eq__(self, other):
if isinstance(other, FixedOffset):
return (other.__offset == self.__offset) and (other.__name == self.__name)
if isinstance(other, tzinfo):
return other == self
return False
def __getinitargs__(self):
return (self.__offset_hours, self.__offset_minutes, self.__name)
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
def __repr__(self):
return "<FixedOffset %r %r>" % (self.__name, self.__offset)
# A class capturing the platform's idea of local time.
STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
"""Local time zone
"""
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
def parse_timezone(matches):
"""Parses ISO 8601 time zone specs into tzinfo offsets
"""
if matches["timezone"] == "Z":
return UTC
sign = matches["tz_sign"]
hours = int(matches['tz_hour'])
minutes = int(matches['tz_minute'])
description = "%s%02d:%02d" % (sign, hours, minutes)
if sign == "-":
hours = -hours
minutes = -minutes
return FixedOffset(hours, minutes, description)
def parse_timezone_str(tzstring):
m = ISO8601_TZ_REGEX.match(tzstring)
if not m:
raise ParseError("Unable to parse timezone string %r" % tzstring)
groups = m.groupdict()
return parse_timezone(groups)
def parse_date(datestring):
"""Parses ISO 8601 dates into datetime objects
The timezone is parsed from the date string. However it is quite common to
have dates without a timezone (not strictly correct). In this case the
default timezone specified in default_timezone is used. This is UTC by
default.
:param datestring: The date to parse as a string
:returns: A datetime.datetime instance
:raises: ParseError when there is a problem parsing the date or
constructing the datetime instance.
"""
m = ISO8601_REGEX.match(datestring)
if not m:
raise ParseError("Unable to parse date string %r" % datestring)
groups = m.groupdict()
tz = parse_timezone(groups)
try:
return (datetime(year=int(groups['year']),
month=int(groups['month']),
day=int(groups['day']),
hour=int(groups['hour']),
minute=int(groups['minute']),
second=int(groups['second']),
tzinfo=tz),
tz)
except Exception as e:
raise ParseError(e)

View File

@@ -0,0 +1,141 @@
{
"basePath": "",
"baseUrl": "https://www.googleapis.com/service_accounts/v1",
"canonicalName": "serviceaccountlookup",
"description": "Pseudo-API to lookup public certificates for a service account anonymously",
"discoveryVersion": "v1",
"documentationLink": "https://example.com/",
"fullyEncodeReservedExpansion": true,
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"id": "serviceaccountlookup:v1",
"kind": "discovery#restDescription",
"name": "serviceaccountlookup",
"ownerDomain": "google.com",
"ownerName": "Google",
"packagePath": "admin",
"parameters": {
"$.xgafv": {
"description": "V1 error format.",
"enum": [
"1",
"2"
],
"enumDescriptions": [
"v1 error format",
"v2 error format"
],
"location": "query",
"type": "string"
},
"access_token": {
"description": "OAuth access token.",
"location": "query",
"type": "string"
},
"alt": {
"default": "json",
"description": "Data format for response.",
"enum": [
"json",
"media",
"proto"
],
"enumDescriptions": [
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location": "query",
"type": "string"
},
"callback": {
"description": "JSONP",
"location": "query",
"type": "string"
},
"fields": {
"description": "Selector specifying which fields to include in a partial response.",
"location": "query",
"type": "string"
},
"key": {
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query",
"type": "string"
},
"oauth_token": {
"description": "OAuth 2.0 token for the current user.",
"location": "query",
"type": "string"
},
"prettyPrint": {
"default": "true",
"description": "Returns response with indentations and line breaks.",
"location": "query",
"type": "boolean"
},
"quotaUser": {
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location": "query",
"type": "string"
},
"uploadType": {
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location": "query",
"type": "string"
},
"upload_protocol": {
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\").",
"location": "query",
"type": "string"
}
},
"protocol": "rest",
"resources": {
"serviceaccounts": {
"methods": {
"lookup": {
"description": "Lookup",
"flatPath": "metadata/x509/{account}",
"httpMethod": "GET",
"id": "serviceaccountslookup.lookup",
"parameterOrder": [
"account"
],
"parameters": {
"account": {
"description": "Email or ID of the service account.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "metadata/x509/{account}",
"response": {
"$ref": "Certificates"
}
}
}
}
},
"rootUrl": "https://www.googleapis.com/service_accounts/v1",
"schemas": {
"Certificates": {
"description": "JSON template for certificates.",
"id": "Certificates",
"properties": {
"email": { "description": "Email of the delegate.",
"type": "string"
}
},
"type": "object"
}
},
"servicePath": "",
"title": "Service Account Lookup Pseudo-API",
"version": "v1",
"version_module": true
}

982
src/gam/six.py Normal file
View File

@@ -0,0 +1,982 @@
# Copyright (c) 2010-2020 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Utilities for writing code that runs on Python 2 and 3"""
from __future__ import absolute_import
import functools
import itertools
import operator
import sys
import types
__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.15.0"
# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)
if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes
MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
if sys.platform.startswith("java"):
# Jython always uses 32 bits.
MAXSIZE = int((1 << 31) - 1)
else:
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
class X(object):
def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X
def _add_doc(func, doc):
"""Add documentation to a function."""
func.__doc__ = doc
def _import_module(name):
"""Import module, returning the module after the last dot."""
__import__(name)
return sys.modules[name]
class _LazyDescr(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, tp):
result = self._resolve()
setattr(obj, self.name, result) # Invokes __set__.
try:
# This is a bit ugly, but it avoids running this again by
# removing this descriptor.
delattr(obj.__class__, self.name)
except AttributeError:
pass
return result
class MovedModule(_LazyDescr):
def __init__(self, name, old, new=None):
super(MovedModule, self).__init__(name)
if PY3:
if new is None:
new = name
self.mod = new
else:
self.mod = old
def _resolve(self):
return _import_module(self.mod)
def __getattr__(self, attr):
_module = self._resolve()
value = getattr(_module, attr)
setattr(self, attr, value)
return value
class _LazyModule(types.ModuleType):
def __init__(self, name):
super(_LazyModule, self).__init__(name)
self.__doc__ = self.__class__.__doc__
def __dir__(self):
attrs = ["__doc__", "__name__"]
attrs += [attr.name for attr in self._moved_attributes]
return attrs
# Subclasses should override this
_moved_attributes = []
class MovedAttribute(_LazyDescr):
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
super(MovedAttribute, self).__init__(name)
if PY3:
if new_mod is None:
new_mod = name
self.mod = new_mod
if new_attr is None:
if old_attr is None:
new_attr = name
else:
new_attr = old_attr
self.attr = new_attr
else:
self.mod = old_mod
if old_attr is None:
old_attr = name
self.attr = old_attr
def _resolve(self):
module = _import_module(self.mod)
return getattr(module, self.attr)
class _SixMetaPathImporter(object):
"""
A meta path importer to import six.moves and its submodules.
This class implements a PEP302 finder and loader. It should be compatible
with Python 2.5 and all existing versions of Python3
"""
def __init__(self, six_module_name):
self.name = six_module_name
self.known_modules = {}
def _add_module(self, mod, *fullnames):
for fullname in fullnames:
self.known_modules[self.name + "." + fullname] = mod
def _get_module(self, fullname):
return self.known_modules[self.name + "." + fullname]
def find_module(self, fullname, path=None):
if fullname in self.known_modules:
return self
return None
def __get_module(self, fullname):
try:
return self.known_modules[fullname]
except KeyError:
raise ImportError("This loader does not know module " + fullname)
def load_module(self, fullname):
try:
# in case of a reload
return sys.modules[fullname]
except KeyError:
pass
mod = self.__get_module(fullname)
if isinstance(mod, MovedModule):
mod = mod._resolve()
else:
mod.__loader__ = self
sys.modules[fullname] = mod
return mod
def is_package(self, fullname):
"""
Return true, if the named module is a package.
We need this method to get correct spec objects with
Python 3.4 (see PEP451)
"""
return hasattr(self.__get_module(fullname), "__path__")
def get_code(self, fullname):
"""Return None
Required, if is_package is implemented"""
self.__get_module(fullname) # eventually raises ImportError
return None
get_source = get_code # same as get_code
_importer = _SixMetaPathImporter(__name__)
class _MovedItems(_LazyModule):
"""Lazy loading of moved objects"""
__path__ = [] # mark as package
_moved_attributes = [
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
MovedAttribute("intern", "__builtin__", "sys"),
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
MovedAttribute("getoutput", "commands", "subprocess"),
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
MovedAttribute("reduce", "__builtin__", "functools"),
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
MovedAttribute("StringIO", "StringIO", "io"),
MovedAttribute("UserDict", "UserDict", "collections"),
MovedAttribute("UserList", "UserList", "collections"),
MovedAttribute("UserString", "UserString", "collections"),
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
MovedModule("builtins", "__builtin__"),
MovedModule("configparser", "ConfigParser"),
MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"),
MovedModule("copyreg", "copy_reg"),
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"),
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
MovedModule("http_cookies", "Cookie", "http.cookies"),
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
MovedModule("html_parser", "HTMLParser", "html.parser"),
MovedModule("http_client", "httplib", "http.client"),
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
MovedModule("cPickle", "cPickle", "pickle"),
MovedModule("queue", "Queue"),
MovedModule("reprlib", "repr"),
MovedModule("socketserver", "SocketServer"),
MovedModule("_thread", "thread", "_thread"),
MovedModule("tkinter", "Tkinter"),
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
MovedModule("tkinter_colorchooser", "tkColorChooser",
"tkinter.colorchooser"),
MovedModule("tkinter_commondialog", "tkCommonDialog",
"tkinter.commondialog"),
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
"tkinter.simpledialog"),
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
]
# Add windows specific modules.
if sys.platform == "win32":
_moved_attributes += [
MovedModule("winreg", "_winreg"),
]
for attr in _moved_attributes:
setattr(_MovedItems, attr.name, attr)
if isinstance(attr, MovedModule):
_importer._add_module(attr, "moves." + attr.name)
del attr
_MovedItems._moved_attributes = _moved_attributes
moves = _MovedItems(__name__ + ".moves")
_importer._add_module(moves, "moves")
class Module_six_moves_urllib_parse(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_parse"""
_urllib_parse_moved_attributes = [
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
MovedAttribute("quote", "urllib", "urllib.parse"),
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote", "urllib", "urllib.parse"),
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"),
MovedAttribute("urlencode", "urllib", "urllib.parse"),
MovedAttribute("splitquery", "urllib", "urllib.parse"),
MovedAttribute("splittag", "urllib", "urllib.parse"),
MovedAttribute("splituser", "urllib", "urllib.parse"),
MovedAttribute("splitvalue", "urllib", "urllib.parse"),
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
]
for attr in _urllib_parse_moved_attributes:
setattr(Module_six_moves_urllib_parse, attr.name, attr)
del attr
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
"moves.urllib_parse", "moves.urllib.parse")
class Module_six_moves_urllib_error(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_error"""
_urllib_error_moved_attributes = [
MovedAttribute("URLError", "urllib2", "urllib.error"),
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
]
for attr in _urllib_error_moved_attributes:
setattr(Module_six_moves_urllib_error, attr.name, attr)
del attr
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
"moves.urllib_error", "moves.urllib.error")
class Module_six_moves_urllib_request(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_request"""
_urllib_request_moved_attributes = [
MovedAttribute("urlopen", "urllib2", "urllib.request"),
MovedAttribute("install_opener", "urllib2", "urllib.request"),
MovedAttribute("build_opener", "urllib2", "urllib.request"),
MovedAttribute("pathname2url", "urllib", "urllib.request"),
MovedAttribute("url2pathname", "urllib", "urllib.request"),
MovedAttribute("getproxies", "urllib", "urllib.request"),
MovedAttribute("Request", "urllib2", "urllib.request"),
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
MovedAttribute("URLopener", "urllib", "urllib.request"),
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
]
for attr in _urllib_request_moved_attributes:
setattr(Module_six_moves_urllib_request, attr.name, attr)
del attr
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
"moves.urllib_request", "moves.urllib.request")
class Module_six_moves_urllib_response(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_response"""
_urllib_response_moved_attributes = [
MovedAttribute("addbase", "urllib", "urllib.response"),
MovedAttribute("addclosehook", "urllib", "urllib.response"),
MovedAttribute("addinfo", "urllib", "urllib.response"),
MovedAttribute("addinfourl", "urllib", "urllib.response"),
]
for attr in _urllib_response_moved_attributes:
setattr(Module_six_moves_urllib_response, attr.name, attr)
del attr
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
"moves.urllib_response", "moves.urllib.response")
class Module_six_moves_urllib_robotparser(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
_urllib_robotparser_moved_attributes = [
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
]
for attr in _urllib_robotparser_moved_attributes:
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
del attr
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
"moves.urllib_robotparser", "moves.urllib.robotparser")
class Module_six_moves_urllib(types.ModuleType):
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
__path__ = [] # mark as package
parse = _importer._get_module("moves.urllib_parse")
error = _importer._get_module("moves.urllib_error")
request = _importer._get_module("moves.urllib_request")
response = _importer._get_module("moves.urllib_response")
robotparser = _importer._get_module("moves.urllib_robotparser")
def __dir__(self):
return ['parse', 'error', 'request', 'response', 'robotparser']
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
"moves.urllib")
def add_move(move):
"""Add an item to six.moves."""
setattr(_MovedItems, move.name, move)
def remove_move(name):
"""Remove item from six.moves."""
try:
delattr(_MovedItems, name)
except AttributeError:
try:
del moves.__dict__[name]
except KeyError:
raise AttributeError("no such move, %r" % (name,))
if PY3:
_meth_func = "__func__"
_meth_self = "__self__"
_func_closure = "__closure__"
_func_code = "__code__"
_func_defaults = "__defaults__"
_func_globals = "__globals__"
else:
_meth_func = "im_func"
_meth_self = "im_self"
_func_closure = "func_closure"
_func_code = "func_code"
_func_defaults = "func_defaults"
_func_globals = "func_globals"
try:
advance_iterator = next
except NameError:
def advance_iterator(it):
return it.next()
next = advance_iterator
try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
if PY3:
def get_unbound_function(unbound):
return unbound
create_bound_method = types.MethodType
def create_unbound_method(func, cls):
return func
Iterator = object
else:
def get_unbound_function(unbound):
return unbound.im_func
def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)
def create_unbound_method(func, cls):
return types.MethodType(func, None, cls)
class Iterator(object):
def next(self):
return type(self).__next__(self)
callable = callable
_add_doc(get_unbound_function,
"""Get the function out of a possibly unbound function""")
get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)
if PY3:
def iterkeys(d, **kw):
return iter(d.keys(**kw))
def itervalues(d, **kw):
return iter(d.values(**kw))
def iteritems(d, **kw):
return iter(d.items(**kw))
def iterlists(d, **kw):
return iter(d.lists(**kw))
viewkeys = operator.methodcaller("keys")
viewvalues = operator.methodcaller("values")
viewitems = operator.methodcaller("items")
else:
def iterkeys(d, **kw):
return d.iterkeys(**kw)
def itervalues(d, **kw):
return d.itervalues(**kw)
def iteritems(d, **kw):
return d.iteritems(**kw)
def iterlists(d, **kw):
return d.iterlists(**kw)
viewkeys = operator.methodcaller("viewkeys")
viewvalues = operator.methodcaller("viewvalues")
viewitems = operator.methodcaller("viewitems")
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
_add_doc(iteritems,
"Return an iterator over the (key, value) pairs of a dictionary.")
_add_doc(iterlists,
"Return an iterator over the (key, [values]) pairs of a dictionary.")
if PY3:
def b(s):
return s.encode("latin-1")
def u(s):
return s
unichr = chr
import struct
int2byte = struct.Struct(">B").pack
del struct
byte2int = operator.itemgetter(0)
indexbytes = operator.getitem
iterbytes = iter
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
del io
_assertCountEqual = "assertCountEqual"
if sys.version_info[1] <= 1:
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
_assertNotRegex = "assertNotRegexpMatches"
else:
_assertRaisesRegex = "assertRaisesRegex"
_assertRegex = "assertRegex"
_assertNotRegex = "assertNotRegex"
else:
def b(s):
return s
# Workaround for standalone backslash
def u(s):
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
unichr = unichr
int2byte = chr
def byte2int(bs):
return ord(bs[0])
def indexbytes(buf, i):
return ord(buf[i])
iterbytes = functools.partial(itertools.imap, ord)
import StringIO
StringIO = BytesIO = StringIO.StringIO
_assertCountEqual = "assertItemsEqual"
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
_assertNotRegex = "assertNotRegexpMatches"
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")
def assertCountEqual(self, *args, **kwargs):
return getattr(self, _assertCountEqual)(*args, **kwargs)
def assertRaisesRegex(self, *args, **kwargs):
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
def assertRegex(self, *args, **kwargs):
return getattr(self, _assertRegex)(*args, **kwargs)
def assertNotRegex(self, *args, **kwargs):
return getattr(self, _assertNotRegex)(*args, **kwargs)
if PY3:
exec_ = getattr(moves.builtins, "exec")
def reraise(tp, value, tb=None):
try:
if value is None:
value = tp()
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
finally:
value = None
tb = None
else:
def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")
exec_("""def reraise(tp, value, tb=None):
try:
raise tp, value, tb
finally:
tb = None
""")
if sys.version_info[:2] > (3,):
exec_("""def raise_from(value, from_value):
try:
raise value from from_value
finally:
value = None
""")
else:
def raise_from(value, from_value):
raise value
print_ = getattr(moves.builtins, "print", None)
if print_ is None:
def print_(*args, **kwargs):
"""The new-style print function for Python 2.4 and 2.5."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return
def write(data):
if not isinstance(data, basestring):
data = str(data)
# If the file has an encoding, encode unicode with it.
if (isinstance(fp, file) and
isinstance(data, unicode) and
fp.encoding is not None):
errors = getattr(fp, "errors", None)
if errors is None:
errors = "strict"
data = data.encode(fp.encoding, errors)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
if sys.version_info[:2] < (3, 3):
_print = print_
def print_(*args, **kwargs):
fp = kwargs.get("file", sys.stdout)
flush = kwargs.pop("flush", False)
_print(*args, **kwargs)
if flush and fp is not None:
fp.flush()
_add_doc(reraise, """Reraise an exception.""")
if sys.version_info[0:2] < (3, 4):
# This does exactly the same what the :func:`py3:functools.update_wrapper`
# function does on Python versions after 3.2. It sets the ``__wrapped__``
# attribute on ``wrapper`` object and it doesn't raise an error if any of
# the attributes mentioned in ``assigned`` and ``updated`` are missing on
# ``wrapped`` object.
def _update_wrapper(wrapper, wrapped,
assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES):
for attr in assigned:
try:
value = getattr(wrapped, attr)
except AttributeError:
continue
else:
setattr(wrapper, attr, value)
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
wrapper.__wrapped__ = wrapped
return wrapper
_update_wrapper.__doc__ = functools.update_wrapper.__doc__
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES):
return functools.partial(_update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
wraps.__doc__ = functools.wraps.__doc__
else:
wraps = functools.wraps
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):
def __new__(cls, name, this_bases, d):
if sys.version_info[:2] >= (3, 7):
# This version introduced PEP 560 that requires a bit
# of extra care (we mimic what is done by __build_class__).
resolved_bases = types.resolve_bases(bases)
if resolved_bases is not bases:
d['__orig_bases__'] = bases
else:
resolved_bases = bases
return meta(name, resolved_bases, d)
@classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
def add_metaclass(metaclass):
"""Class decorator for creating a class with a metaclass."""
def wrapper(cls):
orig_vars = cls.__dict__.copy()
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str):
slots = [slots]
for slots_var in slots:
orig_vars.pop(slots_var)
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
if hasattr(cls, '__qualname__'):
orig_vars['__qualname__'] = cls.__qualname__
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper
def ensure_binary(s, encoding='utf-8', errors='strict'):
"""Coerce **s** to six.binary_type.
For Python 2:
- `unicode` -> encoded to `str`
- `str` -> `str`
For Python 3:
- `str` -> encoded to `bytes`
- `bytes` -> `bytes`
"""
if isinstance(s, binary_type):
return s
if isinstance(s, text_type):
return s.encode(encoding, errors)
raise TypeError("not expecting type '%s'" % type(s))
def ensure_str(s, encoding='utf-8', errors='strict'):
"""Coerce *s* to `str`.
For Python 2:
- `unicode` -> encoded to `str`
- `str` -> `str`
For Python 3:
- `str` -> `str`
- `bytes` -> decoded to `str`
"""
# Optimization: Fast return for the common case.
if type(s) is str:
return s
if PY2 and isinstance(s, text_type):
return s.encode(encoding, errors)
elif PY3 and isinstance(s, binary_type):
return s.decode(encoding, errors)
elif not isinstance(s, (text_type, binary_type)):
raise TypeError("not expecting type '%s'" % type(s))
return s
def ensure_text(s, encoding='utf-8', errors='strict'):
"""Coerce *s* to six.text_type.
For Python 2:
- `unicode` -> `unicode`
- `str` -> `unicode`
For Python 3:
- `str` -> `str`
- `bytes` -> decoded to `str`
"""
if isinstance(s, binary_type):
return s.decode(encoding, errors)
elif isinstance(s, text_type):
return s
else:
raise TypeError("not expecting type '%s'" % type(s))
def python_2_unicode_compatible(klass):
"""
A class decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
# Complete the moves implementation.
# This code is at the end of this module to speed up module loading.
# Turn this module into a package.
__path__ = [] # required for PEP 302 and PEP 451
__package__ = __name__ # see PEP 366 @ReservedAssignment
if globals().get("__spec__") is not None:
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
# Remove other six meta path importers, since they cause problems. This can
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
# this for some reason.)
if sys.meta_path:
for i, importer in enumerate(sys.meta_path):
# Here's some real nastiness: Another "instance" of the six module might
# be floating around. Therefore, we can't use isinstance() to check for
# the six meta path importer, since the other six instance will have
# inserted an importer with different class.
if (type(importer).__name__ == "_SixMetaPathImporter" and
importer.name == __name__):
del sys.meta_path[i]
break
del i, importer
# Finally, add the importer to the meta path import hook.
sys.meta_path.append(_importer)

View File

@@ -1,12 +0,0 @@
rm -rf gam
rm -rf build
rm -rf dist
rm -rf gam-$1-linux-$(arch).tar.xz
export LD_LIBRARY_PATH=/usr/local/lib
pyinstaller --clean -F --distpath=gam linux-gam.spec
cp LICENSE gam
cp whatsnew.txt gam
cp GamCommands.txt gam
tar cfJ gam-$1-linux-$(arch).tar.xz gam/

View File

@@ -1,28 +0,0 @@
# -*- mode: python -*-
a = Analysis(['gam.py'],
hiddenimports=[],
hookspath=None,
excludes=['_tkinter'],
runtime_hooks=None)
for d in a.datas:
if 'pyconfig' in d[0]:
a.datas.remove(d)
break
a.datas += [('cloudprint-v2.json', 'cloudprint-v2.json', 'DATA')]
# dynamically determine where httplib2/cacerts.txt lives
import importlib
proot = os.path.dirname(importlib.import_module('httplib2').__file__)
a.datas += [('httplib2/cacerts.txt', os.path.join(proot, 'cacerts.txt'), 'DATA')]
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='gam',
debug=False,
strip=None,
upx=False,
console=True )

Some files were not shown because too many files have changed in this diff Show More