Compare commits

..

18 Commits

Author SHA1 Message Date
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
20 changed files with 356 additions and 639 deletions

View File

@@ -17,7 +17,7 @@ defaults:
working-directory: src
env:
SCRATCH_COUNTER: 2
SCRATCH_COUNTER: 3
OPENSSL_CONFIG_OPTS: no-fips --api=3.0.0
OPENSSL_INSTALL_PATH: ${{ github.workspace }}/bin/ssl
OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl
@@ -36,58 +36,63 @@ jobs:
goal: build
arch: x86_64
openssl_archs: linux-x86_64
- os: [self-hosted, linux, arm64]
- os: ubuntu-24.04
jid: 2
goal: build
arch: x86_64
openssl_archs: linux-x86_64
- os: [self-hosted, linux, arm64]
jid: 3
goal: build
arch: aarch64
openssl_archs: linux-aarch64
- os: ubuntu-22.04
jid: 3
jid: 4
goal: build
arch: x86_64
openssl_archs: linux-x86_64
staticx: yes
- os: [self-hosted, linux, arm64]
jid: 4
jid: 5
goal: build
arch: aarch64
openssl_archs: linux-aarch64
staticx: yes
- os: macos-13
jid: 5
jid: 6
goal: build
arch: x86_64
openssl_archs: darwin64-x86_64
- os: macos-14
jid: 6
jid: 7
goal: build
arch: aarch64
openssl_archs: darwin64-arm64
- os: windows-2022
jid: 7
jid: 8
goal: build
arch: Win64
openssl_archs: VC-WIN64A
- os: ubuntu-24.04
goal: test
python: "3.9"
jid: 8
arch: x86_64
- os: ubuntu-24.04
goal: test
python: "3.10"
jid: 9
arch: x86_64
- os: ubuntu-24.04
goal: test
python: "3.11"
python: "3.10"
jid: 10
arch: x86_64
- os: ubuntu-24.04
goal: test
python: "3.12"
python: "3.11"
jid: 11
arch: x86_64
- os: ubuntu-24.04
goal: test
python: "3.12"
jid: 12
arch: x86_64
steps:
@@ -110,7 +115,7 @@ jobs:
with:
path: |
cache.tar.xz
key: gam-${{ matrix.jid }}-20241008
key: gam-${{ matrix.jid }}-20241014
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -181,7 +186,7 @@ jobs:
run: |
echo "RUNNING: apt update..."
sudo apt-get -qq --yes update
sudo apt-get -qq --yes install swig libpcsclite-dev libxslt1-dev
sudo apt-get -qq --yes install swig libpcsclite-dev libxslt1-dev libsqlite3-dev
- name: MacOS install tools
if: runner.os == 'macOS'
@@ -697,6 +702,7 @@ jobs:
export MSI_FILENAME="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${GAM_ARCHIVE_ARCH}.msi"
# auto-generate a lib.wxs based on the files PyInstaller created for the lib/ directory
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/heat.exe dir "${gampath}/lib" -ke -srd -cg Lib -gg -dr lib -directoryid lib -out lib.wxs
$PYTHON tools/gen-wix-xml-filelist.py lib.wxs
echo "-- begin lib.wxs --"
cat lib.wxs
echo "-- end lib.wxs --"

View File

