Multiple updates

This commit is contained in:
Ross Scroggs
2023-09-15 19:44:26 -07:00
parent effa972a40
commit d16ce28ee5
25 changed files with 490 additions and 413 deletions

View File

@ -100,6 +100,7 @@ gam print aliases [todrive <ToDriveAttribute>*]
```
By default, group and user aliases in all domains in the account are selected; these options allow selection of subsets of aliases:
* `domain|domains <DomainNameEntity>` - Limit aliases to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Print aliases for users/groups that match a query; each query is run against each domain
* `limittoou <OrgUnitItem>` - Print aliases for users in the specified `<OrgUnitItem>`
* `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`

View File

@ -371,12 +371,6 @@
<CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String>
<CustomerID> ::= <String>
<DataStudioAssetID> ::= <String>
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DeliverySetting> ::=
allmail|
abridged|daily|
@ -452,6 +446,12 @@
<LabelID> ::= Label_<String>
<LabelName> ::= <String>
<LabelReplacement> ::= <String>
<LookerStudioAssetID> ::= <String>
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted

View File

@ -556,9 +556,13 @@ is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- You can predefine this item with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- You can predefine this item with the `print_cros_ous_and_children` variable in `gam.cfg`.
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- You can predefine this list with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
- You can predefine this list with the `print_cros_ous_and_children` variable in `gam.cfg`.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
@ -704,9 +708,13 @@ is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- You can predefine this item with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- You can predefine this item with the `print_cros_ous_and_children` variable in `gam.cfg`.
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- You can predefine this list with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
- You can predefine this list with the `print_cros_ous_and_children` variable in `gam.cfg`.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.

View File

@ -165,10 +165,6 @@ Data fields identified in a `csvkmd` argument.
<CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>)
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DeviceIDEntity> ::=
<DeviceIDList> | (device_sn <SerialNumber>)
(query:<QueryDevice>) | (query <QueryDevice>)
@ -282,6 +278,10 @@ Data fields identified in a `csvkmd` argument.
<LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelNameEntity> ::=
<LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioAssetIDEntity> ::=
<LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MessageIDEntity> ::=
<MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MobileEntity> ::=

View File

@ -3,6 +3,7 @@
- [Windows Command Prompt](#windows-command-prompt)
- [Windows PowerShell](#windows-powershell)
- [List quoting rules](#list-quoting-rules)
- [Queries example](#queries-example)
## Linux and MacOS
@ -60,3 +61,19 @@ Typically, you will enclose the entire list in double quotes and quote each item
* ```"'it em' 'it,em' \"it'em\""```
Typical places where these rules apply are lists of OUs and Contact Groups.
## Queries example
### Linux and MacOS
```
gam print users queries "\"orgUnitPath='/Students/Lower School/2027'\",\"orgUnitPath='/Students/Lower School/2028'\""
```
### Windows Command Prompt
```
gam print users queries "\"orgUnitPath='/Students/Lower School/2027'\",\"orgUnitPath='/Students/Lower School/2028'\""
```
### Windows Power Shell
```
gam print users queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Students/Lower\ School/2028\'`""
```

View File

@ -10,6 +10,27 @@ 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.63.15
Added `print_cros_ous` and `print_cros_ous_and_children` variables to `gam.cfg` that provide a default list of OUs for these commands:
```
gam print cros
gam print crosactivity
```
Updated `group` commands that manage members to handle the following error:
```
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
```
Updated Data Studio to Looker Studio; added the following command synonyms:
* `lookerstudioassets` for `datastudioassets`
* 'lookerstudiopermissions` for `datastudiopermissions`
Corrected error message in `gam add datastudiopermissions`:
* Old -`ERROR: Missing argument: Expected <DataStudioAssetMembersEntity>`
* New - `ERROR: Missing argument: Expected <LookerStudioPermissionEntity>
### 6.63.14
Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move

View File

@ -587,6 +587,7 @@ gam print group-members [todrive <ToDriveAttribute>*]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain
@ -698,6 +699,7 @@ gam show group-members
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain

View File

@ -429,6 +429,7 @@ gam print groups [todrive <ToDriveAttribute>*]
```
By default, all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain

View File

@ -175,6 +175,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = false
@ -331,7 +333,7 @@ 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
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.10.8 64-bit final
MacOS High Sierra 10.13.6 x86_64
@ -598,6 +600,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False
@ -797,6 +801,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; C:\GAMConfig\oauth2service.json
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False
@ -975,7 +981,7 @@ writes the credentials into the file oauth2.txt.
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final
Windows-10-10.0.17134 AMD64
@ -1244,6 +1250,8 @@ Section: DEFAULT
output_timeformat = ''
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = False

View File

@ -30,8 +30,6 @@
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*"
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
@ -63,6 +61,8 @@
<LabelIDList> ::= "<LabelID>(,<LabelID>)*"
<LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*"
<LanguageList> ::= "<Language>(,<Language>)*"
<LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<MessageIDList> ::= "<MessageID>(,<MessageID>)*"

View File

@ -1,19 +1,19 @@
# Users - Data Studio
# Users - Looker Studio
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Display Data Studio assets](#display-data-studio-assets)
- [Manage Data Studio permissions](#manage-data-studio-permissions)
- [Display Looker Studio assets](#display-data-studio-assets)
- [Manage Looker Studio permissions](#manage-data-studio-permissions)
- [Add Permissions](#add-permissions)
- [Delete Permissions](#delete-permissions)
- [Update Permissions](#update-permissions)
- [Display Data Studio permissions](#display-data-studio-permissions)
- [Display Looker Studio permissions](#display-data-studio-permissions)
## API documentation
* https://developers.google.com/datastudio/api/reference
* https://developers.google.com/looker-studio/integrate/api/reference
## Notes
To use these commands you must add the 'Data Studio API' to your project and update your service account authorization.
To use these commands you must add the 'Looker Studio API' to your project and update your service account authorization.
```
gam update project
gam user user@domain.com check serviceaccount
@ -27,33 +27,33 @@ gam user user@domain.com check serviceaccount
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<DataStudioAssetID> ::= <String>
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioAssetID> ::= <String>
<LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<LookerStudioAssetIDEntity> ::=
<LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
<DataStudioPermission> ::=
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
```
Data Studio assets have an ID that is referred to by Google as its `name`; this is the value
you will use wherever `<DataStudioAssetID>` is required.
Looker Studio assets have an ID that is referred to by Google as its `name`; this is the value
you will use wherever `<LookerStudioAssetID>` is required.
## Display Data Studio assets
## Display Looker Studio assets
```
gam <UserTypeEntity> show datastudioassets
gam <UserTypeEntity> show lookerstudioassets
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson]
```
@ -65,7 +65,7 @@ By default, all assets of type `report` not in the trash are displayed; use the
* `includetrashed` - Display assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Display a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Display a specific list of `assetids`
The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles.
Use this option if you discover asset titles containing these special characters; it is not common.
@ -73,11 +73,11 @@ Use this option if you discover asset titles containing these special characters
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson [quotechar <Character>]]
```
@ -89,7 +89,7 @@ By default, all assets of type `report` not in the trash are displayed; use the
* `includetrashed` - Display assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Display a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Display a specific list of `assetids`
The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles.
Use this option if you discover asset titles containing these special characters; it is not common.
@ -100,22 +100,22 @@ When using the `formatjson` option, double quotes are used extensively in the da
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Manage Data Studio permissions
## Manage Looker Studio permissions
* The owner of an asset can not have it's role changed.
* The owner of an asset can not be deleted.
* A new owner can not be added to an asset.
`<EmailAddress>` in `<DataStudioPermission>` must be complete, GAM will not add a domain name.
`<EmailAddress>` in `<LookerStudioPermission>` must be complete, GAM will not add a domain name.
A viewer can not manage permissions.
### Add permissions
```
gam <UserTypeEntity> add datastudiopermissions
gam <UserTypeEntity> add lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)]
(role editor|viewer <DataStudioPermissionEntity>)+
(assetids <LookerStudioAssetIDEntity)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
```
By default, the permission is added to all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -126,19 +126,19 @@ By default, the permission is added to all assets of type `report` not in the tr
* `includetrashed` - Add permission to assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Add permission to a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Add permission to a specific list of `assetids`
By default, when a permission is added, GAM outputs details of the permission. The `nodetails` option
suppresses this output.
### Delete permissions
```
gam <UserTypeEntity> delete datastudiopermissions
gam <UserTypeEntity> delete lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)]
(role any <DataStudioPermissionEntity>)+
(assetids <LookerStudioAssetIDEntity)]
(role any <LookerStudioPermissionEntity>)+
[nodetails]
```
By default, the permission is deleted from all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -149,7 +149,7 @@ By default, the permission is deleted from all assets of type `report` not in th
* `includetrashed` - Delete permission from assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Delete permission from a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Delete permission from a specific list of `assetids`
By default, when a permission is deleted, GAM outputs details of the permission. The `nodetails` option
suppresses this output.
@ -157,12 +157,12 @@ suppresses this output.
### Update permissions
A permission is updated by deleting the existing permission and then adding the new permission.
```
gam <UserTypeEntity> update datastudiopermissions
gam <UserTypeEntity> update lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)]
(role editor|viewer <DataStudioPermissionEntity>)+
(assetids <LookerStudioAssetIDEntity)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
```
By default, the permission is updated in all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -173,20 +173,20 @@ By default, the permission is updated in all assets of type `report` not in the
* `includetrashed` - Update permission in assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Update permission in a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Update permission in a specific list of `assetids`
By default, when a permission is updated, GAM outputs details of the permission. The `nodetails` option
suppresses this output.
## Display Data Studio permissions
## Display Looker Studio permissions
A viewer can not display permissions.
```
gam <UserTypeEntity> show datastudiopermissions
gam <UserTypeEntity> show lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson]
```
@ -198,19 +198,19 @@ By default, permissions for all assets of type `report` not in the trash are dis
* `includetrashed` - Display permissions for assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
The Data Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
The Looker Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print datastudiopermissions [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> print lookerstudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson [quotechar <Character>]]
```
@ -222,9 +222,9 @@ By default, permissions for all assets of type `report` not in the trash are dis
* `includetrashed` - Display permissions for assets in the trash
* `orderby title [ascending|descending]` - Order of assets
* Specific
* `assetids <DataStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
* `assetids <LookerStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
The Data Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
The Looker Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.

