|
|
|
|
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
|
|
|
|
__version__ = '7.04.02'
|
|
|
|
|
__version__ = '7.05.03'
|
|
|
|
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
|
|
|
|
|
|
|
|
|
#pylint: disable=wrong-import-position
|
|
|
|
|
@@ -4710,7 +4710,7 @@ def getAPIService(api, httpObj):
|
|
|
|
|
|
|
|
|
|
def getService(api, httpObj):
|
|
|
|
|
### 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)
|
|
|
|
|
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]:
|
|
|
|
|
@@ -4727,8 +4727,8 @@ def getService(api, httpObj):
|
|
|
|
|
GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {})
|
|
|
|
|
GM.Globals[GM.CURRENT_API_SERVICES][api][version] = service._rootDesc.copy()
|
|
|
|
|
### Drive v3beta
|
|
|
|
|
if mapDriveURL:
|
|
|
|
|
setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/'))
|
|
|
|
|
# if mapDriveURL:
|
|
|
|
|
# setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/'))
|
|
|
|
|
if GM.Globals[GM.CACHE_DISCOVERY_ONLY]:
|
|
|
|
|
clearServiceCache(service)
|
|
|
|
|
return service
|
|
|
|
|
@@ -5571,6 +5571,8 @@ def buildGAPIServiceObject(api, user, i=0, count=0, displayError=True):
|
|
|
|
|
userEmail = getSaUser(user)
|
|
|
|
|
httpObj = getHttpObj(cache=GM.Globals[GM.CACHE_DIR])
|
|
|
|
|
service = getService(api, httpObj)
|
|
|
|
|
if api == API.MEET_BETA:
|
|
|
|
|
api = API.MEET
|
|
|
|
|
credentials = getSvcAcctCredentials(api, userEmail)
|
|
|
|
|
request = transportCreateRequest(httpObj)
|
|
|
|
|
triesLimit = 3
|
|
|
|
|
@@ -5981,6 +5983,8 @@ def getCIGroupTransitiveMemberRoleFixType(groupName, tmember):
|
|
|
|
|
member['type'] = Ent.TYPE_USER if not tid.endswith('.iam.gserviceaccount.com') else Ent.TYPE_SERVICE_ACCOUNT
|
|
|
|
|
elif ttype == 'groups':
|
|
|
|
|
member['type'] = Ent.TYPE_GROUP
|
|
|
|
|
elif tid.startswith('cbcm-browser.'):
|
|
|
|
|
member['type'] = Ent.TYPE_CBCM_BROWSER
|
|
|
|
|
else:
|
|
|
|
|
member['type'] = Ent.TYPE_OTHER
|
|
|
|
|
else:
|
|
|
|
|
@@ -7322,12 +7326,6 @@ def _getRawFields(requiredField=None):
|
|
|
|
|
return rawFields
|
|
|
|
|
return f'{requiredField},{rawFields}'
|
|
|
|
|
|
|
|
|
|
def _addInitialField(fieldsList, initialField):
|
|
|
|
|
if isinstance(initialField, list):
|
|
|
|
|
fieldsList.extend(initialField)
|
|
|
|
|
else:
|
|
|
|
|
fieldsList.append(initialField)
|
|
|
|
|
|
|
|
|
|
def CheckInputRowFilterHeaders(titlesList, rowFilter, rowDropFilter):
|
|
|
|
|
status = True
|
|
|
|
|
for filterVal in rowFilter:
|
|
|
|
|
@@ -7742,6 +7740,12 @@ def RowFilterMatch(row, titlesList, rowFilter, rowFilterModeAll, rowDropFilter,
|
|
|
|
|
# }
|
|
|
|
|
# fieldsList is the list of API fields
|
|
|
|
|
def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsArg='fields', onlyFieldsArg=False):
|
|
|
|
|
def addInitialField():
|
|
|
|
|
if isinstance(initialField, list):
|
|
|
|
|
fieldsList.extend(initialField)
|
|
|
|
|
else:
|
|
|
|
|
fieldsList.append(initialField)
|
|
|
|
|
|
|
|
|
|
def addMappedFields(mappedFields):
|
|
|
|
|
if isinstance(mappedFields, list):
|
|
|
|
|
fieldsList.extend(mappedFields)
|
|
|
|
|
@@ -7750,11 +7754,11 @@ def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsA
|
|
|
|
|
|
|
|
|
|
if not onlyFieldsArg and myarg in fieldsChoiceMap:
|
|
|
|
|
if not fieldsList and initialField is not None:
|
|
|
|
|
_addInitialField(fieldsList, initialField)
|
|
|
|
|
addInitialField()
|
|
|
|
|
addMappedFields(fieldsChoiceMap[myarg])
|
|
|
|
|
elif myarg == fieldsArg:
|
|
|
|
|
if not fieldsList and initialField is not None:
|
|
|
|
|
_addInitialField(fieldsList, initialField)
|
|
|
|
|
addInitialField()
|
|
|
|
|
for field in _getFieldsList():
|
|
|
|
|
if field in fieldsChoiceMap:
|
|
|
|
|
addMappedFields(fieldsChoiceMap[field])
|
|
|
|
|
@@ -7931,14 +7935,21 @@ class CSVPrintFile():
|
|
|
|
|
fieldsList.append(fields)
|
|
|
|
|
self.AddTitles(fields.replace('.', GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]))
|
|
|
|
|
|
|
|
|
|
def addInitialField(self, initialField, fieldsChoiceMap, fieldsList):
|
|
|
|
|
if isinstance(initialField, list):
|
|
|
|
|
for field in initialField:
|
|
|
|
|
self.AddField(field, fieldsChoiceMap, fieldsList)
|
|
|
|
|
else:
|
|
|
|
|
self.AddField(initialField, fieldsChoiceMap, fieldsList)
|
|
|
|
|
|
|
|
|
|
def GetFieldsListTitles(self, fieldName, fieldsChoiceMap, fieldsList, initialField=None):
|
|
|
|
|
if fieldName in fieldsChoiceMap:
|
|
|
|
|
if not fieldsList and initialField is not None:
|
|
|
|
|
_addInitialField(fieldsList, initialField)
|
|
|
|
|
self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
|
|
|
|
|
self.AddField(fieldName, fieldsChoiceMap, fieldsList)
|
|
|
|
|
elif fieldName == 'fields':
|
|
|
|
|
if not fieldsList and initialField is not None:
|
|
|
|
|
_addInitialField(fieldsList, initialField)
|
|
|
|
|
self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
|
|
|
|
|
for field in _getFieldsList():
|
|
|
|
|
if field in fieldsChoiceMap:
|
|
|
|
|
self.AddField(field, fieldsChoiceMap, fieldsList)
|
|
|
|
|
@@ -9831,7 +9842,7 @@ def MultiprocessGAMCommands(items, showCmds):
|
|
|
|
|
if GM.Globals[GM.MULTIPROCESS_EXIT_CONDITION] is not None and checkChildProcessRC(result[1]):
|
|
|
|
|
GM.Globals[GM.MULTIPROCESS_EXIT_PROCESSING] = True
|
|
|
|
|
|
|
|
|
|
def signal_handler(sig, frame):
|
|
|
|
|
def signal_handler(*_):
|
|
|
|
|
nonlocal controlC
|
|
|
|
|
controlC = True
|
|
|
|
|
|
|
|
|
|
@@ -13098,6 +13109,7 @@ CUSTOMER_REPORT_SERVICES = {
|
|
|
|
|
'app_maker',
|
|
|
|
|
'apps_scripts',
|
|
|
|
|
'calendar',
|
|
|
|
|
'chat',
|
|
|
|
|
'classroom',
|
|
|
|
|
'cros',
|
|
|
|
|
'device_management',
|
|
|
|
|
@@ -13111,6 +13123,7 @@ CUSTOMER_REPORT_SERVICES = {
|
|
|
|
|
|
|
|
|
|
USER_REPORT_SERVICES = {
|
|
|
|
|
'accounts',
|
|
|
|
|
'chat',
|
|
|
|
|
'classroom',
|
|
|
|
|
'docs',
|
|
|
|
|
'drive',
|
|
|
|
|
@@ -17245,7 +17258,7 @@ def checkOrgUnitPathExists(cd, orgUnitPath, i=0, count=0, showError=False):
|
|
|
|
|
return (False, orgUnitPath, orgUnitPath)
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
if exception is None:
|
|
|
|
|
if not fromOrgUnitPath:
|
|
|
|
|
@@ -17326,7 +17339,7 @@ def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quick
|
|
|
|
|
|
|
|
|
|
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}
|
|
|
|
|
def _callbackMoveUsersToOrgUnit(request_id, response, exception):
|
|
|
|
|
def _callbackMoveUsersToOrgUnit(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
if exception is None:
|
|
|
|
|
if not fromOrgUnitPath:
|
|
|
|
|
@@ -27479,6 +27492,8 @@ def printShowChatEvents(users):
|
|
|
|
|
csvPF.writeCSVfile('Chat Events')
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
kvList = [Ent.USER, user]
|
|
|
|
|
if entityTypeList is not None:
|
|
|
|
|
@@ -27502,7 +27517,10 @@ MEET_SPACE_OPTIONS_MAP = {
|
|
|
|
|
'reactionrestriction': 'reactionRestriction',
|
|
|
|
|
'presentrestriction': 'presentRestriction',
|
|
|
|
|
'defaultjoinasviewer': 'defaultJoinAsViewerType',
|
|
|
|
|
'firstjoiner': 'firstJoinerType'
|
|
|
|
|
'firstjoiner': 'firstJoinerType',
|
|
|
|
|
'autorecording': 'recordingConfig',
|
|
|
|
|
'autosmartnotes': 'smartNotesConfig',
|
|
|
|
|
'autotranscription': 'transcriptionConfig',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEET_SPACE_ACCESSTYPE_CHOICES = {'open', 'trusted', 'restricted'}
|
|
|
|
|
@@ -27516,9 +27534,15 @@ MEET_SPACE_RESTRICTIONS_CHOICES_MAP = {
|
|
|
|
|
'norestriction': 'NO_RESTRICTION'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
|
|
|
|
'hostsonly': 'HOSTS_ONLY',
|
|
|
|
|
'anyone': 'ANYONE'
|
|
|
|
|
#MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
|
|
|
|
# 'hostsonly': 'HOSTS_ONLY',
|
|
|
|
|
# 'anyone': 'ANYONE'
|
|
|
|
|
# }
|
|
|
|
|
|
|
|
|
|
MEET_SPACE_ARTIFACT_SUB_OPTIONS = {
|
|
|
|
|
'recordingConfig': 'autoRecordingGeneration',
|
|
|
|
|
'smartNotesConfig': 'autoSmartNotesGeneration',
|
|
|
|
|
'transcriptionConfig': 'autoTranscriptionGeneration'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# [accesstype open|trusted|restricted]
|
|
|
|
|
@@ -27529,7 +27553,10 @@ MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
|
|
|
|
# [presentrestriction hostsonly|norestriction]
|
|
|
|
|
# [defaultjoinasviewer <Boolean>]
|
|
|
|
|
# [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)
|
|
|
|
|
if option is None:
|
|
|
|
|
return False
|
|
|
|
|
@@ -27539,15 +27566,17 @@ def _getMeetSpaceParameters(myarg, body, updateMask):
|
|
|
|
|
body['config'][option] = getChoice(MEET_SPACE_ENTRYPOINTACCESS_CHOICES_MAP, mapChoice=True)
|
|
|
|
|
elif option == 'moderation':
|
|
|
|
|
body['config'][option] = 'ON' if getBoolean() else 'OFF'
|
|
|
|
|
elif option in {'chatrestriction', 'reactionrestriction', 'presentrestriction'}:
|
|
|
|
|
body['config'].setdefault('moderationRestictions', {})
|
|
|
|
|
elif option in {'chatRestriction', 'reactionRestriction', 'presentRestriction'}:
|
|
|
|
|
body['config'].setdefault('moderationRestrictions', {})
|
|
|
|
|
body['config']['moderationRestrictions'][option] = getChoice(MEET_SPACE_RESTRICTIONS_CHOICES_MAP, mapChoice=True)
|
|
|
|
|
option = f'moderationRestrictions.{option}'
|
|
|
|
|
elif option == 'defaultJoinAsViewerType':
|
|
|
|
|
body['config'][option] = 'ON' if getBoolean() else 'OFF'
|
|
|
|
|
elif option == 'firstJoinerType':
|
|
|
|
|
body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True)
|
|
|
|
|
updateMask.append(f'config.{option}')
|
|
|
|
|
# elif option == 'firstJoinerType':
|
|
|
|
|
# body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True)
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# gam <UserTypeEntity> create meetspace
|
|
|
|
|
@@ -27562,10 +27591,9 @@ def createMeetSpace(users):
|
|
|
|
|
# 'firstJoinerType': 'ANYONE',
|
|
|
|
|
}}
|
|
|
|
|
returnIdOnly = False
|
|
|
|
|
updateMask = []
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
if _getMeetSpaceParameters(myarg, body, updateMask):
|
|
|
|
|
if _getMeetSpaceParameters(myarg, body):
|
|
|
|
|
pass
|
|
|
|
|
elif myarg == 'returnidonly':
|
|
|
|
|
returnIdOnly = True
|
|
|
|
|
@@ -27600,12 +27628,11 @@ def updateMeetSpace(users):
|
|
|
|
|
FJQC = FormatJSONQuoteChar()
|
|
|
|
|
name = None
|
|
|
|
|
body = {'config': {}}
|
|
|
|
|
updateMask = []
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
if (myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/')):
|
|
|
|
|
name = getSpaceName(myarg)
|
|
|
|
|
elif _getMeetSpaceParameters(myarg, body, updateMask):
|
|
|
|
|
elif _getMeetSpaceParameters(myarg, body):
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
FJQC.GetFormatJSON(myarg)
|
|
|
|
|
@@ -27620,7 +27647,7 @@ def updateMeetSpace(users):
|
|
|
|
|
try:
|
|
|
|
|
space = callGAPI(meet.spaces(), 'patch',
|
|
|
|
|
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:
|
|
|
|
|
entityActionPerformed(kvList, i, count)
|
|
|
|
|
Ind.Increment()
|
|
|
|
|
@@ -29226,6 +29253,7 @@ DEVICE_FIELDS_CHOICE_MAP = {
|
|
|
|
|
'releaseversion': 'releaseVersion',
|
|
|
|
|
'securitypatchtime': 'securityPatchTime',
|
|
|
|
|
'serialnumber': 'serialNumber',
|
|
|
|
|
'unifieddeviceid': 'unifiedDeviceId',
|
|
|
|
|
'wifimacaddresses': 'wifiMacAddresses'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -31998,7 +32026,7 @@ def doUpdateGroups():
|
|
|
|
|
GAPI.INVALID_MEMBER: Msg.INVALID_MEMBER,
|
|
|
|
|
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()
|
|
|
|
|
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]))
|
|
|
|
|
@@ -32087,7 +32115,7 @@ def doUpdateGroups():
|
|
|
|
|
GAPI.CONDITION_NOT_MET: f'{Msg.NOT_A} {Ent.Singular(Ent.MEMBER)}',
|
|
|
|
|
GAPI.INVALID_MEMBER: Msg.DOES_NOT_EXIST}
|
|
|
|
|
|
|
|
|
|
def _callbackRemoveGroupMembers(request_id, response, exception):
|
|
|
|
|
def _callbackRemoveGroupMembers(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
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]))
|
|
|
|
|
@@ -32186,7 +32214,7 @@ def doUpdateGroups():
|
|
|
|
|
except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e:
|
|
|
|
|
_showFailure(group, member, role, str(e), j, jcount)
|
|
|
|
|
|
|
|
|
|
def _callbackUpdateGroupMembers(request_id, response, exception):
|
|
|
|
|
def _callbackUpdateGroupMembers(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
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]))
|
|
|
|
|
@@ -33423,6 +33451,7 @@ PRINT_GROUPS_JSON_TITLES = ['email', 'JSON']
|
|
|
|
|
|
|
|
|
|
# gam print groups [todrive <ToDriveAttribute>*]
|
|
|
|
|
# [([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryUserList>)]))|
|
|
|
|
|
# (group|group_ns|group_susp <GroupItem>)|
|
|
|
|
|
# (select <GroupEntity>)]
|
|
|
|
|
# [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
|
|
|
|
# [descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
|
|
|
|
|
@@ -33635,6 +33664,12 @@ def doPrintGroups():
|
|
|
|
|
pass
|
|
|
|
|
elif getGroupMatchPatterns(myarg, matchPatterns, False):
|
|
|
|
|
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':
|
|
|
|
|
entitySelection = getEntityList(Cmd.OB_GROUP_ENTITY)
|
|
|
|
|
elif myarg in SUSPENDED_ARGUMENTS:
|
|
|
|
|
@@ -33959,6 +33994,8 @@ def infoGroupMembers(entityList, ciGroupsAPI=False):
|
|
|
|
|
printKeyValueList(['type', result['type']])
|
|
|
|
|
for field in ['createTime', 'updateTime']:
|
|
|
|
|
printKeyValueList([field, formatLocalTime(result[field])])
|
|
|
|
|
if 'deliverySetting' in result:
|
|
|
|
|
printKeyValueList(['deliverySetting', result['deliverySetting']])
|
|
|
|
|
Ind.Decrement()
|
|
|
|
|
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden) as e:
|
|
|
|
|
entityActionFailedWarning([entityType, groupKey], str(e), j, jcount)
|
|
|
|
|
@@ -34202,7 +34239,7 @@ def doPrintGroupMembers():
|
|
|
|
|
pass
|
|
|
|
|
elif getMemberMatchOptions(myarg, memberOptions):
|
|
|
|
|
pass
|
|
|
|
|
elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
|
|
|
|
|
elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='email'):
|
|
|
|
|
pass
|
|
|
|
|
elif myarg == 'membernames':
|
|
|
|
|
memberOptions[MEMBEROPTION_MEMBERNAMES] = True
|
|
|
|
|
@@ -36121,8 +36158,9 @@ def getCIGroupTransitiveMembers(ci, groupName, membersList, i, count):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, count,
|
|
|
|
|
memberOptions, memberDisplayOptions, level, typesSet):
|
|
|
|
|
printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, groupName, i, count)
|
|
|
|
|
memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs):
|
|
|
|
|
nameToPrint = groupEmail if groupEmail else groupName
|
|
|
|
|
printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, nameToPrint, i, count)
|
|
|
|
|
validRoles = _getCIRoleVerification(memberRoles)
|
|
|
|
|
if memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP]:
|
|
|
|
|
groupMembers = []
|
|
|
|
|
@@ -36137,12 +36175,11 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
|
|
|
|
groupMembers = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
|
|
|
|
|
pageMessage=getPageMessageForWhom(),
|
|
|
|
|
throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
|
|
|
|
|
parent=groupName, view='FULL',
|
|
|
|
|
fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
|
|
|
|
|
parent=groupName, **kwargs)
|
|
|
|
|
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
|
|
|
|
GAPI.forbidden, GAPI.badRequest, GAPI.invalid, GAPI.invalidArgument, GAPI.systemError,
|
|
|
|
|
GAPI.permissionDenied, GAPI.serviceNotAvailable):
|
|
|
|
|
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupName, i, count)
|
|
|
|
|
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, nameToPrint, i, count)
|
|
|
|
|
return
|
|
|
|
|
checkCategory = memberDisplayOptions['showCategory']
|
|
|
|
|
if not memberOptions[MEMBEROPTION_RECURSIVE]:
|
|
|
|
|
@@ -36176,7 +36213,7 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
|
|
|
|
memberName not in membersSet):
|
|
|
|
|
membersSet.add(memberName)
|
|
|
|
|
member['level'] = level
|
|
|
|
|
member['subgroup'] = groupName
|
|
|
|
|
member['subgroup'] = nameToPrint
|
|
|
|
|
membersList.append(member)
|
|
|
|
|
else:
|
|
|
|
|
if memberName not in membersSet:
|
|
|
|
|
@@ -36185,37 +36222,41 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
|
|
|
|
checkCIMemberMatch(member, memberOptions) and
|
|
|
|
|
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
|
|
|
|
member['level'] = level
|
|
|
|
|
member['subgroup'] = groupName
|
|
|
|
|
member['subgroup'] = nameToPrint
|
|
|
|
|
membersList.append(member)
|
|
|
|
|
_, gname = member['name'].rsplit('/', 1)
|
|
|
|
|
groupMemberList.append(f'groups/{gname}')
|
|
|
|
|
groupMemberList.append((f'groups/{gname}', memberName))
|
|
|
|
|
for member in groupMemberList:
|
|
|
|
|
getCIGroupMembers(ci, member, memberRoles, membersList, membersSet, i, count,
|
|
|
|
|
memberOptions, memberDisplayOptions, level+1, typesSet)
|
|
|
|
|
getCIGroupMembers(ci, member[0], memberRoles, membersList, membersSet, i, count,
|
|
|
|
|
memberOptions, memberDisplayOptions, level+1, typesSet, member[1], kwargs)
|
|
|
|
|
else:
|
|
|
|
|
for member in groupMembers:
|
|
|
|
|
getCIGroupMemberRoleFixType(member)
|
|
|
|
|
memberName = member.get('preferredMemberKey', {}).get('id', '')
|
|
|
|
|
if member['type'] != Ent.TYPE_GROUP:
|
|
|
|
|
if (member['type'] in typesSet and
|
|
|
|
|
checkCIMemberMatch(member, memberOptions) and
|
|
|
|
|
_checkMemberRole(member, validRoles) and
|
|
|
|
|
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
|
|
|
|
member['level'] = level
|
|
|
|
|
member['subgroup'] = groupName
|
|
|
|
|
member['subgroup'] = nameToPrint
|
|
|
|
|
membersList.append(member)
|
|
|
|
|
else:
|
|
|
|
|
if (member['type'] in typesSet and
|
|
|
|
|
checkCIMemberMatch(member, memberOptions) and
|
|
|
|
|
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
|
|
|
|
member['level'] = level
|
|
|
|
|
member['subgroup'] = groupName
|
|
|
|
|
member['subgroup'] = nameToPrint
|
|
|
|
|
membersList.append(member)
|
|
|
|
|
_, gname = member['name'].rsplit('/', 1)
|
|
|
|
|
getCIGroupMembers(ci, f'groups/{gname}', memberRoles, membersList, membersSet, i, count,
|
|
|
|
|
memberOptions, memberDisplayOptions, level+1, typesSet)
|
|
|
|
|
memberOptions, memberDisplayOptions, level+1, typesSet, memberName, kwargs)
|
|
|
|
|
|
|
|
|
|
CIGROUPMEMBERS_FIELDS_CHOICE_MAP = {
|
|
|
|
|
'createtime': 'createTime',
|
|
|
|
|
'delivery': 'deliverySetting',
|
|
|
|
|
'deliverysettings': 'deliverySetting',
|
|
|
|
|
'email': 'preferredMemberKey',
|
|
|
|
|
'expiretime': 'expireTime',
|
|
|
|
|
'id': 'name',
|
|
|
|
|
'memberkey': 'preferredMemberKey',
|
|
|
|
|
@@ -36236,6 +36277,16 @@ CIGROUPMEMBERS_SORT_FIELDS = [
|
|
|
|
|
]
|
|
|
|
|
CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
|
|
|
|
|
|
|
|
|
|
def _getCIListGroupMembersArgs(listView):
|
|
|
|
|
if listView == 'full':
|
|
|
|
|
return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
|
|
|
|
|
'fields': 'nextPageToken,memberships(*)'}
|
|
|
|
|
if listView == 'basic':
|
|
|
|
|
return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
|
|
|
|
|
'fields': 'nextPageToken,memberships(name,preferredMemberKey,roles,type)'}
|
|
|
|
|
return {'view': 'BASIC', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_BASIC],
|
|
|
|
|
'fields': 'nextPageToken,memberships(*)'}
|
|
|
|
|
|
|
|
|
|
# gam print cigroup-members [todrive <ToDriveAttribute>*]
|
|
|
|
|
# [(cimember|ciowner <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
|
|
|
|
|
# [showownedby <UserItem>]
|
|
|
|
|
@@ -36245,6 +36296,7 @@ CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
|
|
|
|
|
# [types <CIGroupMemberTypeList>]
|
|
|
|
|
# [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
|
|
|
|
# <CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
|
|
|
|
|
# [minimal|basic|full]
|
|
|
|
|
# [(recursive [noduplicates])|includederivedmembership] [nogroupeemail]
|
|
|
|
|
# [formatjson [quotechar <Character>]]
|
|
|
|
|
def doPrintCIGroupMembers():
|
|
|
|
|
@@ -36262,6 +36314,7 @@ def doPrintCIGroupMembers():
|
|
|
|
|
rolesSet = set()
|
|
|
|
|
typesSet = set()
|
|
|
|
|
matchPatterns = {}
|
|
|
|
|
listView = 'full'
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
if myarg == 'todrive':
|
|
|
|
|
@@ -36290,7 +36343,7 @@ def doPrintCIGroupMembers():
|
|
|
|
|
pass
|
|
|
|
|
elif getMemberMatchOptions(myarg, memberOptions):
|
|
|
|
|
pass
|
|
|
|
|
elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
|
|
|
|
|
elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='preferredMemberKey'):
|
|
|
|
|
pass
|
|
|
|
|
elif myarg == 'noduplicates':
|
|
|
|
|
memberOptions[MEMBEROPTION_NODUPLICATES] = True
|
|
|
|
|
@@ -36302,8 +36355,12 @@ def doPrintCIGroupMembers():
|
|
|
|
|
memberOptions[MEMBEROPTION_RECURSIVE] = False
|
|
|
|
|
elif myarg == 'nogroupemail':
|
|
|
|
|
groupColumn = False
|
|
|
|
|
elif myarg in {'minimal', 'basic', 'full'}:
|
|
|
|
|
listView = myarg
|
|
|
|
|
else:
|
|
|
|
|
FJQC.GetFormatJSONQuoteChar(myarg, False)
|
|
|
|
|
if listView == 'minimal' and memberOptions[MEMBEROPTION_RECURSIVE]:
|
|
|
|
|
usageErrorExit(Msg.ARE_MUTUALLY_EXCLUSIVE.format('minimal', 'recursive'))
|
|
|
|
|
if not typesSet:
|
|
|
|
|
typesSet = {Ent.TYPE_USER} if memberOptions[MEMBEROPTION_RECURSIVE] else ALL_CIGROUP_MEMBER_TYPES
|
|
|
|
|
fields = ','.join(set(groupFieldsLists['ci']))
|
|
|
|
|
@@ -36330,6 +36387,7 @@ def doPrintCIGroupMembers():
|
|
|
|
|
if showOwnedBy:
|
|
|
|
|
getRolesSet.add(Ent.ROLE_OWNER)
|
|
|
|
|
getRoles = ','.join(sorted(getRolesSet))
|
|
|
|
|
kwargs = _getCIListGroupMembersArgs(listView)
|
|
|
|
|
level = 0
|
|
|
|
|
i = 0
|
|
|
|
|
count = len(entityList)
|
|
|
|
|
@@ -36356,7 +36414,7 @@ def doPrintCIGroupMembers():
|
|
|
|
|
membersList = []
|
|
|
|
|
membersSet = set()
|
|
|
|
|
getCIGroupMembers(ci, groupEntity['name'], getRoles, membersList, membersSet, i, count,
|
|
|
|
|
memberOptions, memberDisplayOptions, level, typesSet)
|
|
|
|
|
memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs)
|
|
|
|
|
if showOwnedBy and not checkCIGroupShowOwnedBy(showOwnedBy, membersList):
|
|
|
|
|
continue
|
|
|
|
|
for member in membersList:
|
|
|
|
|
@@ -36374,6 +36432,8 @@ def doPrintCIGroupMembers():
|
|
|
|
|
row['subgroup'] = member['subgroup']
|
|
|
|
|
if memberDisplayOptions['showCategory']:
|
|
|
|
|
row['category'] = member['category']
|
|
|
|
|
if listView == 'minimal':
|
|
|
|
|
dmember.pop('type', None)
|
|
|
|
|
mapCIGroupMemberFieldNames(dmember)
|
|
|
|
|
if not FJQC.formatJSON:
|
|
|
|
|
csvPF.WriteRowTitles(flattenJSON(dmember, flattened=row, timeObjects=CIGROUPMEMBERS_TIME_OBJECTS))
|
|
|
|
|
@@ -36403,17 +36463,19 @@ def doPrintCIGroupMembers():
|
|
|
|
|
# [showownedby <UserItem>]
|
|
|
|
|
# [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
|
|
|
|
# [descriptionmatchpattern [not] <RegularExpression>]
|
|
|
|
|
# [roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
|
|
|
|
|
# [roles <GroupRoleList>] [members] [managers] [owners]
|
|
|
|
|
# [internal] [internaldomains <DomainList>] [external]
|
|
|
|
|
# [types <CIGroupMemberTypeList>]
|
|
|
|
|
# [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
|
|
|
|
# [includederivedmembership]
|
|
|
|
|
# [minimal|basic|full]
|
|
|
|
|
# [(depth <Number>) | includederivedmembership]
|
|
|
|
|
def doShowCIGroupMembers():
|
|
|
|
|
def _roleOrder(key):
|
|
|
|
|
return {Ent.ROLE_OWNER: 0, Ent.ROLE_MANAGER: 1, Ent.ROLE_MEMBER: 2}.get(key, 3)
|
|
|
|
|
|
|
|
|
|
def _typeOrder(key):
|
|
|
|
|
return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2, Ent.TYPE_EXTERNAL: 3}.get(key, 4)
|
|
|
|
|
return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2,
|
|
|
|
|
Ent.TYPE_CBCM_BROWSER: 3, Ent.TYPE_OTHER: 4, Ent.TYPE_EXTERNAL: 5}.get(key, 6)
|
|
|
|
|
|
|
|
|
|
def _showGroup(groupName, groupEmail, depth):
|
|
|
|
|
if includeDerivedMembership:
|
|
|
|
|
@@ -36424,8 +36486,7 @@ def doShowCIGroupMembers():
|
|
|
|
|
try:
|
|
|
|
|
membersList = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
|
|
|
|
|
throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
|
|
|
|
|
parent=groupName, view='FULL',
|
|
|
|
|
fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
|
|
|
|
|
parent=groupName, **kwargs)
|
|
|
|
|
for member in membersList:
|
|
|
|
|
getCIGroupMemberRoleFixType(member)
|
|
|
|
|
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
|
|
|
|
@@ -36446,7 +36507,10 @@ def doShowCIGroupMembers():
|
|
|
|
|
if (_checkMemberRole(member, rolesSet) and
|
|
|
|
|
member['type'] in typesSet and
|
|
|
|
|
checkCIMemberMatch(member, memberOptions)):
|
|
|
|
|
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
|
|
|
|
|
if listView != 'minimal':
|
|
|
|
|
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
|
|
|
|
|
else:
|
|
|
|
|
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["preferredMemberKey"]["id"]}'
|
|
|
|
|
if checkCategory:
|
|
|
|
|
memberDetails += f', {member["category"]}'
|
|
|
|
|
for field in ['createTime', 'updateTime', 'expireTime']:
|
|
|
|
|
@@ -36471,6 +36535,7 @@ def doShowCIGroupMembers():
|
|
|
|
|
matchPatterns = {}
|
|
|
|
|
maxdepth = -1
|
|
|
|
|
includeDerivedMembership = False
|
|
|
|
|
listView = 'full'
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
if myarg == 'showownedby':
|
|
|
|
|
@@ -36501,6 +36566,8 @@ def doShowCIGroupMembers():
|
|
|
|
|
maxdepth = getInteger(minVal=-1)
|
|
|
|
|
elif myarg == 'includederivedmembership':
|
|
|
|
|
includeDerivedMembership = True
|
|
|
|
|
elif myarg in {'minimal', 'basic', 'full'}:
|
|
|
|
|
listView = myarg
|
|
|
|
|
else:
|
|
|
|
|
unknownArgumentExit()
|
|
|
|
|
if not rolesSet:
|
|
|
|
|
@@ -36510,6 +36577,7 @@ def doShowCIGroupMembers():
|
|
|
|
|
checkCategory = memberDisplayOptions['showCategory']
|
|
|
|
|
fields = ','.join(set(groupFieldsLists['ci']))
|
|
|
|
|
entityList = getCIGroupMembersEntityList(ci, entityList, query, subTitle, matchPatterns, groupFieldsLists['ci'], None)
|
|
|
|
|
kwargs = _getCIListGroupMembersArgs(listView)
|
|
|
|
|
i = 0
|
|
|
|
|
count = len(entityList)
|
|
|
|
|
for group in entityList:
|
|
|
|
|
@@ -42289,7 +42357,7 @@ def doPrintVaultCounts():
|
|
|
|
|
# gam [<UserTypeEntity>] print siteacls <SiteEntity> [todrive <ToDriveAttribute>*]
|
|
|
|
|
# gam [<UserTypeEntity>] print siteactivity <SiteEntity> [todrive <ToDriveAttribute>*]
|
|
|
|
|
# [startindex <Number>] [maxresults <Number>] [updated_min <Date>] [updated_max <Date>]
|
|
|
|
|
def deprecatedUserSites(users):
|
|
|
|
|
def deprecatedUserSites(_):
|
|
|
|
|
deprecatedCommandExit()
|
|
|
|
|
|
|
|
|
|
def deprecatedDomainSites():
|
|
|
|
|
@@ -43611,7 +43679,7 @@ def waitForMailbox(entityList):
|
|
|
|
|
Ind.Decrement()
|
|
|
|
|
|
|
|
|
|
def getUserLicenses(lic, user, skus):
|
|
|
|
|
def _callbackGetLicense(request_id, response, exception):
|
|
|
|
|
def _callbackGetLicense(_, response, exception):
|
|
|
|
|
if exception is None:
|
|
|
|
|
if response and 'skuId' in response:
|
|
|
|
|
licenses.append(response['skuId'])
|
|
|
|
|
@@ -44724,7 +44792,7 @@ def doPrintUsers(entityList=None):
|
|
|
|
|
return
|
|
|
|
|
sortRows = True
|
|
|
|
|
# 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')
|
|
|
|
|
if projectionSet or len(set(fieldsList)) > 1 or showValidColumn:
|
|
|
|
|
jcount = len(entityList)
|
|
|
|
|
@@ -48117,7 +48185,7 @@ def _batchAddItemsToCourse(croom, courseId, i, count, addParticipants, role):
|
|
|
|
|
_ADD_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
|
|
|
|
|
GAPI.ALREADY_EXISTS: Msg.DUPLICATE,
|
|
|
|
|
GAPI.FAILED_PRECONDITION: Msg.NOT_ALLOWED}
|
|
|
|
|
def _callbackAddItemsToCourse(request_id, response, exception):
|
|
|
|
|
def _callbackAddItemsToCourse(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
if exception is None:
|
|
|
|
|
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
|
|
|
@@ -48197,7 +48265,7 @@ def _batchRemoveItemsFromCourse(croom, courseId, i, count, removeParticipants, r
|
|
|
|
|
_REMOVE_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
|
|
|
|
|
GAPI.FORBIDDEN: Msg.FORBIDDEN,
|
|
|
|
|
GAPI.PERMISSION_DENIED: Msg.PERMISSION_DENIED}
|
|
|
|
|
def _callbackRemoveItemsFromCourse(request_id, response, exception):
|
|
|
|
|
def _callbackRemoveItemsFromCourse(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
if exception is None:
|
|
|
|
|
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
|
|
|
@@ -48409,7 +48477,7 @@ def doCourseRemoveItems(courseIdList, getEntityListArg):
|
|
|
|
|
|
|
|
|
|
# gam courses <CourseEntity> clear teachers|students
|
|
|
|
|
# gam course <CourseID> clear teacher|student
|
|
|
|
|
def doCourseClearParticipants(courseIdList, getEntityListArg):
|
|
|
|
|
def doCourseClearParticipants(courseIdList, _):
|
|
|
|
|
croom = buildGAPIObject(API.CLASSROOM)
|
|
|
|
|
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
|
|
|
|
|
checkForExtraneousArguments()
|
|
|
|
|
@@ -48425,7 +48493,7 @@ def doCourseClearParticipants(courseIdList, getEntityListArg):
|
|
|
|
|
# gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity>
|
|
|
|
|
# gam courses <CourseEntity> 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)
|
|
|
|
|
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
|
|
|
|
|
if role == Ent.TEACHER:
|
|
|
|
|
@@ -58161,6 +58229,7 @@ def initCopyMoveOptions(copyCmd):
|
|
|
|
|
'showPermissionMessages': False,
|
|
|
|
|
'sendEmailIfRequired': False,
|
|
|
|
|
'useDomainAdminAccess': False,
|
|
|
|
|
'enforceExpansiveAccess': False,
|
|
|
|
|
'copiedShortcutsPointToCopiedFiles': True,
|
|
|
|
|
'createShortcutsForNonmovableFiles': False,
|
|
|
|
|
'duplicateFiles': DUPLICATE_FILE_OVERWRITE_OLDER,
|
|
|
|
|
@@ -58259,6 +58328,8 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
|
|
|
|
|
elif myarg == 'mappermissionsdomain':
|
|
|
|
|
oldDomain = getString(Cmd.OB_DOMAIN_NAME).lower()
|
|
|
|
|
copyMoveOptions['mapPermissionsDomains'][oldDomain] = getString(Cmd.OB_DOMAIN_NAME).lower()
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
copyMoveOptions['enforceExpansiveAccess'] = getBoolean()
|
|
|
|
|
else:
|
|
|
|
|
# Move arguments
|
|
|
|
|
if not copyMoveOptions['copyCmd']:
|
|
|
|
|
@@ -58530,6 +58601,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|
|
|
|
updateTargetPerms[permissionId].update(updatePerm)
|
|
|
|
|
updateTargetPerms[permissionId]['updates'] = updatePerm
|
|
|
|
|
copySourcePerms.pop(permissionId)
|
|
|
|
|
deleteUpdateKwargs = {'useDomainAdminAccess': copyMoveOptions['useDomainAdminAccess']}
|
|
|
|
|
if entityType != Ent.SHAREDDRIVE:
|
|
|
|
|
deleteUpdateKwargs['enforceExpansiveAccess'] = copyMoveOptions['enforceExpansiveAccess']
|
|
|
|
|
Ind.Increment()
|
|
|
|
|
action = Act.Get()
|
|
|
|
|
Act.Set(Act.COPY)
|
|
|
|
|
@@ -58548,8 +58622,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|
|
|
|
callGAPI(drive.permissions(), 'create',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS,
|
|
|
|
|
# retryReasons=[GAPI.INVALID_SHARING_REQUEST],
|
|
|
|
|
useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'],
|
|
|
|
|
fileId=newFileId, sendNotificationEmail=sendNotificationEmail, emailMessage=None,
|
|
|
|
|
body=permission, fields='', useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
|
|
|
|
body=permission, fields='', supportsAllDrives=True)
|
|
|
|
|
if copyMoveOptions['showPermissionMessages']:
|
|
|
|
|
entityActionPerformed(kvList, k, kcount)
|
|
|
|
|
break
|
|
|
|
|
@@ -58587,7 +58662,8 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|
|
|
|
try:
|
|
|
|
|
callGAPI(drive.permissions(), 'delete',
|
|
|
|
|
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']:
|
|
|
|
|
entityActionPerformed(kvList, k, kcount)
|
|
|
|
|
except (GAPI.notFound, GAPI.permissionNotFound,
|
|
|
|
|
@@ -58612,8 +58688,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|
|
|
|
callGAPI(drive.permissions(), 'update',
|
|
|
|
|
bailOnInternalError=True,
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
|
|
|
|
fileId=newFileId, permissionId=permissionId, removeExpiration=removeExpiration,
|
|
|
|
|
body=permission['updates'], useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
|
|
|
|
removeExpiration=removeExpiration,
|
|
|
|
|
**deleteUpdateKwargs,
|
|
|
|
|
fileId=newFileId, permissionId=permissionId, body=permission['updates'], supportsAllDrives=True)
|
|
|
|
|
if copyMoveOptions['showPermissionMessages']:
|
|
|
|
|
entityActionPerformed(kvList, k, kcount)
|
|
|
|
|
except (GAPI.notFound, GAPI.permissionNotFound,
|
|
|
|
|
@@ -58887,6 +58964,7 @@ copyReturnItemMap = {
|
|
|
|
|
# [sendemailifrequired [<Boolean>]]
|
|
|
|
|
# [suppressnotselectedmessages [<Boolean>]]
|
|
|
|
|
# [verifyorganizer [<Boolean>]]
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
def copyDriveFile(users):
|
|
|
|
|
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
|
|
|
|
|
row = {'User': user, fileNameTitle: oldName, 'id': oldId,
|
|
|
|
|
@@ -59614,7 +59692,9 @@ def _updateMoveFilePermissions(drive, user, i, count,
|
|
|
|
|
try:
|
|
|
|
|
callGAPI(drive.permissions(), 'delete',
|
|
|
|
|
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']:
|
|
|
|
|
entityActionPerformed(kvList, k, kcount)
|
|
|
|
|
except (GAPI.notFound, GAPI.permissionNotFound,
|
|
|
|
|
@@ -59702,6 +59782,7 @@ def _updateMoveFilePermissions(drive, user, i, count,
|
|
|
|
|
# [retainsourcefolders [<Boolean>]]
|
|
|
|
|
# [sendemailifrequired [<Boolean>]]
|
|
|
|
|
# [verifyorganizer [<Boolean>]]
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
def moveDriveFile(users):
|
|
|
|
|
def _cloneFolderMove(drive, user, i, count, j, jcount,
|
|
|
|
|
source, targetChildren, newFolderName, newParentId, newParentName, mergeParentModifiedTime,
|
|
|
|
|
@@ -60045,9 +60126,8 @@ def moveDriveFile(users):
|
|
|
|
|
parentBody = {}
|
|
|
|
|
parentParms = initDriveFileAttributes()
|
|
|
|
|
copyMoveOptions = initCopyMoveOptions(False)
|
|
|
|
|
newParentsSpecified = False
|
|
|
|
|
newParentsSpecified = updateFilePermissions = False
|
|
|
|
|
movedFiles = {}
|
|
|
|
|
updateFilePermissions = False
|
|
|
|
|
verifyOrganizer = True
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
@@ -60936,6 +61016,7 @@ TRANSFER_DRIVEFILE_ACL_ROLES_MAP = {
|
|
|
|
|
# [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none]
|
|
|
|
|
# [nonowner_targetrole reader|commenter|writer|editor|fileorganizer|current|none|source]
|
|
|
|
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
# [preview] [todrive <ToDriveAttribute>*]
|
|
|
|
|
def transferDrive(users):
|
|
|
|
|
|
|
|
|
|
@@ -61122,6 +61203,7 @@ def transferDrive(users):
|
|
|
|
|
callGAPI(sourceDrive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.INVALID_OWNERSHIP_TRANSFER,
|
|
|
|
|
GAPI.PERMISSION_NOT_FOUND, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=childFileId, permissionId=targetPermissionId,
|
|
|
|
|
transferOwnership=True, body={'role': 'owner'}, fields='')
|
|
|
|
|
if removeSourceParents:
|
|
|
|
|
@@ -61310,6 +61392,7 @@ def transferDrive(users):
|
|
|
|
|
if ownerRetainRoleBody['role'] != 'writer':
|
|
|
|
|
callGAPI(targetDrive.permissions(), 'update',
|
|
|
|
|
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='')
|
|
|
|
|
else:
|
|
|
|
|
callGAPI(targetDrive.permissions(), 'delete',
|
|
|
|
|
@@ -61359,6 +61442,7 @@ def transferDrive(users):
|
|
|
|
|
if nonOwnerRetainRoleBody['role'] != 'current':
|
|
|
|
|
callGAPI(ownerDrive.permissions(), 'update',
|
|
|
|
|
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='')
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
@@ -61519,7 +61603,7 @@ def transferDrive(users):
|
|
|
|
|
targetUserFolderPattern = '#user# old files'
|
|
|
|
|
targetUserOrphansFolderPattern = '#user# orphaned files'
|
|
|
|
|
targetIds = [None, None]
|
|
|
|
|
createShortcutsForNonmovableFiles = False
|
|
|
|
|
createShortcutsForNonmovableFiles = enforceExpansiveAccess = False
|
|
|
|
|
mergeWithTarget = False
|
|
|
|
|
thirdPartyOwners = {}
|
|
|
|
|
skipFileIdEntity = initDriveFileEntity()
|
|
|
|
|
@@ -61537,6 +61621,8 @@ def transferDrive(users):
|
|
|
|
|
nonOwnerRetainRoleBody['role'] = 'current'
|
|
|
|
|
elif myarg == 'nonownertargetrole':
|
|
|
|
|
nonOwnerTargetRoleBody['role'] = getChoice(TRANSFER_DRIVEFILE_ACL_ROLES_MAP, mapChoice=True)
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
elif myarg == 'noretentionmessages':
|
|
|
|
|
showRetentionMessages = False
|
|
|
|
|
elif myarg == 'orderby':
|
|
|
|
|
@@ -61774,6 +61860,7 @@ def getPermissionIdForEmail(user, i, count, email):
|
|
|
|
|
# [<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]]
|
|
|
|
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
|
|
|
|
# [preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
# [todrive <ToDriveAttribute>*]
|
|
|
|
|
def transferOwnership(users):
|
|
|
|
|
def _identifyFilesToTransfer(fileEntry):
|
|
|
|
|
@@ -61822,7 +61909,7 @@ def transferOwnership(users):
|
|
|
|
|
body = {}
|
|
|
|
|
newOwner = getEmailAddress()
|
|
|
|
|
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
|
|
|
|
changeParents = filepath = includeTrashed = noRecursion = False
|
|
|
|
|
changeParents = enforceExpansiveAccess = filepath = includeTrashed = noRecursion = False
|
|
|
|
|
pathDelimiter = '/'
|
|
|
|
|
csvPF = fileTree = None
|
|
|
|
|
addParents = ''
|
|
|
|
|
@@ -61849,6 +61936,8 @@ def transferOwnership(users):
|
|
|
|
|
csvPF.GetTodriveParameters()
|
|
|
|
|
elif getDriveFileParentAttribute(myarg, parentParms):
|
|
|
|
|
changeParents = True
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
else:
|
|
|
|
|
unknownArgumentExit()
|
|
|
|
|
Act.Set(Act.TRANSFER_OWNERSHIP)
|
|
|
|
|
@@ -61966,6 +62055,7 @@ def transferOwnership(users):
|
|
|
|
|
Act.Set(action)
|
|
|
|
|
callGAPI(drive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
|
|
|
|
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
|
|
|
|
|
else:
|
|
|
|
|
@@ -61987,6 +62077,7 @@ def transferOwnership(users):
|
|
|
|
|
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
|
|
|
|
|
callGAPI(drive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
|
|
|
|
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
|
|
|
|
|
except GAPI.invalidSharingRequest as e:
|
|
|
|
|
@@ -62059,6 +62150,7 @@ def transferOwnership(users):
|
|
|
|
|
# [keepuser | (retainrole reader|commenter|writer|editor|none)] [noretentionmessages]
|
|
|
|
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
|
|
|
|
# [preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
# [todrive <ToDriveAttribute>*]
|
|
|
|
|
def claimOwnership(users):
|
|
|
|
|
def _identifyFilesToClaim(fileEntry):
|
|
|
|
|
@@ -62119,6 +62211,7 @@ def claimOwnership(users):
|
|
|
|
|
if sourceRetainRoleBody['role'] != 'writer':
|
|
|
|
|
callGAPI(sourceDrive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=ofileId, permissionId=oldOwnerPermissionId, body=sourceRetainRoleBody, fields='')
|
|
|
|
|
else:
|
|
|
|
|
callGAPI(sourceDrive.permissions(), 'delete',
|
|
|
|
|
@@ -62142,7 +62235,7 @@ def claimOwnership(users):
|
|
|
|
|
onlyOwners = set()
|
|
|
|
|
skipOwners = set()
|
|
|
|
|
subdomains = []
|
|
|
|
|
filepath = includeTrashed = False
|
|
|
|
|
enforceExpansiveAccess = filepath = includeTrashed = False
|
|
|
|
|
pathDelimiter = '/'
|
|
|
|
|
addParents = ''
|
|
|
|
|
parentBody = {}
|
|
|
|
|
@@ -62177,6 +62270,8 @@ def claimOwnership(users):
|
|
|
|
|
includeTrashed = True
|
|
|
|
|
elif myarg == 'orderby':
|
|
|
|
|
OBY.GetChoice()
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
elif myarg == 'restricted':
|
|
|
|
|
bodyShare['copyRequiresWriterPermission'] = getBoolean()
|
|
|
|
|
elif myarg == 'writerscanshare':
|
|
|
|
|
@@ -62347,6 +62442,7 @@ def claimOwnership(users):
|
|
|
|
|
Act.Set(action)
|
|
|
|
|
callGAPI(sourceDrive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
|
|
|
|
kvList = [Ent.USER, user, entityType, fileDesc]
|
|
|
|
|
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
|
|
|
|
|
@@ -62371,6 +62467,7 @@ def claimOwnership(users):
|
|
|
|
|
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
|
|
|
|
|
callGAPI(sourceDrive.permissions(), 'update',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
|
|
|
|
enforceExpansiveAccess=enforceExpansiveAccess,
|
|
|
|
|
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
|
|
|
|
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
|
|
|
|
|
_processRetainedRole(user, i, count, oldOwner, entityType, xferFileId, fileDesc, l, lcount)
|
|
|
|
|
@@ -62907,11 +63004,12 @@ def doCreateDriveFileACL():
|
|
|
|
|
|
|
|
|
|
# gam [<UserTypeEntity>] update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
|
|
|
|
|
# (role <DriveFileACLRole>) [expiration <Time>] [removeexpiration [<Boolean>]]
|
|
|
|
|
# [updatesheetprotectedranges [<Boolean>]]
|
|
|
|
|
# [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
# [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
|
|
|
|
|
def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
fileIdEntity = getDriveFileEntity()
|
|
|
|
|
isEmail, permissionId = getPermissionId()
|
|
|
|
|
enforceExpansiveAccess = None
|
|
|
|
|
removeExpiration = showTitles = updateSheetProtectedRanges = False
|
|
|
|
|
showDetails = True
|
|
|
|
|
csvPF = None
|
|
|
|
|
@@ -62930,6 +63028,8 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
showTitles = True
|
|
|
|
|
elif myarg == 'updatesheetprotectedranges':
|
|
|
|
|
updateSheetProtectedRanges = getBoolean()
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
elif myarg == 'nodetails':
|
|
|
|
|
showDetails = False
|
|
|
|
|
elif myarg == 'csv':
|
|
|
|
|
@@ -62947,6 +63047,9 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
|
|
|
|
if 'role' not in body:
|
|
|
|
|
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
|
|
|
|
|
updateKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
|
|
|
|
|
if enforceExpansiveAccess is not None:
|
|
|
|
|
updateKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
|
|
|
|
|
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
|
|
|
|
|
if csvPF and showTitles:
|
|
|
|
|
csvPF.AddTitles(fileNameTitle)
|
|
|
|
|
@@ -62984,7 +63087,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
permission = callGAPI(drive.permissions(), 'update',
|
|
|
|
|
bailOnInternalError=True,
|
|
|
|
|
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,
|
|
|
|
|
transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True)
|
|
|
|
|
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
|
|
|
|
|
@@ -63080,7 +63183,7 @@ def createDriveFilePermissions(users, useDomainAdminAccess=False):
|
|
|
|
|
except ValueError:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def _callbackCreatePermission(request_id, response, exception):
|
|
|
|
|
def _callbackCreatePermission(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
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]))
|
|
|
|
|
@@ -63228,11 +63331,12 @@ def doCreatePermissions():
|
|
|
|
|
createDriveFilePermissions([_getAdminEmail()], True)
|
|
|
|
|
|
|
|
|
|
# gam [<UserTypeEntity>] delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
|
|
|
|
|
# [updatesheetprotectedranges [<Boolean>]]
|
|
|
|
|
# [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
# [showtitles]
|
|
|
|
|
def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
fileIdEntity = getDriveFileEntity()
|
|
|
|
|
isEmail, permissionId = getPermissionId()
|
|
|
|
|
enforceExpansiveAccess = None
|
|
|
|
|
showTitles = updateSheetProtectedRanges = False
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
@@ -63240,11 +63344,16 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
showTitles = getBoolean()
|
|
|
|
|
elif myarg == 'updatesheetprotectedranges':
|
|
|
|
|
updateSheetProtectedRanges = getBoolean()
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
elif myarg in ADMIN_ACCESS_OPTIONS:
|
|
|
|
|
useDomainAdminAccess = True
|
|
|
|
|
else:
|
|
|
|
|
unknownArgumentExit()
|
|
|
|
|
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
|
|
|
|
deleteKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
|
|
|
|
|
if enforceExpansiveAccess is not None:
|
|
|
|
|
deleteKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
|
|
|
|
|
i, count, users = getEntityArgument(users)
|
|
|
|
|
for user in users:
|
|
|
|
|
i += 1
|
|
|
|
|
@@ -63277,7 +63386,8 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
|
|
|
|
break
|
|
|
|
|
callGAPI(drive.permissions(), 'delete',
|
|
|
|
|
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)
|
|
|
|
|
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
|
|
|
|
|
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission)
|
|
|
|
|
@@ -63299,6 +63409,7 @@ def doDeleteDriveFileACLs():
|
|
|
|
|
|
|
|
|
|
# gam [<UserTypeEntity>] delete permissions <DriveFileEntity> <DriveFilePermissionIDEntity> [asadmin]
|
|
|
|
|
# <PermissionMatch>* [<PermissionMatchAction>]
|
|
|
|
|
# [enforceexpansiveaccess [<Boolean>]]
|
|
|
|
|
def deletePermissions(users, useDomainAdminAccess=False):
|
|
|
|
|
def convertJSONPermissions(jsonPermissions):
|
|
|
|
|
permissionIds = []
|
|
|
|
|
@@ -63308,7 +63419,7 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
|
|
|
|
permissionIds.append(permission['id'])
|
|
|
|
|
return permissionIds
|
|
|
|
|
|
|
|
|
|
def _callbackDeletePermissionId(request_id, response, exception):
|
|
|
|
|
def _callbackDeletePermissionId(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
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]))
|
|
|
|
|
@@ -63333,7 +63444,8 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
|
|
|
|
callGAPI(drive.permissions(), 'delete',
|
|
|
|
|
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS,
|
|
|
|
|
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]))
|
|
|
|
|
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
|
|
|
|
|
GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission,
|
|
|
|
|
@@ -63353,12 +63465,15 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
|
|
|
|
jsonData = getJSON([])
|
|
|
|
|
PM = PermissionMatch()
|
|
|
|
|
PM.SetDefaultMatch(False, {'role': 'owner'})
|
|
|
|
|
enforceExpansiveAccess = False
|
|
|
|
|
while Cmd.ArgumentsRemaining():
|
|
|
|
|
myarg = getArgument()
|
|
|
|
|
if myarg in ADMIN_ACCESS_OPTIONS:
|
|
|
|
|
useDomainAdminAccess = True
|
|
|
|
|
elif PM and PM.ProcessArgument(myarg):
|
|
|
|
|
pass
|
|
|
|
|
elif myarg == 'enforceexpansiveaccess':
|
|
|
|
|
enforceExpansiveAccess = getBoolean()
|
|
|
|
|
else:
|
|
|
|
|
unknownArgumentExit()
|
|
|
|
|
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
|
|
|
|
@@ -68589,7 +68704,7 @@ def deleteLabels(users, labelEntity):
|
|
|
|
|
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]))
|
|
|
|
|
|
|
|
|
|
def _callbackDeleteLabel(request_id, response, exception):
|
|
|
|
|
def _callbackDeleteLabel(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
if exception is None:
|
|
|
|
|
entityActionPerformed([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
|
|
|
@@ -69190,7 +69305,7 @@ def _processMessagesThreads(users, entityType):
|
|
|
|
|
GAPI.INVALID_MESSAGE_ID: Msg.INVALID_MESSAGE_ID,
|
|
|
|
|
GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION}
|
|
|
|
|
|
|
|
|
|
def _callbackProcessMessage(request_id, response, exception):
|
|
|
|
|
def _callbackProcessMessage(request_id, _, exception):
|
|
|
|
|
ri = request_id.splitlines()
|
|
|
|
|
if exception is None:
|
|
|
|
|
if not csvPF:
|
|
|
|
|
|