Compare commits

...

12 Commits

Author SHA1 Message Date
Ross Scroggs
d9f8c644fe Handle ERROR 400: malformedWorkingLocationEvent error
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-25 08:32:54 -08:00
Ross Scroggs
0a755335da #1754 - Fixed bug in gam all users print users issuspended false allfields that caused a trap.
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-24 13:06:34 -08:00
Ross Scroggs
d4200b66dc Chat usage reports are now available.
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-02-22 07:53:15 -08:00
Ross Scroggs
2afc28e017 Updated from v1beta1 to v1 for Cloud Identity - Policy.
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-21 07:22:17 -08:00
Ross Scroggs
90a2d385d6 Force rebuild
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-20 20:24:42 -08:00
Jay Lee
f123fe197f actions: remove collab to see if it fixes Vault API 2025-02-20 17:20:27 -05:00
Ross Scroggs
8503aabefe Enabled support for Limited Access
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-19 19:07:03 -08:00
Ross Scroggs
80933755c4 Enabled support for Limited Access 2025-02-19 18:59:37 -08:00
Ross Scroggs
03148a6ae8 Added initial support for Meet API v2beta
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-18 14:25:35 -08:00
Ross Scroggs
96acd40692 Increment scratch_counter to flush out bug
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2025-02-18 12:23:11 -08:00
Ross Scroggs
3004da5ad7 Create meet-v2beta.json 2025-02-18 10:47:03 -08:00
Ross Scroggs
bd699e2b31 Added initial support for Meet API v2beta 2025-02-18 10:40:44 -08:00
8 changed files with 1388 additions and 60 deletions

View File

@@ -18,7 +18,7 @@ defaults:
working-directory: src working-directory: src
env: env:
SCRATCH_COUNTER: 9 SCRATCH_COUNTER: 11
OPENSSL_CONFIG_OPTS: no-fips --api=3.0.0 OPENSSL_CONFIG_OPTS: no-fips --api=3.0.0
OPENSSL_INSTALL_PATH: ${{ github.workspace }}/bin/ssl OPENSSL_INSTALL_PATH: ${{ github.workspace }}/bin/ssl
OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl
@@ -917,7 +917,7 @@ jobs:
$gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all $gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all
$gam calendar $gam_user printevents after -0d $gam calendar $gam_user printevents after -0d
$gam config enable_dasa false save $gam config enable_dasa false save
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" collaborators $newuser returnidonly) matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly)
$gam create vaulthold matter $matterid name "GHA hold $newbase" corpus mail accounts $newuser $gam create vaulthold matter $matterid name "GHA hold $newbase" corpus mail accounts $newuser
$gam print vaultmatters matterstate open $gam print vaultmatters matterstate open
$gam print vaultholds matter $matterid $gam print vaultholds matter $matterid

View File

