def _valid_member(login_id): try: valid_net_id(login_id) return 1 except UserPolicyException: try: valid_gmail_id(login_id) return 1 except UserPolicyException: pass return 0
def _get_members(group_id): valid_members = {} invalid_members = {} member_group_ids = [] try: valid_group_id(group_id) for member in gws.get_members(group_id): try: if member.is_uwnetid(): valid_net_id(member.name) valid_members[member.name] = member elif member.is_eppn(): valid_gmail_id(member.name) valid_members[member.name] = member elif member.is_group(): (valid_sub, invalid_sub, member_subgroups) = _get_members(member.name) valid_members.update(valid_sub) invalid_members.update(invalid_sub) member_group_ids += [member.name] + member_subgroups except (UserPolicyException, GroupPolicyException) as err: member.error = err invalid_members[member.name] = member except DataFailureException as err: # Group not found or access denied is ok if err.status == 404: raise GroupNotFoundException( "Group not found: {}".format(group_id)) elif err.status == 401: raise GroupUnauthorizedException( "Group not permitted for {}: {}".format( gws.act_as, group_id)) else: raise except GroupPolicyException as err: raise except RecursionError as err: logger.info("Error: {}, Group: {}, Member groups: {}".format( err, group_id, member_group_ids)) raise return (valid_members, invalid_members, member_group_ids)
def _get_current_members(self, group): (members, invalid_members, member_groups) = get_effective_members(group.group_id, act_as=group.added_by) self._reconcile_member_groups(group, member_groups) for member in invalid_members: self.logger.info("Skip group member %s (%s)" % (member.name, member.error)) current_members = [] for member in members: login_id = member.name if member.is_uwnetid(): user_id = member.name elif member.is_eppn(): user_id = valid_gmail_id(member.name) else: continue # Skip members already in academic course sections, removing # from -group section enrollments = self.cached_course_enrollments[group.course_id] match = next( (m for m in enrollments if (m.login_id is not None and m.login_id.lower() == login_id.lower())), None ) if match: self.logger.info("Skip group member %s (present in %s)" % (member.name, match.sis_section_id)) continue course_member = CourseMember( course_id=group.course_id, name=user_id, member_type=member.member_type, role=group.role ) course_member.login = login_id current_members.append(course_member) return current_members
def _update_group(self, group, member, is_deleted): if member.is_group(): self._update_group_member_group(group, member.name, is_deleted) elif member.is_uwnetid() or member.is_eppn(): try: if member.name not in self._valid_members: if member.is_uwnetid(): valid_net_id(member.name) elif member.is_eppn(): valid_gmail_id(member.name) self._valid_members.append(member.name) self._update_group_member(group, member, is_deleted) except UserPolicyException: self._log.info('%s IGNORE invalid user %s' % ( log_prefix, member.name)) else: self._log.info('%s IGNORE member type %s (%s)' % ( log_prefix, member.member_type, member.name))
def _get_members(group_id): valid_members = {} invalid_members = {} member_group_ids = [] try: valid_group_id(group_id) for member in gws.get_members(group_id): try: if member.is_uwnetid(): valid_net_id(member.name) valid_members[member.name] = member elif member.is_eppn(): valid_gmail_id(member.name) valid_members[member.name] = member elif member.is_group(): (valid_sub, invalid_sub, member_subgroups) = _get_members(member.name) valid_members.update(valid_sub) invalid_members.update(invalid_sub) member_group_ids += [member.name] + member_subgroups except (UserPolicyException, GroupPolicyException) as err: member.error = err invalid_members[member.name] = member except DataFailureException as err: # Group not found or access denied is ok if err.status == 404: raise GroupNotFoundException("Group not found: %s" % group_id) elif err.status == 401: raise GroupUnauthorizedException("Group not permitted for %s: %s" % (gws.actas, group_id)) else: raise except GroupPolicyException as err: raise return (valid_members, invalid_members, member_group_ids)
def _update_group_member(self, group, member, is_deleted): # validity is assumed if the course model exists if member.is_uwnetid(): user_id = member.name elif member.is_eppn(): user_id = valid_gmail_id(member.name) else: return try: (cm, created) = CourseMemberModel.objects.get_or_create( name=user_id, member_type=member.member_type, course_id=group.course_id, role=group.role) except CourseMemberModel.MultipleObjectsReturned: models = CourseMemberModel.objects.filter( name=user_id, member_type=member.member_type, course_id=group.course_id, role=group.role) self._log.debug('%s MULTIPLE (%s): %s in %s as %s' % ( log_prefix, len(models), user_id, group.course_id, group.role)) cm = models[0] created = False for m in models[1:]: m.delete() if is_deleted: # user in other member groups not deleted if self._user_in_member_group(group, member): is_deleted = None elif self._user_in_course(group, member): # official student/instructor not added via group is_deleted = True cm.is_deleted = is_deleted cm.priority = PRIORITY_DEFAULT if not cm.queue_id else PRIORITY_HIGH cm.save() self._log.info('%s %s %s to %s as %s' % ( log_prefix, 'DELETED' if is_deleted else 'ACTIVE', user_id, group.course_id, group.role))
def GET(self, request, **kwargs): course_id = kwargs.get('canvas_course_id', None) image_size = request.GET.get('image_size', 120) page = request.GET.get('page', 1) if not course_id: return self.error_response(400, 'Missing course ID') blti_data = self.get_session(request) user_id = blti_data.get('custom_canvas_user_id') params = { 'page': page, 'per_page': getattr(settings, 'COURSE_ROSTER_PER_PAGE', 50), 'enrollment_type': ['student'], 'include': ['enrollments', 'avatar_url'] } @retry(SSLError, tries=3, delay=1, logger=logger) def _get_users_for_course(canvas, course_id, params): return canvas.get_users_for_course(course_id, params) canvas = Users(as_user=user_id) try: users = _get_users_for_course(canvas, course_id, params) except DataFailureException as err: return self.error_response(500, err.msg) people = [] for user in users: try: valid_reg_id(user.sis_user_id) photo_url = IDPhoto(reg_id=user.sis_user_id, image_size=image_size).get_url() avatar_url = self._avatar_url(user.avatar_url, image_size) except UserPolicyException: try: valid_gmail_id(user.login_id) photo_url = self._avatar_url(user.avatar_url, image_size) avatar_url = '' except UserPolicyException: continue search_name = '%s %s' % (user.name, user.login_id) people.append({ 'user_url': user.enrollments[0].html_url, 'photo_url': photo_url, 'avatar_url': avatar_url, 'login_id': user.login_id, 'name': user.name, 'search_name': search_name.lower(), 'sections': [e.section_id for e in user.enrollments], }) try: url_parts = urlparse(canvas.next_page_url) next_page = parse_qs(url_parts.query).get('page', [])[0] except Exception as err: next_page = None return self.json_response({ 'people': people, 'next_page': next_page })
def handle(self, *args, **options): last_access_report = '/home/jlaney/Downloads/last_user_access_csv_29_Feb_2016_507320160229-22874-1e0l09o.csv' enrollment_report = '/home/jlaney/Downloads/provisioning_csv_29_Feb_2016_507420160229-30814-ftbhlm.csv' users_all = 0 users_uw = 0 users_google = 0 users_unknown = 0 users_no_sisid = 0 users_uw_login_one_year = 0 users_google_login_one_year = 0 users_uw_login_never = 0 users_google_login_never = 0 users_uw_no_enrollments = 0 users_google_no_enrollments = 0 enrollments = {} with open(enrollment_report, 'rb') as csvfile: reader = csv.reader(csvfile) for row in reader: sis_user_id = row[3] if len(sis_user_id): if sis_user_id in enrollments: enrollments[sis_user_id] += 1 else: enrollments[sis_user_id] = 1 with open(last_access_report, 'rb') as csvfile: reader = csv.reader(csvfile) for row in reader: sis_user_id = row[1] if len(sis_user_id): last_access = row[3] try: valid_reg_id(sis_user_id) users_all += 1 users_uw += 1 if len(last_access): if not self.logged_in_past_year(last_access): users_uw_login_one_year += 1 else: users_uw_login_never += 1 if sis_user_id not in enrollments: users_uw_no_enrollments += 1 except UserPolicyException: try: valid_gmail_id(sis_user_id) users_all += 1 users_google += 1 if len(last_access): if not self.logged_in_past_year(last_access): users_google_login_one_year += 1 else: users_google_login_never += 1 if sis_user_id not in enrollments: users_google_no_enrollments += 1 except UserPolicyException: users_unknown += 1 #print sis_user_id else: if row[2] != 'Student, Test': users_no_sisid += 1 print '\n\n' print 'All users: %s' % users_all print 'UW users: %s' % users_uw print 'UW users with 0 enrollments: %s' % users_uw_no_enrollments print 'UW users with 0 logins: %s' % users_uw_login_never print 'UW users who have not logged in the past year: %s' % users_uw_login_one_year print '\n\n' print 'Google users: %s' % users_google print 'Google users with 0 enrollments: %s' % users_google_no_enrollments print 'Google users with 0 logins: %s' % users_google_login_never print 'Google users who have not logged in the past year: %s' % users_google_login_one_year print '\n\n' print 'No SIS ID users: %s' % users_no_sisid print 'Bad SIS ID users: %s' % users_unknown print '\n\n'
def handle(self, *args, **options): last_access_report = options.get('last_access_report') enrollment_report = options.get('enrollment_report') users_all = 0 users_uw = 0 users_google = 0 users_unknown = 0 users_no_sisid = 0 users_uw_login_one_year = 0 users_google_login_one_year = 0 users_uw_login_never = 0 users_google_login_never = 0 users_uw_no_enrollments = 0 users_google_no_enrollments = 0 enrollments = {} with open(enrollment_report, 'rb') as csvfile: reader = csv.reader(csvfile) for row in reader: sis_user_id = row[3] if len(sis_user_id): if sis_user_id in enrollments: enrollments[sis_user_id] += 1 else: enrollments[sis_user_id] = 1 with open(last_access_report, 'rb') as csvfile: reader = csv.reader(csvfile) for row in reader: sis_user_id = row[1] if len(sis_user_id): last_access = row[3] try: valid_reg_id(sis_user_id) users_all += 1 users_uw += 1 if len(last_access): if not self.logged_in_past_year(last_access): users_uw_login_one_year += 1 else: users_uw_login_never += 1 if sis_user_id not in enrollments: users_uw_no_enrollments += 1 except UserPolicyException: try: valid_gmail_id(sis_user_id) users_all += 1 users_google += 1 if len(last_access): if not self.logged_in_past_year(last_access): users_google_login_one_year += 1 else: users_google_login_never += 1 if sis_user_id not in enrollments: users_google_no_enrollments += 1 except UserPolicyException: users_unknown += 1 else: if row[2] != 'Student, Test': users_no_sisid += 1 print('\n\n') print('All users: {}'.format(users_all)) print('UW users: {}'.format(users_uw)) print( 'UW users with 0 enrollments: {}'.format(users_uw_no_enrollments)) print('UW users with 0 logins: {}'.format(users_uw_login_never)) print('UW users who have not logged in the past year: {}'.format( users_uw_login_one_year)) print('\n\n') print('Google users: {}'.format(users_google)) print('Google users with 0 enrollments: {}'.format( users_google_no_enrollments)) print( 'Google users with 0 logins: {}'.format(users_google_login_never)) print('Google users who have not logged in the past year: {}'.format( users_google_login_one_year)) print('\n\n') print('No SIS ID users: {}'.format(users_no_sisid)) print('Bad SIS ID users: {}'.format(users_unknown)) print('\n\n')