Compare commits

..

3 Commits

Author SHA1 Message Date
Ross Scroggs
96aa4f3bd2 Added commands to create|delete|display Drive Label permissions. 2024-02-24 16:56:16 -08:00
Ross Scroggs
883979f5f5 Added options showvalidcolumn and addcsvdata to `gam print use 2024-02-23 14:41:45 -08:00
Ross Scroggs
b03a43777d Update DuetAI licenses to Gemini 2024-02-22 08:33:53 -08:00
17 changed files with 622 additions and 94 deletions

View File

@@ -89,15 +89,6 @@ If you run a Google Workspace Education SKU, verify that the super admin you'll
* Choose "All users are 18 or older"
* Click "SAVE"
Verify whether the super admin you'll be using is in an OU where reauthentication is required.
* Access the admin console and go to Security -> Overview
* Scroll down and open Google Cloud session control section
* Select the OU containing the super admin
* If Require reauthentication is selected and Exempt Trusted apps is not checked, you'll have to do `gam oauth create` at whatever frequency is specified
* If that sounds unappealing, check Exempt Trusted apps
* Click "OVERRIDE"
* Follow the steps below to mark GAM as a trusted app
Based on your domain policies, you may have to mark GAM as a trusted app. These steps are performed after a project is created.
* Access the admin console and go to Security -> Access and data control -> API controls
* Check Trust internal, domain-owned apps
@@ -114,6 +105,15 @@ Based on your domain policies, you may have to mark GAM as a trusted app. These
* Click Next/Continue
* Click Finish
Verify whether the super admin you'll be using is in an OU where reauthentication is required.
* Access the admin console and go to Security -> Overview
* Scroll down and open Google Cloud session control section
* Select the OU containing the super admin
* If Require reauthentication is selected and Exempt Trusted apps is not checked, you'll have to do `gam oauth create` at whatever frequency is specified
* If that sounds unappealing, check Exempt Trusted apps
* Click "OVERRIDE"
* Follow the steps below to mark GAM as a trusted app
## Headless computers and Cloud Shells
With many thanks to Jay, `gam oauth create` now uses a new client access authentication flow
as required by Google for headless computers/cloud shells; this is required as of February 28, 2022.

View File

@@ -119,7 +119,7 @@
#7a4706|#8a1c0a|#994a64|#ffffff
<LanguageCode> ::=
ach|af|ag|ak|am|ar|az|be|bem|bg|bn|br|bs|ca|chr|ckb|co|crs|cs|cy|da|de|
ee|el|en|en-gb|en-us|eo|es|es-419|et|eu|fa|fi|fil|fo|fr|fr-ca|fy|
ee|el|en|en-ca|en-gb|en-us|eo|es|es-419|et|eu|fa|fi|fil|fo|fr|fr-ca|fy|
ga|gaa|gd|gl|gn|gu|ha|haw|he|hi|hr|ht|hu|hy|ia|id|ig|in|is|it|iw|ja|jw|
ka|kg|kk|km|kn|ko|kri|ku|ky|la|lg|ln|lo|loz|lt|lua|lv|
mfe|mg|mi|mk|ml|mn|mo|mr|ms|mt|my|ne|nl|nn|no|nso|ny|nyn|oc|om|or|
@@ -232,8 +232,11 @@
101035 |
101036 |
101037 |
101038 |
101039 |
101040 |
101043 |
101047 |
Google-Apps |
Google-Chrome-Device-Management |
Google-Drive-storage |
@@ -249,12 +252,17 @@
4tb | drive4tb | googledrivestorage4tb | Google-Drive-storage-4TB |
8tb | drive8tb | googledrivestorage8tb | Google-Drive-storage-8TB |
16tb | drive16tb | googledrivestorage16tb | Google-Drive-storage-16TB |
appsheetcore | 1010380001 |
appsheetstandard | appsheetenterprisestandard | 1010380002 |
appsheetplus | appsheetenterpriseplus | 1010380003 |
assuredcontrols | 1010390001 |
bce | beyondcorp | beyondcorpenterprise | 1010400001 |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 |
cloudidentitypremium | identitypremium | 1010050001 |
cloudsearch | 1010350001 |
geminibiz | 1010470003 |
geminient| duetai | 1010470001 |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 |
@@ -270,6 +278,7 @@
gwesstaff | workspaceeducationstandardstaff | 1010310006 |
gwesstudent | workspaceeducationstandardstudent | 1010310007 |
gwetlu | workspaceeducationupgrade | 1010370001 |
gwlabs | workspacelabs | 1010470002
meetdialing | googlemeetglobaldialing | 1010360001 |
postini | gams | gsuitegams | gsuitepostini | gsuitemessagesecurity | Google-Apps-For-Postini |
standard | free | Google-Apps |
@@ -278,16 +287,22 @@
voicepremier | gvpremier | googlevoicepremier | 1010330002 |
voicestandard | gvstandard | googlevoicestandard | 1010330004 |
voicestarter | gvstarter | googlevoicestarter | 1010330003 |
wsas | plusstorage | 1010430001 |
wsbizplus | workspacebusinessplus | 1010020025 |
wsbizplusarchived | workspacebusinessplusarchived | 1010340003 |
wsbizstan | workspacebusinessstandard | 1010020028 |
wsbizstanarchived | workspacebusinessstandardarchived | 1010340006 |
wsbizstarter | workspacebusinessstarter | wsbizstart | 1010020027 |
wsbizstarterarchived | workspacebusinessstarterarchived | 1010340005 |
wsentess | workspaceenterpriseessentials | 1010060003 |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 |
wsentstan | workspaceenterprisestandard | 1010020026 |
wsentstanarchived | workspaceenterprisestandardarchived | 1010340004 |
wsentstarter | workspaceenterprisestarter | 1010020029 | wes |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030
wsessplus | workspaceessentialsplus | 1010060005 |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030 |
wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031
```
## Items built from primitives
```
@@ -346,7 +361,7 @@
<ChannelCustomerID> ::= <String>
<ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | <String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>
<ChatThread> ::= spaces/<String>/threads/<String>
<ClassroomInvitationID> ::= <String>
<ClientID> ::= <String>
@@ -421,6 +436,7 @@
<DriveLabelFieldID> ::= <String>
<DriveLabelSelectionID> ::= <String>
<DriveLabelName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]
<DriveLabelPermissionName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]/permissions/(audiences|groups|people)/<String>
<EmailAddress> ::= <String>@<DomainName>
<EmailItem> ::= <EmailAddress>|<UniqueID>|<String>
<EmailReplacement> ::= <String>
@@ -456,6 +472,11 @@
<Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted
<MessageContent> ::=
(message|textmessage|htmlmessage <String>)|
(file|textfile|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)
<MessageID> ::= <String>
<Namespace> ::= <String>
<NotesName> ::= notes/<String>
@@ -529,7 +550,7 @@
<ServiceAccountDisplayName> ::= <String>
Maximum of 100 characters
<ServiceAccountDescrition> ::= <String>
Maximumof 256 chcracters
Maximum of 256 chcracters
<ServiceAccountEmail> ::= <ServiceAccountName>@<ProjectID>.iam.gserviceaccount.com
<ServiceAccountUniqueID> ::= <Number>
<ServiceAccountKey> ::= <String>
@@ -584,8 +605,10 @@
(tdlocale <Locale>)|
(tdnobrowser [<Boolean>])|
(tdnoemail [<Boolean>])|
(tdnoescapechar [<Boolean>])|
(tdparent (id:<DriveFolderID>)|<DriveFolderName>)|
(tdshare <EmailAddress> commenter|reader|writer)|
(tdretaintitle [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)*|
(tdsheet (id:<Number>)|<String>)|
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
(tdsheettitle <String>)|

View File

@@ -262,6 +262,8 @@ Data fields identified in a `csvkmd` argument.
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveLabelNameEntity> ::=
<DriveLabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<DriveLabelPermissionNameEntity> ::=
<DriveLabelPermissionNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<EmailAddressEntity> ::=
<EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<FilterIDEntity> ::=

View File

@@ -10,6 +10,37 @@ 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.70.05
Added commands to create|delete|display Drive Label permissions.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users-Drive-Labels
### 6.70.04
Added option `showvalidcolumn` to `gam print users` that can be used to identify whether
users are defined in the domain. Typically, you would read CSV file of email addresses
to verify as domain members.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users#verify-domain-membership
Added option `addcsvdata <FieldName> <String>` to `gam print users` that adds
additional columns of data to the CSV file output. Typically, you would read CSV file of email addresses
to generate a CSV file of results and copy data from the input CSV to the outout CSV.
### 6.70.03
Renamed license product DuetAI to Gemini
* ProductID - 101047
Renamed license SKU DuetAI for Google Workspace to Gemini Enterprise
* ProductID - 101047
* SKUID - 1010470001 | geminient | duetai
Added support for license SKU Gemini Business
* ProductID - 101047
* SKUID - 1010470003 | geminibiz
### 6.70.02
In 6.69.00, GAM starting using course owner access when using `copyfrom` in `gam create|update course`

View File

@@ -334,7 +334,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.70.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.70.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.2 64-bit final
MacOS Sonoma 14.2.1 x86_64
@@ -1002,7 +1002,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.70.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.70.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.2 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -24,7 +24,7 @@
| Cloud Identity Free | 101001 |
| Cloud Identity Premium | 101005 |
| Cloud Search | 101035 |
| Duet AI | 101047 |
| Gemini | 101047 |
| Google Chrome Device Management | Google-Chrome-Device-Management |
| Google Drive Storage | Google-Drive-storage |
| Google Meet Global Dialing | 101036 |
@@ -46,11 +46,12 @@
| Cloud Identity Free | 1010010001 | cloudidentity |
| Cloud Identity Premium | 1010050001 | cloudidentitypremium |
| Cloud Search | 1010350001 | cloudsearch |
| Duet AI | 1010470001 | duetai |
| G Suite Basic | Google-Apps-For-Business | gsuitebasic |
| G Suite Business | Google-Apps-Unlimited | gsuitebusiness |
| G Suite Legacy | Google-Apps | standard |
| G Suite Lite | Google-Apps-Lite | gsuitelite |
| Gemini Business | 1010470003 | geminibiz
| Gemini Enterprise | 1010470001 | geminient | duetai |
| Google Apps Message Security | Google-Apps-For-Postini | postini |
| Google Chrome Device Management | Google-Chrome-Device-Management | cdm |
| Google Drive Storage 16TB | Google-Drive-storage-16TB | 16tb |

View File

@@ -43,6 +43,7 @@
<DriveFolderNameList> ::= "<DriveFolderName>(,<DriveFolderName>)*"
<DriveLabelIDList> ::= "<DriveLabelID>(,<DriveLabelID>)*"
<DriveLabelNameList> ::= "<DriveLabelName>(,<DriveLabelName>)*"
<DriveLabelPermissionNameList> ::= "<DriveLabelPermissionName>(,<DriveLabelPermissionName>)*"
<DriveLabelFieldIDList> ::= "<DriveLabelFieldID>(,<DriveLabelFieldID>)*"
<DriveLabelSelectionIDList> ::= "<DriveLabelSelectionID>(,<DriveLabelSelectionID>)*"
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"

View File

@@ -6,12 +6,15 @@
- [Introduction](#introduction)
- [Display Drive Labels](#display-drive-labels)
- [Process File Drive Labels](#process-file-drive-labels)
- [Manage Drive Label Permissions](#manage-drive-label-permissions)
- [Display Drive Label Permissions](#display-drive-label-permissions)
## API documentation
* https://support.google.com/a/answer/9292382
* https://developers.google.com/drive/labels/guides/overview
* https://developers.google.com/drive/labels/guides/authorize
* https://developers.google.com/drive/labels/reference/rest/v2beta/labels
* https://developers.google.com/drive/labels/reference/rest/v2beta/labels.permissions
* https://developers.google.com/drive/api/guides/about-labels
* https://developers.google.com/drive/api/v3/reference/files
@@ -19,13 +22,15 @@
To use these commands you must add the 'Drive Labels API' to your project and update your service account authorization.
```
gam update project
gam user user@domain.com check serviceaccount
gam user user@domain.com update serviceaccount
```
Supported editions for this feature: Business Standard and Business Plus; Enterprise; Education Standard and Education Plus; G Suite Business; Essentials.
## Definitions
* [`<DriveFileEntity>`](Drive-File-Selection)
* [`<UserTypeEntity>`](Collections-of-Users)
* [`<DriveLabelNameEntity>`, `<DriveLabelPermissionNameEntity'](Collections-of-Items)
* [`<UserTypeEntity>`](Collections-of-Items)
```
<DriveLabelID> ::= <String>
@@ -35,7 +40,11 @@ Supported editions for this feature: Business Standard and Business Plus; Enterp
<DriveLabelNameList> ::= "<DriveLabelName>(,<DriveLabelName)*"
<DriveLabelNameEntity> ::=
<DriveLabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
<DriveLabelPermissionName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]/permissions/(audiences|groups|people)/<String>
<DriveLabelPermissionNameList> ::= "<DriveLabelPermissionName>(,<DriveLabelPermissionName>)*"
<DriveLabelPermissionNameEntity> ::=
<DriveLabelPermissionNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<DriveLabelFieldID> ::= <String>
<DriveLabelSelectionID> ::= <String>
@@ -86,9 +95,9 @@ A domain administrator with the Drive and Docs administrator privilege can searc
owned by their organization, regardless of the admin's membership in any given Shared Drive.
Three forms of the commands are available:
* `gam action ...` - The administrator named in oauth2.txt is used, domain administrator access implied and labels of type `SHARED` and `ADMIN`can be written
* `gam <UserTypeEntity> action ... adminaccess` - The user named in `<UserTypeEntty>` is used, adminaccess indicates that labels of type `SHARED` and `ADMIN`can be written
* `gam <UserTypeEntity> action ...` - The user named in `<UserTypeEntty>` is used, access is limited, onlylabels of type `SHARED` can be written
* `gam action ...` - The administrator named in oauth2.txt is used, domain administrator access implied and labels of type `SHARED` and `ADMIN`can be processed
* `gam <UserTypeEntity> action ... adminaccess` - The user named in `<UserTypeEntty>` is used, adminaccess indicates that labels of type `SHARED` and `ADMIN`can be processed
* `gam <UserTypeEntity> action ...` - The user named in `<UserTypeEntty>` is used, access is limited, onlylabels of type `SHARED` can be processed
## Display Drive Labels
@@ -156,3 +165,51 @@ gam <UserTypeEntity> process filedrivelabels <DriveFileEntity>
By default, details of the process labels are displayed, use `nodetails` to suppress this display.
## Manage Drive Label Permissions
Create a permission for a Drive Label by specifying the label name and the principal.
```
gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
(user <UserItem>) | (group <GroupItem) | (audience <String>)
role applier|editor|organizer|reader
[nodetails|formatjson] [adminaccess|asadmin]
```
By default, when a permission is created, GAM outputs details of the permission as indented keywords and values.
* `nodetails` - Suppress the details output.
* `formatjson` - Output the details in JSON format.
Delete a Drive Label permission by specifying the label name and the principal.
```
gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
(user <UserItem>) | (group <GroupItem) | (audience <String>)
[adminaccess|asadmin]
```
Delete a Drive Label permission by specifying the label permission name.
```
gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
[adminaccess|asadmin]
```
## Display Drive Label Permissions
Display permissions for a collection of Drive Label permission names.
```
gam [<UserTypeEntity>] show drivelabelpermissions <DriveLabelNameEntity>
[formatjson] [adminaccess|asadmin]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam [<UserTypeEntity>] print drivelabelpermissions <DriveLabelNameEntity> [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]] [adminaccess|asadmin]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
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.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@@ -39,6 +39,7 @@
- [Print domain counts for users specified by `<UserTypeEntity>`](#print-domain-counts-for-users-specified-by-usertypeentity)
- [Print user list](#print-user-list)
- [Display user counts](#display-user-counts)
- [Verify domain membership]($verify-domain-membership)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/users
@@ -981,14 +982,16 @@ gam print users [todrive <ToDriveAttribute>*]
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])
[orderby <UserOrderByFieldName> [ascending|descending]]
[groups|groupsincolumns]
[license|licenses|licence|licences]
[license|licenses|licence|licences|licensebyuser|licensesbyuser|licencebyuser|licencesbyuser]
[onelicenseperrow|onelicenceperrow]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username]
[userview] [allfields|basic|full|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
```
By default, users in all domains in the account are selected; these options allow selection of subsets of users:
@@ -1008,11 +1011,13 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
[onelicenseperrow|onelicenceperrow]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username][schemas|custom all|<SchemaNameList>]
[userview] [allfields|basic|full|(<UserFieldName>*|fields <UserFieldNameList>)]
[emailpart|emailparts|username]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
[orderby <UserOrderByFieldName> [ascending|descending]]
[groups|groupsincolumns]
@@ -1021,10 +1026,11 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username]
[userview] [allfields|basic|full|(<UserFieldName>*|fields <UserFieldNameList>)]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
```
By default, Gam gets no group membership information for each user. The `groups` and `groupsincolumns`
@@ -1079,6 +1085,17 @@ In the output, primaryEmail is the always the first column; these options contro
* `<UserFieldName>*|fields <UserFieldNameList>` - The columns appear in the order that the fields are specified.
* `scalarsfirst [true]` - When columns are sorted by name, scalar fields appear before repeating fields.
By default, if `<UserTypeEntity>` includes an email address the is not a user member of the domain,
an error message is generated.
```
User: testuserxxx@domain.com, Does not exist
```
Using option `showvalidcolumn`, a new column `Found` indicates domain membership; no errors are generated
Add additional columns of data from the command line to the output
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
* `formatjson` - Display the fields in JSON format.
@@ -1249,3 +1266,34 @@ count=$(gam print users query "orgUnitPath='/Students/Middle School'" showitemco
Windows PowerShell
count = & gam print users query "orgUnitPath='/Students/Middle School'" showitemcountonly
```
## Verify domain membership
You have a CSV file of email addresses and want to verify of the addresses are valid users in your domain.
```
# Users.csv
$ more Users.csv
primaryEmail,name
testuser1@domain.com,Test User 1
testuserxxx@domain.com,Test User XXX
testuser2@domain.com,Test User 2
# Without showvalidcolumn, non-domain users generate an error
$ gam redirect csv - multiprocess csv Users.csv gam user "~primaryEmail" print users fields primaryemail,id addcsvdata name "~name"
2024-02-23T11:29:00.407-08:00,0/3,Using 3 processes...
2024-02-23T11:29:00.410-08:00,0,Processing item 3/3
User: testuserxxx@domain.com, Does not exist
2024-02-23T11:29:06.511-08:00,0/3,Processing complete
primaryEmail,id,name
testuser1@domain.com,118080758787650801331,Test User 1
testuser2@domain.com,107344800159717682514,Test User 2
# Using showvalidcolumn, a new column `Valid` indicates domain membership; no errors are generated
$ gam redirect csv - multiprocess csv Users.csv gam user "~primaryEmail" print users fields primaryemail,id addcsvdata name "~name" showvalidcolumn
2024-02-23T11:29:22.287-08:00,0/3,Using 3 processes...
2024-02-23T11:29:22.292-08:00,0,Processing item 3/3
2024-02-23T11:29:23.366-08:00,0/3,Processing complete
primaryEmail,id,Valid,name
testuser1@domain.com,118080758787650801331,True,Test User 1
testuserxxx@domain.com,,False,Test User XXX
testuser2@domain.com,107344800159717682514,True,Test User 2
```

View File

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

View File

@@ -22,43 +22,6 @@ If an item contains spaces, it should be surrounded by ".
<FalseValues>= false|off|no|disabled|0
<TrueValues> ::= true|on|yes|enabled|1
<Charset> ::= ascii|latin1|mbcs|utf-8|utf-8-sig|utf-16|<String>
<CalendarColorIndex> ::= <Number in range 1-24>
<CalendarColorName> ::=
amethyst|avocado|banana|basil|birch|blueberry|
cherryblossom|citron|cobalt|cocoa|eucalyptus|flamingo|
grape|graphite|lavender|mango|peacock|pistachio|
pumpkin|radicchio|sage|tangerine|tomato|wisteria|
<ColorHex> ::= "#<Hex><Hex><Hex><Hex><Hex><Hex>"
<ColorNameGoogle> ::=
asparagus|bluevelvet|bubblegum|cardinal|chocolateicecream|denim|desertsand|
earthworm|macaroni|marsorange|mountaingray|mountaingrey|mouse|oldbrickred|
pool|purpledino|purplerain|rainysky|seafoam|slimegreen|spearmint|
toyeggplant|vernfern|wildstrawberries|yellowcab
<ColorNameWeb> ::=
aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|
blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|
cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|
darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|
darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|
darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|
firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|
gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|
lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|
lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|
lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|
lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|
mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|
mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|
navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|
palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|
peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|
sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|
slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|
wheat|white|whitesmoke|yellow|yellowgreen
<ColorName> ::= <ColorNameGoogle>|<ColorNameWeb>
<ColorValue> ::= <ColorName>|<ColorHex>
<DayOfWeek> ::= mon|tue|wed|thu|fri|sat|sun
<BCP47LanguageCode> ::=
ar-sa| # Arabic Saudi Arabia
cs-cz| # Czech Czech Republic
@@ -97,6 +60,43 @@ If an item contains spaces, it should be surrounded by ".
zh-cn| # Chinese China
zh-hk| # Chinese Hong Kong
zh-tw # Chinese Taiwan
<Charset> ::= ascii|latin1|mbcs|utf-8|utf-8-sig|utf-16|<String>
<CalendarColorIndex> ::= <Number in range 1-24>
<CalendarColorName> ::=
amethyst|avocado|banana|basil|birch|blueberry|
cherryblossom|citron|cobalt|cocoa|eucalyptus|flamingo|
grape|graphite|lavender|mango|peacock|pistachio|
pumpkin|radicchio|sage|tangerine|tomato|wisteria|
<ColorHex> ::= "#<Hex><Hex><Hex><Hex><Hex><Hex>"
<ColorNameGoogle> ::=
asparagus|bluevelvet|bubblegum|cardinal|chocolateicecream|denim|desertsand|
earthworm|macaroni|marsorange|mountaingray|mountaingrey|mouse|oldbrickred|
pool|purpledino|purplerain|rainysky|seafoam|slimegreen|spearmint|
toyeggplant|vernfern|wildstrawberries|yellowcab
<ColorNameWeb> ::=
aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|
blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|
cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|
darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|
darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|
darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|
firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|
gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|
lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|
lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|
lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|
lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|
mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|
mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|
navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|
palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|
peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|
sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|
slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|
wheat|white|whitesmoke|yellow|yellowgreen
<ColorName> ::= <ColorNameGoogle>|<ColorNameWeb>
<ColorValue> ::= <ColorName>|<ColorHex>
<DayOfWeek> ::= mon|tue|wed|thu|fri|sat|sun
<EventColorIndex> ::= <Number in range 1-11>
<EventColorName> ::=
banana|basil|blueberry|flamingo|graphite|grape|
@@ -267,7 +267,8 @@ If an item contains spaces, it should be surrounded by ".
cloudidentity | identity | 1010010001 |
cloudidentitypremium | identitypremium | 1010050001 |
cloudsearch | 1010350001 |
duetai | 1010470001 |
geminibiz | 1010470003 |
geminient| duetai | 1010470001 |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 |
@@ -441,6 +442,7 @@ If an item contains spaces, it should be surrounded by ".
<DriveLabelFieldID> ::= <String>
<DriveLabelSelectionID> ::= <String>
<DriveLabelName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]
<DriveLabelPermissionName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]/permissions/(audiences|groups|people)/<String>
<EmailAddress> ::= <String>@<DomainName>
<EmailItem> ::= <EmailAddress>|<UniqueID>|<String>
<EmailReplacement> ::= <String>
@@ -583,6 +585,7 @@ If an item contains spaces, it should be surrounded by ".
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<Tag> ::= <String>
@@ -641,6 +644,7 @@ If an item contains spaces, it should be surrounded by ".
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
<CalendarACLScopeList> ::= "<CalendarACLScope>(,<CalendarACLScope>)*"
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<CIGroupAliasList> ::= "<CIGroupAlias>(,<CIGroupAlias>)*"
<CIGroupTypeList> ::= "<CIGroupType>(,<CIGroupType>)*"
<ClassroomInvitationIDList> ::= "<ClassroomInvitationID>(,<ClassroomInvitationID>)*"
@@ -673,6 +677,7 @@ If an item contains spaces, it should be surrounded by ".
<DriveFolderNameList> ::= "<DriveFolderName>(,<DriveFolderName>)*"
<DriveLabelIDList> ::= "<DriveLabelID>(,<DriveLabelID>)*"
<DriveLabelNameList> ::= "<DriveLabelName>(,<DriveLabelName>)*"
<DriveLabelPermissionNameList> ::= "<DriveLabelPermissionName>(,<DriveLabelPermissionName>)*"
<DriveLabelFieldIDList> ::= "<DriveLabelFieldID>(,<DriveLabelFieldID>)*"
<DriveLabelSelectionIDList> ::= "<DriveLabelSelectionID>(,<DriveLabelSelectionID>)*"
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
@@ -1095,6 +1100,8 @@ Specify a collection of items by directly specifying them; the item type is dete
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveLabelNameEntity> ::=
<DriveLabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<DriveLabelPermissionNameEntity> ::=
<DriveLabelPermissionNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<EmailAddressEntity> ::=
<EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<FilterIDEntity> ::=
@@ -3395,6 +3402,21 @@ gam [<UserTypeEntity>] show drivelabels
[basic|full] [languagecode <LanguageCode>]
[publishedonly [<Boolean>]] [minimumrole applier|editor|organizer|reader]
[formatjson] [adminaccess|asadmin]
`
gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
(user <UserItem>) | (group <GroupItem) | (audience <String>)
role applier|editor|organizer|reader
[formatjson] [adminaccess|asadmin]
gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
(user <UserItem>) | (group <GroupItem) | (audience <String>)
[adminaccess|asadmin]
gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
[adminaccess|asadmin]
gam [<UserTypeEntity>] print drivelabelpermissions <DriveLabelNameEntity> [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]] [adminaccess|asadmin]
gam [<UserTypeEntity>] show drivelabelpermissions <DriveLabelNameEntity>
[formatjson] [adminaccess|asadmin]
# Email Audit Monitor
@@ -5413,10 +5435,11 @@ gam print users [todrive <ToDriveAttribute>*]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username]
[userview] [basic|full|allfields | <UserFieldName>* | fields <UserFieldNameList>]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
Print fields for specified users.
@@ -5429,10 +5452,11 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username]
[userview] [basic|full|allfields | <UserFieldName>* | fields <UserFieldNameList>]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
@@ -5443,10 +5467,11 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
[schemas|custom|customschemas all|<SchemaNameList>]
[emailpart|emailparts|username]
[userview] [basic|full|allfields | <UserFieldName>* | fields <UserFieldNameList>]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
The first column will always be primaryEmail; the remaining field names will be sorted if allfields, basic, full or sortheaders is specified;

