Compare commits

...

12 Commits

18 changed files with 460 additions and 223 deletions

View File

@@ -347,7 +347,7 @@ If none of the following options are selected, all events are selected.
* `<EventSelectProperty>* <EventMatchProperty>*` - Properties used to select events
The Google Calendar API processes `<EventSelectProperty>*`; you may specify none or multiple properties.
* `after|starttime|timemin <Time>` - Lower bound (inclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `after|starttime|timemin <Time>` - Lower bound (exclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `before|endtime|timemax <Time>` - Upper bound (exclusive) for an event's start time to filter by. If timeMin is set, timeMax must be greater than timeMin.
* `eventtypes <EventTypeList>` - Select events based on their type.
* `query <QueryCalendar>` - Free text search terms to find events that match these terms in any field, except for extended properties

View File

@@ -1,5 +1,5 @@
# Downloads
You can download the current GAMADV-XTD3 release from the [GitHub Releases](https://github.com/taers232c/GAMADV-XTD3/releases) page. Choose one of the following:
# Downloads-Installs
You can download and install the current GAMADV-XTD3 release from the [GitHub Releases](https://github.com/taers232c/GAMADV-XTD3/releases) page. Choose one of the following:
* Executable Archive, Automatic, Linux/Mac OS/Google Cloud Shell/Raspberry Pi/ChromeOS
- Start a terminal session and execute one of the following commands:
@@ -42,31 +42,21 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Mac OS, versions prior to Big Sur
- `gamadv-xtd3-6.wx.yz-macos-x86_64-legacy.tar`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Windows 64 bit
- `gamadv-xtd3-6.wx.yz-windows-x86_64.zip`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
- Start a Command Prompt/PowerShell session and cd to the install directory.
* Executable Installer, Manual, Windows 64 bit
- `gamadv-xtd3-6.wx.yz-windows-x86_64.msi`
- Download the installer and run it.
- Start a Command Prompt/PowerShell session and cd to the install directory.
* Executable Archive, Manual, Windows 32 bit
- `gamadv-xtd3-6.wx.yz-windows-x86.zip`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Installer, Manual, Windows 32 bit
- `gamadv-xtd3-6.wx.yz-windows-x86.msi`
- Download the installer and run it.
* Winget
- `winget install taers232c.GAMADV-XTD3 --location C:\GAMADV-XTD3`
- Specify an alternate location if desired
- Start a Command Prompt/PowerShell session and cd to the install directory.
* Source, all platforms
- `Source code(zip)`
- `Source code(tar.gz)`

View File

@@ -10,6 +10,53 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation
### 6.77.14
Fixed bug in `gam calendars <CalendarEntity> import event icaluid <iCalUID> json <JSONdata>` that caused an error.
### 6.77.13
Updated `gam <UserTypeEntity> print|show filecounts` to reflect that Shared Drives now
have a capacity of 500000 files/folders/shortcuts.
### 6.77.12
Fixed bug in `gam <UserTypeEntity> print chatspaces todrive` that caused an error.
### 6.77.11
Added option `convertmbtogb` to `gam report usage customer|user` and
`gam report customer|user` that causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
### 6.77.10
Fixed bug in `gam <UserTypeEntity> get profilephoto` where data written to stdout, e.g. `> filename`,
was not properly base64 encoded.
### 6.77.09
Added option `usertokencounts` to `gam <UserTypeEntity> print|show tokens` that causes GAM to display
each user and their number of access tokens; there are no details.
### 6.77.08
Fixed bugs in `gam <UserTypeEntity> delete chatmember <ChatSpace> ... group <GroupItem>`
and `gam <UserTypeEntity> sync chatmember <ChatSpace> ... groups <GroupEntity>` that caused an error.
### 6.77.07
Fixed bug in `gam <UserTypeEntity> create chatmember <ChatSpace> ... group <GroupItem>` that caused an error.
### 6.77.06
Updated `gam update ou <OrgUnitItem> ... parent <OrgUnitItem>` to handle the following error
that occurs when `parent <OrgUnitItem>` is the same as or a sub-OU of `ou <OrgUnitItem>`.
```
ERROR: 412: conditionNotMet - OrgUnit hierarchy has cycle
```
### 6.77.05
Added option `onlyusers <UserTypeEntity>` to `gam <UserTypeEntity> claim ownership <DriveFileEntity>`

View File

@@ -2,10 +2,10 @@
Use these steps if you have never used any version of GAM in your domain. They will create your GAM project
and all necessary authentications.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Downloads-Installs](Downloads-Installs)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
- [GAM Configuration](gam.cfg)
## Linux and MacOS and Google Cloud Shell
@@ -25,6 +25,11 @@ probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
Make the directory:
```
mkdir -p /Users/admin/GAMconfig
```
Add the following line:
```
export GAMCFGDIR="/Users/admin/GAMConfig"
@@ -54,11 +59,6 @@ You need to make sure the GAM configuration directory actually exists. Test that
ls -l $GAMCFGDIR
```
If this gives you an error, make the directory:
```
mkdir -p $GAMCFGDIR
```
### Set a working directory
You should establish a GAM working directory; you will store your GAM related
@@ -98,8 +98,7 @@ ln -s "/Users/admin/bin/gamadv-xtd3/gam" /usr/local/bin/gam
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
admin@server:~$ cd /Users/admin/bin/gamadv-xtd3
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config drive_dir /Users/admin/GAMWork verify
admin@server:/Users/admin$ gam config drive_dir /Users/admin/GAMWork verify
Created: /Users/admin/GAMConfig
Created: /Users/admin/GAMConfig/gamcache
Config File: /Users/admin/GAMConfig/gam.cfg, Initialized
@@ -109,20 +108,20 @@ Section: DEFAULT
[long list of all config settings that should match the directories you specified]
...
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Verify initialization, this was a successful installation.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $GAMCFGDIR
admin@server:/Users/admin$ ls -l $GAMCFGDIR
total 48
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
-rw-rw-rw-+ 1 admin staff 0 Mar 3 09:23 oauth2.txt.lock
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Create your project with local browser
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam create project
admin@server:/Users/admin$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
@@ -186,12 +185,12 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Create your project without local browser (Google Cloud Shell for instance)
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
admin@server:/Users/admin/bin/gamadv-xtd3$ gam create project
admin@server:/Users/admin$ gam config no_browser true save
admin@server:/Users/admin$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
@@ -254,7 +253,7 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Enable GAMADV-XTD3 client access
@@ -262,7 +261,7 @@ You select a list of scopes, GAM uses a browser to get final authorization from
writes the credentials into the file oauth2.txt.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth create
admin@server:/Users/admin$ gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -343,14 +342,14 @@ Enter verification code or paste "Unable to connect" URL from other computer (on
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
If clicking on the link in the instructions does not work (i.e. you get a 404 or 400 error message, instead of something about 'unable to connect') the URL in the link is too long. Most likely, you have selected all scopes. Try again with fewer scopes until it works. (there is no harm in repeatedly trying)
### Enable GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
$ gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
@@ -405,7 +404,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -415,7 +414,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
@@ -459,14 +458,14 @@ All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam info domain
admin@server:/Users/admin$ gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -474,7 +473,7 @@ Primary Domain Verified: True
Default Language: en
...
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config customer_id C01234567 domain domain.com timezone local save verify
admin@server:/Users/admin$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/admin/GAMConfig/gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
@@ -482,7 +481,7 @@ Section: DEFAULT
[long list of all config settings that should match the data you specified]
...
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
## Windows
@@ -538,8 +537,7 @@ At this point, you should restart Command Prompt so that it has the updated path
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
C:>cd C:\GAMADV-XTD3
C:\GAMADV-XTD3>gam config drive_dir C:\GAMWork verify
C:\>gam config drive_dir C:\GAMWork verify
Created: C:\GAMConfig
Created: C:\GAMConfig\gamcache
Config File: C:\GAMConfig\gam.cfg, Initialized
@@ -549,11 +547,11 @@ Section: DEFAULT
[long list of all config settings that should match the directories you specified]
...
C:\GAMADV-XTD3>
C:\>
```
### Verify initialization, this was a successful installation.
```
C:\GAMADV-XTD3>dir %GAMCFGDIR%
C:\>dir %GAMCFGDIR%
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
@@ -566,12 +564,12 @@ C:\GAMADV-XTD3>dir %GAMCFGDIR%
03/03/2017 10:15 AM 0 oauth2.txt.lock
2 File(s) 15,769 bytes
3 Dir(s) 110,532,562,944 bytes free
C:\GAMADV-XTD3>
C:\>
```
### Create your project with local browser
```
C:\GAMADV-XTD3>gam create project
C:\>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
@@ -635,12 +633,12 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
C:\GAMADV-XTD3>
C:\>
```
### Create your project without local browser (headless server for instance)
```
C:\GAMADV-XTD3>gam config no_browser true save
C:\GAMADV-XTD3>gam create project
C:\>gam config no_browser true save
C:\>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
@@ -703,7 +701,7 @@ Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
C:\GAMADV-XTD3>
C:\>
```
### Enable GAMADV-XTD3 client access
@@ -711,7 +709,7 @@ You select a list of scopes, GAM uses a browser to get final authorization from
writes the credentials into the file oauth2.txt.
```
C:\GAMADV-XTD3>gam oauth create
C:\>gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -792,11 +790,11 @@ Enter verification code or paste "Unable to connect" URL from other computer (on
The authentication flow has completed.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Created
C:\GAMADV-XTD3>
C:\>
```
### Enable GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
C:\>gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
@@ -850,7 +848,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
C:\GAMADV-XTD3>
C:\>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -860,7 +858,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
C:\>gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
@@ -904,14 +902,14 @@ All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
C:\>
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
C:\GAMADV-XTD3>gam info domain
C:\>gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -919,7 +917,7 @@ Primary Domain Verified: True
Default Language: en
...
C:\GAMADV-XTD3>gam config customer_id C01234567 domain domain.com timezone local save verify
C:\>gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: C:\GAMConfig\gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
@@ -927,5 +925,5 @@ Section: DEFAULT
[long list of all config settings that should match the directories you specified]
...
C:\GAMADV-XTD3>
C:\>
```

View File

@@ -2,9 +2,9 @@
Use these steps to update your version of GAMADV-XTD3.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
- [GAM Configuration](gam.cfg)
## Linux and MacOS and Google Cloud Shell

View File

@@ -2,10 +2,10 @@
Use these steps if you have used any version of GAMADV-X or GAMADV-XTD in your domain.
They will update your GAM project and all necessary authentications.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Downloads-Installs](Downloads-Installs)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
- [GAM Configuration](gam.cfg)
## Linux and MacOS and Google Cloud Shell
@@ -23,29 +23,32 @@ GAMADV-XTD3 uses the same configuration directory and gam.cfg file as GAMADV-X a
### Update your alias
You should update your alias to point to /Users/admin/bin/gamadv-xtd3/gam.
Add the following line:
Add/edit the following line:
```
alias gam="/Users/admin/bin/gamadv-xtd3/gam"
```
to one of these files if you're running bash or an equivalent file if you're running some other shell:
to one of these files based on your shell:
```
~/.bash_aliases
~/.bash_profile
~/.bashrc
~/.zshrc
~/.profile
```
If you already have a gam alias for standard GAM and want to run it and GAMADV-XTD3, give your new alias a different name:
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
alias gam3="/Users/admin/bin/gamadv-xtd3/gam"
source <Filename>
```
### Do you have a browser?
If your computer doesn't support a browser, Google Cloud Shell for instance, execute this command:
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
admin@server:/Users/admin$ gam config no_browser true save
```
### Update your project to include the additional APIs that GAMADV-XTD3 uses.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
admin@server:/Users/admin$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -75,7 +78,7 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Update GAMADV-XTD3 client access.
@@ -90,7 +93,7 @@ gam config no_browser true oauth update
```
You will be given instructions on how to get the authorization on another computer and apply it locally.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth update
admin@server:/Users/admin$ gam oauth update
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
@@ -165,11 +168,11 @@ set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Updated
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Update GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user user@domain.com check serviceaccount
admin@server:/Users/admin$ gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
@@ -218,7 +221,7 @@ Scopes fields will be pre-populated. Please click Authorize to allow these
scopes access. After authorizing it may take some time for this test to pass so
wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -228,7 +231,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user user@domain.com check serviceaccount
admin@server:/Users/admin$ gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
@@ -271,7 +274,7 @@ Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 34
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
## Windows
@@ -305,15 +308,17 @@ Click OK
Exit Control Panel
```
At this point, you should restart Command Prompt so that it has the updated path and environment variables.
### Do you have a compatible browser?
If the computer on which you are running GAM does not have access to a browser or
your default browser is Internet Explorer or Edge, issue this command:
```
C:\GAMADV-X>gam config no_browser true save
C:\>gam config no_browser true save
```
### Update your project to include the additional APIs that GAMADV-XTD3 uses.
```
C:\GAMADV-XTD3>gam update project
C:\>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -343,7 +348,7 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
C:\>
```
### Update GAMADV-XTD3 client access.
@@ -361,7 +366,7 @@ You can open the file with Notepad/Wordpad, do a control-A to select the text, c
start a browser and paste the URL (control-V) into the address bar. Authenticate and copy the Verification code
back to your Command Prompt/PowerShell window.
```
C:\GAMADV-XTD3>gam oauth update
C:\>gam oauth update
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
@@ -436,11 +441,11 @@ set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Updated
C:\GAMADV-XTD3>
C:\>
```
### Enable GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user user@domain.com check serviceaccount
C:\>gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
@@ -489,7 +494,7 @@ Scopes fields will be pre-populated. Please click Authorize to allow these
scopes access. After authorizing it may take some time for this test to pass so
wait a few moments and then try this command again.
C:\GAMADV-XTD3>
C:\>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -499,7 +504,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user user@domain.com check serviceaccount
C:\>gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
@@ -542,5 +547,5 @@ Domain-wide Delegation authentication:, User: admin@domain.com, Scopes: 34
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
C:\>
```

View File

@@ -2,10 +2,10 @@
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
and all necessary authentications.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Downloads-Installs](Downloads-Installs)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
- [GAM Configuration](gam.cfg)
## Linux and MacOS and Google Cloud Shell
@@ -25,6 +25,11 @@ probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
Make the directory:
```
mkdir -p /Users/admin/GAMconfig
```
Add the following line:
```
export GAMCFGDIR="/Users/admin/GAMConfig"
@@ -69,32 +74,38 @@ to one of these files based on your shell:
~/.profile
```
If you already have an alias for standard GAM but are no longer going to run it, delete these lines:
```
function gam() { "/Users/admin/bin/gam/gam" "$@" ; }"
alias gam="/Users/admin/bin/gam/gam"
```
If you already have an alias for standard GAM and want to run it and GAMADV-XTD3, give your old alias a different name:
```
function gamstd() { "/Users/admin/bin/gam/gam" "$@" ; }"
alias gamstd="/Users/admin/bin/gam/gam"
```
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
source <Filename>
```
If you already have a gam alias for standard GAM and want to run it and GAMADV-XTD3, give your new alias a different name:
```
alias gam3="/Users/admin/bin/gamadv-xtd3/gam"
```
Set environment variable OLDGAMPATH to point to the existing Gam directory; /Users/admin/bin/gam will be used in this example.
If your existing Gam is in another directory, substitute that value in the directions.
```
admin@server:~$ cd /Users/admin/bin/gamadv-xtd3
admin@server:/Users/admin/bin/gamadv-xtd3$ export OLDGAMPATH=/Users/admin/bin/gam
admin@server:/Users/admin$ export OLDGAMPATH=/Users/admin/bin/gam
```
Verify that OLDGAMPATH points to the correct location.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $OLDGAMPATH/*.json
admin@server:/Users/admin$ ls -l $OLDGAMPATH/*.json
-rw-r-----@ 1 admin staff 553 Feb 26 10:39 /Users/admin/bin/gam/client_secrets.json
-rw-r-----@ 1 admin staff 2377 Feb 26 10:39 /Users/admin/bin/gam/oauth2service.json
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config drive_dir /Users/admin/GAMWork verify
admin@server:/Users/admin$ gam config drive_dir /Users/admin/GAMWork verify
Created: /Users/admin/GAMConfig
Created: /Users/admin/GAMConfig/gamcache
Copied: /Users/admin/bin/gam/oauth2service.json, To: /Users/admin/GAMConfig/oauth2service.json
@@ -219,11 +230,11 @@ Section: DEFAULT
user_max_results = 500
user_service_account_access_only = false
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Verify initialization, this was a successful installation.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $GAMCFGDIR
admin@server:/Users/admin$ ls -l $GAMCFGDIR
total 48
-rw-r-----+ 1 admin staff 553 Mar 3 09:23 client_secrets.json
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
@@ -232,21 +243,21 @@ drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
-rw-r-----+ 1 admin staff 5104 Mar 3 09:23 oauth2.txt
-rw-rw-rw-+ 1 admin staff 0 Mar 3 09:23 oauth2.txt.lock
-rw-r-----+ 1 admin staff 2377 Mar 3 09:23 oauth2service.json
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
If the verification looks like this, then you'll have to copy client_secrets.json and oauth2service.json manually.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $GAMCFGDIR
admin@server:/Users/admin$ ls -l $GAMCFGDIR
total 40
-rw-r-----+ 1 admin admin 1427 Nov 1 11:38 gam.cfg
drwxr-x---+ 16 admin admin 544 Nov 2 07:25 gamcache
-rw-r--r--+ 1 admin admin 10 Nov 2 15:31 lastupdatecheck.txt
-rw-rw-rw-+ 1 admin admin 0 Sep 19 17:28 oauth2.txt.lock
admin@server:/Users/admin/bin/gamadv-xtd3$ cp -p $OLDGAMPATH/client_secrets.json $GAMCFGDIR/
admin@server:/Users/admin/bin/gamadv-xtd3$ cp -p $OLDGAMPATH/oauth2service.json $GAMCFGDIR/
admin@server:/Users/admin/bin/gamadv-xtd3$ cp -p $OLDGAMPATH/oauth2.txt $GAMCFGDIR/
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $GAMCFGDIR
admin@server:/Users/admin$ cp -p $OLDGAMPATH/client_secrets.json $GAMCFGDIR/
admin@server:/Users/admin$ cp -p $OLDGAMPATH/oauth2service.json $GAMCFGDIR/
admin@server:/Users/admin$ cp -p $OLDGAMPATH/oauth2.txt $GAMCFGDIR/
admin@server:/Users/admin$ ls -l $GAMCFGDIR
total 40
-rw-r-----+ 1 admin staff 553 Mar 3 09:23 client_secrets.json
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
@@ -258,7 +269,7 @@ drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
```
### Update your project with local browser to include the additional APIs that GAMADV-XTD3 uses.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
admin@server:/Users/admin$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -288,12 +299,12 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Update your project without local browser (Google Cloud Shell for instance) to include the additional APIs that GAMADV-XTD3 uses
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
admin@server:/Users/admin$ gam config no_browser true save
admin@server:/Users/admin$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -322,7 +333,7 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Enable GAMADV-XTD3 client access
@@ -332,17 +343,17 @@ You select a list of scopes, GAM uses a browser to get final authorization from
writes the credentials into the file oauth2.txt.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
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
GAMADV-XTD3 6.77.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64
Path: /Users/admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth create
admin@server:/Users/admin$ gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -423,11 +434,11 @@ Enter verification code or paste "Unable to connect" URL from other computer (on
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Enable GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
$ gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
@@ -482,7 +493,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -492,7 +503,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
admin@server:/Users/admin$ gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
@@ -536,14 +547,14 @@ All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam info domain
admin@server:/Users/admin$ gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -551,7 +562,7 @@ Primary Domain Verified: True
Default Language: en
...
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config customer_id C01234567 domain domain.com timezone local save verify
admin@server:/Users/admin$ gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/admin/GAMConfig/gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
@@ -668,7 +679,7 @@ Section: DEFAULT
user_max_results = 500
user_service_account_access_only = false
admin@server:/Users/admin/bin/gamadv-xtd3$
admin@server:/Users/admin$
```
## Windows
@@ -728,12 +739,11 @@ At this point, you should restart Command Prompt so that it has the updated path
Set environment variable OLDGAMPATH to point to the existing Gam directory; C:\GAM will be used in this example.
If your existing Gam is in another directory, substitute that value in the directions.
```
C:>cd C:\GAMADV-XTD3
C:\GAMADV-XTD3>set OLDGAMPATH=C:\GAM
C:\>set OLDGAMPATH=C:\GAM
```
### Verify that OLDGAMPATH points to the correct location.
```
C:\GAMADV-XTD3>dir %OLDGAMPATH%\*.json
C:\>dir %OLDGAMPATH%\*.json
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
@@ -748,8 +758,7 @@ C:\GAMADV-XTD3>dir %OLDGAMPATH%\*.json
```
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
C:>cd C:\GAMADV-XTD3
C:\GAMADV-XTD3>gam config drive_dir C:\GAMWork verify
C:\>gam config drive_dir C:\GAMWork verify
Created: C:\GAMConfig
Created: C:\GAMConfig\gamcache
Copied: C:\GAM\oauth2service.json, To: C:\GAMConfig\oauth2service.json
@@ -871,11 +880,11 @@ Section: DEFAULT
user_max_results = 500
user_service_account_access_only = false
C:\GAMADV-XTD3>
C:\>
```
### Verify initialization, this was a successful installation.
```
C:\GAMADV-XTD3>dir %GAMCFGDIR%
C:\>dir %GAMCFGDIR%
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
@@ -892,11 +901,11 @@ C:\GAMADV-XTD3>dir %GAMCFGDIR%
03/03/2017 10:15 AM 2,377 oauth2service.json
6 File(s) 15,769 bytes
3 Dir(s) 110,532,562,944 bytes free
C:\GAMADV-XTD3>
C:\>
```
If the verification looks like this, then you'll have to copy client_secrets.json and oauth2service.json manually.
```
C:\GAMADV-XTD3>dir %GAMCFGDIR%
C:\>dir %GAMCFGDIR%
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
@@ -911,13 +920,13 @@ C:\GAMADV-XTD3>dir %GAMCFGDIR%
3 File(s) 1,135 bytes
3 Dir(s) 110,532,562,944 bytes free
C:\GAMADV-XTD3>copy %OLDGAMPATH%\client_secrets.json %HOMEPATH%\.gam\
C:\>copy %OLDGAMPATH%\client_secrets.json %GAMCFGDIR%
1 file(s) copied.
C:\GAMADV-XTD3>copy %OLDGAMPATH%\oauth2service.json %HOMEPATH%\.gam\
C:\>copy %OLDGAMPATH%\oauth2service.json %GAMCFGDIR%
1 file(s) copied.
C:\GAMADV-XTD3>dir %GAMCFGDIR%
C:\>dir %GAMCFGDIR%
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
@@ -936,7 +945,7 @@ C:\GAMADV-XTD3>dir %GAMCFGDIR%
```
### Update your project with local browser to include the additional APIs that GAMADV-XTD3 uses.
```
C:\GAMADV-XTD3>gam update project
C:\>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -963,12 +972,12 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
C:\>
```
### Update your project without local browser (headless server for instance) to include the additional APIs that GAMADV-XTD3 uses
```
C:\GAMADV-XTD3>gam config no_browser true save
C:\GAMADV-XTD3>gam update project
C:\>gam config no_browser true save
C:\>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
@@ -997,7 +1006,7 @@ Enable 3 APIs
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
C:\>
```
### Enable GAMADV-XTD3 client access
@@ -1006,17 +1015,17 @@ Create oauth2.txt; it must be deleted and recreated because it is in a different
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version
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
GAMADV-XTD3 6.77.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
Windows-10-10.0.17134 AMD64
Path: C:\GAMADV-XTD3
Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
C:\GAMADV-XTD3>gam oauth create
C:\>gam oauth create
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
@@ -1097,12 +1106,12 @@ Enter verification code or paste "Unable to connect" URL from other computer (on
The authentication flow has completed.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Created
C:\GAMADV-XTD3>
C:\>
```
### Enable GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
C:\>gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
@@ -1156,7 +1165,7 @@ Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
C:\GAMADV-XTD3>
C:\>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
@@ -1166,7 +1175,7 @@ If not, make sure that you are logged in as a domain admin, then re-enter the li
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
C:\>gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
@@ -1210,14 +1219,14 @@ All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
C:\>
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
C:\GAMADV-XTD3>gam info domain
C:\>gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
@@ -1225,7 +1234,7 @@ Primary Domain Verified: True
Default Language: en
...
C:\GAMADV-XTD3>gam config customer_id C01234567 domain domain.com timezone local save verify
C:\>gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: C:\GAMConfig\gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
@@ -1344,5 +1353,5 @@ Section: DEFAULT
user_max_results = 500
user_service_account_access_only = false
C:\GAMADV-XTD3>
C:\>
```

View File

@@ -188,6 +188,7 @@ gam report usage customer [todrive <ToDriveAttribute>*]
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
[convertmbtogb]
```
Limit the time period.
* `start <Date>` - Default value is 30 days prior to `end <Date>`
@@ -196,6 +197,9 @@ Limit the time period.
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
Option `convertmbtogb` causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
### Example
Jay provided this example.
```
@@ -237,6 +241,7 @@ gam report customers|customer|domain [todrive <ToDriveAttributes>*]
[(nodatechange | limitdatechanges <Integer>) | (fulldatarequired all|<CustomerServiceNameList>)]
[(fields|parameters <String>)|(services <CustomerServiceNameList>)]
[noauthorizedapps]
[convertmbtogb]
```
Specify the report date; the default is today's date.
* `date <Date>` - A single date; there is one API call
@@ -246,6 +251,9 @@ Specify the report date; the default is today's date.
* `thismonth` - The current calendar month up to the current time; there is an API call per date
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month; there is an API call per date
Option `convertmbtogb` causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
If no report is available for the specified date, can an earlier date be used?
* `limitdatechanges -1' - Back up to earlier dates to find report data; this is the default.
* `limitdatechanges 0 | nodatechange' - Do not report on an earlier date if no report data is available for the specified date.
@@ -298,6 +306,7 @@ gam report usage user [todrive]
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
[convertmbtogb]
```
Select the users for whom information is desired.
* `user all` - All users, the default; there is one API call
@@ -313,6 +322,9 @@ Limit the time period.
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
Option `convertmbtogb` causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
## User reports
User reports are generally available up to four days before the current date.
```
@@ -335,6 +347,7 @@ gam report users|user [todrive <ToDriveAttributes>*]
[(fields|parameters <String>)|(services <UserServiceNameList>)]
[aggregatebydate|aggregatebyuser [Boolean]]
[maxresults <Number>]
[convertmbtogb]
```
Select the users for whom information is desired.
* `user all` - All users, the default; there is one API call
@@ -354,6 +367,9 @@ Specify the report date; the default is today's date.
* `thismonth` - The current calendar month up to the current time; there is an API call per date
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month; there is an API call per date
Option `convertmbtogb` causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
If no report is available for the specified date, can an earlier date be used?
* `limitdatechanges -1' - Back up to earlier dates to find report data; this is the default.
* `limitdatechanges 0 | nodatechange' - Do not report on an earlier date if no report data is available for the specified date.

View File

@@ -519,13 +519,17 @@ count = & gam print resources showitemcountonly
These commands operate on a single resource calendar.
```
gam resource <ResourceID> add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
[sendnotifications <Boolean>]
gam resource <ResourceID> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
[sendnotifications <Boolean>]
gam resource <ResourceID> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
```
These commands operate on multiple resource calendars.
```
gam resources <ResourceEntity> add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
[sendnotifications <Boolean>]
gam resources <ResourceEntity> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
[sendnotifications <Boolean>]
gam resources <ResourceEntity> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
```
## Display resource calendar ACLs

View File

@@ -429,7 +429,7 @@ If none of the following options are selected, all events are selected.
* `<EventSelectProperty>* <EventMatchProperty>*` - Properties used to select events
The Google Calendar API processes `<EventSelectProperty>*`; you may specify none or multiple properties.
* `after|starttime|timemin <Time>` - Lower bound (inclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `after|starttime|timemin <Time>` - Lower bound (exclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `before|endtime|timemax <Time>` - Upper bound (exclusive) for an event's start time to filter by. If timeMin is set, timeMax must be greater than timeMin.
* `eventtypes <EventTypeList>` - Select events based on their type.
* `query <QueryCalendar>` - Free text search terms to find events that match these terms in any field, except for extended properties

View File

@@ -28,7 +28,7 @@
- [Display file list](#display-file-list)
- [File selection by name and entity shortcuts for Display file list](#file-selection-by-name-and-entity-shortcuts-for-display-file-list)
- [File selection starting point for Display file list](#file-selection-starting-point-for-display-file-list)
- [File selection with a particular drive label](#file-selection-with-a-particular-drive-label)
- [File selection with or without a particular drive label](#file-selection-with-or-without-a-particular-drive-label)
- [Handle empty file lists](#handle-empty-file-lists)
- [Display disk usage](#display-disk-usage)
@@ -540,6 +540,9 @@ See: [Drive File Selection](Drive-File-Selection) for details of `<DriveFileName
my_3p_shortcuts |
my_items |
my_forms |
my_top_files |
my_top_folders |
my_top_items |
others_files |
others_folders |
others_forms |
@@ -1475,7 +1478,7 @@ testuser@domain.com,Bottom Folder 11,1,My Drive/Top Folder/Middle Folder 1/Botto
testuser@domain.com,Bottom Sheet 11,1,My Drive/Top Folder/Middle Folder 1/Bottom Folder 11/Bottom Sheet 11
```
## File selection with a particular drive label
## File selection with or without a particular drive label
The Drive API doesn't support querying for a drive label, so GAM must do the filtering.
Get the label id.
@@ -1485,9 +1488,13 @@ gam show drivelabels
Find the label with properties:title: XXX where XXX is the desired label title, then get its id: value
List the files.
List the files with the label
```
gam config csv_output_row_filter "labelInfo.labels.0.id:regex:PutLabelIdHere" user user@domain.com print filelist fields id,name,labelinfo includelabels PutLabelIdHere
gam config csv_output_row_filter "labels:count>0" user user@domain.com print filelist fields id,name,mimetype showlabels ids includelabels PutLabelIdHere
```
List the files without the label
```
gam config csv_output_row_filter "labels:count=0" user user@domain.com print filelist fields id,name,mimetype showlabels ids includelabels PutLabelIdHere
```
Adjust the `fields` list as desired.

View File

@@ -619,11 +619,10 @@ You may get the following error from Google when trying to download a file:
Download Failed: This file has been identified as malware or spam and cannot be downloaded.
```
Use the `acknowledgeabuse` option to control downloading the file.
* `acknowledgeabuse` - Download the file
* `acknowledgeabuse true` - Download the file
* `acknowledgeabuse` - Download the file; `the user is acknowledging the risk of downloading known malware or other abusive files`
* `acknowledgeabuse true` - Download the file; `the user is acknowledging the risk of downloading known malware or other abusive files`
* `acknowledgeabuse false` - Do not download the file; this is the default
Whether the user is acknowledging the risk of downloading known malware or other abusive files.
### Example: Download a CSV file and execute a Gam command on its contents
Suppose you have a Google Sheets file UserSheet with multiple sheets, one of which is named NewUsers; it has a column labelled primaryEmail.

View File

@@ -203,6 +203,17 @@ File Sheet.json contains:
gam user testuser@domain.com update sheet <DriveFileItem> json file Sheet.json
```
Rename a tab/sheet in a spreadsheet.
```
Get the sheet IDs.
gam user testuser@domain.com info sheet <DriveFileItem> fields sheets
Get the desired sheetId from the output.
File Sheet.json contains:
{"requests": [{"updateSheetProperties": {"properties": {"sheetId": 1234567890, "title": "New Title"}, "fields": "title"}}]}
gam user testuser@domain.com update sheet <DriveFileItem> json file Sheet.json
```
Delete a column from a tab in a spreadsheet.
```
Get the sheet IDs.

View File

@@ -3,6 +3,7 @@
- [Definitions](#definitions)
- [Delete a user's token](#delete-a-users-token)
- [Display individual user's tokens](#display-individual-users-tokens)
- [Display individual user's token counts](#display-individual-users-token-counts)
- [Display aggregated user's tokens](#display-aggregated-users-tokens)
## API documentation
@@ -27,6 +28,9 @@ gam <UserTypeEntity> show tokens|token|3lo|oauth [clientid <ClientID>]
gam print tokens|token [todrive <ToDriveAttributes>*] [clientid <ClientID>]
[orderby clientid|id|appname|displaytext] [delimiter <Character>]
[<UserTypeEntity>]
gam show tokens|token [clientid <ClientID>]
[orderby clientid|id|appname|displaytext] [delimiter <Character>]
[<UserTypeEntity>]
```
By default, all client tokens for a user are displayed, use `clientid <ClientID>` to display a specific client token.
@@ -43,6 +47,26 @@ This example shows which domain users have the Google Apps Sync for Microsoft Ou
gam all users print token clientid 1095133494869.apps.googleusercontent.com
```
## Display individual user's token counts
```
gam <UserTypeEntity> print tokens|token [todrive <ToDriveAttributes>*] [clientid <ClientID>]
usertokencounts
gam <UserTypeEntity> show tokens|token|3lo|oauth [clientid <ClientID>]
usertokencounts
gam print tokens|token [todrive <ToDriveAttributes>*] [clientid <ClientID>]
usertokencounts
[<UserTypeEntity>]
gam show tokens|token [clientid <ClientID>]
usertokencounts
[<UserTypeEntity>]
```
### Example
This example shows which domain users have any access tokens.
```
gam config csv_output_row_filter "tokenCount:count>0" all users print tokens usertokencounts
```
## Display aggregated user's tokens
```
gam <UserTypeEntity> print tokens|token [todrive <ToDriveAttributes>*] [clientid <ClientID>]

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAMADV-XTD3 6.77.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 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
GAMADV-XTD3 6.77.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 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
GAMADV-XTD3 6.77.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 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/gamadv-xtd3
Version Check:
Current: 5.35.08
Latest: 6.77.05
Latest: 6.77.14
echo $?
1
```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
6.77.05
6.77.14
```
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 6.77.05 - https://github.com/taers232c/GAMADV-XTD3
GAM 6.77.14 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64

View File

@@ -1073,6 +1073,7 @@ Specify a collection of items by directly specifying them; the item type is dete
others_3p_shortcuts |
others_items |
writable_files
<DriveFileEntityShortcut> ::=
alldrives |
mydrive_any |
@@ -1088,6 +1089,7 @@ Specify a collection of items by directly specifying them; the item type is dete
sharedwithme_all |
sharedwithme_mydrive |
sharedwithme_notmydrive
<DriveFileEntity> ::=
<DriveFileIDEntity> |
<DriveFileNameEntity> |
@@ -4269,11 +4271,13 @@ gam report usage user [todrive <ToDriveAttribute>*]
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
[convertmbtogb]
gam report usage customer [todrive <ToDriveAttribute>*]
[([start|startdate <Date>] [end|enddate <Date>])|(range <Date> <Date>)|
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
[convertmbtogb]
<ActivityApplicationName> ::=
access|accesstransparency|
@@ -4333,6 +4337,7 @@ gam report customers|customer|domain [todrive <ToDriveAttribute>*]
yesterday|today|thismonth|(previousmonths <Integer>)]
[(nodatechange | limitdatechanges <Integer>) | (fulldatarequired all|<CustomerServiceNameList>)]
[(fields|parameters <String>)|(services <CustomerServiceNameList>)] [noauthorizedapps]
[convertmbtogb]
<UserServiceName> ::=
accounts|
@@ -4353,6 +4358,7 @@ gam report users|user [todrive <ToDriveAttribute>*]
[(fields|parameters <String>)|(services <UserServiceNameList>)]
[aggregatebydate|aggregatebyuser [Boolean]]
[maxresults <Number>]
[convertmbtogb]
# Reseller
@@ -6462,6 +6468,7 @@ gam <UserTypeEntity> get drivefile <DriveFileEntity> [revision <DriveFileRevisio
[(format <FileFormatList>)|(gsheet|csvsheet <SheetEntity>)] [exportsheetaspdf <String>]
[targetfolder <FilePath>] [targetname <FileName>|-]
[donotfollowshortcuts [<Boolean>]] [overwrite [<Boolean>]] [showprogress [<Boolean>]]
[acknowledgeabuse [<Boolean>]]
gam <UserTypeEntity> delete drivefile <DriveFileEntity> [purge|untrash|trash]
gam <UserTypeEntity> purge drivefile <DriveFileEntity>
@@ -8180,11 +8187,18 @@ gam <UserTypeEntity> show sheetrange <DriveFileEntity>
gam <UserTypeEntity> delete tokens clientid <ClientID>
gam <UserTypeEntity> print tokens|token [todrive <ToDriveAttribute>*] [clientid <ClientID>]
[aggregateby|orderby clientid|id|appname|displaytext] [delimiter <Character>]
[usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)]
[delimiter <Character>]
gam <UserTypeEntity> show tokens|token|3lo|oauth [clientid <ClientID>]
[aggregateby|orderby clientid|id|appname|displaytext]
[usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)]
[delimiter <Character>]
gam print tokens|token [todrive <ToDriveAttribute>*] [clientid <ClientID>]
[aggregateby|orderby clientid|id|appname|displaytext] [delimiter <Character>]
[usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)]
[delimiter <Character>]
[<UserTypeEntity>]
gam show tokens|token [clientid <ClientID>]
[usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)]
[delimiter <Character>]
[<UserTypeEntity>]
# Users - YouTube

View File

@@ -2,6 +2,52 @@
Merged GAM-Team version
6.77.14
Fixed bug in `gam calendars <CalendarEntity> import event icaluid <iCalUID> json <JSONdata>` that caused an error.
6.77.13
Updated `gam <UserTypeEntity> print|show filecounts` to reflect that Shared Drives now
have a capacity of 500000 files/folders/shortcuts.
6.77.12
Fixed bug in `gam <UserTypeEntity> print chatspaces todrive` that caused an error.
6.77.11
Added option `convertmbtogb` to `gam report usage customer|user` and
`gam report customer|user` that causes GAM to convert parameters expressed in megabytes
(name ends with _in_mb) to gigabytes (name converted to _in_gb) with two decimal places.
6.77.10
Fixed bug in `gam <UserTypeEntity> get profilephoto` where data written to stdout, e.g. `> filename`,
was not properly base64 encoded.
6.77.09
Added option `usertokencounts` to `gam <UserTypeEntity> print|show tokens` that causes GAM to display
each user and their number of access tokens; there are no details.
6.77.08
Fixed bugs in `gam <UserTypeEntity> delete chatmember <ChatSpace> ... group <GroupItem>`
and `gam <UserTypeEntity> sync chatmember <ChatSpace> ... groups <GroupEntity>` that caused an error.
6.77.07
Fixed bug in `gam <UserTypeEntity> create chatmember <ChatSpace> ... group <GroupItem>` that caused an error.
6.77.06
Updated `gam update ou <OrgUnitItem> ... parent <OrgUnitItem>` to handle the following error
that occurs when `parent <OrgUnitItem>` is the same as or a sub-OU of `ou <OrgUnitItem>`.
```
ERROR: 412: conditionNotMet - OrgUnit hierarchy has cycle
```
6.77.05
Added option `onlyusers <UserTypeEntity>` to `gam <UserTypeEntity> claim ownership <DriveFileEntity>`

View File

@@ -216,7 +216,7 @@ SECONDS_PER_DAY = 86400
SECONDS_PER_WEEK = 604800
MAX_GOOGLE_SHEET_CELLS = 10000000 # See https://support.google.com/drive/answer/37603
MAX_LOCAL_GOOGLE_TIME_OFFSET = 30
SHARED_DRIVE_MAX_FILES_FOLDERS = 400000
SHARED_DRIVE_MAX_FILES_FOLDERS = 500000
UTF8 = 'utf-8'
UTF8_SIG = 'utf-8-sig'
EV_GAMCFGDIR = 'GAMCFGDIR'
@@ -5703,6 +5703,8 @@ def convertUIDtoEmailAddressWithType(emailAddressOrUID, cd=None, sal=None, email
# Convert UID to email address
def convertUIDtoEmailAddress(emailAddressOrUID, cd=None, emailTypes=None,
checkForCustomerId=False, ciGroupsAPI=False, aliasAllowed=True):
if emailAddressOrUID.startswith('cbcm-browser.'):
return emailAddressOrUID
email, _ = convertUIDtoEmailAddressWithType(emailAddressOrUID, cd, emailTypes,
checkForCustomerId, ciGroupsAPI, aliasAllowed)
return email
@@ -13063,6 +13065,12 @@ def getUserOrgUnits(cd, orgUnit, orgUnitId):
GAPI.invalidCustomerId, GAPI.loginRequired, GAPI.resourceNotFound, GAPI.forbidden):
checkEntityDNEorAccessErrorExit(cd, Ent.ORGANIZATIONAL_UNIT, orgUnit)
# Convert report mb item to gb
def convertReportMBtoGB(name, item):
if item is not None:
item['intValue'] = f"{int(item['intValue'])/1024:.2f}"
return name.replace('_in_mb', '_in_gb')
REPORTS_PARAMETERS_SIMPLE_TYPES = ['intValue', 'boolValue', 'datetimeValue', 'stringValue']
# gam report usage user [todrive <ToDriveAttribute>*]
@@ -13070,10 +13078,12 @@ REPORTS_PARAMETERS_SIMPLE_TYPES = ['intValue', 'boolValue', 'datetimeValue', 'st
# [([start|startdate <Date>] [end|enddate <Date>])|(range <Date> <Date>)|
# thismonth|(previousmonths <Integer>)]
# [fields|parameters <String>)]
# [convertmbtogb]
# gam report usage customer [todrive <ToDriveAttribute>*]
# [([start|startdate <Date>] [end|enddate <Date>])|(range <Date> <Date>)|
# thismonth|(previousmonths <Integer>)]
# [fields|parameters <String>)]
# [convertmbtogb]
def doReportUsage():
def usageEntitySelectors():
selectorChoices = Cmd.USER_ENTITY_SELECTORS+Cmd.USER_CSVDATA_ENTITY_SELECTORS
@@ -13118,7 +13128,7 @@ def doReportUsage():
if customerId == GC.MY_CUSTOMER:
customerId = None
parameters = set()
select = showOrgUnit = False
convertMbToGb = select = showOrgUnit = False
userKey = 'all'
cd = orgUnit = orgUnitId = None
userOrgUnits = {}
@@ -13178,6 +13188,8 @@ def doReportUsage():
_, users = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
orgUnit = orgUnitId = None
select = True
elif myarg == 'convertmbtogb':
convertMbToGb = True
else:
unknownArgumentExit()
if startEndTime.endDateTime is None:
@@ -13259,6 +13271,8 @@ def doReportUsage():
for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES:
if ptype in item:
if ptype != 'datetimeValue':
if convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, item)
row[name] = item[ptype]
else:
row[name] = formatLocalTime(item[ptype])
@@ -13361,11 +13375,13 @@ REPORT_ACTIVITIES_TIME_OBJECTS = {'time'}
# [(fields|parameters <String>)|(services <UserServiceNameList>)]
# [aggregatebydate|aggregatebyuser [Boolean]]
# [maxresults <Number>]
# [convertmbtogb]
# gam report customers|customer|domain [todrive <ToDriveAttribute>*]
# [(date <Date>)|(range <Date> <Date>)|
# yesterday|today|thismonth|(previousmonths <Integer>)]
# [nodatechange | (fulldatarequired all|<CustomerServiceNameList>)]
# [(fields|parameters <String>)|(services <CustomerServiceNameList>)] [noauthorizedapps]
# [convertmbtogb]
def doReport():
def processUserUsage(usage, lastDate):
if not usage:
@@ -13399,6 +13415,8 @@ def doReport():
csvPF.AddTitles('accounts:disabled_time')
except ValueError:
pass
elif convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, item)
csvPF.AddTitles(name)
for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES:
if ptype in item:
@@ -13432,6 +13450,8 @@ def doReport():
if repsvc not in includeServices:
continue
if 'intValue' in item:
if convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, None)
csvPF.AddTitles(name)
eventCounts.setdefault(email, {})
eventCounts[email].setdefault(name, 0)
@@ -13455,6 +13475,8 @@ def doReport():
if repsvc not in includeServices:
continue
if 'intValue' in item:
if convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, None)
csvPF.AddTitles(name)
eventCounts.setdefault(lastDate, {})
eventCounts[lastDate].setdefault(name, 0)
@@ -13477,6 +13499,8 @@ def doReport():
continue
for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES:
if ptype in item:
if convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, item)
csvPF.AddTitles(name)
if ptype != 'datetimeValue':
row[name] = item[ptype]
@@ -13541,6 +13565,8 @@ def doReport():
for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES:
if ptype in item:
if ptype != 'datetimeValue':
if convertMbToGb and name.endswith('_in_mb'):
name = convertReportMBtoGB(name, item)
csvPF.WriteRow({'date': lastDate, 'name': name, 'value': item[ptype]})
else:
csvPF.WriteRow({'date': lastDate, 'name': name, 'value': formatLocalTime(item[ptype])})
@@ -13610,8 +13636,8 @@ def doReport():
filterTimes = {}
maxActivities = maxEvents = 0
maxResults = 1000
aggregateByDate = aggregateByUser = countsOnly = eventRowFilter = exitUserLoop = noAuthorizedApps = \
normalizeUsers = select = summary = userCustomerRange = False
aggregateByDate = aggregateByUser = convertMbToGb = countsOnly = eventRowFilter = exitUserLoop = \
noAuthorizedApps = normalizeUsers = select = summary = userCustomerRange = False
limitDateChanges = -1
allVerifyUser = userKey = 'all'
cd = orgUnit = orgUnitId = None
@@ -13690,6 +13716,8 @@ def doReport():
includeServices.add(repsvc)
else:
invalidChoiceExit(repsvc, fullDataServices, True)
elif usageReports and myarg == 'convertmbtogb':
convertMbToGb = True
elif customerReports and myarg == 'noauthorizedapps':
noAuthorizedApps = True
elif activityReports and myarg == 'maxactivities':
@@ -13861,6 +13889,8 @@ def doReport():
for usageDate, events in iter(eventCounts.items()):
row = {'date': usageDate}
for event, count in iter(events.items()):
if convertMbToGb and event.endswith('_in_gb'):
count = f'{count/1024:.2f}'
row[event] = count
csvPF.WriteRow(row)
csvPF.SortRows('date', False)
@@ -13871,6 +13901,8 @@ def doReport():
if showOrgUnit:
row['orgUnitPath'] = userOrgUnits.get(email, UNKNOWN)
for event, count in iter(events.items()):
if convertMbToGb and event.endswith('_in_gb'):
count = f'{count/1024:.2f}'
row[event] = count
csvPF.WriteRow(row)
csvPF.SortRows('email', False)
@@ -16434,12 +16466,12 @@ def doDeleteAdmin():
callGAPI(cd.roleAssignments(), 'delete',
throwReasons=[GAPI.NOT_FOUND, GAPI.OPERATION_NOT_SUPPORTED, GAPI.FORBIDDEN,
GAPI.INVALID_INPUT, GAPI.SERVICE_NOT_AVAILABLE, GAPI.RESOURCE_NOT_FOUND,
GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND],
GAPI.FAILED_PRECONDITION, GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
customer=GC.Values[GC.CUSTOMER_ID], roleAssignmentId=roleAssignmentId)
entityActionPerformed([Ent.ADMIN_ROLE_ASSIGNMENT, roleAssignmentId])
except (GAPI.notFound, GAPI.operationNotSupported, GAPI.forbidden,
GAPI.invalidInput, GAPI.serviceNotAvailable, GAPI.resourceNotFound) as e:
GAPI.invalidInput, GAPI.serviceNotAvailable, GAPI.resourceNotFound, GAPI.failedPrecondition) as e:
entityActionFailedWarning([Ent.ADMIN_ROLE_ASSIGNMENT, roleAssignmentId], str(e))
except (GAPI.badRequest, GAPI.customerNotFound):
accessErrorExit(cd)
@@ -17213,13 +17245,15 @@ def _doUpdateOrgs(entityList):
try:
callGAPI(cd.orgunits(), 'update',
throwReasons=[GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND, GAPI.BACKEND_ERROR, GAPI.INVALID_ORGUNIT_NAME,
GAPI.BAD_REQUEST, GAPI.INVALID_CUSTOMER_ID, GAPI.LOGIN_REQUIRED],
GAPI.CONDITION_NOT_MET, GAPI.BAD_REQUEST, GAPI.INVALID_CUSTOMER_ID, GAPI.LOGIN_REQUIRED],
customerId=GC.Values[GC.CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(orgUnitPath)), body=body, fields='')
entityActionPerformed([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], i, count)
except (GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.backendError):
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.DOES_NOT_EXIST, i, count)
except GAPI.invalidOrgunitName as e:
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath, Ent.NAME, body['name']], str(e), i, count)
except GAPI.conditionNotMet as e:
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], str(e), i, count)
except (GAPI.badRequest, GAPI.invalidCustomerId, GAPI.loginRequired):
checkEntityAFDNEorAccessErrorExit(cd, Ent.ORGANIZATIONAL_UNIT, orgUnitPath)
@@ -25668,7 +25702,7 @@ def printShowChatSpaces(users):
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
if getFieldsList(myarg, CHAT_SPACES_FIELDS_CHOICE_MAP, fieldsList, initialField='name', onlyFieldsArg=True):
elif getFieldsList(myarg, CHAT_SPACES_FIELDS_CHOICE_MAP, fieldsList, initialField='name', onlyFieldsArg=True):
pass
elif not useAdminAccess and _getChatSpaceListParms(myarg, kwargs):
pass
@@ -25729,6 +25763,12 @@ 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):
userList.append(convertEmailAddressToUID(user, cd, emailType='user'))
def normalizeGroupMember(cd, group, groupList):
groupList.append(convertEmailAddressToUID(group, cd, emailType='group'))
# gam <UserTypeEntity> create chatmember <ChatSpace>
# [type human|bot] [role member|manager]
# (user <UserItem>)* (members <UserTypeEntity>)*
@@ -25789,14 +25829,16 @@ def createChatMember(users):
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
parent = getChatSpace(myarg)
elif myarg == 'user':
userList.append(getEmailAddress(returnUIDprefix='uid:'))
normalizeUserMember(cd, getEmailAddress(returnUIDprefix='uid:'), userList)
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
userList.extend(members)
for user in members:
normalizeUserMember(cd, user, userList)
elif myarg == 'group':
groupList.append(getEmailAddress(returnUIDprefix='uid:'))
normalizeGroupMember(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
elif myarg == 'groups':
groupList.extend(getEntityList(Cmd.OB_GROUP_ENTITY))
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
elif myarg == 'role':
role = getChoice(CHAT_MEMBER_ROLE_MAP, mapChoice=True)
elif myarg == 'type':
@@ -25812,12 +25854,10 @@ def createChatMember(users):
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER
userMembers = []
for user in userList:
name = normalizeEmailAddressOrUID(user)
userMembers.append({'member': {'name': f'users/{name}', 'type': mtype}})
userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}})
groupMembers = []
for group in groupList:
name = normalizeEmailAddressOrUID(group)
groupMembers.append({'groupMember': {'name': f'groups/{name}'}})
groupMembers.append({'groupMember': {'name': f'groups/{group}'}})
i, count, users = getEntityArgument(users)
if useAdminAccess:
_chkChatAdminAccess(count)
@@ -25879,7 +25919,8 @@ def deleteUpdateChatMember(users):
parent = None
body = {}
memberNames = []
userGroupList = []
userList = []
groupList = []
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
@@ -25895,14 +25936,16 @@ def deleteUpdateChatMember(users):
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
parent = getChatSpace(myarg)
elif myarg == 'user':
userGroupList.append(getEmailAddress(returnUIDprefix='uid:'))
normalizeUserMember(cd, getEmailAddress(returnUIDprefix='uid:'), userList)
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
userGroupList.extend(members)
for user in members:
normalizeUserMember(cd, user, userList)
elif deleteMode and myarg == 'group':
userGroupList.append(getEmailAddress(returnUIDprefix='uid:'))
normalizeGroupMember(cd, getEmailAddress(returnUIDprefix='uid:'), groupList)
elif deleteMode and myarg == 'groups':
userGroupList.extend(getEntityList(Cmd.OB_GROUP_ENTITY))
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
else:
unknownArgumentExit()
if not deleteMode and 'role' not in body:
@@ -25913,11 +25956,12 @@ def deleteUpdateChatMember(users):
else: # {Act.DELETE, Act.UPDATE}
if not parent:
missingArgumentExit('space')
if not userGroupList:
if not userList and not groupList:
missingArgumentExit('user|members|group|groups')
for user in userGroupList:
name = normalizeEmailAddressOrUID(user)
memberNames.append(f'{parent}/members/{name}')
for user in userList:
memberNames.append(f'{parent}/members/{user}')
for group in groupList:
memberNames.append(f'{parent}/members/group-{group}')
i, count, users = getEntityArgument(users)
if useAdminAccess:
_chkChatAdminAccess(count)
@@ -26022,6 +26066,7 @@ def syncChatMembers(users):
role = CHAT_MEMBER_ROLE_MAP['member']
mtype = CHAT_MEMBER_TYPE_MAP['human']
syncOperation = 'addremove'
kwargs = {}
preview = False
csvPF = None
userList = []
@@ -26043,14 +26088,17 @@ def syncChatMembers(users):
elif myarg == 'actioncsv':
csvPF = CSVPrintFile(CHAT_SYNC_PREVIEW_TITLES)
elif myarg == 'users':
userList.extend(getEntityList(Cmd.OB_USER_ENTITY))
for user in getEntityList(Cmd.OB_USER_ENTITY):
normalizeUserMember(cd, user, userList)
usersSpecified = True
elif myarg in {'member', 'members'}:
_, members = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
userList.extend(members)
for user in members:
normalizeUserMember(cd, user, userList)
usersSpecified = True
elif myarg == 'groups':
groupList.extend(getEntityList(Cmd.OB_GROUP_ENTITY))
for group in getEntityList(Cmd.OB_GROUP_ENTITY):
normalizeGroupMember(cd, group, groupList)
groupsSpecified = True
else:
unknownArgumentExit()
@@ -26060,20 +26108,19 @@ def syncChatMembers(users):
userMembers = {}
syncUsersSet = set()
for user in userList:
name = normalizeEmailAddressOrUID(user)
memberName = f'{parent}/members/{name}'
userMembers[memberName] = {'member': {'name': f'users/{name}', 'type': mtype}}
memberName = f'{parent}/members/{user}'
userMembers[memberName] = {'member': {'name': f'users/{user}', 'type': mtype}}
syncUsersSet.add(memberName)
groupMembers = {}
syncGroupsSet = set()
for group in groupList:
name = normalizeEmailAddressOrUID(group)
memberName = f'{parent}/members/{name}'
groupMembers[memberName] = {'groupMember': {'name': f'groups/{name}'}}
memberName = f'{parent}/members/group-{group}'
groupMembers[memberName] = {'groupMember': {'name': f'groups/{group}'}}
syncGroupsSet.add(memberName)
qfilter = f'{Ent.Singular(Ent.CHAT_SPACE)}: {parent}'
i, count, users = getEntityArgument(users)
if useAdminAccess:
kwargs['filter'] = 'member.type != "BOT"'
_chkChatAdminAccess(count)
for user in users:
i += 1
@@ -26086,15 +26133,13 @@ def syncChatMembers(users):
members = callGAPIpages(chat.spaces().members(), 'list', 'memberships',
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
pageSize=CHAT_PAGE_SIZE, parent=parent, showGroups=groupsSpecified, **kwargsUAA)
parent=parent, showGroups=groupsSpecified, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
for member in members:
if 'member' in member:
if member['member']['type'] == mtype and member['role'] == role:
_getChatMemberEmail(cd, member)
currentUsersSet.add(f"{parent}/members/{member['member']['email']}")
currentUsersSet.add(member['name'])
elif 'groupMember' in member:
_getChatMemberEmail(cd, member)
currentGroupsSet.add(f"{parent}/members/{member['groupMember']['email']}")
currentGroupsSet.add(member['name'])
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue
@@ -36873,7 +36918,7 @@ def _getCalendarEventAttribute(myarg, body, parameters, function):
parameters['attendees'].append(addAttendee)
elif myarg == 'json':
jsonData = getJSON(EVENT_JSON_CLEAR_FIELDS)
if function == 'insert':
if function in {'insert', 'import'}:
body.update(jsonData)
clearJSONfields(body, EVENT_JSON_INSERT_CLEAR_FIELDS)
elif function == 'update':
@@ -59160,6 +59205,7 @@ HTTP_ERROR_PATTERN = re.compile(r'^.*returned "(.*)">$')
# [(format <FileFormatList>)|(gsheet|csvsheet <SheetEntity>)] [exportsheetaspdf <String>]
# [targetfolder <FilePath>] [targetname -|<FileName>]
# [donotfollowshortcuts [<Boolean>]] [overwrite [<Boolean>]] [showprogress [<Boolean>]]
# [acknowledgeabuse [<Boolean>]]
def getDriveFile(users):
def closeRemoveTargetFile(f):
if f and not targetStdout:
@@ -65741,7 +65787,7 @@ def getPhoto(users, profileMode):
entityActionFailedWarning([Ent.USER, user, Ent.PHOTO, filename], Msg.NOT_ALLOWED, i, count)
continue
if showPhotoData:
writeStdout(base64.urlsafe_b64encode(photo_data).decode(UTF8)+'\n')
writeStdout(base64.encodebytes(photo_data).decode(UTF8))
except (httplib2.HttpLib2Error, google.auth.exceptions.TransportError, RuntimeError) as e:
entityActionFailedWarning([Ent.USER, user, Ent.PHOTO, filename], str(e), i, count)
continue
@@ -66420,7 +66466,7 @@ def deleteTokens(users):
TOKENS_FIELDS_TITLES = ['clientId', 'displayText', 'anonymous', 'nativeApp', 'userKey', 'scopes']
TOKENS_AGGREGATE_FIELDS_TITLES = ['clientId', 'displayText', 'anonymous', 'nativeApp', 'users', 'scopes']
TOKENS_ORDERBY_CHOICE_MAP = {
TOKENS_AGGREGATE_ORDERBY_CHOICE_MAP = {
'clientid': 'clientId',
'id': 'clientId',
'displaytext': 'displayText',
@@ -66429,6 +66475,7 @@ TOKENS_ORDERBY_CHOICE_MAP = {
TOKENS_TITLE_MAP = {
'clientId': 'Client ID',
'displayText': 'App Name',
'user': 'user',
}
def _printShowTokens(entityType, users):
@@ -66470,11 +66517,13 @@ def _printShowTokens(entityType, users):
elif myarg == 'clientid':
clientId = commonClientIds(getString(Cmd.OB_CLIENT_ID))
elif myarg == 'orderby':
orderBy = getChoice(TOKENS_ORDERBY_CHOICE_MAP, mapChoice=True)
orderBy = getChoice(TOKENS_AGGREGATE_ORDERBY_CHOICE_MAP, mapChoice=True)
elif myarg == 'aggregateusersby':
aggregateUsersBy = getChoice(TOKENS_ORDERBY_CHOICE_MAP, mapChoice=True)
aggregateUsersBy = getChoice(TOKENS_AGGREGATE_ORDERBY_CHOICE_MAP, mapChoice=True)
if aggregateUsersBy == 'displayText':
tokenNameIdMap = {}
elif myarg == 'usertokencounts':
aggregateUsersBy = 'user'
elif myarg == 'delimiter':
delimiter = getCharacter()
elif not entityType:
@@ -66487,8 +66536,10 @@ def _printShowTokens(entityType, users):
if csvPF:
if not aggregateUsersBy:
csvPF.SetTitles(['user']+TOKENS_FIELDS_TITLES)
else:
elif aggregateUsersBy != 'user':
csvPF.SetTitles(TOKENS_AGGREGATE_FIELDS_TITLES)
else:
csvPF.SetTitles(['user', 'tokenCount'])
else:
if not aggregateUsersBy:
tokenTitle = TOKENS_TITLE_MAP[orderBy]
@@ -66513,8 +66564,8 @@ def _printShowTokens(entityType, users):
throwReasons=[GAPI.USER_NOT_FOUND, GAPI.DOMAIN_NOT_FOUND,
GAPI.DOMAIN_CANNOT_USE_APIS, GAPI.FORBIDDEN, GAPI.BAD_REQUEST],
userKey=user, fields=f'items({fields})')
jcount = len(results)
if not aggregateUsersBy:
jcount = len(results)
if not csvPF:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.ACCESS_TOKEN, i, count)
Ind.Increment()
@@ -66533,7 +66584,7 @@ def _printShowTokens(entityType, users):
csvPF.WriteRow(row)
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT]:
csvPF.WriteRowNoFilter({'user': user})
else:
elif aggregateUsersBy != 'user':
if results:
for token in results:
tokcid = token['clientId']
@@ -66547,6 +66598,8 @@ def _printShowTokens(entityType, users):
if tokname not in tokenNameIdMap:
tokenNameIdMap[tokname] = set()
tokenNameIdMap[tokname].add(tokcid)
else: # aggregateUsersBy == 'user':
aggregateTokensById[user] = jcount
except (GAPI.notFound, GAPI.resourceNotFound) as e:
entityActionFailedWarning([Ent.USER, user, Ent.ACCESS_TOKEN, clientId], str(e), i, count)
except (GAPI.userNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden, GAPI.badRequest):
@@ -66579,20 +66632,33 @@ def _printShowTokens(entityType, users):
for _, tokenIds in sorted(iter(tokenNameIdMap.items())):
for tokcid in sorted(tokenIds):
_printToken(aggregateTokensById[tokcid])
else: # aggregateUsersBy == 'user':
if not csvPF:
jcount = len(aggregateTokensById)
j = 0
for user, count in sorted(iter(aggregateTokensById.items())):
j += 1
printEntityKVList([Ent.USER, user], [Ent.Plural(Ent.ACCESS_TOKEN), count], j, jcount)
else:
for user, count in sorted(iter(aggregateTokensById.items())):
csvPF.WriteRow({'user': user, 'tokenCount': count})
if csvPF:
csvPF.writeCSVfile('OAuth Tokens')
# gam <UserTypeEntity> print tokens|token [todrive <ToDriveAttribute>*] [clientid <ClientID>]
# [aggregateusersby|orderby clientid|id|appname|displaytext] [delimiter <Character>]
# [usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)] [delimiter <Character>]
# gam <UserTypeEntity> show tokens|token|3lo|oauth [clientid <ClientID>]
# [aggregateusersby|orderby clientid|id|appname|displaytext]
# [usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)] [delimiter <Character>]
def printShowTokens(users):
_printShowTokens(Cmd.ENTITY_USERS, users)
# gam print tokens|token [todrive <ToDriveAttribute>*] [clientid <ClientID>]
# [aggregateusersby|orderby clientid|id|appname|displaytext] [delimiter <Character>]
# [usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)] [delimiter <Character>]
# [<UserTypeEntity>]
def doPrintTokens():
# gam show tokens|token [clientid <ClientID>]
# [usertokencounts|(aggregateusersby|orderby clientid|id|appname|displaytext)] [delimiter <Character>]
# [<UserTypeEntity>]
def doPrintShowTokens():
_printShowTokens(None, None)
# gam <UserTypeEntity> deprovision|deprov [popimap] [signout] [turnoff2sv]
@@ -73844,7 +73910,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_SITEACL: doProcessDomainSiteACLs,
Cmd.ARG_SITEACTIVITY: doPrintDomainSiteActivity,
Cmd.ARG_SVCACCT: doPrintShowSvcAccts,
Cmd.ARG_TOKEN: doPrintTokens,
Cmd.ARG_TOKEN: doPrintShowTokens,
Cmd.ARG_TRANSFERAPPS: doShowTransferApps,
Cmd.ARG_USER: doPrintUsers,
Cmd.ARG_USERS: doPrintUsers,
@@ -73959,6 +74025,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_SITE: doPrintShowDomainSites,
Cmd.ARG_SITEACL: doProcessDomainSiteACLs,
Cmd.ARG_SVCACCT: doPrintShowSvcAccts,
Cmd.ARG_TOKEN: doPrintShowTokens,
Cmd.ARG_TRANSFERAPPS: doShowTransferApps,
Cmd.ARG_USERINVITATION: doPrintShowCIUserInvitations,
Cmd.ARG_VAULTEXPORT: doPrintShowVaultExports,