@@ -3846,6 +3846,7 @@ gam info group|groups <GroupEntity>
[formatjson] [formatjson]
gam print groups [todrive <ToDriveAttribute>*] gam print groups [todrive <ToDriveAttribute>*]
[([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryGroupList>)]))| [([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryGroupList>)]))|
(group|group_ns|group_susp <GroupItem>)|
(select <GroupEntity>)] (select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>] [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)* [descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
@@ -4072,6 +4073,7 @@ gam show cigroup-members
releaseversion| releaseversion|
securitypatchtime| securitypatchtime|
serialnumber| serialnumber|
unifieddeviceid|
wifimacaddresses wifimacaddresses
<DeviceFieldNameList> ::= "<DeviceFieldName>(,<DeviceFieldName>)*" <DeviceFieldNameList> ::= "<DeviceFieldName>(,<DeviceFieldName>)*"
@@ -4473,6 +4475,7 @@ gam report <ActivityApplicationName> [todrive <ToDriveAttribute>*]
app_maker| app_maker|
apps_scripts| apps_scripts|
calendar| calendar|
chat|
classroom| classroom|
cros| cros|
device_management| device_management|
@@ -4493,6 +4496,7 @@ gam report customers|customer|domain [todrive <ToDriveAttribute>*]
<UserServiceName> ::= <UserServiceName> ::=
accounts| accounts|
chat|
classroom| classroom|
docs| docs|
drive| drive|
@@ -4963,6 +4967,7 @@ gam create|add permissions <SharedDriveEntityAdmin> <DriveFilePermissionEntity>
<PermissionMatch>* [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchAction>]
gam delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity> gam delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity>
<PermissionMatch>* [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchAction>]
[enforceexpansiveaccess [<Boolean>]]
In these commands, you specify an administrator and then indicate that you want domain administrator access with the adminaccess option. In these commands, you specify an administrator and then indicate that you want domain administrator access with the adminaccess option.
@@ -4976,9 +4981,11 @@ gam <UserTypeEntity> create|add drivefileacl <SharedDriveEntityAdmin>
adminaccess adminaccess
gam <UserTypeEntity> update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail> gam <UserTypeEntity> update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]] (role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
[enforceexpansiveaccess [<Boolean>]]
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])] [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
adminaccess adminaccess
gam <UserTypeEntity> delete drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail> gam <UserTypeEntity> delete drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
[enforceexpansiveaccess [<Boolean>]]
[showtitles] adminaccess [showtitles] adminaccess
gam <UserTypeEntity> info drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail> adminaccess gam <UserTypeEntity> info drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail> adminaccess
[showtitles] [showtitles]
@@ -5004,6 +5011,7 @@ gam <UserTypeEntity> create|add permissions <SharedDriveEntityAdmin> <DriveFileP
<PermissionMatch>* [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchAction>]
gam <UserTypeEntity> delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity> adminaccess gam <UserTypeEntity> delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity> adminaccess
<PermissionMatch>* [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchAction>]
[enforceexpansiveaccess [<Boolean>]]
In these commands, the Google administrator named in oauth2.txt is used. In these commands, the Google administrator named in oauth2.txt is used.
@@ -6566,6 +6574,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
[sendemailifrequired [<Boolean>]] [sendemailifrequired [<Boolean>]]
[suppressnotselectedmessages [<Boolean>]] [suppressnotselectedmessages [<Boolean>]]
[verifyorganizer [<Boolean>]] [verifyorganizer [<Boolean>]]
[enforceexpansiveaccess [<Boolean>]]
gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileName>] gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileName>]
[summary [<Boolean>]] [showpermissionmessages [<Boolean>]] [summary [<Boolean>]] [showpermissionmessages [<Boolean>]]
@@ -6589,6 +6598,7 @@ gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileNam
[retainsourcefolders [<Boolean>]] [retainsourcefolders [<Boolean>]]
[sendemailifrequired [<Boolean>]] [sendemailifrequired [<Boolean>]]
[verifyorganizer [<Boolean>]] [verifyorganizer [<Boolean>]]
[enforceexpansiveaccess [<Boolean>]]
gam <UserTypeEntity> get document <DriveFileEntity> gam <UserTypeEntity> get document <DriveFileEntity>
[viewmode default|suggestions_inline|preview_suggestions_accepted|preview_without_suggestions] [viewmode default|suggestions_inline|preview_suggestions_accepted|preview_without_suggestions]
@@ -6694,10 +6704,10 @@ gam <UserTypeEntity> create|add drivefileacl <DriveFileEntity> [adminaccess|asad
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])] [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
gam <UserTypeEntity> update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> gam <UserTypeEntity> update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]] (role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
[updatesheetprotectedranges [<Boolean>]] [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])] [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
gam <UserTypeEntity> delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> gam <UserTypeEntity> delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
[updatesheetprotectedranges [<Boolean>]] [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
[showtitles] [showtitles]
gam <UserTypeEntity> info drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> gam <UserTypeEntity> info drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
[showtitles] [showtitles]
@@ -6821,6 +6831,7 @@ gam <UserTypeEntity> print filerevisions <DriveFileEntity> [todrive <ToDriveAttr
gam <UserTypeEntity> transfer ownership <DriveFileEntity> <UserItem> gam <UserTypeEntity> transfer ownership <DriveFileEntity> <UserItem>
[<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]] [<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]]
[enforceexpansiveaccess [<Boolean>]]
(orderby <DriveFileOrderByFieldName> [ascending|descending])* (orderby <DriveFileOrderByFieldName> [ascending|descending])*
[preview] [filepath] [pathdelimiter <Character>] [buildtree] [preview] [filepath] [pathdelimiter <Character>] [buildtree]
[todrive <ToDriveAttribute>*] [todrive <ToDriveAttribute>*]
@@ -6829,6 +6840,7 @@ gam <UserTypeEntity> claim ownership <DriveFileEntity>
[skipids <DriveFileEntity>] [onlyusers|skipusers <UserTypeEntity>] [subdomains <DomainNameEntity>] [skipids <DriveFileEntity>] [onlyusers|skipusers <UserTypeEntity>] [subdomains <DomainNameEntity>]
[restricted [<Boolean>]] [writerscanshare|writerscantshare [<Boolean>]] [restricted [<Boolean>]] [writerscanshare|writerscantshare [<Boolean>]]
[keepuser | (retainrole commenter|reader|writer|editor|fileorganizer|none)] [noretentionmessages] [keepuser | (retainrole commenter|reader|writer|editor|fileorganizer|none)] [noretentionmessages]
[enforceexpansiveaccess [<Boolean>]]
(orderby <DriveFileOrderByFieldName> [ascending|descending])* (orderby <DriveFileOrderByFieldName> [ascending|descending])*
[preview] [filepath] [pathdelimiter <Character>] [buildtree] [preview] [filepath] [pathdelimiter <Character>] [buildtree]
[todrive <ToDriveAttribute>*] [todrive <ToDriveAttribute>*]
@@ -6836,6 +6848,7 @@ gam <UserTypeEntity> claim ownership <DriveFileEntity>
gam <UserTypeEntity> transfer drive <UserItem> [select <DriveFileEntity>] gam <UserTypeEntity> transfer drive <UserItem> [select <DriveFileEntity>]
[(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)] [(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)]
[targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>] [targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>]
[enforceexpansiveaccess [<Boolean>]]
[mergewithtarget [<Boolean>]] [mergewithtarget [<Boolean>]]
[skipids <DriveFileEntity>] [skipids <DriveFileEntity>]
[keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages] [keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages]
@@ -7882,7 +7895,15 @@ gam <UserTypeEntity> show lookerstudiopermissions
<MeetSpaceName> ::= spaces/<String> | <String> <MeetSpaceName> ::= spaces/<String> | <String>
<MeetSpaceOptions> ::= <MeetSpaceOptions> ::=
accesstype open|trusted|restricted | accesstype open|trusted|restricted |
entrypointaccess all|creatorapponly entrypointaccess all|creatorapponly |
moderation <Boolean> |
chatrestriction hostsonly|norestriction |
reactionrestriction hostsonly|norestriction |
presentrestriction hostsonly|norestriction |
defaultjoinasviewer <Boolean> |
recording <Boolean> |
transcription <Boolean> |
smartnotes <Boolean>
gam <UserTypeEntity> create meetspace gam <UserTypeEntity> create meetspace
<MeetSpaceOptions>* <MeetSpaceOptions>*

View File

@@ -1,3 +1,77 @@
7.05.04
Updated `gam calendars <CalendarEntity> update events` and `gam <UserTypeEntity> update events`
to handle the following error:
```
ERROR 400: malformedWorkingLocationEvent - A working location event must have a visibility setting of public.
```
7.05.03
Fixed bug in `gam all users print users issuspended false allfields` that caused a trap.
7.05.02
Chat usage reports are now available. Added `chat` to `<CustomerServiceName>` and `<UserServiceName>`
for use in `gam report customer|user`.
* https://workspaceupdates.googleblog.com/2025/02/chat-usage-analytics-updates.html
7.05.01
Updated from `v1beta1` to `v1` for `Cloud Identity - Policy`.
* See: https://workspaceupdates.googleblog.com/2025/02/policy-api-general-availability.html
7.05.00
Enabled support for Limited Access as described here:
* https://workspaceupdates.googleblog.com/2025/02/updating-access-experience-in-google-drive.html
Note that the rollout may take 15 days.
Added option `inheritedpermissionsdisabled [<Boolean>]` to `<DriveFileAttribute>`; this
attribute can be set on folders.
Added `inheritedpermissionsdisabled` to `<DriveFieldName>`.
Added `capabilities.candisableinheritedpermissions` and `capabilities.canenableinheritedpermissions`
to `<DriveCapabilitiesSubfieldName>`.
Added option `enforceexpansiveaccess [<Boolean>]` to all commands that delete or update
drive file ACLs/permissions.
```
gam <UserTypeEntity> delete permissions
gam <UserTypeEntity> delete drivefileacl
gam <UserTypeEntity> update drivefileacl
gam <UserTypeEntity> copy drivefile
gam <UserTypeEntity> move drivefile
gam <UserTypeEntity> transfer ownership
gam <UserTypeEntity> claim ownership
gam <UserTypeEntity> transfer drive
```
7.04.05
Added initial support for Meet API v2beta; you must be in the Developer Preview program
for this to be effective.
* https://developers.google.com/meet/api/guides/beta/configuration-beta#auto-artifacts
Added `meet_v2_beta` Boolean variable to `gam.cfg`. When this variable is true,
the following options are added to `<MeetSpaceOptions>` used in `gam <UserTypeEntity> create|update meetspace`.
```
moderation <Boolean> |
chatrestriction hostsonly|norestriction |
reactionrestriction hostsonly|norestriction |
presentrestriction hostsonly|norestriction |
defaultjoinasviewer <Boolean> |
recording <Boolean> |
transcription <Boolean> |
smartnotes <Boolean>
```
This isn't called beta for nothing, I have found problems and reported them.
7.04.04 7.04.04
Updated `gam print group-members|cigroup-members` to include the `email` column Updated `gam print group-members|cigroup-members` to include the `email` column

View File

@@ -31,6 +31,7 @@ for pkg in GAM_VER_LIBS:
datas += [('gam/cbcm-v1.1beta1.json', '.')] datas += [('gam/cbcm-v1.1beta1.json', '.')]
datas += [('gam/contactdelegation-v1.json', '.')] datas += [('gam/contactdelegation-v1.json', '.')]
datas += [('gam/datastudio-v1.json', '.')] datas += [('gam/datastudio-v1.json', '.')]
datas += [('gam/meet-v2beta.json', '.')]
datas += [('gam/serviceaccountlookup-v1.json', '.')] datas += [('gam/serviceaccountlookup-v1.json', '.')]
datas += [('cacerts.pem', '.')] datas += [('cacerts.pem', '.')]
hiddenimports = [ hiddenimports = [

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.04.04' __version__ = '7.05.04'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -4710,7 +4710,7 @@ def getAPIService(api, httpObj):
def getService(api, httpObj): def getService(api, httpObj):
### Drive v3beta ### Drive v3beta
mapDriveURL = api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA] # mapDriveURL = api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]
hasLocalJSON = API.hasLocalJSON(api) hasLocalJSON = API.hasLocalJSON(api)
api, version, v2discovery = API.getVersion(api) api, version, v2discovery = API.getVersion(api)
if api in GM.Globals[GM.CURRENT_API_SERVICES] and version in GM.Globals[GM.CURRENT_API_SERVICES][api]: if api in GM.Globals[GM.CURRENT_API_SERVICES] and version in GM.Globals[GM.CURRENT_API_SERVICES][api]:
@@ -4727,8 +4727,8 @@ def getService(api, httpObj):
GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {}) GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {})
GM.Globals[GM.CURRENT_API_SERVICES][api][version] = service._rootDesc.copy() GM.Globals[GM.CURRENT_API_SERVICES][api][version] = service._rootDesc.copy()
### Drive v3beta ### Drive v3beta
if mapDriveURL: # if mapDriveURL:
setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/')) # setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/'))
if GM.Globals[GM.CACHE_DISCOVERY_ONLY]: if GM.Globals[GM.CACHE_DISCOVERY_ONLY]:
clearServiceCache(service) clearServiceCache(service)
return service return service
@@ -5571,6 +5571,8 @@ def buildGAPIServiceObject(api, user, i=0, count=0, displayError=True):
userEmail = getSaUser(user) userEmail = getSaUser(user)
httpObj = getHttpObj(cache=GM.Globals[GM.CACHE_DIR]) httpObj = getHttpObj(cache=GM.Globals[GM.CACHE_DIR])
service = getService(api, httpObj) service = getService(api, httpObj)
if api == API.MEET_BETA:
api = API.MEET
credentials = getSvcAcctCredentials(api, userEmail) credentials = getSvcAcctCredentials(api, userEmail)
request = transportCreateRequest(httpObj) request = transportCreateRequest(httpObj)
triesLimit = 3 triesLimit = 3
@@ -9840,7 +9842,7 @@ def MultiprocessGAMCommands(items, showCmds):
if GM.Globals[GM.MULTIPROCESS_EXIT_CONDITION] is not None and checkChildProcessRC(result[1]): if GM.Globals[GM.MULTIPROCESS_EXIT_CONDITION] is not None and checkChildProcessRC(result[1]):
GM.Globals[GM.MULTIPROCESS_EXIT_PROCESSING] = True GM.Globals[GM.MULTIPROCESS_EXIT_PROCESSING] = True
def signal_handler(sig, frame): def signal_handler(*_):
nonlocal controlC nonlocal controlC
controlC = True controlC = True
@@ -13107,6 +13109,7 @@ CUSTOMER_REPORT_SERVICES = {
'app_maker', 'app_maker',
'apps_scripts', 'apps_scripts',
'calendar', 'calendar',
'chat',
'classroom', 'classroom',
'cros', 'cros',
'device_management', 'device_management',
@@ -13120,6 +13123,7 @@ CUSTOMER_REPORT_SERVICES = {
USER_REPORT_SERVICES = { USER_REPORT_SERVICES = {
'accounts', 'accounts',
'chat',
'classroom', 'classroom',
'docs', 'docs',
'drive', 'drive',
@@ -17254,7 +17258,7 @@ def checkOrgUnitPathExists(cd, orgUnitPath, i=0, count=0, showError=False):
return (False, orgUnitPath, orgUnitPath) return (False, orgUnitPath, orgUnitPath)
def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quickCrOSMove, fromOrgUnitPath=None): def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quickCrOSMove, fromOrgUnitPath=None):
def _callbackMoveCrOSesToOrgUnit(request_id, response, exception): def _callbackMoveCrOSesToOrgUnit(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
if not fromOrgUnitPath: if not fromOrgUnitPath:
@@ -17335,7 +17339,7 @@ def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quick
def _batchMoveUsersToOrgUnit(cd, orgUnitPath, i, count, items, fromOrgUnitPath=None): def _batchMoveUsersToOrgUnit(cd, orgUnitPath, i, count, items, fromOrgUnitPath=None):
_MOVE_USER_REASON_TO_MESSAGE_MAP = {GAPI.USER_NOT_FOUND: Msg.DOES_NOT_EXIST, GAPI.DOMAIN_NOT_FOUND: Msg.SERVICE_NOT_APPLICABLE, GAPI.FORBIDDEN: Msg.SERVICE_NOT_APPLICABLE} _MOVE_USER_REASON_TO_MESSAGE_MAP = {GAPI.USER_NOT_FOUND: Msg.DOES_NOT_EXIST, GAPI.DOMAIN_NOT_FOUND: Msg.SERVICE_NOT_APPLICABLE, GAPI.FORBIDDEN: Msg.SERVICE_NOT_APPLICABLE}
def _callbackMoveUsersToOrgUnit(request_id, response, exception): def _callbackMoveUsersToOrgUnit(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
if not fromOrgUnitPath: if not fromOrgUnitPath:
@@ -27488,6 +27492,8 @@ def printShowChatEvents(users):
csvPF.writeCSVfile('Chat Events') csvPF.writeCSVfile('Chat Events')
def buildMeetServiceObject(api=API.MEET, user=None, i=0, count=0, entityTypeList=None): def buildMeetServiceObject(api=API.MEET, user=None, i=0, count=0, entityTypeList=None):
if GC.Values[GC.MEET_V2_BETA]:
api = API.MEET_BETA
user, meet = buildGAPIServiceObject(api, user, i, count) user, meet = buildGAPIServiceObject(api, user, i, count)
kvList = [Ent.USER, user] kvList = [Ent.USER, user]
if entityTypeList is not None: if entityTypeList is not None:
@@ -27511,7 +27517,10 @@ MEET_SPACE_OPTIONS_MAP = {
'reactionrestriction': 'reactionRestriction', 'reactionrestriction': 'reactionRestriction',
'presentrestriction': 'presentRestriction', 'presentrestriction': 'presentRestriction',
'defaultjoinasviewer': 'defaultJoinAsViewerType', 'defaultjoinasviewer': 'defaultJoinAsViewerType',
'firstjoiner': 'firstJoinerType' 'firstjoiner': 'firstJoinerType',
'autorecording': 'recordingConfig',
'autosmartnotes': 'smartNotesConfig',
'autotranscription': 'transcriptionConfig',
} }
MEET_SPACE_ACCESSTYPE_CHOICES = {'open', 'trusted', 'restricted'} MEET_SPACE_ACCESSTYPE_CHOICES = {'open', 'trusted', 'restricted'}
@@ -27525,9 +27534,15 @@ MEET_SPACE_RESTRICTIONS_CHOICES_MAP = {
'norestriction': 'NO_RESTRICTION' 'norestriction': 'NO_RESTRICTION'
} }
MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = { #MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
'hostsonly': 'HOSTS_ONLY', # 'hostsonly': 'HOSTS_ONLY',
'anyone': 'ANYONE' # 'anyone': 'ANYONE'
# }
MEET_SPACE_ARTIFACT_SUB_OPTIONS = {
'recordingConfig': 'autoRecordingGeneration',
'smartNotesConfig': 'autoSmartNotesGeneration',
'transcriptionConfig': 'autoTranscriptionGeneration'
} }
# [accesstype open|trusted|restricted] # [accesstype open|trusted|restricted]
@@ -27538,7 +27553,10 @@ MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
# [presentrestriction hostsonly|norestriction] # [presentrestriction hostsonly|norestriction]
# [defaultjoinasviewer <Boolean>] # [defaultjoinasviewer <Boolean>]
# [firstjoiner hostsonly|anyone] # [firstjoiner hostsonly|anyone]
def _getMeetSpaceParameters(myarg, body, updateMask): # [autorecording <Boolean>]
# [autosmartnotes <Boolean>]
# [autotranscription <Boolean>]
def _getMeetSpaceParameters(myarg, body):
option = MEET_SPACE_OPTIONS_MAP.get(myarg, None) option = MEET_SPACE_OPTIONS_MAP.get(myarg, None)
if option is None: if option is None:
return False return False
@@ -27548,15 +27566,17 @@ def _getMeetSpaceParameters(myarg, body, updateMask):
body['config'][option] = getChoice(MEET_SPACE_ENTRYPOINTACCESS_CHOICES_MAP, mapChoice=True) body['config'][option] = getChoice(MEET_SPACE_ENTRYPOINTACCESS_CHOICES_MAP, mapChoice=True)
elif option == 'moderation': elif option == 'moderation':
body['config'][option] = 'ON' if getBoolean() else 'OFF' body['config'][option] = 'ON' if getBoolean() else 'OFF'
elif option in {'chatrestriction', 'reactionrestriction', 'presentrestriction'}: elif option in {'chatRestriction', 'reactionRestriction', 'presentRestriction'}:
body['config'].setdefault('moderationRestictions', {}) body['config'].setdefault('moderationRestrictions', {})
body['config']['moderationRestrictions'][option] = getChoice(MEET_SPACE_RESTRICTIONS_CHOICES_MAP, mapChoice=True) body['config']['moderationRestrictions'][option] = getChoice(MEET_SPACE_RESTRICTIONS_CHOICES_MAP, mapChoice=True)
option = f'moderationRestrictions.{option}'
elif option == 'defaultJoinAsViewerType': elif option == 'defaultJoinAsViewerType':
body['config'][option] = 'ON' if getBoolean() else 'OFF' body['config'][option] = 'ON' if getBoolean() else 'OFF'
elif option == 'firstJoinerType': # elif option == 'firstJoinerType':
body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True) # body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True)
updateMask.append(f'config.{option}') elif option in {'recordingConfig', 'transcriptionConfig', 'smartNotesConfig'}:
body['config'].setdefault('artifactConfig', {})
body['config']['artifactConfig'].setdefault(option, {})
body['config']['artifactConfig'][option][MEET_SPACE_ARTIFACT_SUB_OPTIONS[option]] = 'ON' if getBoolean() else 'OFF'
return True return True
# gam <UserTypeEntity> create meetspace # gam <UserTypeEntity> create meetspace
@@ -27571,10 +27591,9 @@ def createMeetSpace(users):
# 'firstJoinerType': 'ANYONE', # 'firstJoinerType': 'ANYONE',
}} }}
returnIdOnly = False returnIdOnly = False
updateMask = []
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if _getMeetSpaceParameters(myarg, body, updateMask): if _getMeetSpaceParameters(myarg, body):
pass pass
elif myarg == 'returnidonly': elif myarg == 'returnidonly':
returnIdOnly = True returnIdOnly = True
@@ -27609,12 +27628,11 @@ def updateMeetSpace(users):
FJQC = FormatJSONQuoteChar() FJQC = FormatJSONQuoteChar()
name = None name = None
body = {'config': {}} body = {'config': {}}
updateMask = []
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if (myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/')): if (myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/')):
name = getSpaceName(myarg) name = getSpaceName(myarg)
elif _getMeetSpaceParameters(myarg, body, updateMask): elif _getMeetSpaceParameters(myarg, body):
pass pass
else: else:
FJQC.GetFormatJSON(myarg) FJQC.GetFormatJSON(myarg)
@@ -27629,7 +27647,7 @@ def updateMeetSpace(users):
try: try:
space = callGAPI(meet.spaces(), 'patch', space = callGAPI(meet.spaces(), 'patch',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
name=name, updateMask=','.join(updateMask), body=body) name=name, updateMask='', body=body)
if not FJQC.formatJSON: if not FJQC.formatJSON:
entityActionPerformed(kvList, i, count) entityActionPerformed(kvList, i, count)
Ind.Increment() Ind.Increment()
@@ -29235,6 +29253,7 @@ DEVICE_FIELDS_CHOICE_MAP = {
'releaseversion': 'releaseVersion', 'releaseversion': 'releaseVersion',
'securitypatchtime': 'securityPatchTime', 'securitypatchtime': 'securityPatchTime',
'serialnumber': 'serialNumber', 'serialnumber': 'serialNumber',
'unifieddeviceid': 'unifiedDeviceId',
'wifimacaddresses': 'wifiMacAddresses' 'wifimacaddresses': 'wifiMacAddresses'
} }
@@ -32007,7 +32026,7 @@ def doUpdateGroups():
GAPI.INVALID_MEMBER: Msg.INVALID_MEMBER, GAPI.INVALID_MEMBER: Msg.INVALID_MEMBER,
GAPI.CYCLIC_MEMBERSHIPS_NOT_ALLOWED: Msg.WOULD_MAKE_MEMBERSHIP_CYCLE} GAPI.CYCLIC_MEMBERSHIPS_NOT_ALLOWED: Msg.WOULD_MAKE_MEMBERSHIP_CYCLE}
def _callbackAddGroupMembers(request_id, response, exception): def _callbackAddGroupMembers(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT])) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -32096,7 +32115,7 @@ def doUpdateGroups():
GAPI.CONDITION_NOT_MET: f'{Msg.NOT_A} {Ent.Singular(Ent.MEMBER)}', GAPI.CONDITION_NOT_MET: f'{Msg.NOT_A} {Ent.Singular(Ent.MEMBER)}',
GAPI.INVALID_MEMBER: Msg.DOES_NOT_EXIST} GAPI.INVALID_MEMBER: Msg.DOES_NOT_EXIST}
def _callbackRemoveGroupMembers(request_id, response, exception): def _callbackRemoveGroupMembers(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT])) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -32195,7 +32214,7 @@ def doUpdateGroups():
except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e: except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount) _showFailure(group, member, role, str(e), j, jcount)
def _callbackUpdateGroupMembers(request_id, response, exception): def _callbackUpdateGroupMembers(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT])) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -33432,6 +33451,7 @@ PRINT_GROUPS_JSON_TITLES = ['email', 'JSON']
# gam print groups [todrive <ToDriveAttribute>*] # gam print groups [todrive <ToDriveAttribute>*]
# [([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryUserList>)]))| # [([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryUserList>)]))|
# (group|group_ns|group_susp <GroupItem>)|
# (select <GroupEntity>)] # (select <GroupEntity>)]
# [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>] # [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
# [descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)* # [descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
@@ -33644,6 +33664,12 @@ def doPrintGroups():
pass pass
elif getGroupMatchPatterns(myarg, matchPatterns, False): elif getGroupMatchPatterns(myarg, matchPatterns, False):
pass pass
elif myarg in {'group', 'groupns', 'groupsusp'}:
entitySelection = [getString(Cmd.OB_EMAIL_ADDRESS)]
if myarg == 'groupns':
isSuspended = False
elif myarg == 'groupsusp':
isSuspended = True
elif myarg == 'select': elif myarg == 'select':
entitySelection = getEntityList(Cmd.OB_GROUP_ENTITY) entitySelection = getEntityList(Cmd.OB_GROUP_ENTITY)
elif myarg in SUSPENDED_ARGUMENTS: elif myarg in SUSPENDED_ARGUMENTS:
@@ -39028,7 +39054,8 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
event = callGAPI(cal.events(), 'patch', event = callGAPI(cal.events(), 'patch',
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN, throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN,
GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT, GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE], GAPI.REQUIRED_ACCESS_LEVEL, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE,
GAPI.MALFORMED_WORKING_LOCATION_EVENT],
calendarId=calId, eventId=eventId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True, calendarId=calId, eventId=eventId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True,
body=body, fields=pfields) body=body, fields=pfields)
if parameters['csvPF'] is None: if parameters['csvPF'] is None:
@@ -39043,7 +39070,7 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
break break
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount) entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
except (GAPI.forbidden, GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit, except (GAPI.forbidden, GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
GAPI.requiredAccessLevel, GAPI.cannotChangeOrganizerOfInstance) as e: GAPI.requiredAccessLevel, GAPI.cannotChangeOrganizerOfInstance, GAPI.malformedWorkingLocationEvent) as e:
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount) entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
except GAPI.notACalendarUser: except GAPI.notACalendarUser:
userCalServiceNotEnabledWarning(calId, i, count) userCalServiceNotEnabledWarning(calId, i, count)
@@ -42331,7 +42358,7 @@ def doPrintVaultCounts():
# gam [<UserTypeEntity>] print siteacls <SiteEntity> [todrive <ToDriveAttribute>*] # gam [<UserTypeEntity>] print siteacls <SiteEntity> [todrive <ToDriveAttribute>*]
# gam [<UserTypeEntity>] print siteactivity <SiteEntity> [todrive <ToDriveAttribute>*] # gam [<UserTypeEntity>] print siteactivity <SiteEntity> [todrive <ToDriveAttribute>*]
# [startindex <Number>] [maxresults <Number>] [updated_min <Date>] [updated_max <Date>] # [startindex <Number>] [maxresults <Number>] [updated_min <Date>] [updated_max <Date>]
def deprecatedUserSites(users): def deprecatedUserSites(_):
deprecatedCommandExit() deprecatedCommandExit()
def deprecatedDomainSites(): def deprecatedDomainSites():
@@ -43653,7 +43680,7 @@ def waitForMailbox(entityList):
Ind.Decrement() Ind.Decrement()
def getUserLicenses(lic, user, skus): def getUserLicenses(lic, user, skus):
def _callbackGetLicense(request_id, response, exception): def _callbackGetLicense(_, response, exception):
if exception is None: if exception is None:
if response and 'skuId' in response: if response and 'skuId' in response:
licenses.append(response['skuId']) licenses.append(response['skuId'])
@@ -44766,7 +44793,7 @@ def doPrintUsers(entityList=None):
return return
sortRows = True sortRows = True
# If no individual fields were specified (allfields, basic, full) or individual fields other than primaryEmail were specified, look up each user # 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: if isSuspended is not None and fieldsList:
fieldsList.append('suspended') fieldsList.append('suspended')
if projectionSet or len(set(fieldsList)) > 1 or showValidColumn: if projectionSet or len(set(fieldsList)) > 1 or showValidColumn:
jcount = len(entityList) jcount = len(entityList)
@@ -48159,7 +48186,7 @@ def _batchAddItemsToCourse(croom, courseId, i, count, addParticipants, role):
_ADD_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST, _ADD_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
GAPI.ALREADY_EXISTS: Msg.DUPLICATE, GAPI.ALREADY_EXISTS: Msg.DUPLICATE,
GAPI.FAILED_PRECONDITION: Msg.NOT_ALLOWED} GAPI.FAILED_PRECONDITION: Msg.NOT_ALLOWED}
def _callbackAddItemsToCourse(request_id, response, exception): def _callbackAddItemsToCourse(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -48239,7 +48266,7 @@ def _batchRemoveItemsFromCourse(croom, courseId, i, count, removeParticipants, r
_REMOVE_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST, _REMOVE_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
GAPI.FORBIDDEN: Msg.FORBIDDEN, GAPI.FORBIDDEN: Msg.FORBIDDEN,
GAPI.PERMISSION_DENIED: Msg.PERMISSION_DENIED} GAPI.PERMISSION_DENIED: Msg.PERMISSION_DENIED}
def _callbackRemoveItemsFromCourse(request_id, response, exception): def _callbackRemoveItemsFromCourse(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -48451,7 +48478,7 @@ def doCourseRemoveItems(courseIdList, getEntityListArg):
# gam courses <CourseEntity> clear teachers|students # gam courses <CourseEntity> clear teachers|students
# gam course <CourseID> clear teacher|student # gam course <CourseID> clear teacher|student
def doCourseClearParticipants(courseIdList, getEntityListArg): def doCourseClearParticipants(courseIdList, _):
croom = buildGAPIObject(API.CLASSROOM) croom = buildGAPIObject(API.CLASSROOM)
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True) role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
checkForExtraneousArguments() checkForExtraneousArguments()
@@ -48467,7 +48494,7 @@ def doCourseClearParticipants(courseIdList, getEntityListArg):
# gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity> # gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity>
# gam courses <CourseEntity> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity> # gam courses <CourseEntity> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
# gam course <CourseID> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity> # gam course <CourseID> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
def doCourseSyncParticipants(courseIdList, getEntityListArg): def doCourseSyncParticipants(courseIdList, _):
croom = buildGAPIObject(API.CLASSROOM) croom = buildGAPIObject(API.CLASSROOM)
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True) role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
if role == Ent.TEACHER: if role == Ent.TEACHER:
@@ -58203,6 +58230,7 @@ def initCopyMoveOptions(copyCmd):
'showPermissionMessages': False, 'showPermissionMessages': False,
'sendEmailIfRequired': False, 'sendEmailIfRequired': False,
'useDomainAdminAccess': False, 'useDomainAdminAccess': False,
'enforceExpansiveAccess': False,
'copiedShortcutsPointToCopiedFiles': True, 'copiedShortcutsPointToCopiedFiles': True,
'createShortcutsForNonmovableFiles': False, 'createShortcutsForNonmovableFiles': False,
'duplicateFiles': DUPLICATE_FILE_OVERWRITE_OLDER, 'duplicateFiles': DUPLICATE_FILE_OVERWRITE_OLDER,
@@ -58301,6 +58329,8 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
elif myarg == 'mappermissionsdomain': elif myarg == 'mappermissionsdomain':
oldDomain = getString(Cmd.OB_DOMAIN_NAME).lower() oldDomain = getString(Cmd.OB_DOMAIN_NAME).lower()
copyMoveOptions['mapPermissionsDomains'][oldDomain] = getString(Cmd.OB_DOMAIN_NAME).lower() copyMoveOptions['mapPermissionsDomains'][oldDomain] = getString(Cmd.OB_DOMAIN_NAME).lower()
elif myarg == 'enforceexpansiveaccess':
copyMoveOptions['enforceExpansiveAccess'] = getBoolean()
else: else:
# Move arguments # Move arguments
if not copyMoveOptions['copyCmd']: if not copyMoveOptions['copyCmd']:
@@ -58572,6 +58602,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
updateTargetPerms[permissionId].update(updatePerm) updateTargetPerms[permissionId].update(updatePerm)
updateTargetPerms[permissionId]['updates'] = updatePerm updateTargetPerms[permissionId]['updates'] = updatePerm
copySourcePerms.pop(permissionId) copySourcePerms.pop(permissionId)
deleteUpdateKwargs = {'useDomainAdminAccess': copyMoveOptions['useDomainAdminAccess']}
if entityType != Ent.SHAREDDRIVE:
deleteUpdateKwargs['enforceExpansiveAccess'] = copyMoveOptions['enforceExpansiveAccess']
Ind.Increment() Ind.Increment()
action = Act.Get() action = Act.Get()
Act.Set(Act.COPY) Act.Set(Act.COPY)
@@ -58590,8 +58623,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
callGAPI(drive.permissions(), 'create', callGAPI(drive.permissions(), 'create',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS, throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS,
# retryReasons=[GAPI.INVALID_SHARING_REQUEST], # retryReasons=[GAPI.INVALID_SHARING_REQUEST],
useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'],
fileId=newFileId, sendNotificationEmail=sendNotificationEmail, emailMessage=None, fileId=newFileId, sendNotificationEmail=sendNotificationEmail, emailMessage=None,
body=permission, fields='', useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True) body=permission, fields='', supportsAllDrives=True)
if copyMoveOptions['showPermissionMessages']: if copyMoveOptions['showPermissionMessages']:
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
break break
@@ -58629,7 +58663,8 @@ def _copyPermissions(drive, user, i, count, j, jcount,
try: try:
callGAPI(drive.permissions(), 'delete', callGAPI(drive.permissions(), 'delete',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
fileId=newFileId, permissionId=permissionId, useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True) **deleteUpdateKwargs,
fileId=newFileId, permissionId=permissionId, supportsAllDrives=True)
if copyMoveOptions['showPermissionMessages']: if copyMoveOptions['showPermissionMessages']:
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
@@ -58654,8 +58689,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
callGAPI(drive.permissions(), 'update', callGAPI(drive.permissions(), 'update',
bailOnInternalError=True, bailOnInternalError=True,
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
fileId=newFileId, permissionId=permissionId, removeExpiration=removeExpiration, removeExpiration=removeExpiration,
body=permission['updates'], useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True) **deleteUpdateKwargs,
fileId=newFileId, permissionId=permissionId, body=permission['updates'], supportsAllDrives=True)
if copyMoveOptions['showPermissionMessages']: if copyMoveOptions['showPermissionMessages']:
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
@@ -58929,6 +58965,7 @@ copyReturnItemMap = {
# [sendemailifrequired [<Boolean>]] # [sendemailifrequired [<Boolean>]]
# [suppressnotselectedmessages [<Boolean>]] # [suppressnotselectedmessages [<Boolean>]]
# [verifyorganizer [<Boolean>]] # [verifyorganizer [<Boolean>]]
# [enforceexpansiveaccess [<Boolean>]]
def copyDriveFile(users): def copyDriveFile(users):
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType): def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
row = {'User': user, fileNameTitle: oldName, 'id': oldId, row = {'User': user, fileNameTitle: oldName, 'id': oldId,
@@ -59656,7 +59693,9 @@ def _updateMoveFilePermissions(drive, user, i, count,
try: try:
callGAPI(drive.permissions(), 'delete', callGAPI(drive.permissions(), 'delete',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
fileId=fileId, permissionId=permissionId, useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True) useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'],
enforceExpansiveAccess=copyMoveOptions['enforceExpansiveAccess'],
fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
if copyMoveOptions['showPermissionMessages']: if copyMoveOptions['showPermissionMessages']:
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
@@ -59744,6 +59783,7 @@ def _updateMoveFilePermissions(drive, user, i, count,
# [retainsourcefolders [<Boolean>]] # [retainsourcefolders [<Boolean>]]
# [sendemailifrequired [<Boolean>]] # [sendemailifrequired [<Boolean>]]
# [verifyorganizer [<Boolean>]] # [verifyorganizer [<Boolean>]]
# [enforceexpansiveaccess [<Boolean>]]
def moveDriveFile(users): def moveDriveFile(users):
def _cloneFolderMove(drive, user, i, count, j, jcount, def _cloneFolderMove(drive, user, i, count, j, jcount,
source, targetChildren, newFolderName, newParentId, newParentName, mergeParentModifiedTime, source, targetChildren, newFolderName, newParentId, newParentName, mergeParentModifiedTime,
@@ -60087,9 +60127,8 @@ def moveDriveFile(users):
parentBody = {} parentBody = {}
parentParms = initDriveFileAttributes() parentParms = initDriveFileAttributes()
copyMoveOptions = initCopyMoveOptions(False) copyMoveOptions = initCopyMoveOptions(False)
newParentsSpecified = False newParentsSpecified = updateFilePermissions = False
movedFiles = {} movedFiles = {}
updateFilePermissions = False
verifyOrganizer = True verifyOrganizer = True
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -60978,6 +61017,7 @@ TRANSFER_DRIVEFILE_ACL_ROLES_MAP = {
# [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none] # [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none]
# [nonowner_targetrole reader|commenter|writer|editor|fileorganizer|current|none|source] # [nonowner_targetrole reader|commenter|writer|editor|fileorganizer|current|none|source]
# (orderby <DriveFileOrderByFieldName> [ascending|descending])* # (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [enforceexpansiveaccess [<Boolean>]]
# [preview] [todrive <ToDriveAttribute>*] # [preview] [todrive <ToDriveAttribute>*]
def transferDrive(users): def transferDrive(users):
@@ -61164,6 +61204,7 @@ def transferDrive(users):
callGAPI(sourceDrive.permissions(), 'update', callGAPI(sourceDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.INVALID_OWNERSHIP_TRANSFER, throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.INVALID_OWNERSHIP_TRANSFER,
GAPI.PERMISSION_NOT_FOUND, GAPI.SHARING_RATE_LIMIT_EXCEEDED], GAPI.PERMISSION_NOT_FOUND, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=childFileId, permissionId=targetPermissionId, fileId=childFileId, permissionId=targetPermissionId,
transferOwnership=True, body={'role': 'owner'}, fields='') transferOwnership=True, body={'role': 'owner'}, fields='')
if removeSourceParents: if removeSourceParents:
@@ -61352,6 +61393,7 @@ def transferDrive(users):
if ownerRetainRoleBody['role'] != 'writer': if ownerRetainRoleBody['role'] != 'writer':
callGAPI(targetDrive.permissions(), 'update', callGAPI(targetDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=childFileId, permissionId=sourcePermissionId, body=ownerRetainRoleBody, fields='') fileId=childFileId, permissionId=sourcePermissionId, body=ownerRetainRoleBody, fields='')
else: else:
callGAPI(targetDrive.permissions(), 'delete', callGAPI(targetDrive.permissions(), 'delete',
@@ -61401,6 +61443,7 @@ def transferDrive(users):
if nonOwnerRetainRoleBody['role'] != 'current': if nonOwnerRetainRoleBody['role'] != 'current':
callGAPI(ownerDrive.permissions(), 'update', callGAPI(ownerDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=childFileId, permissionId=sourcePermissionId, body=sourceUpdateRole, fields='') fileId=childFileId, permissionId=sourcePermissionId, body=sourceUpdateRole, fields='')
else: else:
try: try:
@@ -61561,7 +61604,7 @@ def transferDrive(users):
targetUserFolderPattern = '#user# old files' targetUserFolderPattern = '#user# old files'
targetUserOrphansFolderPattern = '#user# orphaned files' targetUserOrphansFolderPattern = '#user# orphaned files'
targetIds = [None, None] targetIds = [None, None]
createShortcutsForNonmovableFiles = False createShortcutsForNonmovableFiles = enforceExpansiveAccess = False
mergeWithTarget = False mergeWithTarget = False
thirdPartyOwners = {} thirdPartyOwners = {}
skipFileIdEntity = initDriveFileEntity() skipFileIdEntity = initDriveFileEntity()
@@ -61579,6 +61622,8 @@ def transferDrive(users):
nonOwnerRetainRoleBody['role'] = 'current' nonOwnerRetainRoleBody['role'] = 'current'
elif myarg == 'nonownertargetrole': elif myarg == 'nonownertargetrole':
nonOwnerTargetRoleBody['role'] = getChoice(TRANSFER_DRIVEFILE_ACL_ROLES_MAP, mapChoice=True) nonOwnerTargetRoleBody['role'] = getChoice(TRANSFER_DRIVEFILE_ACL_ROLES_MAP, mapChoice=True)
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
elif myarg == 'noretentionmessages': elif myarg == 'noretentionmessages':
showRetentionMessages = False showRetentionMessages = False
elif myarg == 'orderby': elif myarg == 'orderby':
@@ -61816,6 +61861,7 @@ def getPermissionIdForEmail(user, i, count, email):
# [<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]] # [<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]]
# (orderby <DriveFileOrderByFieldName> [ascending|descending])* # (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [preview] [filepath] [pathdelimiter <Character>] [buildtree] # [preview] [filepath] [pathdelimiter <Character>] [buildtree]
# [enforceexpansiveaccess [<Boolean>]]
# [todrive <ToDriveAttribute>*] # [todrive <ToDriveAttribute>*]
def transferOwnership(users): def transferOwnership(users):
def _identifyFilesToTransfer(fileEntry): def _identifyFilesToTransfer(fileEntry):
@@ -61864,7 +61910,7 @@ def transferOwnership(users):
body = {} body = {}
newOwner = getEmailAddress() newOwner = getEmailAddress()
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP) OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
changeParents = filepath = includeTrashed = noRecursion = False changeParents = enforceExpansiveAccess = filepath = includeTrashed = noRecursion = False
pathDelimiter = '/' pathDelimiter = '/'
csvPF = fileTree = None csvPF = fileTree = None
addParents = '' addParents = ''
@@ -61891,6 +61937,8 @@ def transferOwnership(users):
csvPF.GetTodriveParameters() csvPF.GetTodriveParameters()
elif getDriveFileParentAttribute(myarg, parentParms): elif getDriveFileParentAttribute(myarg, parentParms):
changeParents = True changeParents = True
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
else: else:
unknownArgumentExit() unknownArgumentExit()
Act.Set(Act.TRANSFER_OWNERSHIP) Act.Set(Act.TRANSFER_OWNERSHIP)
@@ -62008,6 +62056,7 @@ def transferOwnership(users):
Act.Set(action) Act.Set(action)
callGAPI(drive.permissions(), 'update', callGAPI(drive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='') fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount) entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
else: else:
@@ -62029,6 +62078,7 @@ def transferOwnership(users):
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='') fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
callGAPI(drive.permissions(), 'update', callGAPI(drive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='') fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount) entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
except GAPI.invalidSharingRequest as e: except GAPI.invalidSharingRequest as e:
@@ -62101,6 +62151,7 @@ def transferOwnership(users):
# [keepuser | (retainrole reader|commenter|writer|editor|none)] [noretentionmessages] # [keepuser | (retainrole reader|commenter|writer|editor|none)] [noretentionmessages]
# (orderby <DriveFileOrderByFieldName> [ascending|descending])* # (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [preview] [filepath] [pathdelimiter <Character>] [buildtree] # [preview] [filepath] [pathdelimiter <Character>] [buildtree]
# [enforceexpansiveaccess [<Boolean>]]
# [todrive <ToDriveAttribute>*] # [todrive <ToDriveAttribute>*]
def claimOwnership(users): def claimOwnership(users):
def _identifyFilesToClaim(fileEntry): def _identifyFilesToClaim(fileEntry):
@@ -62161,6 +62212,7 @@ def claimOwnership(users):
if sourceRetainRoleBody['role'] != 'writer': if sourceRetainRoleBody['role'] != 'writer':
callGAPI(sourceDrive.permissions(), 'update', callGAPI(sourceDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=ofileId, permissionId=oldOwnerPermissionId, body=sourceRetainRoleBody, fields='') fileId=ofileId, permissionId=oldOwnerPermissionId, body=sourceRetainRoleBody, fields='')
else: else:
callGAPI(sourceDrive.permissions(), 'delete', callGAPI(sourceDrive.permissions(), 'delete',
@@ -62184,7 +62236,7 @@ def claimOwnership(users):
onlyOwners = set() onlyOwners = set()
skipOwners = set() skipOwners = set()
subdomains = [] subdomains = []
filepath = includeTrashed = False enforceExpansiveAccess = filepath = includeTrashed = False
pathDelimiter = '/' pathDelimiter = '/'
addParents = '' addParents = ''
parentBody = {} parentBody = {}
@@ -62219,6 +62271,8 @@ def claimOwnership(users):
includeTrashed = True includeTrashed = True
elif myarg == 'orderby': elif myarg == 'orderby':
OBY.GetChoice() OBY.GetChoice()
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
elif myarg == 'restricted': elif myarg == 'restricted':
bodyShare['copyRequiresWriterPermission'] = getBoolean() bodyShare['copyRequiresWriterPermission'] = getBoolean()
elif myarg == 'writerscanshare': elif myarg == 'writerscanshare':
@@ -62389,6 +62443,7 @@ def claimOwnership(users):
Act.Set(action) Act.Set(action)
callGAPI(sourceDrive.permissions(), 'update', callGAPI(sourceDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='') fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
kvList = [Ent.USER, user, entityType, fileDesc] kvList = [Ent.USER, user, entityType, fileDesc]
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount) entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
@@ -62413,6 +62468,7 @@ def claimOwnership(users):
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='') fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
callGAPI(sourceDrive.permissions(), 'update', callGAPI(sourceDrive.permissions(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
enforceExpansiveAccess=enforceExpansiveAccess,
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='') fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount) entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
_processRetainedRole(user, i, count, oldOwner, entityType, xferFileId, fileDesc, l, lcount) _processRetainedRole(user, i, count, oldOwner, entityType, xferFileId, fileDesc, l, lcount)
@@ -62949,11 +63005,12 @@ def doCreateDriveFileACL():
# gam [<UserTypeEntity>] update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin] # gam [<UserTypeEntity>] update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
# (role <DriveFileACLRole>) [expiration <Time>] [removeexpiration [<Boolean>]] # (role <DriveFileACLRole>) [expiration <Time>] [removeexpiration [<Boolean>]]
# [updatesheetprotectedranges [<Boolean>]] # [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
# [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])] # [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
def updateDriveFileACLs(users, useDomainAdminAccess=False): def updateDriveFileACLs(users, useDomainAdminAccess=False):
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
isEmail, permissionId = getPermissionId() isEmail, permissionId = getPermissionId()
enforceExpansiveAccess = None
removeExpiration = showTitles = updateSheetProtectedRanges = False removeExpiration = showTitles = updateSheetProtectedRanges = False
showDetails = True showDetails = True
csvPF = None csvPF = None
@@ -62972,6 +63029,8 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
showTitles = True showTitles = True
elif myarg == 'updatesheetprotectedranges': elif myarg == 'updatesheetprotectedranges':
updateSheetProtectedRanges = getBoolean() updateSheetProtectedRanges = getBoolean()
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
elif myarg == 'nodetails': elif myarg == 'nodetails':
showDetails = False showDetails = False
elif myarg == 'csv': elif myarg == 'csv':
@@ -62989,6 +63048,9 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess) _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
if 'role' not in body: if 'role' not in body:
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}') missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
updateKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
if enforceExpansiveAccess is not None:
updateKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects() printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
if csvPF and showTitles: if csvPF and showTitles:
csvPF.AddTitles(fileNameTitle) csvPF.AddTitles(fileNameTitle)
@@ -63026,7 +63088,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
permission = callGAPI(drive.permissions(), 'update', permission = callGAPI(drive.permissions(), 'update',
bailOnInternalError=True, bailOnInternalError=True,
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
useDomainAdminAccess=useDomainAdminAccess, **updateKwargs,
fileId=fileId, permissionId=permissionId, removeExpiration=removeExpiration, fileId=fileId, permissionId=permissionId, removeExpiration=removeExpiration,
transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True) transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True)
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET: if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
@@ -63122,7 +63184,7 @@ def createDriveFilePermissions(users, useDomainAdminAccess=False):
except ValueError: except ValueError:
return None return None
def _callbackCreatePermission(request_id, response, exception): def _callbackCreatePermission(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if int(ri[RI_J]) == 1: if int(ri[RI_J]) == 1:
entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMITTEE, int(ri[RI_I]), int(ri[RI_COUNT])) entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMITTEE, int(ri[RI_I]), int(ri[RI_COUNT]))
@@ -63270,11 +63332,12 @@ def doCreatePermissions():
createDriveFilePermissions([_getAdminEmail()], True) createDriveFilePermissions([_getAdminEmail()], True)
# gam [<UserTypeEntity>] delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin] # gam [<UserTypeEntity>] delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
# [updatesheetprotectedranges [<Boolean>]] # [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
# [showtitles] # [showtitles]
def deleteDriveFileACLs(users, useDomainAdminAccess=False): def deleteDriveFileACLs(users, useDomainAdminAccess=False):
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
isEmail, permissionId = getPermissionId() isEmail, permissionId = getPermissionId()
enforceExpansiveAccess = None
showTitles = updateSheetProtectedRanges = False showTitles = updateSheetProtectedRanges = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -63282,11 +63345,16 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
showTitles = getBoolean() showTitles = getBoolean()
elif myarg == 'updatesheetprotectedranges': elif myarg == 'updatesheetprotectedranges':
updateSheetProtectedRanges = getBoolean() updateSheetProtectedRanges = getBoolean()
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
elif myarg in ADMIN_ACCESS_OPTIONS: elif myarg in ADMIN_ACCESS_OPTIONS:
useDomainAdminAccess = True useDomainAdminAccess = True
else: else:
unknownArgumentExit() unknownArgumentExit()
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess) _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
deleteKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
if enforceExpansiveAccess is not None:
deleteKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
@@ -63319,7 +63387,8 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
break break
callGAPI(drive.permissions(), 'delete', callGAPI(drive.permissions(), 'delete',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
useDomainAdminAccess=useDomainAdminAccess, fileId=fileId, permissionId=permissionId, supportsAllDrives=True) **deleteKwargs,
fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount) entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET: if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission) _updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission)
@@ -63341,6 +63410,7 @@ def doDeleteDriveFileACLs():
# gam [<UserTypeEntity>] delete permissions <DriveFileEntity> <DriveFilePermissionIDEntity> [asadmin] # gam [<UserTypeEntity>] delete permissions <DriveFileEntity> <DriveFilePermissionIDEntity> [asadmin]
# <PermissionMatch>* [<PermissionMatchAction>] # <PermissionMatch>* [<PermissionMatchAction>]
# [enforceexpansiveaccess [<Boolean>]]
def deletePermissions(users, useDomainAdminAccess=False): def deletePermissions(users, useDomainAdminAccess=False):
def convertJSONPermissions(jsonPermissions): def convertJSONPermissions(jsonPermissions):
permissionIds = [] permissionIds = []
@@ -63350,7 +63420,7 @@ def deletePermissions(users, useDomainAdminAccess=False):
permissionIds.append(permission['id']) permissionIds.append(permission['id'])
return permissionIds return permissionIds
def _callbackDeletePermissionId(request_id, response, exception): def _callbackDeletePermissionId(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if int(ri[RI_J]) == 1: if int(ri[RI_J]) == 1:
entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMISSION_ID, int(ri[RI_I]), int(ri[RI_COUNT])) entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMISSION_ID, int(ri[RI_I]), int(ri[RI_COUNT]))
@@ -63375,7 +63445,8 @@ def deletePermissions(users, useDomainAdminAccess=False):
callGAPI(drive.permissions(), 'delete', callGAPI(drive.permissions(), 'delete',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS, throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS,
retryReasons=[GAPI.SERVICE_LIMIT], retryReasons=[GAPI.SERVICE_LIMIT],
useDomainAdminAccess=useDomainAdminAccess, fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True) useDomainAdminAccess=useDomainAdminAccess, enforceExpansiveAccess=enforceExpansiveAccess,
fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True)
entityActionPerformed([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionPerformed([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission,
@@ -63395,12 +63466,15 @@ def deletePermissions(users, useDomainAdminAccess=False):
jsonData = getJSON([]) jsonData = getJSON([])
PM = PermissionMatch() PM = PermissionMatch()
PM.SetDefaultMatch(False, {'role': 'owner'}) PM.SetDefaultMatch(False, {'role': 'owner'})
enforceExpansiveAccess = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if myarg in ADMIN_ACCESS_OPTIONS: if myarg in ADMIN_ACCESS_OPTIONS:
useDomainAdminAccess = True useDomainAdminAccess = True
elif PM and PM.ProcessArgument(myarg): elif PM and PM.ProcessArgument(myarg):
pass pass
elif myarg == 'enforceexpansiveaccess':
enforceExpansiveAccess = getBoolean()
else: else:
unknownArgumentExit() unknownArgumentExit()
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess) _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
@@ -68631,7 +68705,7 @@ def deleteLabels(users, labelEntity):
http_status, reason, message = checkGAPIError(exception) http_status, reason, message = checkGAPIError(exception)
entityActionFailedWarning([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], formatHTTPError(http_status, reason, message), int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionFailedWarning([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], formatHTTPError(http_status, reason, message), int(ri[RI_J]), int(ri[RI_JCOUNT]))
def _callbackDeleteLabel(request_id, response, exception): def _callbackDeleteLabel(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
entityActionPerformed([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionPerformed([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -69232,7 +69306,7 @@ def _processMessagesThreads(users, entityType):
GAPI.INVALID_MESSAGE_ID: Msg.INVALID_MESSAGE_ID, GAPI.INVALID_MESSAGE_ID: Msg.INVALID_MESSAGE_ID,
GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION} GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION}
def _callbackProcessMessage(request_id, response, exception): def _callbackProcessMessage(request_id, _, exception):
ri = request_id.splitlines() ri = request_id.splitlines()
if exception is None: if exception is None:
if not csvPF: if not csvPF:

View File

@@ -75,6 +75,7 @@ KEEP = 'keep'
LICENSING = 'licensing' LICENSING = 'licensing'
LOOKERSTUDIO = 'datastudio' LOOKERSTUDIO = 'datastudio'
MEET = 'meet' MEET = 'meet'
MEET_BETA = 'meetbeta'
OAUTH2 = 'oauth2' OAUTH2 = 'oauth2'
ORGPOLICY = 'orgpolicy' ORGPOLICY = 'orgpolicy'
PEOPLE = 'people' PEOPLE = 'people'
@@ -226,7 +227,7 @@ _INFO = {
CLOUDIDENTITY_INBOUND_SSO: {'name': 'Cloud Identity Inbound SSO API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'}, CLOUDIDENTITY_INBOUND_SSO: {'name': 'Cloud Identity Inbound SSO API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_ORGUNITS: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'}, CLOUDIDENTITY_ORGUNITS: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_ORGUNITS_BETA: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'}, CLOUDIDENTITY_ORGUNITS_BETA: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_POLICY: {'name': 'Cloud Identity Policy API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'}, CLOUDIDENTITY_POLICY: {'name': 'Cloud Identity Policy API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDIDENTITY_USERINVITATIONS: {'name': 'Cloud Identity User Invitations API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'}, CLOUDIDENTITY_USERINVITATIONS: {'name': 'Cloud Identity User Invitations API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True}, CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True},
CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False}, CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False},
@@ -251,6 +252,7 @@ _INFO = {
LICENSING: {'name': 'License Manager 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}, LOOKERSTUDIO: {'name': 'Looker Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
MEET: {'name': 'Meet API', 'version': 'v2', 'v2discovery': True}, MEET: {'name': 'Meet API', 'version': 'v2', 'v2discovery': True},
MEET_BETA: {'name': 'Meet API', 'version': 'v2beta', 'v2discovery': True, 'localjson': True, 'mappedAPI': MEET},
OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False}, OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False},
ORGPOLICY: {'name': 'Organization Policy API', 'version': 'v2', 'v2discovery': True}, ORGPOLICY: {'name': 'Organization Policy API', 'version': 'v2', 'v2discovery': True},
PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True}, PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True},

View File

@@ -177,6 +177,8 @@ INTER_BATCH_WAIT = 'inter_batch_wait'
LICENSE_MAX_RESULTS = 'license_max_results' LICENSE_MAX_RESULTS = 'license_max_results'
# License SKUs to process # License SKUs to process
LICENSE_SKUS = 'license_skus' LICENSE_SKUS = 'license_skus'
# Use Meet V2 beta
MEET_V2_BETA = 'meet_v2_beta'
# When retrieving lists of Google Group members from API, how many should be retrieved in each chunk # When retrieving lists of Google Group members from API, how many should be retrieved in each chunk
MEMBER_MAX_RESULTS = 'member_max_results' MEMBER_MAX_RESULTS = 'member_max_results'
# CI API Group members max page size when view=BASIC # CI API Group members max page size when view=BASIC
@@ -388,6 +390,7 @@ Defaults = {
INTER_BATCH_WAIT: '0', INTER_BATCH_WAIT: '0',
LICENSE_MAX_RESULTS: '100', LICENSE_MAX_RESULTS: '100',
LICENSE_SKUS: '', LICENSE_SKUS: '',
MEET_V2_BETA: FALSE,
MEMBER_MAX_RESULTS: '200', MEMBER_MAX_RESULTS: '200',
MEMBER_MAX_RESULTS_CI_BASIC: '1000', MEMBER_MAX_RESULTS_CI_BASIC: '1000',
MEMBER_MAX_RESULTS_CI_FULL: '500', MEMBER_MAX_RESULTS_CI_FULL: '500',
@@ -555,6 +558,7 @@ VAR_INFO = {
INTER_BATCH_WAIT: {VAR_TYPE: TYPE_FLOAT, VAR_LIMITS: (0.0, 60.0)}, INTER_BATCH_WAIT: {VAR_TYPE: TYPE_FLOAT, VAR_LIMITS: (0.0, 60.0)},
LICENSE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 1000)}, LICENSE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 1000)},
LICENSE_SKUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, LICENSE_SKUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
MEET_V2_BETA: {VAR_TYPE: TYPE_BOOLEAN},
MEMBER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)}, MEMBER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
MEMBER_MAX_RESULTS_CI_BASIC: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)}, MEMBER_MAX_RESULTS_CI_BASIC: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
MEMBER_MAX_RESULTS_CI_FULL: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)}, MEMBER_MAX_RESULTS_CI_FULL: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)},

1152
src/gam/meet-v2beta.json Normal file

File diff suppressed because it is too large Load Diff