-Classroom Guardian API commands

-Allow pulling new activity reports w/o code changes
-GAM 3.7 baby!
This commit is contained in:
Jay Lee 2016-08-18 08:05:16 -04:00
parent 2c15230756
commit 7a2785ba5c

View File

@ -24,7 +24,7 @@ For more information, see http://git.io/gam
""" """
__author__ = u'Jay Lee <jay0lee@gmail.com>' __author__ = u'Jay Lee <jay0lee@gmail.com>'
__version__ = u'3.66' __version__ = u'3.7'
__license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
import sys, os, time, datetime, random, socket, csv, platform, re, base64, string, codecs, StringIO, subprocess, collections, mimetypes import sys, os, time, datetime, random, socket, csv, platform, re, base64, string, codecs, StringIO, subprocess, collections, mimetypes
@ -1365,7 +1365,7 @@ def showReport():
for app in auth_apps: # put apps at bottom for app in auth_apps: # put apps at bottom
csvRows.append(app) csvRows.append(app)
writeCSVfile(csvRows, titles, u'Customer Report - %s' % try_date, todrive=to_drive) writeCSVfile(csvRows, titles, u'Customer Report - %s' % try_date, todrive=to_drive)
elif report in [u'doc', u'docs', u'drive', u'calendar', u'calendars', u'login', u'logins', u'admin', u'token', u'tokens', u'group', u'groups', u'mobile']: else:
if report in [u'doc', u'docs']: if report in [u'doc', u'docs']:
report = u'drive' report = u'drive'
elif report in [u'calendars']: elif report in [u'calendars']:
@ -2211,6 +2211,100 @@ def doGetDataTransferInfo():
print u' None' print u' None'
print print
def doPrintGuardians():
croom = buildGAPIObject(u'classroom')
invitedEmailAddress = None
studentIds = [u'-',]
states = None
service = croom.userProfiles().guardians()
items = u'guardians'
guardians = []
show_csv = True
csvRows = []
todrive = False
titles = []
i = 3
while i < len(sys.argv):
if sys.argv[i].lower() == u'invitedguardian':
invitedEmailAddress = sys.argv[i+1]
i += 2
elif sys.argv[i].lower() == u'nocsv':
show_csv = False
i += 1
elif sys.argv[i].lower() == u'todrive':
todrive = True
i += 1
elif sys.argv[i].lower() == u'student':
studentIds = [sys.argv[i+1],]
i += 2
elif sys.argv[i].lower() == u'invitations':
service = croom.userProfiles().guardianInvitations()
items = u'guardianInvitations'
if states == None:
states = [u'COMPLETE', u'PENDING', u'GUARDIAN_INVITATION_STATE_UNSPECIFIED']
i += 1
elif sys.argv[i].lower() == u'states':
states = sys.argv[i+1].split(u',')
i += 2
elif sys.argv[i].lower() in usergroup_types:
studentIds = getUsersToModify(entity_type=sys.argv[i], entity=sys.argv[i+1])
i += 2
n = 1
for studentId in studentIds:
kwargs = {u'invitedEmailAddress': invitedEmailAddress, u'studentId': studentId}
if items == u'guardianInvitations':
kwargs[u'states'] = states
if studentId != u'-':
sys.stderr.write('\r')
sys.stderr.flush()
sys.stderr.write(u'Getting guardians for %s (%s/%s)%s' % (studentId, n, len(studentIds), u' ' * 40))
student_guardians = callGAPIpages(service, u'list', items=items, soft_errors=True, **kwargs)
# add student email to results since API does not return it
i = 0
while i < len(student_guardians):
student_guardians[i][u'studentEmail'] = studentId
i += 1
guardians = guardians + student_guardians
n += 1
sys.stderr.write(u'\n')
if show_csv:
for guardian in guardians:
addRowTitlesToCSVfile(flatten_json(guardian), csvRows, titles)
writeCSVfile(csvRows, titles, u'Guardians', todrive)
else:
for guardian in guardians:
print_json(None, guardian)
def doInviteGuardian():
croom = buildGAPIObject(u'classroom')
body = {u'invitedEmailAddress': sys.argv[3]}
studentId = sys.argv[4]
result = callGAPI(croom.userProfiles().guardianInvitations(), u'create', studentId=studentId, body=body)
print u'Invited email %s as guardian of %s. Invite ID %s' % (result[u'invitedEmailAddress'], studentId, result[u'invitationId'])
def doDeleteGuardian():
croom = buildGAPIObject(u'classroom')
guardianId = sys.argv[3]
studentId = sys.argv[4]
try:
callGAPI(croom.userProfiles().guardians(), u'delete', throw_reasons=[u'notFound'], studentId=studentId, guardianId=guardianId)
print u'Deleted %s as a guardian of %s' % (guardianId, studentId)
except googleapiclient.errors.HttpError:
# See if there's a pending invitation
states = [u'COMPLETE', u'PENDING', u'GUARDIAN_INVITATION_STATE_UNSPECIFIED']
results = callGAPIpages(croom.userProfiles().guardianInvitations(), u'list', items=u'guardianInvitations', studentId=studentId, invitedEmailAddress=guardianId, states=states)
if len(results) < 1:
print u'%s is not a guardian of %s and no invitation exists.' % (guardianId, studentId)
sys.exit(0)
for result in results:
if result[u'state'] != u'PENDING':
print u'%s is not a guardian of %s and invitation %s status is %s, not PENDING. Doing nothing.' % (guardianId, studentId, result[u'invitationId'], result[u'state'])
continue
invitationId = result[u'invitationId']
body = { u'state': u'COMPLETE' }
callGAPI(croom.userProfiles().guardianInvitations(), u'patch', studentId=studentId, invitationId=invitationId, updateMask=u'state', body=body)
print u'Cancelling %s invitation for %s as guardian of %s' % (result[u'state'], result[u'invitedEmailAddress'], studentId)
def doCreateCourse(): def doCreateCourse():
croom = buildGAPIObject(u'classroom') croom = buildGAPIObject(u'classroom')
body = {} body = {}
@ -7836,6 +7930,7 @@ def print_json(object_name, object_value, spacing=u''):
else: else:
print_json(None, a_value, u' %s' % spacing) print_json(None, a_value, u' %s' % spacing)
elif isinstance(object_value, dict): elif isinstance(object_value, dict):
print
if object_name != None: if object_name != None:
sys.stdout.write(u'\n') sys.stdout.write(u'\n')
for another_object in object_value: for another_object in object_value:
@ -10080,7 +10175,7 @@ possible_scopes = [u'https://www.googleapis.com/auth/admin.directory.group',
u'https://www.googleapis.com/auth/siteverification', # Site Verification API u'https://www.googleapis.com/auth/siteverification', # Site Verification API
u'https://mail.google.com/', # IMAP/SMTP authentication for admin notifications u'https://mail.google.com/', # IMAP/SMTP authentication for admin notifications
u'https://www.googleapis.com/auth/admin.directory.userschema', # Customer User Schema u'https://www.googleapis.com/auth/admin.directory.userschema', # Customer User Schema
u'https://www.googleapis.com/auth/classroom.rosters https://www.googleapis.com/auth/classroom.courses https://www.googleapis.com/auth/classroom.profile.emails https://www.googleapis.com/auth/classroom.profile.photos', # Classroom API [u'https://www.googleapis.com/auth/classroom.rosters', u'https://www.googleapis.com/auth/classroom.courses', u'https://www.googleapis.com/auth/classroom.profile.emails', u'https://www.googleapis.com/auth/classroom.profile.photos', u'https://www.googleapis.com/auth/classroom.guardianlinks.students'], # Classroom API
u'https://www.googleapis.com/auth/cloudprint', # CloudPrint API u'https://www.googleapis.com/auth/cloudprint', # CloudPrint API
u'https://www.googleapis.com/auth/admin.datatransfer', # Data Transfer API u'https://www.googleapis.com/auth/admin.datatransfer', # Data Transfer API
u'https://www.googleapis.com/auth/admin.directory.customer', # Customer API u'https://www.googleapis.com/auth/admin.directory.customer', # Customer API
@ -10130,7 +10225,7 @@ access or an 'a' to grant action-only access.
[%%s] %s) Site Verification API [%%s] %s) Site Verification API
[%%s] %s) IMAP/SMTP Access (send notifications to admin) [%%s] %s) IMAP/SMTP Access (send notifications to admin)
[%%s] %s) User Schemas (supports read-only) [%%s] %s) User Schemas (supports read-only)
[%%s] %s) Classroom API [%%s] %s) Classroom API (counts as 5 scopes)
[%%s] %s) Cloud Print API [%%s] %s) Cloud Print API
[%%s] %s) Data Transfer API (supports read-only) [%%s] %s) Data Transfer API (supports read-only)
[%%s] %s) Customer Directory API (supports read-only) [%%s] %s) Customer Directory API (supports read-only)
@ -10142,6 +10237,9 @@ access or an 'a' to grant action-only access.
%%s) Continue %%s) Continue
''' % tuple(range(0, num_scopes)) ''' % tuple(range(0, num_scopes))
selected_scopes = [u'*'] * num_scopes selected_scopes = [u'*'] * num_scopes
# default to off for old email audit API (soon to be removed from GAM)
selected_scopes[7] = u' '
# default to off for notifications API (not super useful)
selected_scopes[16] = u' ' selected_scopes[16] = u' '
select_all_scopes = unicode(str(num_scopes)) select_all_scopes = unicode(str(num_scopes))
unselect_all_scopes = unicode(str(num_scopes+1)) unselect_all_scopes = unicode(str(num_scopes+1))
@ -10205,11 +10303,18 @@ access or an 'a' to grant action-only access.
scopes = [u'email',] # Email Display Scope, always included scopes = [u'email',] # Email Display Scope, always included
for i in range(0, len(selected_scopes)): for i in range(0, len(selected_scopes)):
if selected_scopes[i] == u'*': if selected_scopes[i] == u'*':
if type(possible_scopes[i]) is unicode:
scopes.append(possible_scopes[i]) scopes.append(possible_scopes[i])
else:
scopes += possible_scopes[i]
elif selected_scopes[i] == u'R': elif selected_scopes[i] == u'R':
scopes.append(u'%s.readonly' % possible_scopes[i]) scopes.append(u'%s.readonly' % possible_scopes[i])
elif selected_scopes[i] == u'A': elif selected_scopes[i] == u'A':
scopes.append(u'%s.action' % possible_scopes[i]) scopes.append(u'%s.action' % possible_scopes[i])
if len(scopes) > 29:
os.system([u'clear', u'cls'][os.name == u'nt'])
print u'ERROR: To many scopes selected, please unselect some.'
sys.exit(3)
try: try:
FLOW = oauth2client.client.flow_from_clientsecrets(GC_Values[GC_CLIENT_SECRETS_JSON], scope=scopes) FLOW = oauth2client.client.flow_from_clientsecrets(GC_Values[GC_CLIENT_SECRETS_JSON], scope=scopes)
except oauth2client.client.clientsecrets.InvalidClientSecretsError: except oauth2client.client.clientsecrets.InvalidClientSecretsError:
@ -10394,6 +10499,8 @@ def ProcessGAMCommand(args):
doCreateDomainAlias() doCreateDomainAlias()
elif argument == u'admin': elif argument == u'admin':
doCreateAdmin() doCreateAdmin()
elif argument in [u'guardianinvite', u'inviteguardian', u'guardian']:
doInviteGuardian()
else: else:
print u'ERROR: %s is not a valid argument for "gam create"' % argument print u'ERROR: %s is not a valid argument for "gam create"' % argument
sys.exit(2) sys.exit(2)
@ -10502,6 +10609,8 @@ def ProcessGAMCommand(args):
doDelDomainAlias() doDelDomainAlias()
elif argument == u'admin': elif argument == u'admin':
doDelAdmin() doDelAdmin()
elif argument in [u'guardian', u'guardians']:
doDeleteGuardian()
else: else:
print u'ERROR: %s is not a valid argument for "gam delete"' % argument print u'ERROR: %s is not a valid argument for "gam delete"' % argument
sys.exit(2) sys.exit(2)
@ -10605,6 +10714,8 @@ def ProcessGAMCommand(args):
doPrintAdmins() doPrintAdmins()
elif argument in [u'roles', u'adminroles']: elif argument in [u'roles', u'adminroles']:
doPrintAdminRoles() doPrintAdminRoles()
elif argument in [u'guardian', u'guardians']:
doPrintGuardians()
else: else:
print u'ERROR: %s is not a valid argument for "gam print"' % argument print u'ERROR: %s is not a valid argument for "gam print"' % argument
sys.exit(2) sys.exit(2)