@@ -1,7 +1,6 @@
# Authorization
- [Introduction](#introduction)
- [Headless computers and Cloud Shells](#headless-computers-and-cloud-shells)
- [Version 5 Update](#version-5-update)
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions)
- [Definitions](#definitions)
@@ -127,25 +126,6 @@ as required by Google for headless computers/cloud shells; this is required as o
* See: https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html
* OAuth out-of-band (oob) flow will be deprecated
## Version 5 Update
GAM version `5.00.00` replaced the deprecated `oauth2client` library with the `google-auth` library.
This change requires a one-time update of the client access file `oauth2.txt`; GAM will continue
to use the old version of `oauth2.txt` until you perform the update. There is a small performance
impact until the update is performed. However, you can't use the updated version of `oauth2.txt`
in prior versions of GAM; if you want to run GAM `5.00.00` and prior versions of GAM,
do not perform the update until you no longer need to run the prior versions of GAM.
If you are running any GAM version `4.85.00` or later, perform the following command
after installing `5.00.00` to perform the update.
```
gam oauth refresh
```
If you are running any GAM version before `4.85.00`, perform the following command
after installing `5.00.00` to perform the update.
```
gam oauth update
```
## API documentation
* https://cloud.google.com/resource-manager/docs/creating-managing-organization#adding_an_organization_administrator
* https://cloud.google.com/service-usage/docs/reference/rest
@@ -213,7 +193,7 @@ perform these steps and then retry the create project command.
## Authorize Service Account Key Uploads
If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxx`,
If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxxxx`,
perform these steps and then you should be able to authorize and use your project.
* Login as an existing super admin at console.cloud.google.com
@@ -293,7 +273,7 @@ You can skip these steps if you know that untrusted third-party apps are allowed
### Default values
* `<AppName>` - "GAM"
* `<ProjectID>` - "gam-project-abc-def-jki" where "abc-def-ghi" are randomly generated
* `<ProjectID>` - "gam-project-a1b2c" where "a1b2c" are randomly generated
* `<ProjectName>` - "GAM Project"
* `<ServiceAccountName>` - `<ProjectID>`
* `<ServiceAccountDisplayName>` - `<ProjectName>`
@@ -382,7 +362,7 @@ gam update project [[admin] <EmailAddress>] [<ProjectIDEntity>]
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `current` - The project referenced in `client_secrets.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -394,7 +374,7 @@ gam delete project [[admin] <EmailAddress>] [<ProjectIDEntity>]
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `current` - The project referenced in `client_secrets.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -414,7 +394,7 @@ gam show projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `current` - The project referenced in `client_secrets.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -432,7 +412,7 @@ gam print projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>] [todrive <To
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `current` - The project referenced in `client_secrets.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -718,7 +698,7 @@ gam create|add svcacct [[admin] <EmailAddress>] [<ProjectIDEntity>]
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `current` - The project referenced in `client_secrets.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -741,7 +721,7 @@ gam delete svcacct [[admin] <EmailAddress>] [<ProjectIDEntity>]
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `current` - The project referenced in `client_secrets.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -762,7 +742,7 @@ gam print svcaccts [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `current` - The project referenced in `client_secrets.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation

View File

@@ -1,4 +1,4 @@
!# CSV Output Filtering
# CSV Output Filtering
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
@@ -11,9 +11,11 @@
- [Column row limiting](#column-row-limiting)
- [Saving filters in gam.cfg](#saving-filters-in-gamcfg)
There are five values in `gam.cfg` that can be used to filter the output from `gam print` commands.
There are seven values in `gam.cfg` that can be used to filter the output from `gam print` commands.
* `csv_output_header_filter` - A list of `<RegularExpressions>` used to select specific column headers to include
* `csv_output_header_drop_filter` - A list of `<RegularExpressions>` used to select specific column headers to exclude
* `csv_output_header_force` - A list of <Strings> used to specify the exact column headers to include
* `csv_output_header_order` - A list of <Strings> used to specify the column header order; any headers in the file but not in the list will appear after the headers in the list.
* `csv_output_row_filter` - A list or JSON dictionary used to include specific rows based on column values
* `csv_output_row_drop_filter` - A list or JSON dictionary used to exclude specific rows based on column values
* `csv_output_row_limit` - A limit on the number of rows written
@@ -334,7 +336,7 @@ gam config csv_output_row_limit 10 auto_batch_min 1 redirect csv ./BigQuotaFiles
```
## Saving filters in gam.cfg
If you define a value for `csv_output_header_filter`, `csv_output_header_drop_filter`, `csv_output_row_filter`, `csv_output_row_drop_filter` or `csv_output_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
If you define a value for `csv_output_header_filter`, `csv_output_header_drop_filter`, `csv_output_header_force`, `csv_output_header_order`, `csv_output_row_filter`, `csv_output_row_drop_filter` or `csv_output_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
it will apply to every `gam print` command which is probably not desirable. You can store them in `gam.cfg` in named sections.
```
[Filter510]

View File

@@ -8,6 +8,7 @@
- [Parameters for Basic Levels](#parameters-for-basic-levels)
- [Create an Access Level](#create-an-access-level)
- [Update an Access Level](#update-an-access-level)
- [Update Access Levels with JSON](#update-access-levels-with-json)
- [Delete an Access Level](#delete-an-access-level)
- [Display all Access Levels](#display-all-access-levels)
- [CAA Region Codes](#caa-region-codes)
@@ -177,6 +178,27 @@ This example adds UK to the allowed regions for CORP_COUNTRIES
gam update caalevel CORP_COUNTRIES basic condition regions US,CA,UK endcondition
```
## Update Access Levels with JSON
Update existing CAA levels via their JSON data; create a CSV file of CAA levels.
```
gam redirect csv ./CAAlevels.csv print caalevels formatjson quotechar "'"
```
Edit the JSON column for the desired CAA level(s) in CAAlevels.csv.
Update the desired CAA level by selecting the row by it's title; repeat for each title to update.
```
gam config csv_input_row_filter "title:text='Example Title'" csv CAAlevels.csv quotechar "'" gam update caalevel "~name" json "~JSON"
```
## Example
Edit CAAlevels.csv and add UK to the allowed regions for CORP_COUNTRIES
```
{"regions": ["US", "CA", "UK"]}
```
Do the update.
```
gam config csv_input_row_filter "title:text='CORP_COUNTRIES'" csv CAAlevels.csv quotechar "'" gam update caalevel "~name" json "~JSON"
```
## Delete an Access Level
Deletes the specified access level.
```

View File

@@ -10,6 +10,57 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.00.24
Updated `gam print|show projects ... showiampolicies 0|1|3` to use non-service account authentication.
### 7.00.23
Updated `gam <UserTypeEntity> create|delete chatmember` to accept external (non-domain) email addresses.
### 7.00.22
Fixed bug in `gam create vaultmatter ... showdetails` that caused a trap.
### 7.00.21
Added `csv_output_header_order` variable to `gam.cfg` that is a list of `<Strings>`
that are used to specify the order of column headers in the CSV file written by a gam print command.
Any headers in the file but not in the list will appear after the headers in the list.
This might be used when the CSV file data is to be processed by another program
that requires that the headers be in a particular order.
### 7.00.20
Fix Windows MSI installer issues on version upgrade. If you are having issues upgrading from a version older than 7.00.20 to this version or newer you may need to do a one time uninstall of GAM7 and then reinstall the new version. No configuration files will be lost during the uninstall / reinstall.
### 7.00.19
Updated `gam update shareddrive <SharedDriveEntity> ou <OrgUnitItem>` to handle the following error
that occurs when an invalid `<SharedDriveEntity>` is specified.
```
ERROR: 400: invalidArgument - Invalid org membership name 0AJ3b2FTPakToUk9PVAxx.~
```
Updated `gam print browsers` to properly format the time field `deviceIdentifiersHistory.records.0.firstRecordTime`.
### 7.00.18
Updated `gam create project` to use a default project name of `gam-project-a1b2c` (`a1b2c` is a random string of 5 characters)
instead of `gam-project-abc-123-xyz` to avoid the following warning:
```
Project: gam-project-abc-123-xyz, Service Account: gam-project-abc-123-xyz@gam-project-abc-123-xyz.iam.gserviceaccount.com, Extracting public certificate
init.py:12382: UserWarning: Attribute's length must be >= 1 and <= 64, but it was 70
init.py:12383: UserWarning: Attribute's length must be >= 1 and <= 64, but it was 70
Project: gam-project-abc-123-xyz, Service Account: gam-project-abc-123-xyz@gam-project-abc-123-xyz.iam.gserviceaccount.com, Done generating private key and public certificate
```
### 7.00.17
Update all user calendar commands to disable falling back to client access if service account
authorization has never been performed.
### 7.00.16
Updated `gam <UserTypeEntity> claim|transfer ownership` to show `Got N Drive Files/Folders that matched query` messages

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.00.16 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.24 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM7 7.00.16 - https://github.com/GAM-team/GAM - pythonsource
GAM7 7.00.24 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -51,6 +51,7 @@ The only `<VariableNames>` recognized in this `<Section>` are:
* `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`

View File

@@ -427,6 +427,15 @@ gam info ou <OrgUnitPath> nousers
gam show teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime
gam print teamdrives query "orgUnitId='03ph8a2z21rexy'" fields id,name,orgunit,createdtime
```
Alternative method; `<OrgUnitPath>` defaults to `/`.
```
gam show oushareddrives
[ou|org|orgunit <OrgUnitPath>]
[formatjson]
gam print oushareddrives [todrive <ToDriveAttribute>*]
[ou|org|orgunit <OrgUnitPath>]
[formatjson [quotechar <Character>]]
```
## Manage Shared Drive access
These commands are used to manage the ACLs on Shared Drives themselves, not the files/folders on the Shared Drives.

View File

@@ -434,6 +434,7 @@ gam <UserTypeEntity> remove chatmember members <ChatMemberList>
```
### Add members to a chat space, asadmin
Creating memberships for users outside the administrator's Google Workspace organization isn't supported using asadmin.
```
gam <UserItem> create chatmember asadmin <ChatSpace>
[type human|bot] [role member|manager]

View File

@@ -811,7 +811,7 @@ User: testuser@domain.com, Drive Files/Folders: 261, Size: 13822521
```
Print file counts for a user.
```
$ gam user testuser@domain,com print filecounts showsize
$ gam user testuser@domain.com print filecounts showsize
Getting all Drive Files/Folders that match query ('me' in owners) for testuser@domain.com
Got 261 Drive Files/Folders that matched query ('me' in owners) for testuser@domain.com...
User,Total,Size,application/octet-stream,application/pdf,application/vnd.google-apps.document,application/vnd.google-apps.drawing,application/vnd.google-apps.drive-sdk.423565144751,application/vnd.google-apps.folder,application/vnd.google-apps.form,application/vnd.google-apps.jam,application/vnd.google-apps.presentation,application/vnd.google-apps.shortcut,application/vnd.google-apps.site,application/vnd.google-apps.spreadsheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.wordprocessingml.template,application/x-gzip,application/zip,image/jpeg,image/vnd.adobe.photoshop,text/csv,text/plain,text/rtf,text/x-sh
@@ -825,6 +825,14 @@ Got 261 Drive Files/Folders that matched query ('me' in owners) for testuser@dom
User,Total,Size,application/octet-stream,application/octet-stream-size,application/pdf,application/pdf-size,application/vnd.google-apps.document,application/vnd.google-apps.document-size,application/vnd.google-apps.drawing,application/vnd.google-apps.drawing-size,application/vnd.google-apps.drive-sdk.423565144751,application/vnd.google-apps.drive-sdk.423565144751-size,application/vnd.google-apps.folder,application/vnd.google-apps.folder-size,application/vnd.google-apps.form,application/vnd.google-apps.form-size,application/vnd.google-apps.jam,application/vnd.google-apps.jam-size,application/vnd.google-apps.presentation,application/vnd.google-apps.presentation-size,application/vnd.google-apps.shortcut,application/vnd.google-apps.shortcut-size,application/vnd.google-apps.site,application/vnd.google-apps.site-size,application/vnd.google-apps.spreadsheet,application/vnd.google-apps.spreadsheet-size,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet-size,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.wordprocessingml.document-size,application/vnd.openxmlformats-officedocument.wordprocessingml.template,application/vnd.openxmlformats-officedocument.wordprocessingml.template-size,application/x-gzip,application/x-gzip-size,application/zip,application/zip-size,image/jpeg,image/jpeg-size,image/vnd.adobe.photoshop,image/vnd.adobe.photoshop-size,text/csv,text/csv-size,text/plain,text/plain-size,text/rtf,text/rtf-size,text/x-sh,text/x-sh-size
testuser@domain.com,261,13822521,8,17,1,9879,98,52858,2,2048,1,0,68,0,3,0,1,1024,1,0,14,0,1,0,24,11264,1,8157,3,34407,1,25906,4,2768,2,765,8,16498,1,13613198,2,397,13,41461,3,1738,1,136
```
Print file counts for a Shared Drive
```
$ gam user testuser@domain.com print filecounts select <SharedDriveID> showsize
Getting all Drive Files/Folders for testuser@domain.com
Got 261 Drive Files/Folders for testuser@domain.com...
User,id,name,Total,Size,Item cap,application/octet-stream,application/pdf,application/vnd.google-apps.document,application/vnd.google-apps.drawing,application/vnd.google-apps.drive-sdk.423565144751,application/vnd.google-apps.folder,application/vnd.google-apps.form,application/vnd.google-apps.jam,application/vnd.google-apps.presentation,application/vnd.google-apps.shortcut,application/vnd.google-apps.site,application/vnd.google-apps.spreadsheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.wordprocessingml.template,application/x-gzip,application/zip,image/jpeg,image/vnd.adobe.photoshop,text/csv,text/plain,text/rtf,text/x-sh
testuser@domain.com,0AMzwfhFBpwLHUkWXYZ,Shared Drive Name,261,13822521,3.45%,8,1,98,2,1,68,3,1,1,14,1,24,1,3,1,4,2,8,1,2,13,3,1
```
Get file count summaries by OU; top level selector is ou, sub level selectors are ou_and_children
```
gam redirect csv ./TopLevelOUs.csv print ous showparent toplevelonly parentselector ou childselector ou_and_children fields orgunitpath

View File

@@ -2,6 +2,7 @@
- [API documentation](#api-documentation)
- [Query documentation](Users-Drive-Query)
- [Python Regular Expressions](Python-Regular-Expressions) Sub function
- [Folders with Limited Access Beta](#folders-with-limited-access-beta)
- [Permission Matches](Permission-Matches)
- [Definitions](#definitions)
- [Create files](#create-files)
@@ -31,6 +32,15 @@
* https://support.google.com/a/users/answer/7338880
* https://developers.google.com/docs/api/reference/rest
## Folders with Limited Access Beta
If you are enrolled in the Beta and want to access the `inheritedpermissionsdisabled` field,
you must turn on Drive API v3 beta.
```
gam config drive_v3_beta true user user@domain.com update drivefile <FolderID> inheritedpermissionsdisabled true
```
## Definitions
* [`<DriveFileEntity>`](Drive-File-Selection)
* [`<UserTypeEntity>`](Collections-of-Users)

View File

@@ -37,7 +37,7 @@
- [Print user domain counts](#print-user-domain-counts)
- [Print domain counts for users in a specific domain and/or selected by a query](#print-domain-counts-for-users-in-a-specific-domain-and-or-selected-by-a-query)
- [Print domain counts for users specified by `<UserTypeEntity>`](#print-domain-counts-for-users-specified-by-usertypeentity)
- [Print user counts by OrgUnit](print-user-counts-by-orgunit)
- [Print user counts by OrgUnit](#print-user-counts-by-orgunit)
- [Print user list](#print-user-list)
- [Display user counts](#display-user-counts)
- [Verify domain membership]($verify-domain-membership)

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAM 7.00.16 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.24 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.00.16 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.24 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAM 7.00.16 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.24 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7
Version Check:
Current: 5.35.08
Latest: 7.00.16
Latest: 7.00.24
echo $?
1
```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.00.16
7.00.24
```
In Linux/MacOS you can do:
```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.00.16 - https://github.com/GAM-team/GAM
GAM 7.00.24 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64

View File

@@ -214,6 +214,12 @@ csv_output_header_force
A list of <Strings> used to specify the exact column headers
for inclusion in the CSV file written by a gam print command
Default: ''
csv_output_header_order
A list of <Strings> used to specify the order of column headers
for inclusion in the CSV file written by a gam print command
Any headers in the file but not in the list will appear after
the headers in the list
Default: ''
csv_output_line_terminator
Allowed values: cr, lf, crlf
Designates character(s) used to terminate the lines of a CSV file.
@@ -305,6 +311,9 @@ drive_max_results
how many should be retrieved in each API call
Default: 1000
Range: 1 - 1000
drive_v3_beta
Enable/disable use of Drive API v3 beta for Limited Folder Access testing
Default: False
drive_v3_native_names
Enable/disable use of Drive API v3 native column names
in all gam print/show commands related to Google Drive

View File

@@ -1,3 +1,56 @@
7.00.24
Updated `gam print|show projects ... showiampolicies 0|1|3` to use non-service account authentication.
7.00.23
Updated `gam <UserTypeEntity> create|delete chatmember` to accept external (non-domain) email addresses.
7.00.22
Fixed bug in `gam create vaultmatter ... showdetails` that caused a trap.
7.00.21
Added `csv_output_header_order` variable to `gam.cfg` that is a list of `<Strings>`
that are used to specify the order of column headers in the CSV file written by a gam print command.
Any headers in the file but not in the list will appear after the headers in the list.
This might be used when the CSV file data is to be processed by another program
that requires that the headers be in a particular order.
7.00.20
Fix Windows MSI installer issues on version upgrade. If you are having issues upgrading from a version older than 7.00.20 to this version or newer you may need to do a one time uninstall of GAM7 and then reinstall the new version.
No configuration files will be lost during the uninstall / reinstall.
7.00.19
Updated `gam update shareddrive <SharedDriveEntity> ou <OrgUnitItem>` to handle the following error
that occurs when an invalid `<SharedDriveEntity>` is specified.
```
ERROR: 400: invalidArgument - Invalid org membership name 0AJ3b2FTPakToUk9PVAxx.~
```
Updated `gam print browsers` to properly format the time field `deviceIdentifiersHistory.records.0.firstRecordTime`.
7.00.18
Updated `gam create project` to use a default project name of `gam-project-a1b2c` (`a1b2c` is a random string of 5 characters)
instead of `gam-project-abc-123-xyz` to avoid the following warning:
```
Project: gam-project-abc-123-xyz, Service Account: gam-project-abc-123-xyz@gam-project-abc-123-xyz.iam.gserviceaccount.com, Extracting public certificate
init.py:12382: UserWarning: Attribute's length must be >= 1 and <= 64, but it was 70
init.py:12383: UserWarning: Attribute's length must be >= 1 and <= 64, but it was 70
Project: gam-project-abc-123-xyz, Service Account: gam-project-abc-123-xyz@gam-project-abc-123-xyz.iam.gserviceaccount.com, Done generating private key and public certificate
```
7.00.17
Update all user calendar commands to disable falling back to client access if service account
authorization has never been performed. Previously, in this circumstance, the admin's calendars
rather than the user's calendars were processed.
7.00.16
Updated `gam <UserTypeEntity> claim|transfer ownership` to show `Got N Drive Files/Folders that matched query` messages

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.00.16'
__version__ = '7.00.24'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -4008,7 +4008,7 @@ def SetGlobalVariables():
GC.Values[itemName] = _getCfgPassword(sectionName, itemName)
elif varType == GC.TYPE_STRING:
GC.Values[itemName] = _getCfgString(sectionName, itemName)
elif varType in {GC.TYPE_STRINGLIST, GC.TYPE_HEADERFORCE}:
elif varType in {GC.TYPE_STRINGLIST, GC.TYPE_HEADERFORCE, GC.TYPE_HEADERORDER}:
GC.Values[itemName] = _getCfgStringList(sectionName, itemName)
elif varType == GC.TYPE_FILE:
GC.Values[itemName] = _getCfgFile(sectionName, itemName)
@@ -4031,6 +4031,7 @@ def SetGlobalVariables():
else:
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER] = _getCfgHeaderFilter(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_FILTER)
GC.Values[GC.CSV_OUTPUT_HEADER_DROP_FILTER] = _getCfgHeaderFilter(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_DROP_FILTER)
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER] = _getCfgStringList(outputFilterSectionName, GC.CSV_OUTPUT_HEADER_ORDER)
GC.Values[GC.CSV_OUTPUT_ROW_FILTER] = _getCfgRowFilter(outputFilterSectionName, GC.CSV_OUTPUT_ROW_FILTER)
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE] = _getCfgChoice(outputFilterSectionName, GC.CSV_OUTPUT_ROW_FILTER_MODE)
GC.Values[GC.CSV_OUTPUT_ROW_DROP_FILTER] = _getCfgRowFilter(outputFilterSectionName, GC.CSV_OUTPUT_ROW_DROP_FILTER)
@@ -4151,7 +4152,7 @@ def SetGlobalVariables():
if GM.Globals[GM.PID] == 0:
for itemName, itemEntry in sorted(iter(GC.VAR_INFO.items())):
varType = itemEntry[GC.VAR_TYPE]
if varType in {GC.TYPE_HEADERFILTER, GC.TYPE_HEADERFORCE, GC.TYPE_ROWFILTER}:
if varType in {GC.TYPE_HEADERFILTER, GC.TYPE_HEADERFORCE, GC.TYPE_HEADERORDER, GC.TYPE_ROWFILTER}:
GM.Globals[GM.PARSER].set(sectionName, itemName, '')
elif (varType == GC.TYPE_INTEGER) and itemName in {GC.CSV_INPUT_ROW_LIMIT, GC.CSV_OUTPUT_ROW_LIMIT}:
GM.Globals[GM.PARSER].set(sectionName, itemName, '0')
@@ -4164,6 +4165,8 @@ def SetGlobalVariables():
GC.Values[GC.CSV_OUTPUT_HEADER_DROP_FILTER] = GM.Globals[GM.CSV_OUTPUT_HEADER_DROP_FILTER][:]
if not GC.Values[GC.CSV_OUTPUT_HEADER_FORCE]:
GC.Values[GC.CSV_OUTPUT_HEADER_FORCE] = GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE][:]
if not GC.Values[GC.CSV_OUTPUT_HEADER_ORDER]:
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER] = GM.Globals[GM.CSV_OUTPUT_HEADER_ORDER][:]
if not GC.Values[GC.CSV_OUTPUT_ROW_FILTER]:
GC.Values[GC.CSV_OUTPUT_ROW_FILTER] = GM.Globals[GM.CSV_OUTPUT_ROW_FILTER][:]
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE] = GM.Globals[GM.CSV_OUTPUT_ROW_FILTER_MODE]
@@ -6056,7 +6059,7 @@ def checkGroupExists(cd, ci, ciGroupsAPI, group, i=0, count=0):
# Turn the entity into a list of Users/CrOS devices
def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isArchived=None,
groupMemberType=Ent.TYPE_USER, noListConversion=False):
groupMemberType=Ent.TYPE_USER, noListConversion=False, recursive=False, noCLArgs=False):
def _incrEntityDoesNotExist(entityType):
entityError['entityType'] = entityType
entityError[ENTITY_ERROR_DNE] += 1
@@ -6227,32 +6230,33 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
isSuspended = True
cd = buildGAPIObject(API.DIRECTORY)
groups = convertEntityToList(entity)
includeDerivedMembership = recursive = False
includeDerivedMembership = False
domains = []
rolesSet = set()
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in GROUP_ROLES_MAP:
rolesSet.add(GROUP_ROLES_MAP[myarg])
elif myarg == 'primarydomain':
domains.append(GC.Values[GC.DOMAIN])
elif myarg == 'domains':
domains.extend(getEntityList(Cmd.OB_DOMAIN_NAME_ENTITY))
elif myarg == 'recursive':
recursive = True
includeDerivedMembership = False
elif myarg == 'includederivedmembership':
includeDerivedMembership = True
recursive = False
elif entityType == Cmd.ENTITY_GROUP_USERS_SELECT and myarg in SUSPENDED_ARGUMENTS:
isSuspended = _getIsSuspended(myarg)
elif entityType == Cmd.ENTITY_GROUP_USERS_SELECT and myarg in ARCHIVED_ARGUMENTS:
isArchived = _getIsArchived(myarg)
elif myarg == 'end':
break
else:
Cmd.Backup()
missingArgumentExit('end')
if not noCLArgs:
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in GROUP_ROLES_MAP:
rolesSet.add(GROUP_ROLES_MAP[myarg])
elif myarg == 'primarydomain':
domains.append(GC.Values[GC.DOMAIN])
elif myarg == 'domains':
domains.extend(getEntityList(Cmd.OB_DOMAIN_NAME_ENTITY))
elif myarg == 'recursive':
recursive = True
includeDerivedMembership = False
elif myarg == 'includederivedmembership':
includeDerivedMembership = True
recursive = False
elif entityType == Cmd.ENTITY_GROUP_USERS_SELECT and myarg in SUSPENDED_ARGUMENTS:
isSuspended = _getIsSuspended(myarg)
elif entityType == Cmd.ENTITY_GROUP_USERS_SELECT and myarg in ARCHIVED_ARGUMENTS:
isArchived = _getIsArchived(myarg)
elif myarg == 'end':
break
else:
Cmd.Backup()
missingArgumentExit('end')
if rolesSet:
memberRoles = ','.join(sorted(rolesSet))
for group in groups:
@@ -6293,19 +6297,19 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
elif entityType in {Cmd.ENTITY_CIGROUP_USERS}:
ci = buildGAPIObject(API.CLOUDIDENTITY_GROUPS)
groups = convertEntityToList(entity)
recursive = False
rolesSet = set()
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in GROUP_ROLES_MAP:
rolesSet.add(GROUP_ROLES_MAP[myarg])
elif myarg == 'recursive':
recursive = True
elif myarg == 'end':
break
else:
Cmd.Backup()
missingArgumentExit('end')
if not noCLArgs:
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in GROUP_ROLES_MAP:
rolesSet.add(GROUP_ROLES_MAP[myarg])
elif myarg == 'recursive':
recursive = True
elif myarg == 'end':
break
else:
Cmd.Backup()
missingArgumentExit('end')
if rolesSet:
memberRoles = ','.join(sorted(rolesSet))
for group in groups:
@@ -7730,6 +7734,7 @@ class CSVPrintFile():
if not self.headerForce and titles is not None:
self.SetTitles(titles)
self.SetJSONTitles(titles)
self.SetHeaderOrder(GC.Values[GC.CSV_OUTPUT_HEADER_ORDER])
if GM.Globals.get(GM.CSV_OUTPUT_COLUMN_DELIMITER) is None:
GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER] = GC.Values.get(GC.CSV_OUTPUT_COLUMN_DELIMITER, ',')
self.SetColumnDelimiter(GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER])
@@ -7739,10 +7744,12 @@ class CSVPrintFile():
GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR] = GC.Values.get(GC.CSV_OUTPUT_NO_ESCAPE_CHAR, False)
self.SetNoEscapeChar(GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR])
self.SetQuoteChar(GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR])
if GM.Globals.get(GM.CSV_OUTPUT_SORT_HEADERS) is None:
# if GM.Globals.get(GM.CSV_OUTPUT_SORT_HEADERS) is None:
if not GM.Globals.get(GM.CSV_OUTPUT_SORT_HEADERS):
GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS] = GC.Values.get(GC.CSV_OUTPUT_SORT_HEADERS, [])
self.SetSortHeaders(GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS])
if GM.Globals.get(GM.CSV_OUTPUT_TIMESTAMP_COLUMN) is None:
# if GM.Globals.get(GM.CSV_OUTPUT_TIMESTAMP_COLUMN) is None:
if not GM.Globals.get(GM.CSV_OUTPUT_TIMESTAMP_COLUMN):
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '')
self.SetTimestampColumn(GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN])
self.SetFormatJSON(False)
@@ -8430,6 +8437,15 @@ class CSVPrintFile():
self.SetTitles(headerForce)
self.SetJSONTitles(headerForce)
def SetHeaderOrder(self, headerOrder):
self.headerOrder = headerOrder
def orderHeaders(self, titlesList):
for title in self.headerOrder:
if title in titlesList:
titlesList.remove(title)
return self.headerOrder+titlesList
@staticmethod
def HeaderFilterMatch(filters, title):
for filterStr in filters:
@@ -8869,14 +8885,21 @@ class CSVPrintFile():
self.FixNodataTitles()
if self.mapDrive3Titles:
self. MapDrive3TitlesToDrive2()
else:
self.titlesList = self.headerForce
if self.timestampColumn:
self.AddTitle(self.timestampColumn)
if self.headerOrder:
self.titlesList = self.orderHeaders(self.titlesList)
titlesList = self.titlesList
else:
if self.fixPaths:
self.FixPathsTitles(self.JSONtitlesList)
if not self.rows and self.nodataFields is not None:
self.FixNodataTitles()
if not self.headerForce:
if self.fixPaths:
self.FixPathsTitles(self.JSONtitlesList)
if not self.rows and self.nodataFields is not None:
self.FixNodataTitles()
else:
self.JSONtitlesList = self.headerForce
if self.timestampColumn:
for i, v in enumerate(self.JSONtitlesList):
if v.startswith('JSON'):
@@ -8885,6 +8908,8 @@ class CSVPrintFile():
break
else:
self.AddJSONTitle(self.timestampColumn)
if self.headerOrder:
self.JSONtitlesList = self.orderHeaders(self.JSONtitlesList)
titlesList = self.JSONtitlesList
normalizeSortHeaders()
if (not self.todrive) or self.todrive['localcopy']:
@@ -9622,7 +9647,7 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
csvColumnDelimiter, csvNoEscapeChar, csvQuoteChar,
csvSortHeaders, csvTimestampColumn,
csvHeaderFilter, csvHeaderDropFilter,
csvHeaderForce,
csvHeaderForce, csvHeaderOrder,
csvRowFilter, csvRowFilterMode, csvRowDropFilter, csvRowDropFilterMode,
csvRowLimit,
showGettings, showGettingsGotNL,
@@ -9646,13 +9671,14 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
GM.Globals[GM.CSV_OUTPUT_HEADER_DROP_FILTER] = csvHeaderDropFilter[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER] = csvHeaderFilter[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE] = csvHeaderForce[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_ORDER] = csvHeaderOrder[:]
GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = csvQuoteChar
GM.Globals[GM.CSV_OUTPUT_ROW_DROP_FILTER] = csvRowDropFilter[:]
GM.Globals[GM.CSV_OUTPUT_ROW_DROP_FILTER_MODE] = csvRowDropFilterMode
GM.Globals[GM.CSV_OUTPUT_ROW_FILTER] = csvRowFilter[:]
GM.Globals[GM.CSV_OUTPUT_ROW_FILTER_MODE] = csvRowFilterMode
GM.Globals[GM.CSV_OUTPUT_ROW_LIMIT] = csvRowLimit
GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS] = csvSortHeaders
GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS] = csvSortHeaders[:]
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = csvTimestampColumn
GM.Globals[GM.CSV_TODRIVE] = todrive.copy()
GM.Globals[GM.DEBUG_LEVEL] = debugLevel
@@ -9660,9 +9686,9 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
GM.Globals[GM.OUTPUT_TIMEFORMAT] = output_timeformat
GM.Globals[GM.NUM_BATCH_ITEMS] = numItems
GM.Globals[GM.PID] = pid
GM.Globals[GM.PRINT_AGU_DOMAINS] = printAguDomains
GM.Globals[GM.PRINT_CROS_OUS] = printCrosOUs
GM.Globals[GM.PRINT_CROS_OUS_AND_CHILDREN] = printCrosOUsAndChildren
GM.Globals[GM.PRINT_AGU_DOMAINS] = printAguDomains[:]
GM.Globals[GM.PRINT_CROS_OUS] = printCrosOUs[:]
GM.Globals[GM.PRINT_CROS_OUS_AND_CHILDREN] = printCrosOUsAndChildren[:]
GM.Globals[GM.SAVED_STDOUT] = None
GM.Globals[GM.SHOW_GETTINGS] = showGettings
GM.Globals[GM.SHOW_GETTINGS_GOT_NL] = showGettingsGotNL
@@ -9869,6 +9895,7 @@ def MultiprocessGAMCommands(items, showCmds):
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER],
GC.Values[GC.CSV_OUTPUT_HEADER_DROP_FILTER],
GC.Values[GC.CSV_OUTPUT_HEADER_FORCE],
GC.Values[GC.CSV_OUTPUT_HEADER_ORDER],
GC.Values[GC.CSV_OUTPUT_ROW_FILTER],
GC.Values[GC.CSV_OUTPUT_ROW_FILTER_MODE],
GC.Values[GC.CSV_OUTPUT_ROW_DROP_FILTER],
@@ -11428,10 +11455,7 @@ def _getAppInfo(myarg, appInfo):
return True
def _generateProjectSvcAcctId(prefix):
psaId = prefix
for _ in range(3):
psaId += f'-{"".join(random.choice(LOWERNUMERIC_CHARS) for _ in range(3))}'
return psaId
return f'{prefix}-{"".join(random.choice(LOWERNUMERIC_CHARS) for _ in range(5))}'
def _getLoginHintProjectInfo(createCmd):
login_hint = None
@@ -11827,10 +11851,11 @@ def doPrintShowProjects():
resource=project['name'], body=policyBody)
return policy
except (GAPI.forbidden, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.PROJECT, project['projectId'], Ent.IAM_POLICY], str(e), i, count)
entityActionFailedWarning([Ent.PROJECT, project['projectId'], Ent.IAM_POLICY, None], str(e), i, count)
return {}
crm, _, login_hint, projects = _getLoginHintProjects(printShowCmd=True, readOnly=True)
readOnly = not Cmd.ArgumentIsAhead('showiampolicies')
crm, _, login_hint, projects = _getLoginHintProjects(printShowCmd=True, readOnly=readOnly)
csvPF = CSVPrintFile(['User', 'projectId']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
oneMemberPerRow = False
@@ -24995,7 +25020,7 @@ def doDeleteBrowsers():
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
checkEntityAFDNEorAccessErrorExit(None, Ent.CHROME_BROWSER, deviceId)
BROWSER_TIME_OBJECTS = {'lastActivityTime', 'lastPolicyFetchTime', 'lastRegistrationTime', 'lastStatusReportTime', 'safeBrowsingWarningsResetTime'}
BROWSER_TIME_OBJECTS = {'firstRecordTime', 'lastActivityTime', 'lastPolicyFetchTime', 'lastRegistrationTime', 'lastStatusReportTime', 'safeBrowsingWarningsResetTime'}
def _showBrowser(browser, FJQC, i=0, count=0):
if FJQC.formatJSON:
@@ -25782,7 +25807,7 @@ CHAT_UPDATE_SPACE_PERMISSIONS_MAP = {
'managewebhooks': 'manageWebhooks',
'replymessages': 'replyMessages',
}
# gam <UserTypeEntity> update chatspace <ChatSpace>
# [restricted|(audience <String>)]|
# ([displayname <String>]
@@ -26091,10 +26116,13 @@ def _getChatMemberEmail(cd, member):
_, memberUid = member['groupMember']['name'].split('/')
member['groupMember']['email'], _ = convertUIDtoEmailAddressWithType(f'uid:{memberUid}', cd, None, emailTypes=['group'])
def normalizeUserMember(cd, user, userList):
def normalizeUserMember(user, userList):
userList.append(normalizeEmailAddressOrUID(user))
def getUserMemberID(cd, user, userList):
userList.append(convertEmailAddressToUID(user, cd, emailType='user'))
def normalizeGroupMember(cd, group, groupList):
def getGroupMemberID(cd, group, groupList):
groupList.append(convertEmailAddressToUID(group, cd, emailType='group'))
# gam <UserTypeEntity> create chatmember <ChatSpace>
@@ -26157,16 +26185,16 @@ def createChatMember(users):
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
parent = getSpaceName(myarg)
elif myarg == 'user':
normalizeUserMember(cd, getEmailAddress(returnUIDprefix='uid:'), userList)
normalizeUserMember(getEmailAddress(returnUIDprefix='uid:'), userList)
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
for user in members:
normalizeUserMember(cd, user, userList)
normalizeUserMember(user, userList)
elif myarg == 'group':
normalizeGroupMember(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
getGroupMemberID(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
elif myarg == 'groups':
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
getGroupMemberID(cd, group, groupList)
elif myarg == 'role':
role = getChoice(CHAT_MEMBER_ROLE_MAP, mapChoice=True)
elif myarg == 'type':
@@ -26264,16 +26292,16 @@ def deleteUpdateChatMember(users):
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
parent = getSpaceName(myarg)
elif myarg == 'user':
normalizeUserMember(cd, getEmailAddress(returnUIDprefix='uid:'), userList)
normalizeUserMember(getEmailAddress(returnUIDprefix='uid:'), userList)
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
for user in members:
normalizeUserMember(cd, user, userList)
normalizeUserMember(user, userList)
elif deleteMode and myarg == 'group':
normalizeGroupMember(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
getGroupMemberID(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
elif deleteMode and myarg == 'groups':
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
getGroupMemberID(cd, group, groupList)
else:
unknownArgumentExit()
if not deleteMode and 'role' not in body:
@@ -26417,16 +26445,16 @@ def syncChatMembers(users):
csvPF = CSVPrintFile(CHAT_SYNC_PREVIEW_TITLES)
elif myarg == 'users':
for user in getEntityList(Cmd.OB_USER_ENTITY):
normalizeUserMember(cd, user, userList)
getUserMemberID(cd, user, userList)
usersSpecified = True
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
for user in members:
normalizeUserMember(cd, user, userList)
getUserMemberID(cd, user, userList)
usersSpecified = True
elif myarg == 'groups':
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
getGroupMemberID(cd, group, groupList)
groupsSpecified = True
else:
unknownArgumentExit()
@@ -37028,11 +37056,13 @@ def checkCalendarExists(cal, calId, showMessage=False):
entityActionFailedWarning([Ent.CALENDAR, calId], str(e))
return None
def validateCalendar(calId, i=0, count=0):
def validateCalendar(calId, i=0, count=0, noClientAccess=False):
cal = None
if not calId.endswith('.calendar.google.com'):
calId, cal = buildGAPIServiceObject(API.CALENDAR, calId, i, count, displayError=False)
calId, cal = buildGAPIServiceObject(API.CALENDAR, calId, i, count, displayError=noClientAccess)
if not cal:
if noClientAccess:
return (calId, None)
cal = buildGAPIObject(API.CALENDAR)
try:
callGAPI(cal.calendars(), 'get',
@@ -41128,7 +41158,7 @@ def doCreateVaultMatter():
break
Ind.Decrement()
if showDetails:
_showVaultMatter(None, matter, cd, None)
_showVaultMatter(matter, cd, None)
VAULT_MATTER_ACTIONS = {
'close': Act.CLOSE,
@@ -49759,7 +49789,7 @@ def _validateUserGetCalendarIds(user, i, count, calendarEntity,
calIds = calendarEntity['dict'][user][:]
else:
calIds = calendarEntity['list'][:]
user, cal = validateCalendar(user, i, count)
user, cal = validateCalendar(user, i, count, noClientAccess=True)
if not cal:
return (user, None, None, 0)
if calendarEntity['resourceIds']:
@@ -50178,7 +50208,7 @@ def printShowCalendars(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, cal = validateCalendar(user, i, count)
user, cal = validateCalendar(user, i, count, noClientAccess=True)
if not cal:
continue
if csvPF:
@@ -50278,7 +50308,7 @@ def printShowCalSettings(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, cal = validateCalendar(user, i, count)
user, cal = validateCalendar(user, i, count, noClientAccess=True)
if not cal:
continue
try:
@@ -50438,7 +50468,7 @@ def transferCalendars(users):
_getCalendarAttributes(targetListBody, returnOnUnknownArgument=True)
else:
unknownArgumentExit()
targetUser, targetCal = validateCalendar(targetUser)
targetUser, targetCal = validateCalendar(targetUser, noClientAccess=True)
if not targetCal:
return
colorRgbFormat = 'backgroundColor' in targetListBody or 'foregroundColor' in targetListBody
@@ -57236,7 +57266,7 @@ def createDriveFile(users):
continue
result = callGAPI(drive.files(), 'create',
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.FORBIDDEN, GAPI.INSUFFICIENT_PERMISSIONS, GAPI.INSUFFICIENT_PARENT_PERMISSIONS,
GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.CANNOT_ADD_PARENT,
GAPI.PERMISSION_DENIED, GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.CANNOT_ADD_PARENT,
GAPI.FILE_NOT_FOUND, GAPI.UNKNOWN_ERROR, GAPI.INTERNAL_ERROR,
GAPI.STORAGE_QUOTA_EXCEEDED, GAPI.TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
GAPI.TEAMDRIVE_FILE_LIMIT_EXCEEDED, GAPI.TEAMDRIVE_HIERARCHY_TOO_DEEP,
@@ -57275,7 +57305,7 @@ def createDriveFile(users):
row.update(addCSVData)
csvPF.WriteRow(row)
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest, GAPI.cannotAddParent,
GAPI.invalidQuery, GAPI.permissionDenied, GAPI.invalid, GAPI.badRequest, GAPI.cannotAddParent,
GAPI.fileNotFound, GAPI.unknownError, GAPI.storageQuotaExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed,
GAPI.teamDriveFileLimitExceeded, GAPI.teamDriveHierarchyTooDeep,
GAPI.uploadTooLarge, GAPI.teamDrivesShortcutFileNotSupported) as e:
@@ -64285,13 +64315,15 @@ def _moveSharedDriveToOU(orgUnit, orgUnitId, driveId, user, i, count, ci, return
'destinationOrgUnit': f'orgUnits/{orgUnitId[3:]}'}
try:
callGAPI(ci.orgUnits().memberships(), 'move',
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.ABORTED],
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN,
GAPI.INVALID_ARGUMENT, GAPI.ABORTED],
name=name, body=cibody)
if not returnIdOnly:
Act.Set(Act.MOVE)
entityModifierNewValueActionPerformed([Ent.SHAREDDRIVE, driveId], Act.MODIFIER_TO, f'{Ent.Singular(Ent.ORGANIZATIONAL_UNIT)}: {orgUnit}', i, count)
entityModifierNewValueActionPerformed([Ent.USER, user, Ent.SHAREDDRIVE, driveId], Act.MODIFIER_TO,
f'{Ent.Singular(Ent.ORGANIZATIONAL_UNIT)}: {orgUnit}', i, count)
except (GAPI.notFound, GAPI.forbidden, GAPI.aborted, GAPI.badRequest, GAPI.internalError,
GAPI.noManageTeamDriveAdministratorPrivilege) as e:
GAPI.noManageTeamDriveAdministratorPrivilege, GAPI.invalidArgument) as e:
entityActionFailedWarning([Ent.USER, user, Ent.SHAREDDRIVE_ID, driveId], str(e), i, count)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userSvcNotApplicableOrDriveDisabled(user, str(e), i, count)

View File

@@ -117,6 +117,8 @@ CSV_OUTPUT_HEADER_FILTER = 'csv_output_header_filter'
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
@@ -309,7 +311,8 @@ 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_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}
@@ -351,6 +354,7 @@ Defaults = {
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: '',
@@ -460,6 +464,7 @@ TYPE_FILE = 'file'
TYPE_FLOAT = 'floa'
TYPE_HEADERFILTER = 'heaf'
TYPE_HEADERFORCE = 'hefo'
TYPE_HEADERORDER = 'heor'
TYPE_INTEGER = 'inte'
TYPE_LANGUAGE = 'lang'
TYPE_LOCALE = 'locl'
@@ -514,6 +519,7 @@ VAR_INFO = {
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},

View File

@@ -65,6 +65,8 @@ CSV_OUTPUT_HEADER_DROP_FILTER = 'cohd'
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
@@ -80,7 +82,7 @@ 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 = 'csv_output_timestamp_column'
CSV_OUTPUT_TIMESTAMP_COLUMN = 'cotc'
# Output sort headers
CSV_OUTPUT_SORT_HEADERS = 'cosh'
# CSV todrive options
@@ -235,6 +237,7 @@ Globals = {
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: [],

View File

@@ -1,441 +0,0 @@
#!/usr/bin/env bash
usage()
{
cat << EOF
GAM installation script.
OPTIONS:
-h show help.
-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=""
strip_gam="--strip-components 0"
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
# remove possible / from end of target_dir
target_dir=${target_dir%/}
update_profile() {
[ "$2" -eq 1 ] || [ -f "$1" ] || return 1
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"
else
echo_yellow "gam alias already exists in profile file $1. Skipping add."
fi
}
echo_red()
{
echo -e "\x1B[1;31m$1"
echo -e '\x1B[0m'
}
echo_green()
{
echo -e "\x1B[1;32m$1"
echo -e '\x1B[0m'
}
echo_yellow()
{
echo -e "\x1B[1;33m$1"
echo -e '\x1B[0m'
}
version_gt()
{
# 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
}
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/GAM-team/GAM/releases/tags/v$gamversion"
fi
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" \
2>&1 /dev/null)
echo_yellow "Getting file and download URL..."
# 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
# but that gets really ugly
pycode="import json
import sys
attrib = sys.argv[1]
gamversion = sys.argv[2]
release = json.load(sys.stdin)
if type(release) is list:
for a_release in release:
if a_release['prerelease'] and gamversion != 'prerelease':
continue
elif a_release['draft'] and gamversion != 'draft':
continue
release = a_release
break
try:
for asset in release['assets']:
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="python3"
$pycmd -V >/dev/null 2>&1
rc=$?
if (( $rc != 0 )); then
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=$?
if (( $rc != 0 )); then
echo_red "ERROR: No version of python installed."
exit
fi
download_urls=$(echo "$release_json" | $pycmd -c "$pycode" browser_download_url "$gamversion")
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"
fullversion=$(sw_vers -productVersion)
# override osversion only if it wasn't set by cli arguments
osversion=${osversion:-${fullversion:0:2}}
download_urls=$(echo -e "$download_urls" | grep "\-macos-")
case $gamarch in
x86_64)
download_url=$(echo -e "$download_urls" | grep "\-x86_64")
minimum_version=13
;;
arm|arm64|aarch64)
download_url=$(echo -e "$download_urls" | grep "\-aarch64")
minimum_version=14
;;
*)
echo_red "ERROR: this installer currently only supports x86_64 and arm64 MacOS. Looks like you're running on ${gamarch}. Exiting."
exit
;;
esac
if [[ "$osversion" -ge "$minimum_version" ]]; then
echo_green "You are running MacOS ${fullversion}, good. Using GAM with ${download_url}."
else
echo_red "Sorry, you are running MacOS ${fullversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting."
exit
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
# Temp dir for archive
temp_archive_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
# 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 -s "${curl_opts[@]}" "$download_url")
mkdir -p "$target_dir"
echo_yellow "Extracting archive to $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."
exit
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/$target_gam" version extended
rc=$?
if (( $rc != 0 )); then
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
echo_green "GAM upgrade complete!"
exit
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
case $yn in
[Yy]*)
break
;;
[Nn]*)
# config_cmd="config no_browser true"
touch "$target_dir/gam/nobrowser.txt" > /dev/null 2>&1
break
;;
*)
echo_red "Please answer yes or no."
;;
esac
done
echo
project_created=false
while true; do
read -p "GAM is now installed. Are you ready to set up a Google API project for GAM? (yes or no) " yn
case $yn in
[Yy]*)
if [ "$adminuser" == "" ]; then
read -p "Please enter your Google Workspace admin email address: " adminuser
fi
# "$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."
project_created=true
break
else
echo_red "Project creation failed. Trying again. Say N to skip project creation."
fi
;;
[Nn]*)
echo -e "\nYou can create an API project later by running:\n\ngam create project\n"
break
;;
*)
echo_red "Please answer yes or no."
;;
esac
done
admin_authorized=false
while $project_created; do
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/$target_gam" $config_cmd oauth create $adminuser
"$target_dir/$target_gam" oauth create $adminuser
rc=$?
if (( $rc == 0 )); then
echo_green "Admin authorization complete."
admin_authorized=true
break
else
echo_red "Admin authorization failed. Trying again. Say N to skip admin authorization."
fi
;;
[Nn]*)
echo -e "\nYou can authorize an admin later by running:\n\ngam oauth create\n"
break
;;
*)
echo_red "Please answer yes or no."
;;
esac
done
service_account_authorized=false
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 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/$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."
service_account_authorized=true
break
else
echo_red "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."
fi
;;
[Nn]*)
echo -e "\nYou can authorize a service account later by running:\n\ngam user $adminuser check serviceaccount\n"
break
;;
*)
echo_red "Please answer yes or no."
;;
esac
done
echo_green "Here's information about your new GAM installation:"
#"$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."
exit
fi
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

View File

@@ -1,58 +1,23 @@
import os
import sys
import uuid
from lxml import etree
import sys
source_dir = sys.argv[1]
template_file = sys.argv[2]
target_file = sys.argv[3]
# Hacky solution to create a Guid for all files
# so Wix is happy and Guid is stable every time.
# uuid5 is used for the Guid and the input is the
# source filename so the Guid will be the same
# every time as long as the source file name is
# the same.
existing_components = {
'gam.exe': ''' <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>
''',
'LICENSE': ''' <Component Id="license" Guid="c76864c5-d005-44d5-bb7c-a27e5923792d">
<File Name="LICENSE" KeyPath="yes" />
</Component>
''',
'gam-setup.bat': ''' <Component Id="gam_setup_bat" Guid="5e6bbacb-d86f-4d80-a10b-89b81ee63fcb">
<File Name="gam-setup.bat" KeyPath="yes" />
</Component>
''',
'GamCommands.txt': ''' <Component Id="GamCommands_txt" Guid="a2dca862-b222-469e-a637-95ea2a1c53e7">
<File Name="GamCommands.txt" KeyPath="yes" />
</Component>
''',
'GamUpdate.txt': ''' <Component Id="GamUpdate_txt" Guid="1b7cdd48-0fff-4943-a219-102fcd14c755">
<File Name="GamUpdate.txt" KeyPath="yes" />
</Component>
''',
'cacerts.pem': ''' <Component Id="cacerts_pem" Guid="61fe2b2d-1646-4bed-b844-193965e97727">
<File Name="cacerts.pem" KeyPath="yes" />
</Component>
''',
}
component_xml = ''
all_files = []
for root, dirs, files in os.walk(source_dir):
for filename in files:
relpath = os.path.relpath(root, source_dir)
if relpath == '.':
all_files.append(filename)
else:
all_files.append(os.path.join(relpath, filename))
all_files.sort()
for filename in all_files:
component_xml += existing_components.get(filename,
f' <Component>\n <File Name="{filename}" KeyPath="yes"/>\n </Component>\n')
with open(template_file, 'r') as f:
template = f.read()
full_xml = template.replace('REPLACE_ME_WITH_FILE_COMPONENTS', component_xml)
with open(target_file, 'w') as f:
f.write(full_xml)
rewrite_file = sys.argv[1]
with open(rewrite_file, 'rb') as f:
input_xml = f.read()
root = etree.fromstring(input_xml)
for elem in root.getiterator():
if 'Guid' in elem.attrib:
source = elem.getchildren()[0].attrib['Source']
stable_uuid = str(uuid.uuid5(uuid.NAMESPACE_URL, source))
elem.attrib['Guid'] = stable_uuid
with open(rewrite_file, 'w') as f:
f.write(etree.tostring(root).decode())