Added use_classroom_owner_access Boolean variable to gam.cfg

This commit is contained in:
Ross Scroggs
2024-02-18 20:59:58 -08:00
parent d949ca2cad
commit d5255615fd
10 changed files with 363 additions and 211 deletions

View File

@@ -3395,7 +3395,7 @@ def SetGlobalVariables():
def _getCfgHeaderFilter(sectionName, itemName):
value = GM.Globals[GM.PARSER].get(sectionName, itemName)
headerFilters = []
if not value:
if not value or (len(value) == 2 and _stringInQuotes(value)):
return headerFilters
splitStatus, filters = shlexSplitListStatus(value)
if splitStatus:
@@ -3411,7 +3411,7 @@ def SetGlobalVariables():
def _getCfgHeaderForce(sectionName, itemName):
value = GM.Globals[GM.PARSER].get(sectionName, itemName)
headerForce = []
if not value:
if not value or (len(value) == 2 and _stringInQuotes(value)):
return headerForce
splitStatus, headerForce = shlexSplitListStatus(value)
if not splitStatus:
@@ -6338,15 +6338,15 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
elif entityType in {Cmd.ENTITY_COURSEPARTICIPANTS, Cmd.ENTITY_TEACHERS, Cmd.ENTITY_STUDENTS}:
croom = buildGAPIObject(API.CLASSROOM)
if not noListConversion:
courses = convertEntityToList(entity)
courseIdList = convertEntityToList(entity)
else:
courses = [entity]
for course in courses:
courseId = addCourseIdScope(course)
courseIdList = [entity]
_, _, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, GC.Values[GC.USE_COURSE_OWNER_ACCESS])
for courseId, courseInfo in coursesInfo.items():
try:
if entityType in {Cmd.ENTITY_COURSEPARTICIPANTS, Cmd.ENTITY_TEACHERS}:
printGettingAllEntityItemsForWhom(Ent.TEACHER, removeCourseIdScope(courseId), entityType=Ent.COURSE)
result = callGAPIpages(croom.courses().teachers(), 'list', 'teachers',
result = callGAPIpages(courseInfo['croom'].courses().teachers(), 'list', 'teachers',
pageMessage=getPageMessageForWhom(),
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.BAD_REQUEST, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -6359,7 +6359,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
entityList.append(email)
if entityType in {Cmd.ENTITY_COURSEPARTICIPANTS, Cmd.ENTITY_STUDENTS}:
printGettingAllEntityItemsForWhom(Ent.STUDENT, removeCourseIdScope(courseId), entityType=Ent.COURSE)
result = callGAPIpages(croom.courses().students(), 'list', 'students',
result = callGAPIpages(courseInfo['croom'].courses().students(), 'list', 'students',
pageMessage=getPageMessageForWhom(),
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.BAD_REQUEST, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -17979,7 +17979,7 @@ def doPrintAliases():
except (GAPI.invalidOrgunit, GAPI.invalidInput):
entityActionFailedWarning([Ent.ALIAS, None], invalidQuery(query))
continue
except GAPI.domainNotFound as e :
except GAPI.domainNotFound as e:
entityActionFailedWarning([Ent.ALIAS, None, Ent.DOMAIN, kwargs['domain']], str(e))
continue
except (GAPI.resourceNotFound, GAPI.forbidden, GAPI.badRequest):
@@ -18008,13 +18008,16 @@ def doPrintAliases():
try:
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
pageMessage=getPageMessage(showFirstLastItems=True), messageAttribute='email',
throwReasons=GAPI.GROUP_LIST_THROW_REASONS,
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
query=query, orderBy='email',
fields=f'nextPageToken,groups({",".join(groupFields)})', **kwargs)
for group in entityList:
writeAliases(group, group['email'], 'Group')
except GAPI.domainNotFound as e :
except (GAPI.invalidMember, GAPI.invalidInput) as e:
if not invalidMember(query):
entityActionFailedExit([Ent.GROUP, None], str(e))
except GAPI.domainNotFound as e:
entityActionFailedWarning([Ent.ALIAS, None, Ent.DOMAIN, kwargs['domain']], str(e))
continue
except (GAPI.resourceNotFound, GAPI.forbidden, GAPI.badRequest):
@@ -41517,7 +41520,7 @@ def doCreateUser():
throwReasons=[GAPI.DUPLICATE, GAPI.DOMAIN_NOT_FOUND,
GAPI.DOMAIN_CANNOT_USE_APIS, GAPI.FORBIDDEN,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE],
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.CONDITION_NOT_MET],
body=body,
fields=fields,
resolveConflictAccount=resolveConflictAccount)
@@ -41536,7 +41539,7 @@ def doCreateUser():
except GAPI.invalidOrgunit:
entityActionFailedExit([Ent.USER, user], Msg.INVALID_ORGUNIT)
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
GAPI.invalid, GAPI.invalidInput, GAPI.invalidParameter) as e:
GAPI.invalid, GAPI.invalidInput, GAPI.invalidParameter, GAPI.conditionNotMet) as e:
entityActionFailedExit([Ent.USER, user], str(e))
if PwdOpts.filename and PwdOpts.password:
writeFile(PwdOpts.filename, f'{user},{PwdOpts.password}\n', mode='a', continueOnError=True)
@@ -41698,7 +41701,7 @@ def updateUsers(entityList):
result = callGAPI(cd.users(), 'insert',
throwReasons=[GAPI.DUPLICATE, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE],
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.CONDITION_NOT_MET],
body=body,
fields=fields,
resolveConflictAccount=resolveConflictAccount)
@@ -41730,7 +41733,7 @@ def updateUsers(entityList):
entityActionFailedWarning([Ent.USER, user], Msg.INVALID_ORGUNIT, i, count)
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden, GAPI.badRequest,
GAPI.invalid, GAPI.invalidInput, GAPI.invalidParameter, GAPI.insufficientArchivedUserLicenses,
GAPI.conflict, GAPI.badRequest, GAPI.backendError, GAPI.systemError) as e:
GAPI.conflict, GAPI.badRequest, GAPI.backendError, GAPI.systemError, GAPI.conditionNotMet) as e:
entityActionFailedWarning([Ent.USER, user], str(e), i, count)
# gam update users <UserTypeEntity> ...
@@ -44212,6 +44215,8 @@ class CourseAttributes():
def __init__(self, croom, updateMode):
self.croom = croom
self.ocroom = croom
self.tcroom = None
self.updateMode = updateMode
self.body = {}
self.courseId = None
@@ -44371,15 +44376,20 @@ class CourseAttributes():
missingArgumentExit('copyfrom <CourseID>')
else:
return True
# ocroom - copyfrom course owner
if self.announcementStates or self.materialStates or self.workStates or self.copyTopics or self.members != 'none':
_, self.ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{self.ownerId}')
if self.ocroom is None:
return False
if self.members != 'none':
_, self.teachers, self.students = _getCourseAliasesMembers(self.croom, self.croom, self.courseId, {'members': self.members},
_, self.teachers, self.students = _getCourseAliasesMembers(self.croom, self.ocroom, self.courseId, {'members': self.members},
'nextPageToken,teachers(profile(emailAddress,id))',
'nextPageToken,students(profile(emailAddress))')
if self.announcementStates:
printGettingAllEntityItemsForWhom(Ent.COURSE_ANNOUNCEMENT_ID, Ent.TypeName(Ent.COURSE, self.courseId), 0, 0,
_gettingCourseEntityQuery(Ent.COURSE_ANNOUNCEMENT_STATE, self.announcementStates))
try:
self.courseAnnouncements = callGAPIpages(self.croom.courses().announcements(), 'list', 'announcements',
self.courseAnnouncements = callGAPIpages(self.ocroom.courses().announcements(), 'list', 'announcements',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.COURSE_ACCESS_THROW_REASONS+[GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44396,7 +44406,7 @@ class CourseAttributes():
printGettingAllEntityItemsForWhom(Ent.COURSE_MATERIAL_ID, Ent.TypeName(Ent.COURSE, self.courseId), 0, 0,
_gettingCourseEntityQuery(Ent.COURSE_MATERIAL_STATE, self.materialStates))
try:
self.courseMaterials = callGAPIpages(self.croom.courses().courseWorkMaterials(), 'list', 'courseWorkMaterial',
self.courseMaterials = callGAPIpages(self.ocroom.courses().courseWorkMaterials(), 'list', 'courseWorkMaterial',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.COURSE_ACCESS_THROW_REASONS+[GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44417,7 +44427,7 @@ class CourseAttributes():
printGettingAllEntityItemsForWhom(Ent.COURSE_WORK_ID, Ent.TypeName(Ent.COURSE, self.courseId), 0, 0,
_gettingCourseEntityQuery(Ent.COURSE_WORK_STATE, self.workStates))
try:
self.courseWorks = callGAPIpages(self.croom.courses().courseWork(), 'list', 'courseWork',
self.courseWorks = callGAPIpages(self.ocroom.courses().courseWork(), 'list', 'courseWork',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.COURSE_ACCESS_THROW_REASONS+[GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44441,7 +44451,7 @@ class CourseAttributes():
if self.copyTopics:
printGettingAllEntityItemsForWhom(Ent.COURSE_TOPIC, Ent.TypeName(Ent.COURSE, self.courseId), 0, 0)
try:
courseTopics = callGAPIpages(self.croom.courses().topics(), 'list', 'topic',
courseTopics = callGAPIpages(self.ocroom.courses().topics(), 'list', 'topic',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.COURSE_ACCESS_THROW_REASONS+[GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44517,14 +44527,16 @@ class CourseAttributes():
newCourseId = newCourse['id']
ownerId = newCourse['ownerId']
teacherFolderId = newCourse['teacherFolder']['id']
# tcroom - new/update course owner
if self.announcementStates or self.materialStates or self.workStates or self.copyTopics:
_, tcroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{ownerId}')
if tcroom is None:
_, self.tcroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{ownerId}')
if self.tcroom is None:
return
if (self.announcementStates or self.materialStates or self.workStates) and self.copyMaterialsFiles:
_, tdrive = buildGAPIServiceObject(API.DRIVE3, f'uid:{ownerId}')
if tdrive is None:
return
# Adds are done with domain admin
if self.members in {'all', 'students'}:
addParticipants = [student['profile']['emailAddress'] for student in self.students if 'emailAddress' in student['profile']]
_batchAddItemsToCourse(self.croom, newCourseId, i, count, addParticipants, Ent.STUDENT)
@@ -44533,7 +44545,7 @@ class CourseAttributes():
_batchAddItemsToCourse(self.croom, newCourseId, i, count, addParticipants, Ent.TEACHER)
if self.copyTopics:
try:
newCourseTopics = callGAPIpages(self.croom.courses().topics(), 'list', 'topic',
newCourseTopics = callGAPIpages(self.tcroom.courses().topics(), 'list', 'topic',
throwReasons=GAPI.COURSE_ACCESS_THROW_REASONS+[GAPI.FAILED_PRECONDITION, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
courseId=newCourseId, fields='nextPageToken,topic(topicId,name)',
@@ -44556,7 +44568,7 @@ class CourseAttributes():
[Ent.COURSE, self.courseId], Msg.DUPLICATE, j, jcount)
continue
try:
result = callGAPI(tcroom.courses().topics(), 'create',
result = callGAPI(self.tcroom.courses().topics(), 'create',
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.FAILED_PRECONDITION, GAPI.INVALID_ARGUMENT, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
courseId=newCourseId, body={'name': topicName}, fields='topicId')
@@ -44583,7 +44595,7 @@ class CourseAttributes():
if self.copyMaterialsFiles:
self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_ANNOUNCEMENT_ID, courseAnnouncementId, teacherFolderId)
try:
result = callGAPI(tcroom.courses().announcements(), 'create',
result = callGAPI(self.tcroom.courses().announcements(), 'create',
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED, GAPI.FORBIDDEN,
GAPI.BAD_REQUEST, GAPI.FAILED_PRECONDITION, GAPI.BACKEND_ERROR, GAPI.INTERNAL_ERROR, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44619,7 +44631,7 @@ class CourseAttributes():
if newTopicId:
body['topicId'] = newTopicId
try:
result = callGAPI(tcroom.courses().courseWorkMaterials(), 'create',
result = callGAPI(self.tcroom.courses().courseWorkMaterials(), 'create',
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED, GAPI.FORBIDDEN,
GAPI.BAD_REQUEST, GAPI.FAILED_PRECONDITION, GAPI.BACKEND_ERROR, GAPI.INTERNAL_ERROR, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -44658,7 +44670,7 @@ class CourseAttributes():
body.pop('dueDate', None)
body.pop('dueTime', None)
try:
result = callGAPI(tcroom.courses().courseWork(), 'create',
result = callGAPI(self.tcroom.courses().courseWork(), 'create',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED, GAPI.FORBIDDEN,
GAPI.BAD_REQUEST, GAPI.FAILED_PRECONDITION, GAPI.BACKEND_ERROR,
@@ -45003,6 +45015,30 @@ def _convertCourseUserIdToEmail(croom, userId, emails, entityValueList, i, count
emails[userId] = userEmail
return userEmail
def _getCoursesOwnerInfo(croom, courseIds, useOwnerAccess):
coursesInfo = {}
for courseId in courseIds:
courseId = addCourseIdScope(courseId)
if courseId not in coursesInfo:
try:
course = callGAPI(croom.courses(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
id=courseId, fields='name,ownerId')
if useOwnerAccess:
_, ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{course["ownerId"]}')
else:
ocroom = croom
if ocroom is not None:
coursesInfo[courseId] = {'name': course['name'], 'croom': ocroom}
except GAPI.notFound:
entityDoesNotExistWarning(Ent.COURSE, courseId)
except (GAPI.permissionDenied, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
except GAPI.forbidden:
ClientAPIAccessDeniedExit()
return 0, len(coursesInfo), coursesInfo
def _getCourseAliasesMembers(croom, ocroom, courseId, courseShowProperties, teachersFields, studentsFields, showGettings=False, i=0, count=0):
aliases = []
teachers = []
@@ -45059,7 +45095,7 @@ def _doInfoCourses(courseIdList):
courseShowProperties = _initCourseShowProperties()
courseShowProperties['ownerEmail'] = True
ownerEmails = {}
useOwnerAccess = False
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
FJQC = FormatJSONQuoteChar()
while Cmd.ArgumentsRemaining():
myarg = getArgument()
@@ -45069,8 +45105,6 @@ def _doInfoCourses(courseIdList):
useOwnerAccess = True
else:
FJQC.GetFormatJSON(myarg)
coursesInfo = {}
_getCoursesOwnerInfo(croom, courseIdList, coursesInfo, not useOwnerAccess)
fields = _setCourseFields(courseShowProperties, False)
if courseShowProperties['members'] != 'none':
if courseShowProperties['countsOnly']:
@@ -45081,14 +45115,9 @@ def _doInfoCourses(courseIdList):
studentsFields = 'nextPageToken,students(profile)'
else:
teachersFields = studentsFields = None
i = 0
count = len(courseIdList)
for courseId in courseIdList:
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, useOwnerAccess)
for courseId, courseInfo in coursesInfo.items():
i += 1
courseId = addCourseIdScope(courseId)
courseInfo = coursesInfo[courseId]
if not courseInfo:
continue
try:
course = callGAPI(croom.courses(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED, GAPI.SERVICE_NOT_AVAILABLE],
@@ -45159,12 +45188,14 @@ def _doInfoCourses(courseIdList):
except GAPI.forbidden:
ClientAPIAccessDeniedExit()
# gam info courses <CourseEntity> [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# gam info courses <CourseEntity> [owneraccess]
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
def doInfoCourses():
_doInfoCourses(getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True))
# gam info course <CourseID> [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# gam info course <CourseID> [owneraccess]
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
def doInfoCourse():
_doInfoCourses(getStringReturnInList(Cmd.OB_COURSE_ID))
@@ -45322,6 +45353,7 @@ def doPrintCourses():
ownerEmails = {}
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
showItemCountOnly = False
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'todrive':
@@ -45342,7 +45374,7 @@ def doPrintCourses():
if applyCourseItemFilter:
if courseShowProperties['fields']:
courseShowProperties['fields'].append(courseItemFilter['timefilter'])
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, useOwnerAccess)
if coursesInfo is None:
if showItemCountOnly:
writeStdout('0\n')
@@ -45381,6 +45413,12 @@ def doPrintCourses():
for field in courseShowProperties['skips']:
course.pop(field, None)
courseId = course['id']
if useOwnerAccess:
_, ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{course["ownerId"]}')
if not ocroom:
continue
else:
ocroom = croom
if courseShowProperties['ownerEmail']:
course['ownerEmail'] = _convertCourseUserIdToEmail(croom, course['ownerId'], ownerEmails,
[Ent.COURSE, courseId, Ent.OWNER_ID, course['ownerId']], i, count)
@@ -45389,7 +45427,7 @@ def doPrintCourses():
if showItemCountOnly:
itemCount += 1
continue
aliases, teachers, students = _getCourseAliasesMembers(croom, croom, courseId, courseShowProperties, teachersFields, studentsFields, True, i, count)
aliases, teachers, students = _getCourseAliasesMembers(croom, ocroom, courseId, courseShowProperties, teachersFields, studentsFields, True, i, count)
if courseShowProperties['aliases']:
if not courseShowProperties['aliasesInColumns']:
course['Aliases'] = delimiter.join([removeCourseAliasScope(alias['alias']) for alias in aliases])
@@ -45614,7 +45652,6 @@ def doPrintCourseTopics():
courseId = course['id']
if courseTopicIdsLists:
courseTopicIds = courseTopicIdsLists[courseId]
if not courseTopicIds:
fields = getItemFieldsFromFieldsList('topic', fieldsList)
printGettingAllEntityItemsForWhom(Ent.COURSE_TOPIC, Ent.TypeName(Ent.COURSE, courseId), i, count)
@@ -46098,6 +46135,7 @@ def doPrintCourseParticipants():
courseShowProperties = _initCourseShowProperties(['name'])
courseShowProperties['members'] = 'all'
showItemCountOnly = False
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'todrive':
@@ -46110,7 +46148,7 @@ def doPrintCourseParticipants():
showItemCountOnly = True
else:
FJQC.GetFormatJSONQuoteChar(myarg, False)
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, useOwnerAccess)
if coursesInfo is None:
if showItemCountOnly:
writeStdout('0\n')
@@ -46132,7 +46170,13 @@ def doPrintCourseParticipants():
for course in coursesInfo:
i += 1
courseId = course['id']
_, teachers, students = _getCourseAliasesMembers(croom, croom, courseId, courseShowProperties, teachersFields, studentsFields, True, i, count)
if useOwnerAccess:
_, ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{course["ownerId"]}')
if not ocroom:
continue
else:
ocroom = croom
_, teachers, students = _getCourseAliasesMembers(croom, ocroom, courseId, courseShowProperties, teachersFields, studentsFields, True, i, count)
if showItemCountOnly:
if courseShowProperties['members'] != 'students':
itemCount += len(teachers)
@@ -46319,29 +46363,6 @@ def _batchRemoveItemsFromCourse(croom, courseId, i, count, removeParticipants, r
dbatch.execute()
Ind.Decrement()
def _getCoursesOwnerInfo(croom, courseIds, coursesInfo, useAdminAccess):
for courseId in courseIds:
courseId = addCourseIdScope(courseId)
if courseId not in coursesInfo:
coursesInfo[courseId] = {}
try:
info = callGAPI(croom.courses(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.SERVICE_NOT_AVAILABLE],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
id=courseId, fields='name,ownerId')
if not useAdminAccess:
_, ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{info["ownerId"]}')
else:
ocroom = croom
if ocroom is not None:
coursesInfo[courseId] = {'name': info['name'], 'croom': ocroom}
except GAPI.notFound:
entityDoesNotExistWarning(Ent.COURSE, courseId)
except (GAPI.permissionDenied, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
except GAPI.forbidden:
ClientAPIAccessDeniedExit()
def _updateCourseOwner(croom, courseId, owner, i, count):
action = Act.Get()
Act.Set(Act.UPDATE_OWNER)
@@ -46398,7 +46419,6 @@ def doCourseAddItems(courseIdList, getEntityListArg):
makeFirstTeacherOwner = checkArgumentPresent(['makefirstteacherowner'])
else:
makeFirstTeacherOwner = False
coursesInfo = {}
if not getEntityListArg:
if role in {Ent.STUDENT, Ent.TEACHER}:
addItems = getStringReturnInList(Cmd.OB_EMAIL_ADDRESS)
@@ -46422,22 +46442,17 @@ def doCourseAddItems(courseIdList, getEntityListArg):
if makeFirstTeacherOwner and addItems:
firstTeacher = normalizeEmailAddressOrUID(addItems[0])
checkForExtraneousArguments()
_getCoursesOwnerInfo(croom, courseIdList, coursesInfo, role != Ent.COURSE_TOPIC)
i = 0
count = len(courseIdList)
for courseId in courseIdList:
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, role == Ent.COURSE_TOPIC)
for courseId, courseInfo in coursesInfo.items():
i += 1
if courseParticipantLists:
addItems = courseParticipantLists[courseId]
firstTeacher = None
if makeFirstTeacherOwner and addItems:
firstTeacher = normalizeEmailAddressOrUID(addItems[0])
courseId = addCourseIdScope(courseId)
courseInfo = coursesInfo[courseId]
if courseInfo:
_batchAddItemsToCourse(courseInfo['croom'], courseId, i, count, addItems, role)
if makeFirstTeacherOwner and firstTeacher:
_updateCourseOwner(courseInfo['croom'], courseId, firstTeacher, i, count)
_batchAddItemsToCourse(courseInfo['croom'], courseId, i, count, addItems, role)
if makeFirstTeacherOwner and firstTeacher:
_updateCourseOwner(courseInfo['croom'], courseId, firstTeacher, i, count)
# gam courses <CourseEntity> remove alias <CourseAliasEntity>
# gam course <CourseID> remove alias <CourseAlias>
@@ -46448,10 +46463,11 @@ def doCourseAddItems(courseIdList, getEntityListArg):
def doCourseRemoveItems(courseIdList, getEntityListArg):
croom = buildGAPIObject(API.CLASSROOM)
role = getChoice(ADD_REMOVE_PARTICIPANT_TYPES_MAP, mapChoice=True)
coursesInfo = {}
if not getEntityListArg:
if role in {Ent.STUDENT, Ent.TEACHER}:
useOwnerAccess = checkArgumentPresent(OWNER_ACCESS_OPTIONS)
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
if checkArgumentPresent(OWNER_ACCESS_OPTIONS):
useOwnerAccess = True
removeItems = getStringReturnInList(Cmd.OB_EMAIL_ADDRESS)
elif role == Ent.COURSE_ALIAS:
useOwnerAccess = False
@@ -46473,17 +46489,12 @@ def doCourseRemoveItems(courseIdList, getEntityListArg):
removeItems = getEntityList(Cmd.OB_COURSE_TOPIC_ID_ENTITY, shlexSplit=True)
courseParticipantLists = removeItems if isinstance(removeItems, dict) else None
checkForExtraneousArguments()
_getCoursesOwnerInfo(croom, courseIdList, coursesInfo, not useOwnerAccess)
i = 0
count = len(courseIdList)
for courseId in courseIdList:
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, useOwnerAccess)
for courseId, courseInfo in coursesInfo.items():
i += 1
if courseParticipantLists:
removeItems = courseParticipantLists[courseId]
courseId = addCourseIdScope(courseId)
courseInfo = coursesInfo[courseId]
if courseInfo:
_batchRemoveItemsFromCourse(courseInfo['croom'], courseId, i, count, removeItems, role)
_batchRemoveItemsFromCourse(courseInfo['croom'], courseId, i, count, removeItems, role)
# gam courses <CourseEntity> clear teachers|students
# gam course <CourseID> clear teacher|student
@@ -46491,14 +46502,13 @@ def doCourseClearParticipants(courseIdList, getEntityListArg):
croom = buildGAPIObject(API.CLASSROOM)
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
checkForExtraneousArguments()
i = 0
count = len(courseIdList)
for courseId in courseIdList:
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, GC.Values[GC.USE_COURSE_OWNER_ACCESS])
for courseId, courseInfo in coursesInfo.items():
i += 1
removeParticipants = getItemsToModify(PARTICIPANT_EN_MAP[role], courseId, noListConversion=True)
if GM.Globals[GM.CLASSROOM_SERVICE_NOT_AVAILABLE]:
continue
_batchRemoveItemsFromCourse(croom, courseId, i, count, removeParticipants, role)
_batchRemoveItemsFromCourse(courseInfo['croom'], courseId, i, count, removeParticipants, role)
# gam courses <CourseEntity> sync students [addonly|removeonly] <UserTypeEntity>
# gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity>
@@ -46525,9 +46535,8 @@ def doCourseSyncParticipants(courseIdList, getEntityListArg):
syncParticipantsSet.add(normalizeEmailAddressOrUID(user))
if makeFirstTeacherOwner:
firstTeacher = normalizeEmailAddressOrUID(syncParticipants[0])
i = 0
count = len(courseIdList)
for courseId in courseIdList:
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, GC.Values[GC.USE_COURSE_OWNER_ACCESS])
for courseId, courseInfo in coursesInfo.items():
i += 1
if courseParticipantLists:
syncParticipantsSet = set()
@@ -46537,21 +46546,18 @@ def doCourseSyncParticipants(courseIdList, getEntityListArg):
syncParticipantsSet.add(normalizeEmailAddressOrUID(user))
if makeFirstTeacherOwner:
firstTeacher = normalizeEmailAddressOrUID(courseParticipantLists[courseId][0])
courseInfo = checkCourseExists(croom, courseId, i, count)
if courseInfo:
courseId = courseInfo['id']
currentParticipantsSet = set()
currentParticipants = getItemsToModify(PARTICIPANT_EN_MAP[role], courseId, noListConversion=True)
if GM.Globals[GM.CLASSROOM_SERVICE_NOT_AVAILABLE]:
continue
for user in currentParticipants:
currentParticipantsSet.add(normalizeEmailAddressOrUID(user))
if syncOperation != 'removeonly':
_batchAddItemsToCourse(croom, courseId, i, count, list(syncParticipantsSet-currentParticipantsSet), role)
if makeFirstTeacherOwner and firstTeacher:
_updateCourseOwner(croom, courseId, firstTeacher, i, count)
if syncOperation != 'addonly':
_batchRemoveItemsFromCourse(croom, courseId, i, count, list(currentParticipantsSet-syncParticipantsSet), role)
currentParticipantsSet = set()
currentParticipants = getItemsToModify(PARTICIPANT_EN_MAP[role], courseId, noListConversion=True)
if GM.Globals[GM.CLASSROOM_SERVICE_NOT_AVAILABLE]:
continue
for user in currentParticipants:
currentParticipantsSet.add(normalizeEmailAddressOrUID(user))
if syncOperation != 'removeonly':
_batchAddItemsToCourse(croom, courseId, i, count, list(syncParticipantsSet-currentParticipantsSet), role)
if makeFirstTeacherOwner and firstTeacher:
_updateCourseOwner(croom, courseId, firstTeacher, i, count)
if syncOperation != 'addonly':
_batchRemoveItemsFromCourse(courseInfo['croom'], courseId, i, count, list(currentParticipantsSet-syncParticipantsSet), role)
def studentUnknownWarning(studentId, errMsg, i, count):
setSysExitRC(SERVICE_NOT_APPLICABLE_RC)
@@ -47208,9 +47214,8 @@ def createClassroomInvitations(users):
croom = buildGAPIObject(API.CLASSROOM)
classroomEmails = {}
courseIds = None
coursesInfo = {}
role = CLASSROOM_ROLE_STUDENT
useAdminAccess = False
useOwnerAccess = True
csvPF = None
FJQC = FormatJSONQuoteChar(csvPF)
while Cmd.ArgumentsRemaining():
@@ -47225,20 +47230,20 @@ def createClassroomInvitations(users):
elif csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg in ADMIN_ACCESS_OPTIONS:
useAdminAccess = True
useOwnerAccess = False
else:
FJQC.GetFormatJSONQuoteChar(myarg, False)
if courseIds is None:
missingArgumentExit('courses <CourseEntity>')
if csvPF:
if FJQC.formatJSON:
csvPF.SetTitles(['userEmail', 'JSON'])
csvPF.SetJSONTitles(['userEmail', 'JSON'])
else:
csvPF.SetTitles(['userId', 'userEmail', 'courseId', 'courseName', 'id', 'role'])
csvPF.SetSortAllTitles()
csvPF.SetTitles(['userEmail', 'courseId', 'courseName', 'id', 'role'])
csvPF.SetSortAllTitles()
courseIdsLists = courseIds if isinstance(courseIds, dict) else None
if courseIdsLists is None:
_getCoursesOwnerInfo(croom, courseIds, coursesInfo, useAdminAccess)
j, jcount, coursesInfo = _getCoursesOwnerInfo(croom, courseIds, useOwnerAccess)
entityType = CLASSROOM_ROLE_ENTITY_MAP[role]
i, count, users = getEntityArgument(users)
for user in users:
@@ -47246,25 +47251,20 @@ def createClassroomInvitations(users):
userId = normalizeEmailAddressOrUID(user)
userEmail = _getClassroomEmail(croom, classroomEmails, userId, userId)
if courseIdsLists:
courseIds = courseIdsLists[user]
_getCoursesOwnerInfo(croom, courseIds, coursesInfo, useAdminAccess)
jcount = len(courseIds)
j, jcount, coursesInfo = _getCoursesOwnerInfo(croom, courseIdsLists[user], useOwnerAccess)
if csvPF or not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, userId], jcount, entityType, i, count)
if jcount == 0:
continue
j = 0
for courseId in courseIds:
for courseId, courseInfo in coursesInfo.items():
j += 1
courseId = addCourseIdScope(courseId)
courseInfo = coursesInfo[courseId]
if not courseInfo:
continue
courseNameId = f'{courseInfo["name"]} ({courseId})'
try:
invitation = callGAPI(courseInfo['croom'].invitations(), 'create',
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.ALREADY_EXISTS, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
body={'userId': userId, 'courseId': courseId, 'role': role})
invitation['courseName'] = courseInfo['name']
invitation['userEmail'] = userEmail
if not csvPF:
if not FJQC.formatJSON:
Ind.Increment()
@@ -47274,14 +47274,12 @@ def createClassroomInvitations(users):
printLine(json.dumps(cleanJSON(invitation), ensure_ascii=False, sort_keys=True))
else:
if not FJQC.formatJSON:
invitation['courseName'] = courseInfo['name']
invitation['userEmail'] = userEmail
csvPF.WriteRow(invitation)
else:
csvPF.WriteRowNoFilter({'userEmail': userEmail,
'JSON': json.dumps(cleanJSON(invitation), ensure_ascii=False, sort_keys=True)})
except GAPI.permissionDenied:
entityUnknownWarning(Ent.USER, userId, i, count)
except GAPI.permissionDenied as e:
entityActionFailedWarning([Ent.USER, userId, Ent.COURSE, courseNameId, entityType, None], str(e), j, jcount)
break
except GAPI.notFound:
entityUnknownWarning(Ent.COURSE, courseNameId, j, jcount)
@@ -47422,6 +47420,49 @@ def printShowClassroomInvitations(users):
if csvPF:
csvPF.writeCSVfile('ClassroomInvitations')
# gam delete classroominvitation courses <CourseEntity> (ids <ClassroomInvitationIDEntity>)|(role all|owner|student|teacher)
def doDeleteClassroomInvitations():
croom = buildGAPIObject(API.CLASSROOM)
courseIdList = invitationIds = None
role = CLASSROOM_ROLE_ALL
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg in {'course', 'courses', 'class', 'classes'}:
courseIdList = getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True)
elif myarg in {'id', 'ids'}:
invitationIds = getEntityList(Cmd.OB_CLASSROOM_INVITATION_ID_ENTITY)
elif myarg == 'role':
role = getChoice(CLASSROOM_ROLE_MAP, mapChoice=True)
else:
unknownArgumentExit()
if courseIdList is None:
missingArgumentExit('courses <CourseEntity>')
entityType = Ent.CLASSROOM_INVITATION
i, count, coursesInfo = _getCoursesOwnerInfo(croom, courseIdList, True)
for courseId, courseInfo in coursesInfo.items():
i += 1
courseNameId = f'{courseInfo["name"]} ({courseId})'
if invitationIds is not None:
userInvitationIds = invitationIds
else:
status, userInvitationIds = _getClassroomInvitationIds(courseInfo['croom'], None, [courseId], role, i, count)
if status < 0:
continue
jcount = len(userInvitationIds)
entityPerformActionNumItems([Ent.COURSE, courseNameId], jcount, entityType, i, count)
Ind.Increment()
j = 0
for invitationId in userInvitationIds:
j += 1
try:
callGAPI(courseInfo['croom'].invitations(), 'delete',
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
id=invitationId)
entityActionPerformed([Ent.COURSE, courseNameId, entityType, invitationId], j, jcount)
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.COURSE, courseNameId, entityType, invitationId], str(e), j, jcount)
Ind.Decrement()
# gam show classroominvitations (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
# [role all|owner|student|teacher] [formatjson]
# gam print classroominvitations [todrive <ToDriveAttribute>*] (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
@@ -51304,6 +51345,11 @@ def _mapDriveRevisionNames(revision):
revision['lastModifyingUserName'] = revision['lastModifyingUser']['displayName']
_mapDriveUser(revision['lastModifyingUser'])
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
'allowFileDiscovery', 'expirationTime', 'deleted', 'permissionDetails' #permissionDetails must be last
]
DRIVE_FIELDS_CHOICE_MAP = {
'alternatelink': 'webViewLink',
'appdatacontents': 'spaces',
@@ -51362,8 +51408,9 @@ DRIVE_FIELDS_CHOICE_MAP = {
'ownernames': 'owners.displayName',
'owners': 'owners',
'parents': 'parents',
'permissions': 'permissions',
'permissiondetails': 'permissions.permissionDetails',
'permissionids': 'permissionIds',
'permissions': 'permissions',
'properties': 'properties',
'quotabytesused': 'quotaBytesUsed',
'quotaused': 'quotaBytesUsed',
@@ -51719,7 +51766,7 @@ def showFileInfo(users):
showLabels = getChoice(SHOWLABELS_CHOICES)
elif myarg == 'showshareddrivepermissions':
getPermissionsForSharedDrives = True
permissionsFields = 'nextPageToken,permissions'
permissionsFields = f'nextPageToken,permissions({",".join(DRIVEFILE_BASIC_PERMISSION_FIELDS)})'
elif myarg == 'returnidonly':
returnIdOnly = True
elif DFF.ProcessArgument(myarg):
@@ -51727,7 +51774,8 @@ def showFileInfo(users):
else:
FJQC.GetFormatJSON(myarg)
if DFF.fieldsList:
getPermissionsForSharedDrives, permissionsFields = _setGetPermissionsForSharedDrives(DFF.fieldsList)
if not getPermissionsForSharedDrives:
getPermissionsForSharedDrives, permissionsFields = _setGetPermissionsForSharedDrives(DFF.fieldsList)
_setSelectionFields()
fields = getFieldsFromFieldsList(DFF.fieldsList)
showNoParents = 'parents' in DFF.fieldsList
@@ -52581,6 +52629,7 @@ DRIVEFILE_ACL_ROLES_MAP = {
}
DRIVEFILE_ACL_PERMISSION_TYPES = ['anyone', 'domain', 'group', 'user'] # anyone must be first element
DRIVEFILE_ACL_PERMISSION_DETAILS_TYPES = ['file', 'member']
class PermissionMatch():
_PERMISSION_MATCH_ACTION_MAP = {'process': True, 'skip': False}
@@ -52667,10 +52716,13 @@ class PermissionMatch():
self.permissionFields.add('expirationTime')
elif myarg == 'deleted':
deletedLocation = Cmd.Location()
body['deleted'] = getBoolean()
body[myarg] = getBoolean()
self.permissionFields.add('deleted')
elif myarg == 'inherited':
body['inherited'] = getBoolean()
body[myarg] = getBoolean()
self.permissionFields.add('permissionDetails')
elif myarg == 'permtype':
body['permissionType'] = getChoice(DRIVEFILE_ACL_PERMISSION_DETAILS_TYPES)
self.permissionFields.add('permissionDetails')
elif myarg in {'em', 'endmatch'}:
break
@@ -52710,21 +52762,27 @@ class PermissionMatch():
if field in {'type', 'role'}:
if permission.get(field, '') not in value:
break
elif field in {'nottype'}:
elif field == 'nottype':
if permission.get('type', '') in value:
break
elif field in {'notrole'}:
elif field == 'notrole':
if permission.get('role', '') in value:
break
elif field in {'allowFileDiscovery', 'deleted'}:
if value != permission.get(field, False):
break
elif field in {'inherited'}:
elif field == 'inherited':
if 'permissionDetails' in permission:
if value != permission['permissionDetails'][0].get(field, False):
break
else:
break
elif field == 'permissionType':
if 'permissionDetails' in permission:
if value != permission['permissionDetails'][0].get(field, ''):
break
else:
break
elif field in {'expirationstart', 'expirationend'}:
if 'expirationTime' in permission:
expirationDateTime, _ = iso8601.parse_date(permission['expirationTime'])
@@ -52736,14 +52794,14 @@ class PermissionMatch():
break
else:
break
elif field in {'emailaddresslist'}:
elif field == 'emailaddresslist':
emailAddress = permission.get('emailAddress')
if emailAddress:
if emailAddress not in value:
break
else:
break
elif field in {'permissionidlist'}:
elif field == 'permissionidlist':
permissionId = permission.get('id')
if permissionId:
if permissionId not in value:
@@ -53141,6 +53199,16 @@ def printFileList(users):
if DLP.onlySharedDrives or getPermissionsForSharedDrives or DFF.showSharedDriveNames:
_setSkipObjects(skipObjects, ['driveId'], DFF.fieldsList)
def _printFileInfoRow(baserow, fileInfo):
row = baserow.copy()
if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
simpleLists=simpleLists, delimiter=delimiter))
else:
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row)
def _printFileInfo(drive, user, f_file, cleanFileName):
driveId = f_file.get('driveId')
checkSharedDrivePermissions = getPermissionsForSharedDrives and driveId and 'permissions' not in f_file
@@ -53218,18 +53286,15 @@ def printFileList(users):
baserow[fileNameTitle] = fileInfo[fileNameTitle]
if 'owners' in fileInfo:
flattenJSON({'owners': fileInfo['owners']}, flattened=baserow, skipObjects=skipObjects)
permissions = fileInfo.pop('permissions')
for permission in permissions:
row = baserow.copy()
for permission in fileInfo.pop('permissions'):
fileInfo['permission'] = permission
if not FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
simpleLists=simpleLists, delimiter=delimiter))
pdetails = fileInfo['permission'].pop('permissionDetails', [])
if not pdetails:
_printFileInfoRow(baserow, fileInfo)
else:
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON(fileInfo, skipObjects=skipObjects, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowTitlesJSONNoFilter(row)
for pdetail in pdetails:
fileInfo['permission']['permissionDetails'] = pdetail
_printFileInfoRow(baserow, fileInfo)
else:
if not countsRowFilter:
csvPF.UpdateMimeTypeCounts(flattenJSON(fileInfo, flattened=row, skipObjects=skipObjects, timeObjects=timeObjects,
@@ -53417,7 +53482,7 @@ def printFileList(users):
showLabels = getChoice(SHOWLABELS_CHOICES)
elif myarg == 'showshareddrivepermissions':
getPermissionsForSharedDrives = True
permissionsFields = 'nextPageToken,permissions'
permissionsFields = f'nextPageToken,permissions({",".join(DRIVEFILE_BASIC_PERMISSION_FIELDS)})'
elif myarg == 'pmfilter':
pmselect = False
elif myarg == 'oneitemperrow':
@@ -53459,9 +53524,10 @@ def printFileList(users):
DLP.Finalize(fileIdEntity)
if DLP.PM.permissionMatches:
getPermissionsForSharedDrives = True
permissionsFields = 'nextPageToken,permissions'
permissionsFields = f'nextPageToken,permissions({",".join(DRIVEFILE_BASIC_PERMISSION_FIELDS)})'
elif DFF.fieldsList:
getPermissionsForSharedDrives, permissionsFields = _setGetPermissionsForSharedDrives(DFF.fieldsList)
if not getPermissionsForSharedDrives:
getPermissionsForSharedDrives, permissionsFields = _setGetPermissionsForSharedDrives(DFF.fieldsList)
if DFF.fieldsList:
_setSelectionFields()
fields = getFieldsFromFieldsList(DFF.fieldsList)
@@ -60875,24 +60941,19 @@ def infoDriveFileACLs(users, useDomainAdminAccess=False):
def doInfoDriveFileACLs():
infoDriveFileACLs([_getAdminEmail()], True)
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
'allowFileDiscovery', 'expirationTime', 'deleted'
]
DRIVEFILE_PERMISSIONS_FOR_VIEW_CHOICES = ['published']
def getDriveFilePermissionsFields(myarg, fieldsList):
if myarg in DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP:
fieldsList.append(DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP[myarg])
elif myarg == 'basicpermissions':
fieldsList.extend(DRIVEFILE_BASIC_PERMISSION_FIELDS)
fieldsList.extend(DRIVEFILE_BASIC_PERMISSION_FIELDS[:-1])
elif myarg == 'fields':
for field in _getFieldsList():
if field in DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP:
fieldsList.append(DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP[field])
elif field == 'basicpermissions':
fieldsList.extend(DRIVEFILE_BASIC_PERMISSION_FIELDS)
fieldsList.extend(DRIVEFILE_BASIC_PERMISSION_FIELDS[:-1])
else:
invalidChoiceExit(field, DRIVE_PERMISSIONS_SUBFIELDS_CHOICE_MAP, True)
else:
@@ -60916,6 +60977,17 @@ def getDriveFilePermissionsFields(myarg, fieldsList):
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
# [formatjson] [adminaccess|asadmin]
def printShowDriveFileACLs(users, useDomainAdminAccess=False):
def _printPermissionRow(baserow, permission):
row = baserow.copy()
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
csvPF = CSVPrintFile(['Owner', 'id'], 'sortall') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
fileIdEntity = getDriveFileEntity()
@@ -61036,16 +61108,14 @@ def printShowDriveFileACLs(users, useDomainAdminAccess=False):
baserow[fileNameTitle] = fileName
if oneItemPerRow:
for permission in permissions:
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
pdetails = permission.pop('permissionDetails', [])
if not pdetails:
_printPermissionRow(baserow, permission)
else:
for pdetail in pdetails:
permission['permissionDetails'] = pdetail
_printPermissionRow(baserow, permission)
else:
row = baserow.copy()
for permission in permissions:
@@ -62287,6 +62357,17 @@ SHOW_NO_PERMISSIONS_DRIVES_CHOICE_MAP = {
# [shownopermissionsdrives false|true|only]
# [formatjsn]
def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
def _printPermissionRow(baserow, permission):
row = baserow.copy()
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
csvPF = CSVPrintFile(['User', 'id', 'name', 'createdTime'], 'sortall') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
roles = set()
@@ -62469,16 +62550,14 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
baserow = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name'], 'createdTime': shareddrive['createdTime']}
if shareddrive['permissions']:
for permission in shareddrive['permissions']:
row = baserow.copy()
_mapDrivePermissionNames(permission)
flattenJSON({'permission': permission}, flattened=row, timeObjects=timeObjects)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
row = baserow.copy()
row['JSON'] = json.dumps(cleanJSON({'permission': permission}, timeObjects=timeObjects),
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row)
pdetails = permission.pop('permissionDetails', [])
if not pdetails:
_printPermissionRow(baserow, permission)
else:
for pdetail in pdetails:
permission['permissionDetails'] = pdetail
_printPermissionRow(baserow, permission)
else:
if not FJQC.formatJSON:
csvPF.WriteRowTitles(baserow)
@@ -71448,6 +71527,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CHROMENETWORK: doDeleteChromeNetwork,
Cmd.ARG_CHROMEPOLICY: doDeleteChromePolicy,
Cmd.ARG_CIGROUP: doDeleteCIGroups,
Cmd.ARG_CLASSROOMINVITATION: doDeleteClassroomInvitations,
Cmd.ARG_CONTACT: doDeleteDomainContacts,
Cmd.ARG_CONTACTPHOTO: doDeleteDomainContactPhoto,
Cmd.ARG_COURSE: doDeleteCourse,