View File

@ -64,9 +64,15 @@ Typically, you will enclose the entire list in double quotes and quote each item
* ```"'it em' 'it,em' \"it'em\""```
For example, a list of queries for Org Units where the Org Unit names contain spaces:
* Linux and MacOS and Windows Command Prompt
```
queries "\"orgUnitPath='/Students/Middle School'\",\"orgUnitPath='/Students/Lower School'\""
```
* Windows Power Shell
```
queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Students/Lower\ School/2028\'`""
```
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
@ -970,6 +976,7 @@ gam print users [todrive <ToDriveAttribute>*]
By default, users in all domains in the account are selected; these options allow selection of subsets of users:
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users
@ -1070,6 +1077,7 @@ gam print users [todrive <ToDriveAttribute>*]
```
By default, users in all domains in the account are selected; these options allow selection of subsets of users:
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users

View File

@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 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.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 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.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 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.63.14
Latest: 6.63.15
echo $?
1
```
@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
6.63.14
6.63.15
```
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.63.14 - https://github.com/taers232c/GAMADV-XTD3
GAM 6.63.15 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 x86_64

View File

@ -125,7 +125,6 @@ Service Account Access
* [Users - Deprovision](Users-Deprovision)
* [Users - Contacts](Users-People-Contacts-Profiles)
* [Users - Contacts - Delegates](Users-Contacts-Delegates)
* [Users - Data Studio](Users-DataStudio)
* [Users - Drive - File Selection](Drive-File-Selection)
* [Users - Drive - Activity/Settings](Users-Drive-Activity-Settings)
* [Users - Drive - Cleanup](Users-Drive-Cleanup)
@ -152,6 +151,7 @@ Service Account Access
* [Users - Gmail - Settings](Users-Gmail-Settings)
* [Users - Group Membership](Users-Group-Membership)
* [Users - Keep](Users-Keep)
* [Users - Looker Studio](Users-Looker-Studio)
* [Users - People - Contacts & Profiles](Users-People-Contacts-Profiles)
* [Users - Photo](Users-Photo)
* [Users - Profile Sharing](Users-Profile-Sharing)

View File

@ -407,6 +407,19 @@ print_agu_domains
gam print groups
gam print|show group-members
gam print users
This allows predefining the list of domains so they don't have to be specified in each command.
Default: Blank
print_cros_ous
A comma separated list of org unit that are used in these commands:
gam print cros
gam print crosactivity
This allows predefining the list of org units so they don't have to be specified in each command.
Default: Blank
print_cros_ous_and_children
A comma separated list of org unit names that are used in these commands:
gam print cros
gam print crosactivity
This allows predefining the list of org units so they don't have to be specified in each command.
Default: Blank
process_wait_limit
When processing batch/CSV files, how long (in seconds) GAM should wait for all batch|csv processes to complete
@ -641,6 +654,8 @@ Section: DEFAULT
output_timeformat = ''
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = false
quick_info_user = false
@ -823,6 +838,8 @@ output_dateformat = ''
output_timeformat = ''
people_max_results = 100
print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0
quick_cros_move = False
quick_info_user = False

94
docs~
View File

@ -1,94 +0,0 @@
# Version and Help
Print the current version of Gam with details
```
gam version
GAMADV-XTD3 6.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
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.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
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.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Time: 2023-06-02T21:10:00-07:00
Your system time differs from admin.googleapis.com by less than 1 second
OpenSSL 3.1.1 30 May 2023
cryptography 41.0.1
filelock 3.12.0
google-api-python-client 2.88.0
google-auth-httplib2 0.1.0
google-auth-oauthlib 1.0.0
google-auth 2.19.1
httplib2 0.22.0
passlib 1.7.4
python-dateutil 2.8.2
yubikey-manager 5.1.1
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
```
Print the current and latest versions of Gam and:
* set the return code to 0 if the current version is the latest version
* set the return code to 1 if the current version is not the latest
```
gam version checkrc
GAM 5.35.08 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.8.1 64-bit final
google-api-python-client 2.77.0
httplib2 0.16.0
oauth2client 4.1.3
MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Version Check:
Current: 5.35.08
Latest: 6.61.18
echo $?
1
```
Print the current version number without details
```
gam version simple
6.61.18
```
In Linux/MacOS you can do:
```
VER=`gam version simple`
echo $VER
```
Print the current version of Gam and address of this Wiki
```
gam help
GAM 6.61.18 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Time: 2023-06-02T21:10:00-07:00
Help: Syntax in file /Users/Admin/bin/gamadv-xtd3/GamCommands.txt
Help: Documentation is at https://github.com/taers232c/GAMADV-XTD3/wiki
```

View File

@ -386,12 +386,6 @@ If an item contains spaces, it should be surrounded by ".
<CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String>
<CustomerID> ::= <String>
<DataStudioAssetID> ::= <String>
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DeliverySetting> ::=
allmail|
abridged|daily|
@ -467,6 +461,12 @@ If an item contains spaces, it should be surrounded by ".
<LabelID> ::= Label_<String>
<LabelName> ::= <String>
<LabelReplacement> ::= <String>
<LookerStudioAssetID> ::= <String>
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted
@ -652,8 +652,6 @@ If an item contains spaces, it should be surrounded by ".
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*"
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
@ -685,6 +683,8 @@ If an item contains spaces, it should be surrounded by ".
<LabelIDList> ::= "<LabelID>(,<LabelID>)*"
<LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*"
<LanguageList> ::= "<Language>(,<Language>)*"
<LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<MessageIDList> ::= "<MessageID>(,<MessageID>)*"
@ -988,10 +988,6 @@ Specify a collection of items by directly specifying them; the item type is dete
<CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>)
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DeviceIDEntity> ::=
<DeviceIDList> | (device_sn <SerialNumber>)
(query:<QueryDevice>) | (query <QueryDevice>)
@ -1105,6 +1101,10 @@ Specify a collection of items by directly specifying them; the item type is dete
<LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelNameEntity> ::=
<LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioAssetIDEntity> ::=
<LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MessageIDEntity> ::=
<MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MobileEntity> ::=
@ -3084,7 +3084,7 @@ gam print|show transferapps
<DataTransferService> ::=
calendar|
currents|
datastudio|"google data studio"|
datastudio|lookerstudio|"google data studio"|
googledrive|gdrive|drive|"drive and docs"
<DataTransferServiceList> ::= "<DataTransferService>(,<DataTransferService>)*"
@ -5788,68 +5788,6 @@ gam <UserTypeEntity> print chatmessages [todrive <ToDriveAttribute>*] <ChatSpace
[showdeleted [<Boolean>]] [filter <String>]
[formatjson [quotechar <Character>]]
# Users - Data Studuo
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
stam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show datastudioassets
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson]
gam <UserTypeEntity> add datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(role editor|viewer <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> delete datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]) |
(assetids <DataStudioAssetIDEntity>)]
(role any <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> update datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(role editor|viewer <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> print datastudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson]
# Users - Drive
<DriveFileOrderByFieldName> ::=
@ -7142,6 +7080,68 @@ gam <UserTypeEntity> update license <SKUID> [product|productid <ProductID>] [fro
gam <UserTypeEntity> delete license <SKUIDList> [product|productid <ProductID>] [preview] [actioncsv]
gam <UserTypeEntity> sync license <SKUIDList> [product|productid <ProductID>] [addonly|removeonly] [allskus|onesku] [preview] [actioncsv]
# Users - Looker Studuo
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
stam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show lookerstudioassets
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson]
gam <UserTypeEntity> add lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> delete lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]) |
(assetids <LookerStudioAssetIDEntity>)]
(role any <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> update lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> print lookerstudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson]
# Users - Contacts and Profiles
<PeopleContactAttribute> ::=

