mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 18:01:36 +00:00
Added option ignorerole to gam update groups|cigroups <GroupEntity> sync [<GroupRole>|ignorerole] ... <UserTypeEntity>
This commit is contained in:
@@ -3442,7 +3442,7 @@ gam update group|groups <GroupEntity> delete|remove [<GroupRole>]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[preview] [actioncsv]
|
||||
<UserItem>|<UserTypeEntity>
|
||||
gam update group|groups <GroupEntity> sync [<GroupRole>]
|
||||
gam update group|groups <GroupEntity> sync [<GroupRole>|ignorerole]
|
||||
[usersonly|groupsonly] [addonly|removeonly]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[removedomainnostatusmembers]
|
||||
@@ -3649,7 +3649,7 @@ gam update cigroups <GroupEntity> delete|remove [<GroupRole>]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[preview] [actioncsv]
|
||||
<UserTypeEntity>
|
||||
gam update cigroups <GroupEntity> sync [<GroupRole>]
|
||||
gam update cigroups <GroupEntity> sync [<GroupRole>|ignorerole]
|
||||
[usersonly|groupsonly] [addonly|removeonly]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[expire|expires <Time>] [preview] [actioncsv]
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
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
|
||||
|
||||
Added option `externalusersallowed <Boolean>` to `gam <UserTypeEntity> create chatspace`
|
||||
|
||||
@@ -120,7 +120,6 @@ import google.oauth2.service_account
|
||||
import google_auth_oauthlib.flow
|
||||
import google_auth_httplib2
|
||||
import httplib2
|
||||
import urllib3.exceptions
|
||||
|
||||
httplib2.RETRIES = 5
|
||||
|
||||
@@ -8952,10 +8951,10 @@ def doCheckConnection():
|
||||
ip = 'unknown'
|
||||
try:
|
||||
ip = socket.getaddrinfo(host, None)[0][-1][0] # works with ipv6
|
||||
except socket.gaierror as err:
|
||||
dns_err = f'{not_okay}\n DNS failure: {err}\n'
|
||||
except socket.gaierror as e:
|
||||
dns_err = f'{not_okay}\n DNS failure: {str(e)}\n'
|
||||
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})...'
|
||||
writeStdout(f'{check_line:<100}')
|
||||
flushStdout()
|
||||
@@ -29123,7 +29122,7 @@ GROUP_PREVIEW_TITLES = ['group', 'email', 'role', 'action', 'message']
|
||||
# [notsuspended|suspended] [notarchived|archived]
|
||||
# [preview] [actioncsv]
|
||||
# <UserTypeEntity>
|
||||
# gam update groups <GroupEntity> sync [<GroupRole>]
|
||||
# gam update groups <GroupEntity> sync [<GroupRole>|ignorerole]
|
||||
# [usersonly|groupsonly] [addonly|removeonly]
|
||||
# [notsuspended|suspended] [notarchived|archived]
|
||||
# [removedomainnostatusmembers]
|
||||
@@ -29159,8 +29158,11 @@ def doUpdateGroups():
|
||||
entityActionNotPerformedWarning([entityType, group, Ent.ROLE, role], Msg.INVALID_ROLE.format(','.join(sorted(GROUP_ROLES_MAP))), i, count)
|
||||
return (None, None)
|
||||
|
||||
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER):
|
||||
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True)
|
||||
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER, allowIgnoreRole=False):
|
||||
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)
|
||||
return (role, groupMemberType)
|
||||
|
||||
@@ -29702,7 +29704,8 @@ def doUpdateGroups():
|
||||
checkForCustomerId=True) for member in removeMembers],
|
||||
role)
|
||||
elif CL_subCommand == 'sync':
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType()
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType(allowIgnoreRole=True)
|
||||
ignoreRole = baseRole == Ent.ROLE_ALL
|
||||
syncOperation = getSyncOperation()
|
||||
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
|
||||
removeDomainNoStatusMembers = checkArgumentPresent('removedomainnostatusmembers')
|
||||
@@ -29780,7 +29783,8 @@ def doUpdateGroups():
|
||||
result = callGAPIpages(cd.members(), 'list', 'members',
|
||||
pageMessage=getPageMessageForWhom(),
|
||||
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)',
|
||||
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
|
||||
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
|
||||
@@ -29791,7 +29795,7 @@ def doUpdateGroups():
|
||||
currentMembersMaps[role] = {}
|
||||
domainNoStatusMembersSets[role] = set()
|
||||
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)
|
||||
if groupMemberType in ('ALL', member['type']) and role in rolesSet:
|
||||
if not removeDomainNoStatusMembers or memberStatus != 'NONE':
|
||||
@@ -29810,11 +29814,11 @@ def doUpdateGroups():
|
||||
[currentMembersMaps[role].get(emailAddress, emailAddress) for emailAddress in currentMembersSets[role]-syncMembersSets[role]],
|
||||
role)
|
||||
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:
|
||||
_batchAddGroupMembers(group, i, count,
|
||||
[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':
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType(defaultRole=None)
|
||||
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
|
||||
@@ -31762,7 +31766,7 @@ def doCreateCIGroup():
|
||||
# [notsuspended|suspended] [notarchived|archived]
|
||||
# [preview] [actioncsv]
|
||||
# <UserTypeEntity>
|
||||
# gam update cigroups <GroupEntity> sync [<GroupRole>]
|
||||
# gam update cigroups <GroupEntity> sync [<GroupRole>|ignorerole]
|
||||
# [usersonly|groupsonly] [addonly|removeonly]
|
||||
# [notsuspended|suspended] [notarchived|archived]
|
||||
# [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)
|
||||
return (None, None)
|
||||
|
||||
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER):
|
||||
role = getChoice(GROUP_ROLES_MAP, defaultChoice=defaultRole, mapChoice=True)
|
||||
def _getRoleGroupMemberType(defaultRole=Ent.ROLE_MEMBER, allowIgnoreRole=False):
|
||||
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)
|
||||
return (role, groupMemberType)
|
||||
|
||||
@@ -32136,7 +32143,8 @@ def doUpdateCIGroups():
|
||||
_showFailure(group, memberEmail, role, str(e), j, jcount)
|
||||
Ind.Decrement()
|
||||
elif CL_subCommand == 'sync':
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType()
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType(allowIgnoreRole=True)
|
||||
ignoreRole = baseRole == Ent.ROLE_ALL
|
||||
syncOperation = getSyncOperation()
|
||||
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
|
||||
expireTime = _getExpireTime(baseRole)
|
||||
@@ -32213,25 +32221,25 @@ def doUpdateCIGroups():
|
||||
currentMembersMaps[role] = {}
|
||||
for member in result:
|
||||
getCIGroupMemberRoleFixType(member)
|
||||
role = member['role']
|
||||
role = member['role'] if not ignoreRole else Ent.ROLE_ALL
|
||||
email = member.get(CIGROUP_MEMBERKEY, {}).get('id', '')
|
||||
if groupMemberType in ('ALL', member['type']) and role in rolesSet:
|
||||
cleanAddress = _cleanConsumerAddress(email, currentMembersMaps[role])
|
||||
currentMembersSets[role].add(cleanAddress)
|
||||
currentMembersNames[cleanAddress] = member['name']
|
||||
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':
|
||||
for role in rolesSet:
|
||||
_batchRemoveGroupMembers(parent, i, count,
|
||||
[{'name': currentMembersNames[emailAddress],
|
||||
'email': currentMembersMaps[role].get(emailAddress, emailAddress)} for emailAddress in currentMembersSets[role]-syncMembersSets[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':
|
||||
baseRole, groupMemberType = _getRoleGroupMemberType()
|
||||
isSuspended, isArchived = _getOptionalIsSuspendedIsArchived()
|
||||
@@ -55108,7 +55116,8 @@ def copyDriveFile(users):
|
||||
try:
|
||||
result = callGAPI(drive.files(), 'copy',
|
||||
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)
|
||||
if not csvPF:
|
||||
entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_TO,
|
||||
@@ -55139,7 +55148,8 @@ def copyDriveFile(users):
|
||||
copyMoveOptions, False,
|
||||
'copyFileInheritedPermissions',
|
||||
'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.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded,
|
||||
GAPI.internalError, GAPI.teamDrivesShortcutFileNotSupported) as e:
|
||||
@@ -55361,7 +55371,7 @@ def copyDriveFile(users):
|
||||
source.update(copyBody)
|
||||
result = callGAPI(drive.files(), 'copy',
|
||||
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,
|
||||
ignoreDefaultVisibility=copyParameters[DFA_IGNORE_DEFAULT_VISIBILITY],
|
||||
keepRevisionForever=copyParameters[DFA_KEEP_REVISION_FOREVER],
|
||||
@@ -55395,7 +55405,8 @@ def copyDriveFile(users):
|
||||
copyMoveOptions, False,
|
||||
'copyFileInheritedPermissions',
|
||||
'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.teamDrivesSharingRestrictionNotAllowed, GAPI.rateLimitExceeded, GAPI.userRateLimitExceeded) as e:
|
||||
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], str(e), j, jcount)
|
||||
|
||||
Reference in New Issue
Block a user