View File

@@ -2,6 +2,37 @@
Merged GAM-Team version
6.70.05
Added commands to create|delete|display Drive Label permissions.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users-Drive-Labels
6.70.04
Added option `showvalidcolumn` to `gam print users` that can be used to identify whether
users are defined in the domain. Typically, you would read CSV file of email addresses
to verify as domain members.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users#verify-domain-membership
Added option `addcsvdata <FieldName> <String>` to `gam print users` that adds
additional columns of data to the CSV file output. Typically, you would read CSV file of email addresses
to generate a CSV file of results and copy data from the input CSV to the outout CSV.
6.70.03
Renamed license product DuetAI to Gemini
* ProductID - 101047
Renamed license SKU DuetAI for Google Workspace to Gemini Enterprise
* ProductID - 101047
* SKUID - 1010470001 | geminient | duetai
Added support for license SKU Gemini Business
* ProductID - 101047
* SKUID - 1010470003 | geminibiz
6.70.02
In 6.69.00, GAM starting using course owner access when using `copyfrom` in `gam create|update course`

View File

@@ -42672,6 +42672,7 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
# [delimiter <Character>] [sortheaders] [formatjson [quotechar <Character>]] [quoteplusphonenumbers]
# [issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
# [showitemcountonly]
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
#
# gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
# [groups|groupsincolumns]
@@ -42683,6 +42684,7 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
# [delimiter <Character>] [sortheaders] [formatjson [quotechar <Character>]] [quoteplusphonenumbers]
# [issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
# [showitemcountonly]
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
#
# gam print users [todrive <ToDriveAttribute>*]
# ([domain <DomainName>] [(query <QueryUser>)|(queries <QueryUserList>)]
@@ -42690,6 +42692,7 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
# [formatjson [quotechar <Character>]] [countonly]
# [issuspended <Boolean>] [aliasmatchpattern <RegularExpression>]
# [showitemcountonly]
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
#
# gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
# [formatjson [quotechar <Character>]] [countonly]
@@ -42697,16 +42700,23 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
# [showitemcountonly]
def doPrintUsers(entityList=None):
def _writeUserEntity(userEntity):
if addCSVData:
userEntity.update(addCSVData)
row = flattenJSON(userEntity, skipObjects=USER_SKIP_OBJECTS, timeObjects=USER_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'primaryEmail': userEntity['primaryEmail'],
'JSON': json.dumps(cleanJSON(userEntity, skipObjects=USER_SKIP_OBJECTS, timeObjects=USER_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
row = {'primaryEmail': userEntity['primaryEmail']}
if showValidColumn:
row[showValidColumn] = userEntity[showValidColumn]
row['JSON'] = json.dumps(cleanJSON(userEntity, skipObjects=USER_SKIP_OBJECTS, timeObjects=USER_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
def _printUser(userEntity, i, count):
if isSuspended is None or isSuspended == userEntity.get('suspended', isSuspended):
if showValidColumn:
userEntity[showValidColumn] = True
userEmail = userEntity['primaryEmail']
if printOptions['emailParts']:
if userEmail.find('@') != -1:
@@ -42785,7 +42795,10 @@ def doPrintUsers(entityList=None):
else:
http_status, reason, message = checkGAPIError(exception)
if reason in GAPI.USER_GET_THROW_REASONS:
entityUnknownWarning(Ent.USER, ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
if not showValidColumn:
entityUnknownWarning(Ent.USER, ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
_writeUserEntity({'primaryEmail': ri[RI_ITEM], showValidColumn: False})
elif (reason == GAPI.INVALID_INPUT) and customFieldMask:
entityActionFailedWarning([Ent.USER, ri[RI_ITEM]], invalidUserSchema(customFieldMask), int(ri[RI_J]), int(ri[RI_JCOUNT]))
elif reason not in GAPI.DEFAULT_RETRY_REASONS:
@@ -42799,7 +42812,10 @@ def doPrintUsers(entityList=None):
userKey=ri[RI_ITEM], projection=projection, customFieldMask=customFieldMask, viewType=viewType, fields=fields)
_printUser(user, int(ri[RI_J]), int(ri[RI_JCOUNT]))
except (GAPI.userNotFound, GAPI.resourceNotFound):
entityUnknownWarning(Ent.USER, ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
if not showValidColumn:
entityUnknownWarning(Ent.USER, ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
_writeUserEntity({'primaryEmail': ri[RI_ITEM], showValidColumn: False})
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
GAPI.badRequest, GAPI.backendError, GAPI.systemError, GAPI.rateLimitExceeded) as e:
entityActionFailedWarning([Ent.USER, ri[RI_ITEM]], str(e), int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -42836,7 +42852,9 @@ def doPrintUsers(entityList=None):
aliasMatchPattern = isSuspended = orgUnitPath = orgUnitPathLower = orderBy = sortOrder = None
viewType = 'admin_view'
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
showValidColumn = ''
showItemCountOnly = False
addCSVData = {}
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'todrive':
@@ -42913,6 +42931,11 @@ def doPrintUsers(entityList=None):
quotePlusPhoneNumbers = True
elif myarg == 'showitemcountonly':
showItemCountOnly = True
elif myarg == 'showvalidcolumn':
showValidColumn = 'Valid'
elif myarg == 'addcsvdata':
k = getString(Cmd.OB_STRING)
addCSVData[k] = getString(Cmd.OB_STRING, minLen=0)
else:
FJQC.GetFormatJSONQuoteChar(myarg, False)
_, _, entityList = getEntityArgument(entityList)
@@ -42926,8 +42949,16 @@ def doPrintUsers(entityList=None):
else:
if FJQC.formatJSON:
printOptions['sortHeaders'] = False
csvPF.SetJSONTitles(['primaryEmail', 'JSON'])
titles = ['primaryEmail']
if showValidColumn:
titles.append(showValidColumn)
titles.append('JSON')
csvPF.SetJSONTitles(titles)
else:
if showValidColumn:
csvPF.AddTitles([showValidColumn])
if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys()))
if printOptions['getGroupFeed']:
if not printOptions['groupsInColumns']:
csvPF.AddTitles(['GroupsCount', 'Groups'])
@@ -43013,7 +43044,7 @@ def doPrintUsers(entityList=None):
# If no individual fields were specified (allfields, basic, full) or individual fields other than primaryEmail were specified, look up each user
if isSuspended is not None:
fieldsList.append('suspended')
if projectionSet or len(set(fieldsList)) > 1:
if projectionSet or len(set(fieldsList)) > 1 or showValidColumn:
jcount = len(entityList)
fields = getFieldsFromFieldsList(fieldsList)
if GC.Values[GC.BATCH_SIZE] > 1 and jcount > 1:
@@ -43045,7 +43076,10 @@ def doPrintUsers(entityList=None):
userKey=userEmail, projection=projection, customFieldMask=customFieldMask, viewType=viewType, fields=fields)
_printUser(user, j, jcount)
except (GAPI.userNotFound, GAPI.resourceNotFound):
entityUnknownWarning(Ent.USER, userEmail, j, jcount)
if not showValidColumn:
entityUnknownWarning(Ent.USER, userEmail, j, jcount)
else:
_writeUserEntity({'primaryEmail': userEmail, showValidColumn: False})
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
GAPI.badRequest, GAPI.backendError, GAPI.systemError, GAPI.rateLimitExceeded) as e:
entityActionFailedWarning([Ent.USER, userEmail], str(e), j, jcount)
@@ -61143,7 +61177,7 @@ def doPrintShowDriveFileACLs():
printShowDriveFileACLs([_getAdminEmail()], True)
DRIVELABELS_PROJECTION_CHOICE_MAP = {'basic': 'LABEL_VIEW_BASIC', 'full': 'LABEL_VIEW_FULL'}
DRIVELABELS_MINIMUM_ROLE_MAP = {
DRIVELABELS_PERMISSION_ROLE_MAP = {
'applier': 'APPLIER',
'editor': 'EDITOR',
'organizer': 'ORGANIZER',
@@ -61162,7 +61196,7 @@ def _getDisplayDriveLabelsParameters(myarg, parameters):
elif myarg == 'publishedonly':
parameters['publishedOnly'] = getBoolean()
elif myarg == 'minimumrole':
parameters['minimumRole'] = getChoice(DRIVELABELS_MINIMUM_ROLE_MAP, mapChoice=True)
parameters['minimumRole'] = getChoice(DRIVELABELS_PERMISSION_ROLE_MAP, mapChoice=True)
else:
return False
return True
@@ -61180,6 +61214,22 @@ def normalizeDriveLabelName(driveLabelName):
return driveLabelName
return f'labels/{driveLabelName}'
def validateDriveLabelName(name, kvList, j, jcount, permName=False):
name = normalizeDriveLabelName(name)
# Label name
if not permName:
mg = re.match(r'^(labels/[^/]+)$', name)
if not mg:
entityActionNotPerformedWarning(kvList, 'Expected labels/<String>', j, jcount)
return None
return name
# Label permission name
mg = re.match(r'^(labels/[^/]+)/permissions/(?:audiences|groups|people)/.+$', name)
if not mg:
entityActionNotPerformedWarning(kvList, 'Expected labels/<String>/permissions/(audiences|groups|people)/<String>', j, jcount)
return (None, None)
return (name, mg.group(1))
def _showDriveLabel(label, j, jcount, FJQC):
if FJQC.formatJSON:
printLine(json.dumps(cleanJSON(label, timeObjects=DRIVELABELS_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
@@ -61193,7 +61243,7 @@ def _showDriveLabel(label, j, jcount, FJQC):
# [[basic|full] [languagecode <BCP47LanguageCode>]
# [formatjson] [adminaccess|asadmin]
def infoDriveLabels(users, useAdminAccess=False):
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_NAME, Ent.DRIVE_LABEL_NAME, shlexSplit=True)
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_NAME, Ent.DRIVE_LABEL, shlexSplit=True)
FJQC = FormatJSONQuoteChar()
parameters = {'useAdminAccess': useAdminAccess}
while Cmd.ArgumentsRemaining():
@@ -61206,15 +61256,18 @@ def infoDriveLabels(users, useAdminAccess=False):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, drive, noteNames, jcount = _validateUserGetObjectList(user, i, count, driveLabelNameEntity,
api=api, showAction=FJQC is None or not FJQC.formatJSON)
user, drive, labelNames, jcount = _validateUserGetObjectList(user, i, count, driveLabelNameEntity,
api=api, showAction=not FJQC.formatJSON)
if jcount == 0:
continue
Ind.Increment()
j = 0
for name in noteNames:
for name in labelNames:
j += 1
name = normalizeDriveLabelName(name)
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_NAME, name]
name = validateDriveLabelName(name, kvList, j, jcount, False)
if name is None:
continue
try:
label = callGAPI(drive.labels(), 'get',
bailOnInternalError=True,
@@ -61223,13 +61276,14 @@ def infoDriveLabels(users, useAdminAccess=False):
name=name, **parameters)
_showDriveLabel(label, j, jcount, FJQC)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_LABEL_NAME, name], str(e), j, jcount)
entityActionFailedWarning(kvList, str(e), j, jcount)
except (GAPI.permissionDenied, GAPI.invalidArgument, GAPI.internalError) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_LABEL_NAME, name], str(e), j, jcount)
entityActionFailedWarning(kvList, str(e), j, jcount)
break
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userSvcNotApplicableOrDriveDisabled(user, str(e), i, count)
break
Ind.Decrement()
def doInfoDriveLabels():
infoDriveLabels([_getAdminEmail()], True)
@@ -61272,7 +61326,7 @@ def printShowDriveLabels(users, useAdminAccess=False):
labels = callGAPIpages(drive.labels(), 'list', 'labels',
pageMessage=pageMessage,
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.PERMISSION_DENIED],
**parameters, fields='nextPageToken,labels', pageSize=GC.Values[GC.DRIVE_MAX_RESULTS])
**parameters, fields='nextPageToken,labels', pageSize=200)
if not csvPF:
jcount = len(labels)
if not FJQC.formatJSON:
@@ -61303,6 +61357,234 @@ def printShowDriveLabels(users, useAdminAccess=False):
def doPrintShowDriveLabels():
printShowDriveLabels([_getAdminEmail()], True)
def _showDriveLabelPermission(labelperm, j, jcount, FJQC):
if FJQC.formatJSON:
printLine(json.dumps(cleanJSON(labelperm), ensure_ascii=False, sort_keys=True))
return
printEntity([Ent.DRIVE_LABEL_PERMISSION_NAME, f'{labelperm["name"]}'], j, jcount)
Ind.Increment()
showJSON(None, labelperm)
Ind.Decrement()
# gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
# (user <UserItem>) | (group <GroupItem) | (audience <String>)
# role applier|editor|organizer|reader
# [nodetails|formatjson] [adminaccess|asadmin]
def createDriveLabelPermissions(users, useAdminAccess=False):
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_NAME, Ent.DRIVE_LABEL_PERMISSION, shlexSplit=True)
FJQC = FormatJSONQuoteChar()
parameters = {'useAdminAccess': useAdminAccess}
body = {}
showDetails = True
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in ADMIN_ACCESS_OPTIONS:
parameters['useAdminAccess'] = True
elif myarg == 'role':
body['role'] = getChoice(DRIVELABELS_PERMISSION_ROLE_MAP, mapChoice=True)
elif myarg in {'user', 'group'}:
email = getEmailAddress(returnUIDprefix='id:')
body['email'], status = convertUIDtoEmailAddressWithType(email, emailTypes=[myarg])
if status == 'unknown':
Cmd.Backup()
usageErrorExit(Msg.ENTITY_DOES_NOT_EXIST.format(email))
elif myarg == 'audience':
audience = getString(Cmd.OB_STRING)
if not audience.startswith('audiences/'):
audience = 'audiences/'+audience
body['audience'] = audience
elif myarg == 'nodetails':
showDetails = False
else:
FJQC.GetFormatJSON(myarg)
if 'role' not in body:
missingArgumentExit(f'role {"|".join(DRIVELABELS_PERMISSION_ROLE_MAP.keys())}')
if 'email' not in body and 'audience' not in body:
missingArgumentExit('(user <UserItem>) | (group <GroupItem) | (audience <String>)')
api = API.DRIVELABELS_ADMIN if parameters['useAdminAccess'] else API.DRIVELABELS_USER
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, drive, labelNames, jcount = _validateUserGetObjectList(user, i, count, driveLabelNameEntity,
api=api, showAction=not FJQC.formatJSON)
if jcount == 0:
continue
Ind.Increment()
j = 0
for name in labelNames:
j += 1
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_NAME, name, Ent.DRIVE_LABEL_PERMISSION, None]
name = validateDriveLabelName(name, kvList, j, jcount, False)
if name is None:
continue
try:
labelperm = callGAPI(drive.labels().permissions(), 'create',
bailOnInternalError=True,
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.PERMISSION_DENIED, GAPI.NOT_FOUND,
GAPI.INVALID, GAPI.INTERNAL_ERROR],
parent=name, body=body, **parameters)
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_PERMISSION, labelperm['name']]
if not FJQC.formatJSON:
entityActionPerformed(kvList, j, jcount)
if showDetails:
Ind.Increment()
_showDriveLabelPermission(labelperm, j, jcount, FJQC)
Ind.Decrement()
except (GAPI.permissionDenied, GAPI.notFound, GAPI.invalid, GAPI.internalError) as e:
entityActionFailedWarning(kvList, str(e), j, jcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userSvcNotApplicableOrDriveDisabled(user, str(e), i, count)
break
Ind.Decrement()
def doCreateDriveLabelPermissions():
createDriveLabelPermissions([_getAdminEmail()], True)
# gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
# (user <UserItem>) | (group <GroupItem) | (audience <String>)
# [adminaccess|asadmin]
# gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
# [adminaccess|asadmin]
def deleteDriveLabelPermissions(users, useAdminAccess=False):
doDelete = Act.Get() == Act.DELETE
if doDelete:
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_NAME, Ent.DRIVE_LABEL, shlexSplit=True)
else:
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_PERMISSION_NAME, Ent.DRIVE_LABEL_PERMISSION, shlexSplit=True)
parameters = {'useAdminAccess': useAdminAccess, 'requests': [None]}
labelperm = ''
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in ADMIN_ACCESS_OPTIONS:
parameters['useAdminAccess'] = True
elif doDelete and myarg in {'user', 'group'}:
labelperm = ['people/', 'groups/'][myarg == 'group']+convertEmailAddressToUID(getEmailAddress(), cd=None, emailType=myarg, savedLocation=None)
elif doDelete and myarg == 'audience':
audience = getString(Cmd.OB_STRING)
if not audience.startswith('audiences/'):
audience = 'audiences/'+audience
labelperm = audience
else:
unknownArgumentExit()
if doDelete and not labelperm:
missingArgumentExit('(user <UserItem>) | (group <GroupItem) | (audience <String>)')
api = API.DRIVELABELS_ADMIN if parameters['useAdminAccess'] else API.DRIVELABELS_USER
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, drive, labelPermNames, jcount = _validateUserGetObjectList(user, i, count, driveLabelNameEntity,
api=api, showAction=True)
if jcount == 0:
continue
Ind.Increment()
j = 0
for name in labelPermNames:
j += 1
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_PERMISSION_NAME, name]
if doDelete:
parent = validateDriveLabelName(name, kvList, j, jcount, False)
if parent is None:
continue
name = parent+'/permissions/'+labelperm
else:
name, parent = validateDriveLabelName(name, kvList, j, jcount, True)
if name is None:
continue
kvList[-1] = name
parameters['requests'][0] = {'name': name}
try:
callGAPI(drive.labels().permissions(), 'batchDelete',
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.PERMISSION_DENIED, GAPI.INVALID, GAPI.NOT_FOUND],
parent=parent, body=parameters)
entityActionPerformed(kvList, j, jcount)
except (GAPI.permissionDenied, GAPI.invalid, GAPI.notFound) as e:
entityActionFailedWarning(kvList, str(e), j, jcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userSvcNotApplicableOrDriveDisabled(user, str(e), i, count)
break
Ind.Decrement()
def doDeleteDriveLabelPermissions():
deleteDriveLabelPermissions([_getAdminEmail()], True)
# gam [<UserTypeEntity>] print drivelabelpermissions <DriveLabelNameEntity> [todrive <ToDriveAttribute>*]
# [formatjson [quotechar <Character>]] [adminaccess|asadmin]
# gam [<UserTypeEntity>] show drivelabelpermissions <DriveLabelNameEntity>
# [formatjson] [adminaccess|asadmin]
def printShowDriveLabelPermissions(users, useAdminAccess=False):
csvPF = CSVPrintFile(['User', 'name', 'email', 'role', 'person', 'group', 'audience'], 'sortall') if Act.csvFormat() else None
driveLabelNameEntity = getUserObjectEntity(Cmd.OB_DRIVE_LABEL_NAME, Ent.DRIVE_LABEL_PERMISSION, shlexSplit=True)
FJQC = FormatJSONQuoteChar(csvPF)
parameters = {'useAdminAccess': useAdminAccess}
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg in ADMIN_ACCESS_OPTIONS:
parameters['useAdminAccess'] = True
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
if csvPF and FJQC.formatJSON:
csvPF.SetJSONTitles(['User', 'name', 'JSON'])
api = API.DRIVELABELS_ADMIN if parameters['useAdminAccess'] else API.DRIVELABELS_USER
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, drive, labelNames, jcount = _validateUserGetObjectList(user, i, count, driveLabelNameEntity,
api=api, showAction=FJQC is None or not FJQC.formatJSON)
if jcount == 0:
continue
Ind.Increment()
j = 0
for name in labelNames:
j += 1
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_NAME, name, Ent.DRIVE_LABEL_PERMISSION, None]
name = validateDriveLabelName(name, kvList, j, jcount, False)
if name is None:
continue
kvList = [Ent.USER, user, Ent.DRIVE_LABEL_NAME, name]
if csvPF:
printGettingAllEntityItemsForWhom(Ent.DRIVE_LABEL_PERMISSION, name, j, jcount)
pageMessage = getPageMessageForWhom()
else:
pageMessage = None
try:
labelperms = callGAPIpages(drive.labels().permissions(), 'list', 'labelPermissions',
pageMessage=pageMessage,
throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.PERMISSION_DENIED, GAPI.NOT_FOUND],
parent=name, **parameters, fields='nextPageToken,labelPermissions', pageSize=200)
if not csvPF:
jcount = len(labelperms)
if not FJQC.formatJSON:
entityPerformActionNumItems(kvList, jcount, Ent.DRIVE_LABEL_PERMISSION, i, count)
Ind.Increment()
j = 0
for labelperm in labelperms:
j += 1
_showDriveLabelPermission(labelperm, j, jcount, FJQC)
Ind.Decrement()
else:
for labelperm in labelperms:
row = flattenJSON(labelperm, flattened={'User': user})
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = {'User': user, 'name': labelperm['name']}
row['JSON'] = json.dumps(cleanJSON(labelperm),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
except (GAPI.permissionDenied, GAPI.notFound) as e:
entityActionFailedWarning(kvList, str(e), j, jcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
userSvcNotApplicableOrDriveDisabled(user, str(e), i, count)
break
Ind.Decrement()
if csvPF:
csvPF.writeCSVfile('Drive Label Permissions')
def doPrintShowDriveLabelPermissions():
printShowDriveLabelPermissions([_getAdminEmail()], True)
DRIVELABEL_FIELD_TYPE_MAP = {
'text': 'setTextValues',
'selection': 'setSelectionValues',
@@ -61406,6 +61688,7 @@ def processFileDriveLabels(users):
entityActionFailedWarning(kvList, str(e), j, jcount)
break
except (GAPI.notFound, GAPI.forbidden, GAPI.internalError,
GAPI.fileNeverWritable, GAPI.applyLabelForbidden,
GAPI.insufficientFilePermissions, GAPI.unknownError, GAPI.invalidInput, GAPI.badRequest,
GAPI.labelMutationUnknownField, GAPI.labelMutationIllegalSelection, GAPI.labelMutationForbidden,
GAPI.labelMultipleValuesForSingularField) as e:
@@ -71709,6 +71992,7 @@ MAIN_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_DOMAIN: doCreateDomain,
Cmd.ARG_DOMAINALIAS: doCreateDomainAlias,
Cmd.ARG_DRIVEFILEACL: doCreateDriveFileACL,
Cmd.ARG_DRIVELABELPERMISSION: doCreateDriveLabelPermissions,
Cmd.ARG_FEATURE: doCreateFeature,
Cmd.ARG_GCPSERVICEACCOUNT: doCreateGCPServiceAccount,
Cmd.ARG_GROUP: doCreateGroup,
@@ -71821,6 +72105,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DOMAINALIAS: doDeleteDomainAlias,
Cmd.ARG_DOMAINCONTACT: doDeleteDomainContacts,
Cmd.ARG_DRIVEFILEACL: doDeleteDriveFileACLs,
Cmd.ARG_DRIVELABELPERMISSION: doDeleteDriveLabelPermissions,
Cmd.ARG_FEATURE: doDeleteFeature,
Cmd.ARG_GROUP: doDeleteGroups,
Cmd.ARG_GUARDIAN: doDeleteGuardian,
@@ -71998,6 +72283,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DOMAINCONTACT: doPrintShowDomainContacts,
Cmd.ARG_DRIVEFILEACL: doPrintShowDriveFileACLs,
Cmd.ARG_DRIVELABEL: doPrintShowDriveLabels,
Cmd.ARG_DRIVELABELPERMISSION: doPrintShowDriveLabelPermissions,
Cmd.ARG_FEATURE: doPrintShowFeatures,
Cmd.ARG_GAL: doPrintShowGAL,
Cmd.ARG_GROUP: doPrintGroups,
@@ -72044,6 +72330,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
'remove':
(Act.REMOVE,
{Cmd.ARG_ALIAS: doRemoveAliases,
Cmd.ARG_DRIVELABELPERMISSION: doDeleteDriveLabelPermissions,
}
),
'reopen':
@@ -72111,6 +72398,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DOMAINCONTACT: doPrintShowDomainContacts,
Cmd.ARG_DRIVEFILEACL: doPrintShowDriveFileACLs,
Cmd.ARG_DRIVELABEL: doPrintShowDriveLabels,
Cmd.ARG_DRIVELABELPERMISSION: doPrintShowDriveLabelPermissions,
Cmd.ARG_FEATURE: doPrintShowFeatures,
Cmd.ARG_GAL: doPrintShowGAL,
Cmd.ARG_GROUPMEMBERS: doShowGroupMembers,
@@ -72296,6 +72584,7 @@ MAIN_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_DOMAINPROFILES: Cmd.ARG_PEOPLEPROFILE,
Cmd.ARG_DRIVEFILEACLS: Cmd.ARG_DRIVEFILEACL,
Cmd.ARG_DRIVELABELS: Cmd.ARG_DRIVELABEL,
Cmd.ARG_DRIVELABELPERMISSIONS: Cmd.ARG_DRIVELABELPERMISSION,
Cmd.ARG_EXPORT: Cmd.ARG_VAULTEXPORT,
Cmd.ARG_EXPORTS: Cmd.ARG_VAULTEXPORT,
Cmd.ARG_FEATURES: Cmd.ARG_FEATURE,
@@ -72708,6 +72997,7 @@ USER_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_DRIVEFILEACL: createDriveFileACL,
Cmd.ARG_DRIVEFILESHORTCUT: createDriveFileShortcut,
Cmd.ARG_DRIVEFOLDERPATH: createDriveFolderPath,
Cmd.ARG_DRIVELABELPERMISSION: createDriveLabelPermissions,
Cmd.ARG_EVENT: createCalendarEvent,
Cmd.ARG_FILTER: createFilter,
Cmd.ARG_FOCUSTIME: createFocusTime,
@@ -72819,6 +73109,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DELEGATE: processDelegates,
Cmd.ARG_DRIVEFILE: deleteDriveFile,
Cmd.ARG_DRIVEFILEACL: deleteDriveFileACLs,
Cmd.ARG_DRIVELABELPERMISSION: deleteDriveLabelPermissions,
Cmd.ARG_EMPTYDRIVEFOLDERS: deleteEmptyDriveFolders,
Cmd.ARG_EVENT: deleteCalendarEvents,
Cmd.ARG_FILEREVISION: deleteFileRevisions,
@@ -72993,6 +73284,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
Cmd.ARG_DRIVEFILEACL: printShowDriveFileACLs,
Cmd.ARG_DRIVELABEL: printShowDriveLabels,
Cmd.ARG_DRIVELABELPERMISSION: printShowDriveLabelPermissions,
Cmd.ARG_DRIVESETTINGS: printShowDriveSettings,
Cmd.ARG_EMPTYDRIVEFOLDERS: printEmptyDriveFolders,
Cmd.ARG_EVENT: printShowCalendarEvents,
@@ -73057,6 +73349,7 @@ USER_COMMANDS_WITH_OBJECTS = {
(Act.REMOVE,
{Cmd.ARG_CALENDAR: removeCalendars,
Cmd.ARG_CHATMEMBER: deleteUpdateChatMember,
Cmd.ARG_DRIVELABELPERMISSION: deleteDriveLabelPermissions,
}
),
'replacedomain':
@@ -73092,6 +73385,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
Cmd.ARG_DRIVEFILEACL: printShowDriveFileACLs,
Cmd.ARG_DRIVELABEL: printShowDriveLabels,
Cmd.ARG_DRIVELABELPERMISSION: printShowDriveLabelPermissions,
Cmd.ARG_DRIVESETTINGS: printShowDriveSettings,
Cmd.ARG_EVENT: printShowCalendarEvents,
Cmd.ARG_FILECOUNT: printShowFileCounts,
@@ -73306,6 +73600,7 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_FILEDRIVELABELS: Cmd.ARG_FILEDRIVELABEL,
Cmd.ARG_DRIVEFILESHORTCUTS: Cmd.ARG_DRIVEFILESHORTCUT,
Cmd.ARG_DRIVELABELS: Cmd.ARG_DRIVELABEL,
Cmd.ARG_DRIVELABELPERMISSIONS: Cmd.ARG_DRIVELABELPERMISSION,
Cmd.ARG_EVENTS: Cmd.ARG_EVENT,
Cmd.ARG_FILECOUNTS: Cmd.ARG_FILECOUNT,
Cmd.ARG_FILEPATHS: Cmd.ARG_FILEPATH,

View File

@@ -567,6 +567,8 @@ class GamCLArgs():
ARG_DRIVEFOLDERPATH = 'drivefolderpath'
ARG_DRIVELABEL = 'drivelabel'
ARG_DRIVELABELS = 'drivelabels'
ARG_DRIVELABELPERMISSION = 'drivelabelpermission'
ARG_DRIVELABELPERMISSIONS = 'drivelabelpermissions'
ARG_DRIVESETTINGS = 'drivesettings'
ARG_DRIVETRASH = 'drivetrash'
ARG_EMPTYDRIVEFOLDERS = 'emptydrivefolders'
@@ -877,6 +879,7 @@ class GamCLArgs():
OB_DRIVE_FOLDER_PATH = 'DriveFolderPath'
OB_DRIVE_LABEL_ID = 'DriveLabelID'
OB_DRIVE_LABEL_NAME = 'DriveLabelName'
OB_DRIVE_LABEL_PERMISSION_NAME = 'DriveLabelPermissionName'
OB_DRIVE_LABEL_FIELD_ID = 'DriveLabelFieldID'
OB_DRIVE_LABEL_SELECTION_ID_LIST = 'DriveLabelSelectionIDList'
OB_EMAIL_ADDRESS = 'EmailAddress'

View File

@@ -191,6 +191,8 @@ class GamEntity():
DRIVE_LABEL_FIELD_ID = 'dlfi'
DRIVE_LABEL_ID = 'dlid'
DRIVE_LABEL_NAME = 'dlna'
DRIVE_LABEL_PERMISSION = 'dlpe'
DRIVE_LABEL_PERMISSION_NAME = 'dlpn'
DRIVE_ORPHAN_FILE_OR_FOLDER = 'orph'
DRIVE_PARENT_FOLDER = 'fipf'
DRIVE_PARENT_FOLDER_ID = 'fipi'
@@ -526,6 +528,8 @@ class GamEntity():
DRIVE_LABEL_FIELD_ID: ['Drive Label Field IDs', 'Drive Label Field ID'],
DRIVE_LABEL_ID: ['Drive Label IDs', 'Drive Label ID'],
DRIVE_LABEL_NAME: ['Drive Label Names', 'Drive Label Name'],
DRIVE_LABEL_PERMISSION: ['Drive Label Permissions', 'Drive Label Permission'],
DRIVE_LABEL_PERMISSION_NAME: ['Drive Label Permission Names', 'Drive Label Permission Name'],
DRIVE_ORPHAN_FILE_OR_FOLDER: ['Drive Orphan Files/Folders', 'Drive Orphan File/Folder'],
DRIVE_PARENT_FOLDER: ['Drive Parent Folders', 'Drive Parent Folder'],
DRIVE_PARENT_FOLDER_ID: ['Drive Parent Folder IDs', 'Drive Parent Folder ID'],

View File

@@ -24,6 +24,7 @@ ABORTED = 'aborted'
ABUSIVE_CONTENT_RESTRICTION = 'abusiveContentRestriction'
ACCESS_NOT_CONFIGURED = 'accessNotConfigured'
ALREADY_EXISTS = 'alreadyExists'
APPLY_LABEL_FORBIDDEN = 'applyLabelForbidden'
AUTH_ERROR = 'authError'
BACKEND_ERROR = 'backendError'
BAD_GATEWAY = 'badGateway'
@@ -243,6 +244,7 @@ DRIVE3_DELETE_ACL_THROW_REASONS = [BAD_REQUEST, CANNOT_REMOVE_OWNER,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED,
NOT_FOUND, PERMISSION_NOT_FOUND]
DRIVE3_MODIFY_LABEL_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, NOT_FOUND, FORBIDDEN, INTERNAL_ERROR,
FILE_NEVER_WRITABLE, APPLY_LABEL_FORBIDDEN,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, INSUFFICIENT_FILE_PERMISSIONS,
UNKNOWN_ERROR, INVALID_INPUT, BAD_REQUEST,
LABEL_MULTIPLE_VALUES_FOR_SINGULAR_FIELD, LABEL_MUTATION_FORBIDDEN,
@@ -349,6 +351,8 @@ class accessNotConfigured(Exception):
pass
class alreadyExists(Exception):
pass
class applyLabelForbidden(Exception):
pass
class authError(Exception):
pass
class backendError(Exception):
@@ -649,6 +653,7 @@ REASON_EXCEPTION_MAP = {
ABUSIVE_CONTENT_RESTRICTION: abusiveContentRestriction,
ACCESS_NOT_CONFIGURED: accessNotConfigured,
ALREADY_EXISTS: alreadyExists,
APPLY_LABEL_FORBIDDEN: applyLabelForbidden,
AUTH_ERROR: authError,
BACKEND_ERROR: backendError,
BAD_REQUEST: badRequest,

View File

@@ -34,7 +34,7 @@ _PRODUCTS = {
'101039': 'Assured Controls',
'101040': 'Beyond Corp Enterprise',
'101043': 'Google Workspace Additional Storage',
'101047': 'Duet AI',
'101047': 'Gemini',
'Google-Apps': 'Google Workspace',
'Google-Chrome-Device-Management': 'Google Chrome Device Management',
'Google-Drive-storage': 'Google Drive Storage',
@@ -86,9 +86,11 @@ _SKUS = {
'1010430001': {
'product': '101043', 'aliases': ['gwas', 'plusstorage'], 'displayName': 'Google Workspace Additional Storage'},
'1010470001': {
'product': '101047', 'aliases': ['duetai'], 'displayName': 'Duet AI for Enterprise'},
'product': '101047', 'aliases': ['geminient', 'duetai'], 'displayName': 'Gemini Enterprise'},
'1010470002': {
'product': '101047', 'aliases': ['gwlabs', 'workspacelabs'], 'displayName': 'Google Workspace Labs'},
'1010470003': {
'product': '101047', 'aliases': ['geminibiz'], 'displayName': 'Gemini Business'},
'Google-Apps': {
'product': 'Google-Apps', 'aliases': ['standard', 'free'], 'displayName': 'G Suite Legacy'},
'Google-Apps-For-Business': {