View File

@ -2,6 +2,27 @@
Merged GAM-Team version
6.63.15
Added `print_cros_ous` and `print_cros_ous_and_children` variables to `gam.cfg` that provide a default list of OUs for these commands:
```
gam print cros
gam print crosactivity
```
Updated `group` commands that manage members to handle the following error:
```
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
```
Updated Data Studio to Looker Studio; added the following command synonyms:
* `lookerstudioassets` for `datastudioassets`
* 'lookerstudiopermissions` for `datastudiopermissions`
Corrected error message in `gam add datastudiopermissions`:
* Old -`ERROR: Missing argument: Expected <DataStudioAssetMembersEntity>`
* New - `ERROR: Missing argument: Expected <LookerStudioPermissionEntity>
6.63.14
Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move

View File

@ -4102,7 +4102,7 @@ def SetGlobalVariables():
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')
# Child process
# Inherit main process output header/row filters/limit if not locally defined
# Inherit main process output header/row filters/limit, print defaults if not locally defined
else:
if not GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]:
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER] = GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER][:]
@ -4120,6 +4120,10 @@ def SetGlobalVariables():
GC.Values[GC.CSV_OUTPUT_ROW_LIMIT] = GM.Globals[GM.CSV_OUTPUT_ROW_LIMIT]
if not GC.Values[GC.PRINT_AGU_DOMAINS]:
GC.Values[GC.PRINT_AGU_DOMAINS] = GM.Globals[GM.PRINT_AGU_DOMAINS]
if not GC.Values[GC.PRINT_CROS_OUS]:
GC.Values[GC.PRINT_CROS_OUS] = GM.Globals[GM.PRINT_CROS_OUS]
if not GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]:
GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN] = GM.Globals[GM.PRINT_CROS_OUS_AND_CHILDREN]
# customer_id, domain and admin_email must be set when enable_dasa = true
if GC.Values[GC.ENABLE_DASA]:
errors = 0
@ -5954,7 +5958,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=includeDerivedMembership,
groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, group)
_incrEntityDoesNotExist(Ent.GROUP)
return
@ -6085,7 +6089,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=includeDerivedMembership,
groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, group)
_incrEntityDoesNotExist(Ent.GROUP)
continue
@ -9300,6 +9304,7 @@ def terminateStdQueueHandler(mpQueue, mpQueueHandler):
def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr,
debugLevel, todrive, printAguDomains,
printCrosOUs, printCrosOUsAndChildren,
output_dateformat, output_timeformat,
csvColumnDelimiter, csvQuoteChar,
csvTimestampColumn,
@ -9339,6 +9344,8 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
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.SAVED_STDOUT] = None
GM.Globals[GM.SYSEXITRC] = 0
if mpQueueCSVFile:
@ -9509,6 +9516,7 @@ def MultiprocessGAMCommands(items, showCmds):
[pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr,
GC.Values[GC.DEBUG_LEVEL], GM.Globals[GM.CSV_TODRIVE],
GC.Values[GC.PRINT_AGU_DOMAINS],
GC.Values[GC.PRINT_CROS_OUS], GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN],
GC.Values[GC.OUTPUT_DATEFORMAT], GC.Values[GC.OUTPUT_TIMEFORMAT],
GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER],
GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR],
@ -12882,6 +12890,7 @@ REPORT_CHOICE_MAP = {
'keep': 'keep',
'login': 'login',
'logins': 'login',
'lookerstudio': 'data_studio',
'meet': 'meet',
'mobile': 'mobile',
'oauthtoken': 'token',
@ -16069,6 +16078,7 @@ SERVICE_NAME_CHOICE_MAP = {
'drive': DRIVE_AND_DOCS_APP_NAME,
'googledrive': DRIVE_AND_DOCS_APP_NAME,
'gdrive': DRIVE_AND_DOCS_APP_NAME,
'lookerstudio': GOOGLE_DATA_STUDIO_APP_NAME,
}
def _validateTransferAppName(apps, appName):
@ -23120,6 +23130,16 @@ def substituteQueryTimes(queries, queryTimes):
for queryTimeName, queryTimeValue in iter(queryTimes.items()):
queries[i] = query.replace(f'#{queryTimeName}#', queryTimeValue)
# Get CrOS devices from gam.cfg print_cros_ous and print_cros_ous_and_children
def getCfgCrOSEntities():
if GC.Values[GC.PRINT_CROS_OUS]:
entityList = getItemsToModify(Cmd.ENTITY_CROS_OUS, GC.Values[GC.PRINT_CROS_OUS])
else:
entityList = []
if GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]:
entityList.extend(getItemsToModify(Cmd.ENTITY_CROS_OUS_AND_CHILDREN, GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]))
return entityList
CROS_ORDERBY_CHOICE_MAP = {
'lastsync': 'lastSync',
'location': 'annotatedLocation',
@ -23287,6 +23307,9 @@ def doPrintCrOSDevices(entityList=None):
selectedLists = {}
queryTimes = {}
selectionAllowed = entityList is None
if selectionAllowed and (GC.Values[GC.PRINT_CROS_OUS] or GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]):
entityList = getCfgCrOSEntities()
selectionAllowed = False
allFields = noLists = oneRow = showDVRstorageFreePercentage = sortHeaders = False
activeTimeRangesOrder = 'ASCENDING'
while Cmd.ArgumentsRemaining():
@ -23545,6 +23568,9 @@ def doPrintCrOSActivity(entityList=None):
selectedLists = {}
queryTimes = {}
selectionAllowed = entityList is None
if selectionAllowed and (GC.Values[GC.PRINT_CROS_OUS] or GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]):
entityList = getCfgCrOSEntities()
selectionAllowed = False
oneUserPerRow = False
directlyInOU = True
activeTimeRangesOrder = 'ASCENDING'
@ -29344,7 +29370,7 @@ def doUpdateGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count)
except (GAPI.duplicate, GAPI.memberNotFound, GAPI.resourceNotFound,
GAPI.invalidMember, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet) as e:
GAPI.invalidMember, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount)
except GAPI.conflict:
_showSuccess(group, member, role, delivery_settings, j, jcount, Msg.ACTION_MAY_BE_DELAYED)
@ -29381,7 +29407,7 @@ def doUpdateGroups():
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
http_status, reason, message = checkGAPIError(exception)
if reason in GAPI.MEMBERS_THROW_REASONS:
if reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
elif reason == GAPI.CONFLICT:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED)
@ -29455,7 +29481,7 @@ def doUpdateGroups():
_showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.resourceNotFound, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.resourceNotFound, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount)
except GAPI.conflict:
_showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount, Msg.ACTION_MAY_BE_DELAYED)
@ -29470,7 +29496,7 @@ def doUpdateGroups():
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
http_status, reason, message = checkGAPIError(exception)
if reason in GAPI.MEMBERS_THROW_REASONS:
if reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
elif reason == GAPI.CONFLICT:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED)
@ -29560,7 +29586,7 @@ def doUpdateGroups():
Act.Set(Act.UPDATE)
else:
_showFailure(group, member, role, str(e), j, jcount)
except (GAPI.invalidMember, GAPI.resourceNotFound) as e:
except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount)
def _callbackUpdateGroupMembers(request_id, response, exception):
@ -29573,11 +29599,18 @@ def doUpdateGroups():
Act.Set(Act.ADD)
_addMember(ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]), ri[RI_ROLE], ri[RI_OPTION], ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
Act.Set(Act.UPDATE)
elif reason in GAPI.MEMBERS_THROW_REASONS:
elif reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
else:
elif reason not in GAPI.DEFAULT_RETRY_REASONS+GAPI.MEMBERS_RETRY_REASONS:
errMsg = getHTTPError(_UPDATE_MEMBER_REASON_TO_MESSAGE_MAP, http_status, reason, message)
_showFailure(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
if addBatchParms['adjust']:
addBatchParms['adjust'] = False
addBatchParms['wait'] += 0.25
writeStderr(f'{WARNING_PREFIX}{Msg.INTER_BATCH_WAIT_INCREASED.format(addBatchParms["wait"])}\n')
time.sleep(0.1)
_updateMember(ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]), ri[RI_ROLE], ri[RI_OPTION], ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
def _batchUpdateGroupMembers(group, i, count, updateMembers, role, delivery_settings):
Act.Set([Act.UPDATE, Act.UPDATE_PREVIEW][preview])
@ -29891,7 +29924,7 @@ def doUpdateGroups():
roles=None if Ent.ROLE_MEMBER in rolesSet or ignoreRole else memberRoles,
fields='nextPageToken,members(email,id,type,status,role)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(entityType, group, i, count)
continue
for role in rolesSet:
@ -30016,7 +30049,7 @@ def doUpdateGroups():
groupKey=group, roles=None if Ent.ROLE_MEMBER in rolesSet else memberRoles,
fields='nextPageToken,members(email,id,type,status,role)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(entityType, group, i, count)
continue
removeMembers = {}
@ -30845,7 +30878,7 @@ def doPrintGroups():
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden) as e:
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT]))
groupData[i]['required'] -= 1
return
@ -30861,7 +30894,7 @@ def doPrintGroups():
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden) as e:
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT]))
break
groupData[i]['required'] -= 1
@ -31238,7 +31271,7 @@ def infoGroupMembers(entityList, ciGroupsAPI=False):
for field in INFO_GROUPMEMBERS_FIELDS:
printKeyValueList([field, result[field]])
Ind.Decrement()
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden) as e:
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([entityType, group], str(e), j, jcount)
except GAPI.memberNotFound:
entityActionFailedWarning([entityType, group, Ent.MEMBER, memberKey], Msg.NOT_AN_ENTITY.format(Ent.Singular(Ent.MEMBER)), j, jcount)
@ -31307,7 +31340,7 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
throwReasons=GAPI.MEMBERS_THROW_REASONS+[GAPI.MEMBER_NOT_FOUND],
retryReasons=GAPI.MEMBERS_RETRY_REASONS,
groupKey=groupEmail, memberKey=member['id'], fields='delivery_settings')['delivery_settings']
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
pass
except GAPI.memberNotFound:
pass
@ -31322,7 +31355,7 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=groupEmail, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
return
if not memberOptions[MEMBEROPTION_RECURSIVE]:
@ -31679,7 +31712,7 @@ def doShowGroupMembers():
groupKey=groupEmail, fields='nextPageToken,members(email,id,role,status,type)', maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
if showOwnedBy and not checkGroupShowOwnedBy(showOwnedBy, membersList):
return
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
if depth == 0:
entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
return
@ -32313,6 +32346,9 @@ def doUpdateCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group)
continue
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, group], str(e))
continue
currentMembersNames = {}
for role in rolesSet:
currentMembersSets[role] = set()
@ -32484,6 +32520,9 @@ def doUpdateCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count)
continue
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([entityType, group], str(e), i, count)
continue
removeMembers = {}
for role in rolesSet:
removeMembers[role] = []
@ -32554,6 +32593,9 @@ def doInfoCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group_id, i, count)
return
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, group_id], str(e), i, count)
return
for member in cachedGroupMembers[group_id]:
member_id = member.get('name', '')
member_id = member_id.split('/')[-1]
@ -32943,6 +32985,8 @@ def doPrintCIGroups():
parent=groupEntity['name'], view='FULL', fields='*', pageSize=pageSize)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupEmail, i, count)
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, groupEmail], str(e), i, count)
if memberRestrictions:
printGettingEntityItemForWhom(Ent.MEMBER_RESTRICTION, groupEmail, i, count)
try:
@ -56832,6 +56876,7 @@ TRANSFER_DRIVEFILE_ACL_ROLES_MAP = {
# [(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)]
# [targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>]
# [mergewithtarget [<Boolean>]]
# [createshortcutsfornonmovablefiles [<Boolean>]]
# [skipids <DriveFileEntity>]
# [keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages]
# [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none]
@ -56905,37 +56950,36 @@ def transferDrive(users):
def _setUpdateRole(permission):
return {'role': permission['role']}
# def _makeXferShortcut(drive, user, j, jcount, entityType, childId, childName, newParentId, newParentName):
# kvList = [Ent.USER, user, entityType, f'{childName}({childId})']
# targetEntityType = Ent.DRIVE_FILE_SHORTCUT if entityType == Ent.DRIVE_FILE else Ent.DRIVE_FOLDER_SHORTCUT
# newParentNameId = f'{newParentName}({newParentId})'
# action = Act.Get()
# existingShortcut = _checkForExistingShortcut(drive, childId, childName, newParentId)
# if existingShortcut:
# Act.Set(Act.CREATE_SHORTCUT)
# entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_PREVIOUSLY_IN,
# [Ent.DRIVE_FOLDER, newParentNameId, targetEntityType, f"{childName}({existingShortcut})"],
# j, jcount)
# Act.Set(action)
# return
# body = {'name': childName, 'mimeType': MIMETYPE_GA_SHORTCUT,
# 'parents': [newParentId], 'shortcutDetails': {'targetId': childId}}
# try:
# 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.FILE_NOT_FOUND, GAPI.UNKNOWN_ERROR,
# GAPI.STORAGE_QUOTA_EXCEEDED, GAPI.TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
# GAPI.TEAMDRIVE_HIERARCHY_TOO_DEEP, GAPI.SHORTCUT_TARGET_INVALID],
# body=body, fields='id', supportsAllDrives=True)
# Act.Set(Act.CREATE_SHORTCUT)
# entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_IN,
# [Ent.DRIVE_FOLDER, newParentNameId, targetEntityType, f"{childName}({result['id']})"],
# j, jcount)
# Act.Set(action)
# except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions, GAPI.invalid, GAPI.badRequest,
# GAPI.fileNotFound, GAPI.unknownError, GAPI.storageQuotaExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed,
# GAPI.teamDriveHierarchyTooDeep, GAPI.shortcutTargetInvalid) as e:
# entityActionFailedWarning(kvList+[Ent.DRIVE_FILE_SHORTCUT, childName], str(e), j, jcount)
def _makeXferShortcut(drive, user, j, jcount, entityType, childId, childName, newParentId):
kvList = [Ent.USER, user, entityType, f'{childName}({childId})']
targetEntityType = Ent.DRIVE_FILE_SHORTCUT if entityType == Ent.DRIVE_FILE else Ent.DRIVE_FOLDER_SHORTCUT
action = Act.Get()
existingShortcut = _checkForExistingShortcut(drive, childId, childName, newParentId)
if existingShortcut:
Act.Set(Act.CREATE_SHORTCUT)
entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_PREVIOUSLY_IN,
[Ent.DRIVE_FOLDER, newParentId, targetEntityType, f"{childName}({existingShortcut})"],
j, jcount)
Act.Set(action)
return
body = {'name': childName, 'mimeType': MIMETYPE_GA_SHORTCUT,
'parents': [newParentId], 'shortcutDetails': {'targetId': childId}}
try:
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.FILE_NOT_FOUND, GAPI.UNKNOWN_ERROR,
GAPI.STORAGE_QUOTA_EXCEEDED, GAPI.TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
GAPI.TEAMDRIVE_HIERARCHY_TOO_DEEP, GAPI.SHORTCUT_TARGET_INVALID],
body=body, fields='id', supportsAllDrives=True)
Act.Set(Act.CREATE_SHORTCUT)
entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_IN,
[Ent.DRIVE_FOLDER, newParentId, targetEntityType, f"{childName}({result['id']})"],
j, jcount)
Act.Set(action)
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions, GAPI.invalid, GAPI.badRequest,
GAPI.fileNotFound, GAPI.unknownError, GAPI.storageQuotaExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed,
GAPI.teamDriveHierarchyTooDeep, GAPI.shortcutTargetInvalid) as e:
entityActionFailedWarning(kvList+[Ent.DRIVE_FILE_SHORTCUT, childName], str(e), j, jcount)
def _transferFile(childEntry, i, count, j, jcount, atSelectTop):
childEntryInfo = childEntry['info']
@ -56956,14 +57000,14 @@ def transferDrive(users):
csvPF.WriteRow({'OldOwner': sourceUser, 'NewOwner': targetUser, 'type': Ent.Singular(childFileType), 'id': childFileId, 'name': childFileName, 'role': 'owner'})
return
Act.Set(Act.TRANSFER_OWNERSHIP)
addTargetParents = set()
addTargetParent = None
removeSourceParents = set()
removeTargetParents = set()
childParents = childEntryInfo.get('parents', [])
if childParents:
for parentId in childParents:
if parentId in parentIdMap:
addTargetParents.add(parentIdMap[parentId])
addTargetParent = parentIdMap[parentId]
if parentId != sourceRootId:
removeSourceParents.add(parentId)
elif not mergeWithTarget and targetFolderId != targetRootId:
@ -56971,7 +57015,7 @@ def transferDrive(users):
else:
if targetIds[TARGET_ORPHANS_PARENT_ID] is None:
_buildTargetUserOrphansFolder()
addTargetParents.add(targetIds[TARGET_ORPHANS_PARENT_ID])
addTargetParent = targetIds[TARGET_ORPHANS_PARENT_ID]
removeTargetParents.add(targetRootId)
try:
actionUser = sourceUser
@ -56992,24 +57036,22 @@ def transferDrive(users):
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS, retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3,
fileId=childFileId, removeParents=','.join(removeSourceParents), fields='')
actionUser = targetUser
if addTargetParents or removeTargetParents:
if addTargetParent or removeTargetParents:
op = 'Add/Remove Target Parents'
callGAPI(targetDrive.files(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.INSUFFICIENT_PARENT_PERMISSIONS],
retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3,
fileId=childFileId,
addParents=','.join(addTargetParents), removeParents=','.join(removeTargetParents), fields='')
addParents=addTargetParent, removeParents=','.join(removeTargetParents), fields='')
entityModifierNewValueItemValueListActionPerformed([Ent.USER, sourceUser, childFileType, childFileName], Act.MODIFIER_TO, None, [Ent.USER, targetUser], j, jcount)
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.unknownError,
GAPI.badRequest, GAPI.sharingRateLimitExceeded,
GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e:
GAPI.badRequest, GAPI.sharingRateLimitExceeded, GAPI.insufficientParentPermissions) as e:
entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount)
# except (GAPI.insufficientFilePermissions, GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e:
# if not createShortcutsForNonmovableFiles:
# entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount)
# else:
# _makeXferShortcut(targetDrive, targetUser, j, jcount, childFileType, childFileId, childFileName, newParentId, newParentName)
except (GAPI.insufficientFilePermissions, GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e:
if not createShortcutsForNonmovableFiles:
entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount)
else:
_makeXferShortcut(targetDrive, targetUser, j, jcount, childFileType, childFileId, childFileName, addTargetParent)
except GAPI.permissionNotFound:
entityDoesNotHaveItemWarning([Ent.USER, actionUser, childFileType, childFileName, Ent.PERMISSION_ID, targetPermissionId], j, jcount)
except GAPI.invalidSharingRequest as e:
@ -57373,7 +57415,7 @@ def transferDrive(users):
targetUserFolderPattern = '#user# old files'
targetUserOrphansFolderPattern = '#user# orphaned files'
targetIds = [None, None]
# createShortcutsForNonmovableFiles = False
createShortcutsForNonmovableFiles = False
mergeWithTarget = False
thirdPartyOwners = {}
skipFileIdEntity = initDriveFileEntity()
@ -57410,8 +57452,8 @@ def transferDrive(users):
buildTree = False
elif myarg == 'mergewithtarget':
mergeWithTarget = getBoolean()
# elif myarg == 'createshortcutsfornonmovablefiles':
# createShortcutsForNonmovableFiles = getBoolean()
elif myarg == 'createshortcutsfornonmovablefiles':
createShortcutsForNonmovableFiles = getBoolean()
elif myarg == 'skipids':
skipFileIdEntity = getDriveFileEntity()
elif myarg == 'preview':
@ -60840,18 +60882,18 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
def doPrintShowSharedDriveACLs():
printShowSharedDriveACLs([_getAdminEmail()], True)
DATASTUDIO_ASSETTYPE_CHOICE_MAP = {
LOOKERSTUDIO_ASSETTYPE_CHOICE_MAP = {
'report': ['REPORT'],
'datasource': ['DATA_SOURCE'],
'all': ['REPORT', 'DATA_SOURCE'],
}
def initDataStudioAssetSelectionParameters():
def initLookerStudioAssetSelectionParameters():
return ({'owner': None, 'title': None, 'includeTrashed': False}, {'assetTypes': ['REPORT']})
def getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
def getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
if myarg in {'assettype', 'assettypes'}:
assetTypes['assetTypes'] = getChoice(DATASTUDIO_ASSETTYPE_CHOICE_MAP, mapChoice=True)
assetTypes['assetTypes'] = getChoice(LOOKERSTUDIO_ASSETTYPE_CHOICE_MAP, mapChoice=True)
elif myarg == 'title':
parameters['title'] = getString(Cmd.OB_STRING)
elif myarg == 'owner':
@ -60862,7 +60904,7 @@ def getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
return False
return True
def _validateUserGetDataStudioAssetIds(user, i, count, entity):
def _validateUserGetLookerStudioAssetIds(user, i, count, entity):
if entity:
if entity['dict']:
entityList = [{'name': item, 'title': item} for item in entity['dict'][user]]
@ -60870,16 +60912,16 @@ def _validateUserGetDataStudioAssetIds(user, i, count, entity):
entityList = [{'name': item, 'title': item} for item in entity['list']]
else:
entityList = []
user, ds = buildGAPIServiceObject(API.DATASTUDIO, user, i, count)
user, ds = buildGAPIServiceObject(API.LOOKERSTUDIO, user, i, count)
if not ds:
return (user, None, None, 0)
return (user, ds, entityList, len(entityList))
def _getDataStudioAssetByID(ds, user, i, count, assetId):
printGettingAllEntityItemsForWhom(Ent.DATASTUDIO_ASSET, user, i, count)
def _getLookerStudioAssetByID(ds, user, i, count, assetId):
printGettingAllEntityItemsForWhom(Ent.LOOKERSTUDIO_ASSET, user, i, count)
try:
return callGAPI(ds.assets(), 'get',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS,
throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=f'assets/{assetId}')
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user], str(e), i, count)
@ -60887,16 +60929,16 @@ def _getDataStudioAssetByID(ds, user, i, count, assetId):
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
return None
def _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, fields, orderBy=None):
def _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, fields, orderBy=None):
assets = []
for assetType in assetTypes['assetTypes']:
entityType = Ent.DATASTUDIO_ASSET_REPORT if assetType == 'REPORT' else Ent.DATASTUDIO_ASSET_DATASOURCE
entityType = Ent.LOOKERSTUDIO_ASSET_REPORT if assetType == 'REPORT' else Ent.LOOKERSTUDIO_ASSET_DATASOURCE
printGettingAllEntityItemsForWhom(entityType, user, i, count)
parameters['assetTypes'] = assetType
try:
assets.extend(callGAPIpages(ds.assets(), 'search', 'assets',
pageMessage=getPageMessage(),
throwReasons=GAPI.DATASTUDIO_THROW_REASONS,
throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
**parameters, orderBy=orderBy, fields=fields))
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user], str(e), i, count)
@ -60906,26 +60948,26 @@ def _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, fields, ord
return (None, 0)
return (assets, len(assets))
DATASTUDIO_ASSETS_ORDERBY_CHOICE_MAP = {
LOOKERSTUDIO_ASSETS_ORDERBY_CHOICE_MAP = {
'title': 'title'
}
DATASTUDIO_ASSETS_TIME_OBJECTS = {'updateTime', 'updateByMeTime', 'createTime', 'lastViewByMeTime'}
LOOKERSTUDIO_ASSETS_TIME_OBJECTS = {'updateTime', 'updateByMeTime', 'createTime', 'lastViewByMeTime'}
# gam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*]
# gam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (assetids <LookerStudioAssetIDEntity>)]
# [stripcrsfromtitle]
# [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show datastudioassets
# gam <UserTypeEntity> show lookerstudioassets
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (assetids <LookerStudioAssetIDEntity>)]
# [stripcrsfromtitle]
# [formatjson]
def printShowDataStudioAssets(users):
def printShowLookerStudioAssets(users):
def _printAsset(asset, user):
if stripCRsFromTitle:
asset['title'] = _stripControlCharsFromName(asset['title'])
@ -60934,33 +60976,33 @@ def printShowDataStudioAssets(users):
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'User': user, 'title': asset['title'],
'JSON': json.dumps(cleanJSON(asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)})
'JSON': json.dumps(cleanJSON(asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)})
def _showAsset(asset):
if stripCRsFromTitle:
asset['title'] = _stripControlCharsFromName(asset['title'])
if FJQC.formatJSON:
printLine(json.dumps(cleanJSON(asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=False))
printLine(json.dumps(cleanJSON(asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=False))
return
printEntity([Ent.DATASTUDIO_ASSET, asset['title']], j, jcount)
printEntity([Ent.LOOKERSTUDIO_ASSET, asset['title']], j, jcount)
Ind.Increment()
showJSON(None, asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS)
showJSON(None, asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS)
Ind.Decrement()
csvPF = CSVPrintFile(['User', 'title']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
OBY = OrderBy(DATASTUDIO_ASSETS_ORDERBY_CHOICE_MAP, ascendingKeyword='ascending', descendingKeyword='')
parameters, assetTypes = initDataStudioAssetSelectionParameters()
OBY = OrderBy(LOOKERSTUDIO_ASSETS_ORDERBY_CHOICE_MAP, ascendingKeyword='ascending', descendingKeyword='')
parameters, assetTypes = initLookerStudioAssetSelectionParameters()
assetIdEntity = None
stripCRsFromTitle = False
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
elif getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass
elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID)
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'stripcrsfromtitle':
stripCRsFromTitle = True
elif myarg == 'orderby':
@ -60970,35 +61012,35 @@ def printShowDataStudioAssets(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity)
user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds:
continue
if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets', OBY.orderBy)
assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets', OBY.orderBy)
if assets is None:
continue
if not csvPF:
if not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.DATASTUDIO_ASSET, i, count)
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
Ind.Increment()
j = 0
for asset in assets:
j += 1
if assetIdEntity:
asset = _getDataStudioAssetByID(ds, user, i, count, asset['name'])
asset = _getLookerStudioAssetByID(ds, user, i, count, asset['name'])
if asset:
_showAsset(asset)
Ind.Decrement()
else:
for asset in assets:
if assetIdEntity:
asset = _getDataStudioAssetByID(ds, user, i, count, asset['name'])
asset = _getLookerStudioAssetByID(ds, user, i, count, asset['name'])
if asset:
_printAsset(asset, user)
if csvPF:
csvPF.writeCSVfile('Data Studio Assets')
csvPF.writeCSVfile('Looker Studio Assets')
def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC):
def _showLookerStudioPermissions(user, asset, permissions, j, jcount, FJQC):
if FJQC is not None and FJQC.formatJSON:
permissions['User'] = user
permissions['assetId'] = asset['name']
@ -61006,7 +61048,7 @@ def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC):
return
permissions = permissions['permissions']
if permissions:
printEntity([Ent.DATASTUDIO_ASSET, asset['title'], Ent.DATASTUDIO_PERMISSION, ''], j, jcount)
printEntity([Ent.LOOKERSTUDIO_ASSET, asset['title'], Ent.LOOKERSTUDIO_PERMISSION, ''], j, jcount)
for role in ['OWNER', 'EDITOR', 'VIEWER']:
members = permissions.get(role, {}).get('members', [])
if members:
@ -61016,25 +61058,25 @@ def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC):
printKeyValueList([lrole, member])
Ind.Decrement()
DATASTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP = {
LOOKERSTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP = {
'editor': 'EDITOR',
'owner': 'OWNER',
'viewer': 'VIEWER',
}
DATASTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP = {
LOOKERSTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP = {
'editor': 'EDITOR',
'viewer': 'VIEWER',
}
DATASTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP = {
LOOKERSTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP = {
'any': None,
'editor': None,
'owner': None,
'viewer': None,
}
DATASTUDIO_PERMISSION_MODIFIER_MAP = {
LOOKERSTUDIO_PERMISSION_MODIFIER_MAP = {
Act.ADD: Act.MODIFIER_TO,
Act.DELETE: Act.MODIFIER_FROM,
Act.UPDATE: Act.MODIFIER_FOR
@ -61044,46 +61086,46 @@ DATASTUDIO_PERMISSION_MODIFIER_MAP = {
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (role editor|viewer <DataStudioPermissionEntity>)+
# (assetids <LookerStudioAssetIDEntity>)]
# (role editor|viewer <LookerStudioPermissionEntity>)+
# [nodetails]
# gam <UserTypeEntity> delete datastudiopermissions
# ([[assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (role any <DataStudioPermissionEntity>)+
# (assetids <LookerStudioAssetIDEntity>)]
# (role any <LookerStudioPermissionEntity>)+
# [nodetails]
# gam <UserTypeEntity> update datastudiopermissions
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (role editor|viewer <DataStudioPermissionEntity>)+
# (assetids <LookerStudioAssetIDEntity>)]
# (role editor|viewer <LookerStudioPermissionEntity>)+
# [nodetails]
def processDataStudioPermissions(users):
def processLookerStudioPermissions(users):
action = Act.Get()
if action == Act.CREATE:
action = Act.ADD
modifier = DATASTUDIO_PERMISSION_MODIFIER_MAP[action]
parameters, assetTypes = initDataStudioAssetSelectionParameters()
modifier = LOOKERSTUDIO_PERMISSION_MODIFIER_MAP[action]
parameters, assetTypes = initLookerStudioAssetSelectionParameters()
permissions = {}
assetIdEntity = None
showDetails = True
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
if getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass
elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID)
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'role':
permissions.setdefault('permissions', {})
if action in {Act.ADD, Act.UPDATE}:
role = getChoice(DATASTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
role = getChoice(LOOKERSTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
else:
role = getChoice(DATASTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
role = getChoice(LOOKERSTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
permissions['permissions'].setdefault(role, {'members': []})
permissions['permissions'][role]['members'].extend(getEntityList(Cmd.OB_DATASTUDIO_ASSET_MEMBERS_ENTITY))
permissions['permissions'][role]['members'].extend(getEntityList(Cmd.OB_LOOKERSTUDIO_PERMISSION_ENTITY))
elif myarg == 'nodetails':
showDetails = False
else:
@ -61096,14 +61138,14 @@ def processDataStudioPermissions(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity)
user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds:
continue
if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
if assets is None:
continue
entityPerformActionSubItemModifierNumItems([Ent.USER, user], Ent.DATASTUDIO_PERMISSION, modifier, jcount, Ent.DATASTUDIO_ASSET, i, count)
entityPerformActionSubItemModifierNumItems([Ent.USER, user], Ent.LOOKERSTUDIO_PERMISSION, modifier, jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
j = 0
for asset in assets:
j += 1
@ -61112,18 +61154,18 @@ def processDataStudioPermissions(users):
body = {'name': asset['name'], 'members': permissions['permissions'][role]['members']}
if action in {Act.DELETE, Act.UPDATE}:
results = callGAPI(ds.assets().permissions(), 'revokeAllPermissions',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS,
throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], body=body)
if action in {Act.ADD, Act.UPDATE}:
body['role'] = role
results = callGAPI(ds.assets().permissions(), 'addMembers',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS,
throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], body=body)
entityActionPerformed([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title'], Ent.DATASTUDIO_PERMISSION, ''], j, jcount)
entityActionPerformed([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title'], Ent.LOOKERSTUDIO_PERMISSION, ''], j, jcount)
if showDetails:
_showDataStudioPermissions(user, asset, results, j, jcount, None)
_showLookerStudioPermissions(user, asset, results, j, jcount, None)
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title']], str(e), j, jcount)
entityActionFailedWarning([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title']], str(e), j, jcount)
continue
except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
@ -61133,18 +61175,18 @@ def processDataStudioPermissions(users):
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)]
# (assetids <LookerStudioAssetIDEntity>)]
# [role editor|owner|viewer]
# [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show datastudiopermissions
# [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)[
# (assetids <LookerStudioAssetIDEntity>)[
# [role editor|owner|viewer]
# [formatjson]
def printShowDataStudioPermissions(users):
def _printDataStudioPermissions(user, asset, permissions):
def printShowLookerStudioPermissions(users):
def _printLookerStudioPermissions(user, asset, permissions):
row = flattenJSON(permissions, flattened={'User': user, 'assetId': asset['name']},
simpleLists=['members'], delimiter=delimiter)
if not FJQC.formatJSON:
@ -61156,19 +61198,19 @@ def printShowDataStudioPermissions(users):
csvPF = CSVPrintFile(['User', 'assetId']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
parameters, assetTypes = initDataStudioAssetSelectionParameters()
parameters, assetTypes = initLookerStudioAssetSelectionParameters()
assetIdEntity = None
role = None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
elif getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass
elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID)
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'role':
role = getChoice(DATASTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
role = getChoice(LOOKERSTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
elif myarg == 'delimiter':
delimiter = getCharacter()
else:
@ -61176,36 +61218,36 @@ def printShowDataStudioPermissions(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity)
user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds:
continue
if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
if assets is None:
continue
if not csvPF and not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.DATASTUDIO_ASSET, i, count)
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
j = 0
for asset in assets:
j += 1
try:
permissions = callGAPI(ds.assets(), 'getPermissions',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS,
throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], role=role)
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title']], str(e), j, jcount)
entityActionFailedWarning([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title']], str(e), j, jcount)
continue
except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
break
if not csvPF:
Ind.Increment()
_showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC)
_showLookerStudioPermissions(user, asset, permissions, j, jcount, FJQC)
Ind.Decrement()
else:
_printDataStudioPermissions(user, asset, permissions)
_printLookerStudioPermissions(user, asset, permissions)
if csvPF:
csvPF.writeCSVfile('Data Studio Permissions')
csvPF.writeCSVfile('Looker Studio Permissions')
def _validateSubkeyRoleGetGroups(user, role, origUser, userGroupLists, i, count):
roleLower = role.lower()
@ -61235,7 +61277,7 @@ def _addUserToGroups(cd, user, addGroupsSet, addGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.duplicate, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet) as e:
except (GAPI.duplicate, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, group, role, user], str(e), j, jcount)
except GAPI.conflict:
entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount)
@ -61302,7 +61344,7 @@ def _deleteUserFromGroups(cd, user, deleteGroupsSet, deleteGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount)
except GAPI.conflict:
entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount)
@ -61402,7 +61444,7 @@ def _updateUserGroups(cd, user, updateGroupsSet, updateGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount)
Ind.Decrement()
@ -61533,7 +61575,7 @@ def syncUserWithGroups(users):
'delivery_settings': result.get('delivery_settings', DELIVERY_SETTINGS_UNDEFINED)}
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), i, count)
currGroupsSet = set(currGroups)
syncGroupsSet = set(syncGroups)
@ -61649,7 +61691,7 @@ def checkUserInGroups(users):
else:
csvPF.WriteRow({'user': user, 'group': groupEmail, 'role': notMemberOrRole})
_setCheckError()
except (GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
_setCheckError()
else:
@ -61672,6 +61714,9 @@ def checkUserInGroups(users):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
_setCheckError()
except (GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
_setCheckError()
Ind.Decrement()
if csvPF:
csvPF.writeCSVfile('User Check Groups')
@ -61793,7 +61838,7 @@ def printShowUserGroups(users):
csvPF.WriteRow({'User': user, 'Group': groupEmail, 'Role': role, 'Status': status, 'Delivery': delivery_settings})
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
if countsOnly:
if not csvPF:
@ -61930,7 +61975,7 @@ def printShowGroupTree(users):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
continue
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e:
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
continue
else:
@ -70558,7 +70603,7 @@ USER_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_CHATSPACE: createChatSpace,
Cmd.ARG_CLASSROOMINVITATION: createClassroomInvitations,
Cmd.ARG_CONTACTDELEGATE: processContactDelegates,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions,
Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: processDelegates,
Cmd.ARG_DRIVEFILE: createDriveFile,
Cmd.ARG_DRIVEFILEACL: createDriveFileACL,
@ -70668,7 +70713,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CHATSPACE: deleteChatSpace,
Cmd.ARG_CLASSROOMINVITATION: deleteClassroomInvitations,
Cmd.ARG_CONTACTDELEGATE: processContactDelegates,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions,
Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: processDelegates,
Cmd.ARG_DRIVEFILE: deleteDriveFile,
Cmd.ARG_DRIVEFILEACL: deleteDriveFileACLs,
@ -70817,8 +70862,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CLASSROOMINVITATION: printShowClassroomInvitations,
Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile,
Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates,
Cmd.ARG_DATASTUDIOASSET: printShowDataStudioAssets,
Cmd.ARG_DATASTUDIOPERMISSION: printShowDataStudioPermissions,
Cmd.ARG_LOOKERSTUDIOASSET: printShowLookerStudioAssets,
Cmd.ARG_LOOKERSTUDIOPERMISSION: printShowLookerStudioPermissions,
Cmd.ARG_DELEGATE: printShowDelegates,
Cmd.ARG_DISKUSAGE: printDiskUsage,
Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
@ -70910,8 +70955,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile,
Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates,
Cmd.ARG_COUNT: showCountUser,
Cmd.ARG_DATASTUDIOASSET: printShowDataStudioAssets,
Cmd.ARG_DATASTUDIOPERMISSION: printShowDataStudioPermissions,
Cmd.ARG_LOOKERSTUDIOASSET: printShowLookerStudioAssets,
Cmd.ARG_LOOKERSTUDIOPERMISSION: printShowLookerStudioPermissions,
Cmd.ARG_DELEGATE: printShowDelegates,
Cmd.ARG_DISKUSAGE: printDiskUsage,
Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
@ -71029,7 +71074,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CALENDARACL: updateCalendarACLs,
Cmd.ARG_CHATMESSAGE: updateChatMessage,
Cmd.ARG_CHATSPACE: updateChatSpace,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions,
Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: updateDelegates,
Cmd.ARG_DRIVEFILE: updateDriveFile,
Cmd.ARG_DRIVEFILEACL: updateDriveFileACLs,
@ -71110,8 +71155,12 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_CONTACTPHOTO: Cmd.ARG_PEOPLECONTACTPHOTO,
Cmd.ARG_CONTACTPHOTOS: Cmd.ARG_PEOPLECONTACTPHOTO,
Cmd.ARG_COUNTS: Cmd.ARG_COUNT,
Cmd.ARG_DATASTUDIOASSETS: Cmd.ARG_DATASTUDIOASSET,
Cmd.ARG_DATASTUDIOPERMISSIONS: Cmd.ARG_DATASTUDIOPERMISSION,
Cmd.ARG_DATASTUDIOASSET: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_DATASTUDIOPERMISSION: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_DATASTUDIOASSETS: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_DATASTUDIOPERMISSIONS: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_LOOKERSTUDIOASSETS: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_LOOKERSTUDIOPERMISSIONS: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_DELEGATES: Cmd.ARG_DELEGATE,
Cmd.ARG_DOMAINCONTACT: Cmd.ARG_PEOPLECONTACT,
Cmd.ARG_DOMAINCONTACTS: Cmd.ARG_PEOPLECONTACT,

View File

@ -47,7 +47,6 @@ CLOUDRESOURCEMANAGER = 'cloudresourcemanager'
CLOUDRESOURCEMANAGER_V1 = 'cloudresourcemanager1'
CONTACTS = 'contacts'
CONTACTDELEGATION = 'contactdelegation'
DATASTUDIO = 'datastudio'
DATATRANSFER = 'datatransfer'
DIRECTORY = 'directory'
DIRECTORY_BETA = 'directory_beta'
@ -69,6 +68,7 @@ IAM_CREDENTIALS = 'iamcredentials'
IAP = 'iap'
KEEP = 'keep'
LICENSING = 'licensing'
LOOKERSTUDIO = 'datastudio'
OAUTH2 = 'oauth2'
PEOPLE = 'people'
PEOPLE_DIRECTORY = 'peopledirectory'
@ -206,7 +206,6 @@ _INFO = {
CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True},
CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False},
CONTACTDELEGATION: {'name': 'Contact Delegation API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
DATASTUDIO: {'name': 'Data Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
DATATRANSFER: {'name': 'Data Transfer API', 'version': 'datatransfer_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DIRECTORY: {'name': 'Directory API', 'version': 'directory_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DIRECTORY_BETA: {'name': 'Directory API', 'version': 'directory_v1.1beta1', 'v2discovery': True, 'mappedAPI': 'admin', 'localjson': True},
@ -227,6 +226,7 @@ _INFO = {
IAP: {'name': 'Cloud Identity-Aware Proxy API', 'version': 'v1', 'v2discovery': True},
KEEP: {'name': 'Keep API', 'version': 'v1', 'v2discovery': True},
LICENSING: {'name': 'License Manager API', 'version': 'v1', 'v2discovery': True},
LOOKERSTUDIO: {'name': 'Looker Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False},
PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True},
PEOPLE_DIRECTORY: {'name': 'People Directory API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': PEOPLE},
@ -546,10 +546,6 @@ _SVCACCT_SCOPES = [
# 'api': CONTACTS,
# 'subscopes': [],
# 'scope': 'https://www.google.com/m8/feeds'},
{'name': 'Data Studio API',
'api': DATASTUDIO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/datastudio'},
{'name': 'Drive API',
'api': DRIVE3,
'subscopes': READONLY,
@ -598,6 +594,10 @@ _SVCACCT_SCOPES = [
'api': KEEP,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/keep'},
{'name': 'Looker Studio API',
'api': LOOKERSTUDIO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/datastudio'},
{'name': 'OAuth2 API',
'api': OAUTH2,
'subscopes': [],

View File

@ -200,6 +200,10 @@ OUTPUT_TIMEFORMAT = 'output_timeformat'
PEOPLE_MAX_RESULTS = 'people_max_results'
# Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'print_agu_domains'
# OrgUnits for print cros
PRINT_CROS_OUS = 'print_cros_ous'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'print_cros_ous_and_children'
# Number of seconds to wait for batch/csv processes to complete
PROCESS_WAIT_LIMIT = 'process_wait_limit'
# Use quick method to move Chromebooks to OU
@ -366,6 +370,8 @@ Defaults = {
OUTPUT_TIMEFORMAT: '',
PEOPLE_MAX_RESULTS: '100',
PRINT_AGU_DOMAINS: '',
PRINT_CROS_OUS: '',
PRINT_CROS_OUS_AND_CHILDREN: '',
PROCESS_WAIT_LIMIT: '0',
QUICK_CROS_MOVE: FALSE,
QUICK_INFO_USER: FALSE,
@ -515,6 +521,8 @@ VAR_INFO = {
OUTPUT_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PEOPLE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
PRINT_AGU_DOMAINS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS_AND_CHILDREN: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PROCESS_WAIT_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)},
QUICK_CROS_MOVE: {VAR_TYPE: TYPE_BOOLEAN},
QUICK_INFO_USER: {VAR_TYPE: TYPE_BOOLEAN},

View File

@ -523,6 +523,10 @@ class GamCLArgs():
ARG_DATASTUDIOASSETS = 'datastudioassets'
ARG_DATASTUDIOPERMISSION = 'datastudiopermission'
ARG_DATASTUDIOPERMISSIONS = 'datastudiopermissions'
ARG_LOOKERSTUDIOASSET = 'lookerstudioasset'
ARG_LOOKERSTUDIOASSETS = 'lookerstudioassets'
ARG_LOOKERSTUDIOPERMISSION = 'lookerstudiopermission'
ARG_LOOKERSTUDIOPERMISSIONS = 'lookerstudiopermissions'
ARG_DATATRANSFER = 'datatransfer'
ARG_DATATRANSFERS = 'datatransfers'
ARG_DELEGATE = 'delegate'
@ -834,7 +838,6 @@ class GamCLArgs():
OB_CROS_ENTITY = 'CrOSEntity'
OB_CUSTOMER_ID = 'CustomerID'
OB_CUSTOMER_AUTH_TOKEN = 'CustomerAuthToken'
OB_DATASTUDIO_ASSET_MEMBERS_ENTITY = 'DataStudioAssetMembersEntity'
OB_DEVICE_FILE_ENTITY = 'DeviceFileEntity'
OB_DEVICE_ENTITY = 'DeviceEntity'
OB_DEVICE_ID = 'DeviceID'
@ -903,6 +906,7 @@ class GamCLArgs():
OB_LABEL_NAME_LIST = 'LabelNameList'
OB_LABEL_REPLACEMENT = 'LabelReplacement'
OB_LANGUAGE_LIST = 'LanguageList'
OB_LOOKERSTUDIO_PERMISSION_ENTITY = 'LookerStudioPermissionEntity'
OB_MATTER_ITEM = 'MatterItem'
OB_MATTER_ITEM_LIST = 'MatterItemList'
OB_MESSAGE_ID = 'MessageID'

View File

@ -149,11 +149,6 @@ class GamEntity():
CROS_SERIAL_NUMBER = 'crsn'
CUSTOMER_DOMAIN = 'cudo'
CUSTOMER_ID = 'cuid'
DATASTUDIO_ASSET = 'dsas'
DATASTUDIO_ASSET_DATASOURCE = 'dsad'
DATASTUDIO_ASSETID = 'dsai'
DATASTUDIO_ASSET_REPORT = 'dsar'
DATASTUDIO_PERMISSION = 'dspe'
DATE = 'date'
DEFAULT_LANGUAGE = 'dfla'
DELEGATE = 'dele'
@ -241,6 +236,11 @@ class GamEntity():
LANGUAGE = 'lang'
LICENSE = 'lice'
LOCATION = 'loca'
LOOKERSTUDIO_ASSET = 'lsas'
LOOKERSTUDIO_ASSET_DATASOURCE = 'lsad'
LOOKERSTUDIO_ASSETID = 'lsai'
LOOKERSTUDIO_ASSET_REPORT = 'lsar'
LOOKERSTUDIO_PERMISSION = 'lspe'
MD5HASH = 'md5h'
MEMBER = 'memb'
MEMBER_NOT_ARCHIVED = 'mena'
@ -475,11 +475,6 @@ class GamEntity():
CROS_SERIAL_NUMBER: ['CrOS Serial Numbers', 'CrOS Serial Numbers'],
CUSTOMER_DOMAIN: ['Customer Domains', 'Customer Domain'],
CUSTOMER_ID: ['Customer IDs', 'Customer ID'],
DATASTUDIO_ASSET: ['Data Studio Assets', 'Data Studio Asset'],
DATASTUDIO_ASSET_DATASOURCE: ['Data Studio DATA_SOURCE Assets', 'Data Studio DATA_SOURCE Asset'],
DATASTUDIO_ASSETID: ['Data Studio Asset IDs', 'Data Studio Asset ID'],
DATASTUDIO_ASSET_REPORT: ['Data Studio REPORT Assets', 'Data Studio REPORT Asset'],
DATASTUDIO_PERMISSION: ['Data Studio Permissions', 'Data Studio Permission'],
DATE: ['Dates', 'Date'],
DEFAULT_LANGUAGE: ['Default Language', 'Default Language'],
DELEGATE: ['Delegates', 'Delegate'],
@ -567,6 +562,11 @@ class GamEntity():
LANGUAGE: ['Languages', 'Language'],
LICENSE: ['Licenses', 'License'],
LOCATION: ['Locations', 'Location'],
LOOKERSTUDIO_ASSET: ['Looker Studio Assets', 'Looker Studio Asset'],
LOOKERSTUDIO_ASSET_DATASOURCE: ['Looker Studio DATA_SOURCE Assets', 'Looker Studio DATA_SOURCE Asset'],
LOOKERSTUDIO_ASSETID: ['Looker Studio Asset IDs', 'Looker Studio Asset ID'],
LOOKERSTUDIO_ASSET_REPORT: ['Looker Studio REPORT Assets', 'Looker Studio REPORT Asset'],
LOOKERSTUDIO_PERMISSION: ['Looker Studio Permissions', 'Looker Studio Permission'],
MD5HASH: ['MD5 hash', 'MD5 Hash'],
MEMBER: ['Members', 'Member'],
MEMBER_NOT_ARCHIVED: ['Members (Not Archived)', 'Member (Not Archived)'],

View File

@ -193,7 +193,6 @@ CISSO_UPDATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, FAILED_PRECONDIT
SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR]
CONTACT_DELEGATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, FAILED_PRECONDITION, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
COURSE_ACCESS_THROW_REASONS = [NOT_FOUND, INSUFFICIENT_PERMISSIONS, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
DATASTUDIO_THROW_REASONS = [INVALID_ARGUMENT, SERVICE_NOT_AVAILABLE, BAD_REQUEST, NOT_FOUND, PERMISSION_DENIED]
DRIVE_USER_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, DOMAIN_POLICY]
DRIVE_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS, UNKNOWN_ERROR, INVALID]
DRIVE_COPY_THROW_REASONS = DRIVE_ACCESS_THROW_REASONS+[CANNOT_COPY_FILE, BAD_REQUEST, RESPONSE_PREPARATION_FAILURE, TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
@ -253,7 +252,8 @@ GROUP_SETTINGS_RETRY_REASONS = [INVALID, SERVICE_LIMIT, SERVICE_NOT_AVAILABLE]
GROUP_LIST_THROW_REASONS = [RESOURCE_NOT_FOUND, DOMAIN_NOT_FOUND, FORBIDDEN, BAD_REQUEST]
GROUP_LIST_USERKEY_THROW_REASONS = GROUP_LIST_THROW_REASONS+[INVALID_MEMBER, INVALID_INPUT]
KEEP_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, PERMISSION_DENIED, INVALID_ARGUMENT, NOT_FOUND]
MEMBERS_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, INVALID, FORBIDDEN]
LOOKERSTUDIO_THROW_REASONS = [INVALID_ARGUMENT, SERVICE_NOT_AVAILABLE, BAD_REQUEST, NOT_FOUND, PERMISSION_DENIED]
MEMBERS_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, INVALID, FORBIDDEN, SERVICE_NOT_AVAILABLE]
MEMBERS_RETRY_REASONS = [SYSTEM_ERROR, SERVICE_NOT_AVAILABLE]
ORGUNIT_GET_THROW_REASONS = [INVALID_ORGUNIT, ORGUNIT_NOT_FOUND, BACKEND_ERROR, BAD_REQUEST, INVALID_CUSTOMER_ID, LOGIN_REQUIRED]
PEOPLE_ACCESS_THROW_REASONS = [SERVICE_NOT_AVAILABLE, FORBIDDEN, PERMISSION_DENIED]

View File

@ -158,6 +158,10 @@ PARSER = 'pars'
PID = 'pid '
# Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'pagu'
# OrgUnits for print cros
PRINT_CROS_OUS = 'pcou'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'pcoc'
# Check API calls rate
RATE_CHECK_COUNT = 'rccn'
RATE_CHECK_START = 'rcst'
@ -272,6 +276,8 @@ Globals = {
PARSER: None,
PID: 0,
PRINT_AGU_DOMAINS: '',
PRINT_CROS_OUS: '',
PRINT_CROS_OUS_AND_CHILDREN: '',
RATE_CHECK_COUNT: 0,
RATE_CHECK_START: 0,
SECTION: None,