Added option ignorerole to gam update groups|cigroups <GroupEntity> sync [<GroupRole>|ignorerole] ... <UserTypeEntity>

This commit is contained in:
Ross Scroggs
2023-08-23 15:43:43 -07:00
parent 0335ea7056
commit a7097a7310
9 changed files with 73 additions and 41 deletions

View File

@@ -178,14 +178,18 @@ testgroup@domain.com,testuser4@domain.com,MEMBER,Remove Failed,Does not exist
## Synchronize members in a group ## Synchronize members in a group
A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`. A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`.
This is done by specific role except for a special case where role is ignored.
``` ```
gam update cigroups <GroupEntity> sync [<GroupRole>] gam update cigroups <GroupEntity> sync [<GroupRole>|ignorerole]
[usersonly|groupsonly] [addonly|removeonly] [usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[expire|expires <Time>] [preview] [actioncsv] [expire|expires <Time>] [preview] [actioncsv]
<UserTypeEntity> <UserTypeEntity>
``` ```
If `<GroupRole>` is not specified, `member` is assumed. If `ignorerole` is specified, GAM removes members regardless of role and adds new members with role MEMBER.
This is a special purpose option, use with caution and ensure that `<UserTypeEntity>` specifies the full desired membership list of all roles.
If neither `<GroupRole>` nor `ignorerole` is specified, `member` is assumed.
When `<UserTypeEntity>` specifies a group or groups: When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added/deleted * `usersonly` - Only the user members from the specified groups are added/deleted

View File

@@ -10,6 +10,12 @@ 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. See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation.
### 6.63.04
Added option `ignorerole` to `gam update groups|cigroups <GroupEntity> sync [<GroupRole>|ignorerole] ... <UserTypeEntity>` that causes GAM
to remove members regardless of role and add new members with role MEMBER. This is a special purpose option, use with caution
and ensure that `<UserTypeEntity>` specifies the full desired membership list of all roles.
### 6.63.03 ### 6.63.03
Added option `externalusersallowed <Boolean>` to `gam <UserTypeEntity> create chatspace` Added option `externalusersallowed <Boolean>` to `gam <UserTypeEntity> create chatspace`

View File

@@ -213,8 +213,9 @@ testgroup@domain.com,testuser4@domain.com,MEMBER,Remove Failed,Does not exist
## Synchronize members in a group ## Synchronize members in a group
A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`. A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`.
This is done by specific role except for a special case where role is ignored.
``` ```
gam update group|groups <GroupEntity> sync [<GroupRole>] gam update group|groups <GroupEntity> sync [<GroupRole>|ignorerole]
[usersonly|groupsonly] [addonly|removeonly] [usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[remove_domain_nostatus_members] [remove_domain_nostatus_members]
@@ -223,7 +224,10 @@ gam update group|groups <GroupEntity> sync [<GroupRole>]
(additionalmembers [<GroupRole>] <EmailAddressEntity>)* (additionalmembers [<GroupRole>] <EmailAddressEntity>)*
<UserItem>|<UserTypeEntity> <UserItem>|<UserTypeEntity>
``` ```
If `<GroupRole>` is not specified, `member` is assumed. If `ignorerole` is specified, GAM removes members regardless of role and adds new members with role MEMBER.
This is a special purpose option, use with caution and ensure that `<UserTypeEntity>` specifies the full desired membership list of all roles.
If neither `<GroupRole>` nor `ignorerole` is specified, `member` is assumed.
When `<UserTypeEntity>` specifies a group or groups: When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added/deleted * `usersonly` - Only the user members from the specified groups are added/deleted

View File

@@ -330,7 +330,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$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version 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 WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.10.8 64-bit final Python 3.10.8 64-bit final
MacOS High Sierra 10.13.6 x86_64 MacOS High Sierra 10.13.6 x86_64
@@ -972,7 +972,7 @@ writes the credentials into the file oauth2.txt.
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version C:\GAMADV-XTD3>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final Python 3.11.4 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAMADV-XTD3 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAMADV-XTD3 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAMADV-XTD3 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3 Path: /Users/Admin/bin/gamadv-xtd3
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 6.63.03 Latest: 6.63.04
echo $? echo $?
1 1
``` ```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
6.63.03 6.63.04
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 6.63.03 - https://github.com/taers232c/GAMADV-XTD3 GAM 6.63.04 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64

View File

@@ -17,6 +17,7 @@ Installation
Configuration Configuration
* [Authorization](Authorization) * [Authorization](Authorization)
* [GAM Configuration](gam.cfg) * [GAM Configuration](gam.cfg)
* [Multiple Customers and Domains](https://github.com/taers232c/GAMADV-XTD3/wiki/gam.cfg#multiple-customers-and-domains)
* [Running GAMADV-XTD3 securely on a Google Compute Engine](Running-GAMADV-XTD3-securely-on-a-Google-Compute-Engine) * [Running GAMADV-XTD3 securely on a Google Compute Engine](Running-GAMADV-XTD3-securely-on-a-Google-Compute-Engine)
* [Using GAMADV-XTD3 with a delegated admin service account](Using-GAMADV-XTD3-with-a-delegated-admin-service-account) * [Using GAMADV-XTD3 with a delegated admin service account](Using-GAMADV-XTD3-with-a-delegated-admin-service-account)
* [Using GAMADV-XTD3 with a YubiKey](Using-GAMADV-XTD3-with-a-YubiKey) * [Using GAMADV-XTD3 with a YubiKey](Using-GAMADV-XTD3-with-a-YubiKey)

View File

@@ -3442,7 +3442,7 @@ gam update group|groups <GroupEntity> delete|remove [<GroupRole>]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[preview] [actioncsv] [preview] [actioncsv]
<UserItem>|<UserTypeEntity> <UserItem>|<UserTypeEntity>
gam update group|groups <GroupEntity> sync [<GroupRole>] gam update group|groups <GroupEntity> sync [<GroupRole>|ignorerole]
[usersonly|groupsonly] [addonly|removeonly] [usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[removedomainnostatusmembers] [removedomainnostatusmembers]
@@ -3649,7 +3649,7 @@ gam update cigroups <GroupEntity> delete|remove [<GroupRole>]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[preview] [actioncsv] [preview] [actioncsv]
<UserTypeEntity> <UserTypeEntity>
gam update cigroups <GroupEntity> sync [<GroupRole>] gam update cigroups <GroupEntity> sync [<GroupRole>|ignorerole]
[usersonly|groupsonly] [addonly|removeonly] [usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived] [notsuspended|suspended] [notarchived|archived]
[expire|expires <Time>] [preview] [actioncsv] [expire|expires <Time>] [preview] [actioncsv]

View File

@@ -2,6 +2,12 @@
Merged GAM-Team version Merged GAM-Team version
6.63.04
Added option `ignorerole` to `gam update groups|cigroups <GroupEntity> sync [<GroupRole>|ignorerole] ... <UserTypeEntity>` that causes GAM
to remove members regardless of role and add new members with role MEMBER. This is a special purpose option, use with caution
and ensure that `<UserTypeEntity>` specifies the full desired membership list of all roles.
6.63.03 6.63.03
Added option `externalusersallowed <Boolean>` to `gam <UserTypeEntity> create chatspace` Added option `externalusersallowed <Boolean>` to `gam <UserTypeEntity> create chatspace`

View File

@@ -120,7 +120,6 @@ import google.oauth2.service_account
import google_auth_oauthlib.flow import google_auth_oauthlib.flow
import google_auth_httplib2 import google_auth_httplib2
import httplib2 import httplib2
import urllib3.exceptions
httplib2.RETRIES = 5 httplib2.RETRIES = 5
@@ -8952,10 +8951,10 @@ def doCheckConnection():
ip = 'unknown' ip = 'unknown'
try: try:
ip = socket.getaddrinfo(host, None)[0][-1][0] # works with ipv6 ip = socket.getaddrinfo(host, None)[0][-1][0] # works with ipv6
except socket.gaierror as err: except socket.gaierror as e:
dns_err = f'{not_okay}\n DNS failure: {err}\n' dns_err = f'{not_okay}\n DNS failure: {str(e)}\n'
except Exception as e: except Exception as e:
dns_err = f'{not_okay}\n Unknown DNS failure: {err}\n' dns_err = f'{not_okay}\n Unknown DNS failure: {str(e)}\n'
check_line = f'Checking {host} ({ip}) ({try_count}/{host_count})...' check_line = f'Checking {host} ({ip}) ({try_count}/{host_count})...'
writeStdout(f'{check_line:<100}') writeStdout(f'{check_line:<100}')
flushStdout() flushStdout()
@@ -29123,7 +29122,7 @@ GROUP_PREVIEW_TITLES = ['group', 'email', 'role', 'action', 'message']
# [notsuspended|suspended] [notarchived|archived] # [notsuspended|suspended] [notarchived|archived]
# [preview] [actioncsv] # [preview] [actioncsv]
# <UserTypeEntity> # <UserTypeEntity>
# gam update groups <GroupEntity> sync [<GroupRole>] # gam update groups <GroupEntity> sync [<GroupRole>|ignorerole]
# [usersonly|groupsonly] [addonly|removeonly] # [usersonly|groupsonly] [addonly|removeonly]
# [notsuspended|suspended] [notarchived|archived] # [notsuspended|suspended] [notarchived|archived]
# [removedomainnostatusmembers] # [removedomainnostatusmembers]
@@ -29159,8 +29158,11 @@ def doUpdateGroups():
entityActionNotPerformedWarning([entityType, group, Ent.ROLE, role], Msg.INVALID_ROLE.format(','.join(sorted(GROUP_ROLES_MAP))), i, count) entityActionNotPerformedWarning([entityType, group, Ent.ROLE, role], Msg.INVALID_ROLE.format(','.join(sorted(GROUP_ROLES_MAP))), i, count)
return (None, None) return (None, None)
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER): def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER, allowIgnoreRole=False):
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True) if not allowIgnoreRole or not checkArgumentPresent(['ignorerole']):
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True)
else:
role = Ent.ROLE_ALL
groupMemberType = getChoice({'usersonly': Ent.TYPE_USER, 'groupsonly': Ent.TYPE_GROUP}, defaultChoice='ALL', mapChoice=True) groupMemberType = getChoice({'usersonly': Ent.TYPE_USER, 'groupsonly': Ent.TYPE_GROUP}, defaultChoice='ALL', mapChoice=True)
return (role, groupMemberType) return (role, groupMemberType)
@@ -29702,7 +29704,8 @@ def doUpdateGroups():
checkForCustomerId=True) for member in removeMembers], checkForCustomerId=True) for member in removeMembers],
role) role)
elif CL_subCommand == 'sync': elif CL_subCommand == 'sync':
baseRole, groupMemberType = _getRoleGroupMemberType() baseRole, groupMemberType = _getRoleGroupMemberType(allowIgnoreRole=True)
ignoreRole = baseRole == Ent.ROLE_ALL
syncOperation = getSyncOperation() syncOperation = getSyncOperation()
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived() isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
removeDomainNoStatusMembers = checkArgumentPresent('removedomainnostatusmembers') removeDomainNoStatusMembers = checkArgumentPresent('removedomainnostatusmembers')
@@ -29780,7 +29783,8 @@ def doUpdateGroups():
result = callGAPIpages(cd.members(), 'list', 'members', result = callGAPIpages(cd.members(), 'list', 'members',
pageMessage=getPageMessageForWhom(), pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS, throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
groupKey=group, roles=None if Ent.ROLE_MEMBER in rolesSet else memberRoles, groupKey=group,
roles=None if Ent.ROLE_MEMBER in rolesSet or ignoreRole else memberRoles,
fields='nextPageToken,members(email,id,type,status,role)', fields='nextPageToken,members(email,id,type,status,role)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
@@ -29791,7 +29795,7 @@ def doUpdateGroups():
currentMembersMaps[role] = {} currentMembersMaps[role] = {}
domainNoStatusMembersSets[role] = set() domainNoStatusMembersSets[role] = set()
for member in result: for member in result:
role = member.get('role', Ent.ROLE_MEMBER) role = member.get('role', Ent.ROLE_MEMBER) if not ignoreRole else Ent.ROLE_ALL
email, memberStatus = _getMemberEmailStatus(member) email, memberStatus = _getMemberEmailStatus(member)
if groupMemberType in ('ALL', member['type']) and role in rolesSet: if groupMemberType in ('ALL', member['type']) and role in rolesSet:
if not removeDomainNoStatusMembers or memberStatus != 'NONE': if not removeDomainNoStatusMembers or memberStatus != 'NONE':
@@ -29810,11 +29814,11 @@ def doUpdateGroups():
[currentMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in currentMembersSets[role]-syncMembersSets[role]], [currentMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in currentMembersSets[role]-syncMembersSets[role]],
role) role)
if syncOperation != 'removeonly': if syncOperation != 'removeonly':
for role in [Ent.ROLE_OWNER, Ent.ROLE_MANAGER, Ent.ROLE_MEMBER]: for role in [Ent.ROLE_OWNER, Ent.ROLE_MANAGER, Ent.ROLE_MEMBER, Ent.ROLE_ALL]:
if role in rolesSet: if role in rolesSet:
_batchAddGroupMembers(group, i, count, _batchAddGroupMembers(group, i, count,
[syncMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in syncMembersSets[role]-currentMembersSets[role]], [syncMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in syncMembersSets[role]-currentMembersSets[role]],
role, delivery_settings) role if role != Ent.ROLE_ALL else Ent.ROLE_MEMBER, delivery_settings)
elif CL_subCommand == 'update': elif CL_subCommand == 'update':
baseRole, groupMemberType = _getRoleGroupMemberType(defaultRole=None) baseRole, groupMemberType = _getRoleGroupMemberType(defaultRole=None)
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived() isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
@@ -31762,7 +31766,7 @@ def doCreateCIGroup():
# [notsuspended|suspended] [notarchived|archived] # [notsuspended|suspended] [notarchived|archived]
# [preview] [actioncsv] # [preview] [actioncsv]
# <UserTypeEntity> # <UserTypeEntity>
# gam update cigroups <GroupEntity> sync [<GroupRole>] # gam update cigroups <GroupEntity> sync [<GroupRole>|ignorerole]
# [usersonly|groupsonly] [addonly|removeonly] # [usersonly|groupsonly] [addonly|removeonly]
# [notsuspended|suspended] [notarchived|archived] # [notsuspended|suspended] [notarchived|archived]
# [expire|expires <Time>] [preview] [actioncsv] # [expire|expires <Time>] [preview] [actioncsv]
@@ -31798,8 +31802,11 @@ def doUpdateCIGroups():
entityActionNotPerformedWarning([entityType, group, Ent.ROLE, role], Msg.INVALID_ROLE.format(','.join(sorted(GROUP_ROLES_MAP))), i, count) entityActionNotPerformedWarning([entityType, group, Ent.ROLE, role], Msg.INVALID_ROLE.format(','.join(sorted(GROUP_ROLES_MAP))), i, count)
return (None, None) return (None, None)
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER): def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER, allowIgnoreRole=False):
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True) if not allowIgnoreRole or not checkArgumentPresent(['ignorerole']):
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True)
else:
role = Ent.ROLE_ALL
groupMemberType = getChoice({'usersonly': Ent.TYPE_USER, 'groupsonly': Ent.TYPE_GROUP}, defaultChoice='ALL', mapChoice=True) groupMemberType = getChoice({'usersonly': Ent.TYPE_USER, 'groupsonly': Ent.TYPE_GROUP}, defaultChoice='ALL', mapChoice=True)
return (role, groupMemberType) return (role, groupMemberType)
@@ -32136,7 +32143,8 @@ def doUpdateCIGroups():
_showFailure(group, memberEmail, role, str(e), j, jcount) _showFailure(group, memberEmail, role, str(e), j, jcount)
Ind.Decrement() Ind.Decrement()
elif CL_subCommand == 'sync': elif CL_subCommand == 'sync':
baseRole, groupMemberType = _getRoleGroupMemberType() baseRole, groupMemberType = _getRoleGroupMemberType(allowIgnoreRole=True)
ignoreRole = baseRole == Ent.ROLE_ALL
syncOperation = getSyncOperation() syncOperation = getSyncOperation()
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived() isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
expireTime = _getExpireTime(baseRole) expireTime = _getExpireTime(baseRole)
@@ -32213,25 +32221,25 @@ def doUpdateCIGroups():
currentMembersMaps[role] = {} currentMembersMaps[role] = {}
for member in result: for member in result:
getCIGroupMemberRoleFixType(member) getCIGroupMemberRoleFixType(member)
role = member['role'] role = member['role'] if not ignoreRole else Ent.ROLE_ALL
email = member.get(CIGROUP_MEMBERKEY, {}).get('id', '') email = member.get(CIGROUP_MEMBERKEY, {}).get('id', '')
if groupMemberType in ('ALL', member['type']) and role in rolesSet: if groupMemberType in ('ALL', member['type']) and role in rolesSet:
cleanAddress = _cleanConsumerAddress(email, currentMembersMaps[role]) cleanAddress = _cleanConsumerAddress(email, currentMembersMaps[role])
currentMembersSets[role].add(cleanAddress) currentMembersSets[role].add(cleanAddress)
currentMembersNames[cleanAddress] = member['name'] currentMembersNames[cleanAddress] = member['name']
del result del result
if syncOperation != 'removeonly':
for role in [Ent.ROLE_OWNER, Ent.ROLE_MANAGER, Ent.ROLE_MEMBER]:
if role in rolesSet:
_batchAddGroupMembers(parent, i, count,
[syncMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in syncMembersSets[role]-currentMembersSets[role]],
role, expireTime)
if syncOperation != 'addonly': if syncOperation != 'addonly':
for role in rolesSet: for role in rolesSet:
_batchRemoveGroupMembers(parent, i, count, _batchRemoveGroupMembers(parent, i, count,
[{'name': currentMembersNames[emailAddress], [{'name': currentMembersNames[emailAddress],
'email': currentMembersMaps[role].get(emailAddress, emailAddress)} for emailAddress in currentMembersSets[role]-syncMembersSets[role]], 'email': currentMembersMaps[role].get(emailAddress, emailAddress)} for emailAddress in currentMembersSets[role]-syncMembersSets[role]],
role) role)
if syncOperation != 'removeonly':
for role in [Ent.ROLE_OWNER, Ent.ROLE_MANAGER, Ent.ROLE_MEMBER, Ent.ROLE_ALL]:
if role in rolesSet:
_batchAddGroupMembers(parent, i, count,
[syncMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in syncMembersSets[role]-currentMembersSets[role]],
role if role != Ent.ROLE_ALL else Ent.ROLE_MEMBER, expireTime)
elif CL_subCommand == 'update': elif CL_subCommand == 'update':
baseRole, groupMemberType = _getRoleGroupMemberType() baseRole, groupMemberType = _getRoleGroupMemberType()
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived() isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
@@ -55108,7 +55116,8 @@ def copyDriveFile(users):
try: try:
result = callGAPI(drive.files(), 'copy', result = callGAPI(drive.files(), 'copy',
bailOnInternalError=True, bailOnInternalError=True,
throwReasons=GAPI.DRIVE_COPY_THROW_REASONS+[GAPI.INTERNAL_ERROR, GAPI.TEAMDRIVES_SHORTCUT_FILE_NOT_SUPPORTED], throwReasons=GAPI.DRIVE_COPY_THROW_REASONS+[GAPI.INTERNAL_ERROR, GAPI.INSUFFICIENT_PARENT_PERMISSIONS,
GAPI.TEAMDRIVES_SHORTCUT_FILE_NOT_SUPPORTED],
fileId=childId, body=child, fields='id,name', supportsAllDrives=True) fileId=childId, body=child, fields='id,name', supportsAllDrives=True)
if not csvPF: if not csvPF:
entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_TO, entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_TO,
@@ -55139,7 +55148,8 @@ def copyDriveFile(users):
copyMoveOptions, False, copyMoveOptions, False,
'copyFileInheritedPermissions', 'copyFileInheritedPermissions',
'copyFileNonInheritedPermissions') 'copyFileNonInheritedPermissions')
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
GAPI.insufficientParentPermissions, GAPI.unknownError,
GAPI.invalid, GAPI.cannotCopyFile, GAPI.badRequest, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable, GAPI.invalid, GAPI.cannotCopyFile, GAPI.badRequest, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
GAPI.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded,
GAPI.internalError, GAPI.teamDrivesShortcutFileNotSupported) as e: GAPI.internalError, GAPI.teamDrivesShortcutFileNotSupported) as e:
@@ -55361,7 +55371,7 @@ def copyDriveFile(users):
source.update(copyBody) source.update(copyBody)
result = callGAPI(drive.files(), 'copy', result = callGAPI(drive.files(), 'copy',
bailOnInternalError=True, bailOnInternalError=True,
throwReasons=GAPI.DRIVE_COPY_THROW_REASONS+[GAPI.INTERNAL_ERROR], throwReasons=GAPI.DRIVE_COPY_THROW_REASONS+[GAPI.INTERNAL_ERROR, GAPI.INSUFFICIENT_PARENT_PERMISSIONS],
fileId=fileId, fileId=fileId,
ignoreDefaultVisibility=copyParameters[DFA_IGNORE_DEFAULT_VISIBILITY], ignoreDefaultVisibility=copyParameters[DFA_IGNORE_DEFAULT_VISIBILITY],
keepRevisionForever=copyParameters[DFA_KEEP_REVISION_FOREVER], keepRevisionForever=copyParameters[DFA_KEEP_REVISION_FOREVER],
@@ -55395,7 +55405,8 @@ def copyDriveFile(users):
copyMoveOptions, False, copyMoveOptions, False,
'copyFileInheritedPermissions', 'copyFileInheritedPermissions',
'copyFileNonInheritedPermissions') 'copyFileNonInheritedPermissions')
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
GAPI.insufficientParentPermissions, GAPI.unknownError,
GAPI.invalid, GAPI.badRequest, GAPI.cannotCopyFile, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable, GAPI.invalid, GAPI.badRequest, GAPI.cannotCopyFile, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
GAPI.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded) as e: GAPI.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], str(e), j, jcount)