def getSubscribedEmails(conversation, exclude=None): """Gets the list of email addresses for all users subscribed to a conversation. Args: conversation: Key (ndb) of GCIConversation. exclude: Keys (ndb) of Users that, if given, will not be in the set of emails. Returns: Set of email addresses. """ conversation_ent = conversation.get() conv_users = queryConversationUserForConversation(conversation) program_key = ndb.Key.to_old_key(conversation_ent.program) addresses = set() for conv_user in conv_users: if conv_user.enable_notifications and (not exclude or conv_user.user not in exclude): profile = profile_logic.getProfileForUsername( conv_user.user.id(), program_key) if not profile: raise Exception( 'Could not find GCIProfile for user %s and program. %s' % (conv_user.name, program_key.name())) addresses.add(profile.contact.email) return addresses
def getSubscribedEmails(conversation, exclude=None): """Gets the list of email addresses for all users subscribed to a conversation. Args: conversation: Key (ndb) of GCIConversation. exclude: Keys (ndb) of Users that, if given, will not be in the set of emails. Returns: Set of email addresses. """ conversation_ent = conversation.get() conv_users = queryConversationUserForConversation(conversation) program_key = ndb.Key.to_old_key(conversation_ent.program) addresses = set() for conv_user in conv_users: if conv_user.enable_notifications and ( not exclude or conv_user.user not in exclude): profile = profile_logic.getProfileForUsername( conv_user.user.id(), program_key) if not profile: raise Exception('Could not find GCIProfile for user %s and program. %s' % (conv_user.name, program_key.name())) addresses.add(profile.contact.email) return addresses
def doesUserBelongInConversation( user, conversation, ignore_auto_update_users=True): """Decides whether the user in a conversation belongs in the conversation. If ignore_auto_update_users is False, True will be returned if the conversation's auto_update_users is False. Args: user: Key (ndb) of a User. conversation: Key (ndb) of a GCIConversation. ignore_auto_update_users: Whether this should ignore the conversation's auto_update_users property. Returns: Whether the user belongs in the conversation. If the conversation's recipients_type is 'User', True is always returned. Also returns true if the user is the conversation's creator. """ conversation_ent = conversation.get() if not conversation_ent.auto_update_users and not ignore_auto_update_users: return True if conversation_ent.creator == user: return True profile = profile_logic.getProfileForUsername( user.id(), conversation_ent.program.to_old_key()) if not profile: raise Exception('Could not find GCIProfile for user and program.') if conversation_ent.recipients_type == conversation_model.PROGRAM: if conversation_ent.include_admins and profile.is_admin: return True elif conversation_ent.include_mentors and profile.is_mentor: return True elif conversation_ent.include_students and profile.is_student: return True elif (profile.is_student and conversation_ent.include_winners and profile.student_data.is_winner): return True else: return False elif conversation_ent.recipients_type == conversation_model.ORGANIZATION: if (conversation_ent.include_admins and conversation_ent.organization in profile.admin_for): return True elif (conversation_ent.include_mentors and conversation_ent.organization in profile.mentor_for): return True elif (profile.is_student and conversation_ent.include_winners and profile.student_data.is_winner and conversation_ent.organization == profile.student_data.winner_for): return True else: return False # This might be reached if conversation recipients_type is 'User' return True
def getProfileForUsername(username, program_key): """Returns profile entity for a user with the specified username and for the specified program. Args: username: a string containing username of the user. program_key: program key. Returns: profile entity for the specified user and program or None if the user does not have a profile for this program. """ return profile_logic.getProfileForUsername(username, program_key, models=types.CI_MODELS)
def context(self): """Returns the context for the current template. """ comments = [] reply = self.data.GET.get('reply') for comment in self.data.comments: # generate Reply form, if needed form = None if self._commentingAllowed(): comment_id = comment.key().id() if self.data.POST and reply == str(comment_id): form = CommentForm(reply=comment_id, data=self.data.POST) else: form = CommentForm(reply=comment_id) # generate author link, if comment sent by a student author_link = None if GCIComment.created_by.get_value_for_datastore(comment): author_key = ndb.Key.from_old_key( GCIComment.created_by.get_value_for_datastore(comment)) else: author_key = None if author_key: author = melange_profile_logic.getProfileForUsername( author_key.id(), self.data.program.key()) if author and author.is_student: author_link = self.data.redirect.profile( author.profile_id).urlOf(url_names.GCI_STUDENT_TASKS) else: author = None item = self.CommentItem(comment, form, author_link, author) comments.append(item) context = { 'profile': self.data.ndb_profile, 'comments': comments, } if self._commentingAllowed(): if self.data.POST and reply == 'self': context['comment_form'] = CommentForm(data=self.data.POST) else: context['comment_form'] = CommentForm() return context
def context(self): """Returns the context for the current template. """ comments = [] reply = self.data.GET.get('reply') for comment in self.data.comments: # generate Reply form, if needed form = None if self._commentingAllowed(): comment_id = comment.key().id() if self.data.POST and reply == str(comment_id): form = CommentForm(reply=comment_id, data=self.data.POST) else: form = CommentForm(reply=comment_id) # generate author link, if comment sent by a student author_link = None if GCIComment.created_by.get_value_for_datastore(comment): author_key = ndb.Key.from_old_key( GCIComment.created_by.get_value_for_datastore(comment)) else: author_key = None if author_key: author = melange_profile_logic.getProfileForUsername( author_key.id(), self.data.program.key()) if author and author.is_student: author_link = self.data.redirect.profile(author.profile_id).urlOf( url_names.GCI_STUDENT_TASKS) else: author = None item = self.CommentItem(comment, form, author_link, author) comments.append(item) context = { 'profile': self.data.ndb_profile, 'comments': comments, } if self._commentingAllowed(): if self.data.POST and reply == 'self': context['comment_form'] = CommentForm(data=self.data.POST) else: context['comment_form'] = CommentForm() return context
def cleanBackupAdmin(username, request_data): """Cleans backup_admin field. Args: username: Username of the user to assign as the backup administrator. request_data: request_data.RequestData for the current request. Raises: django_forms.ValidationError if no profile exists for at least one of the submitted usernames. """ username = username.strip() profile = profile_logic.getProfileForUsername(username, request_data.program.key(), models=request_data.models) if not profile: raise django_forms.ValidationError(PROFILE_DOES_NOT_EXIST % username) elif profile.key == request_data.ndb_profile.key: raise django_forms.ValidationError(OTHER_PROFILE_IS_THE_CURRENT_PROFILE) else: return profile
def cleanBackupAdmin(username, request_data): """Cleans backup_admin field. Args: username: Username of the user to assign as the backup administrator. request_data: request_data.RequestData for the current request. Raises: django_forms.ValidationError if no profile exists for at least one of the submitted usernames. """ username = username.strip() profile = profile_logic.getProfileForUsername( username, request_data.program.key(), models=request_data.models) if not profile: raise django_forms.ValidationError(PROFILE_DOES_NOT_EXIST % username) elif profile.key == request_data.ndb_profile.key: raise django_forms.ValidationError(OTHER_PROFILE_IS_THE_CURRENT_PROFILE) else: return profile
def _continueShipmentSync(self, request, *args, **kwargs): """Continue syncing shipment data. POST Args: program_key: the key of the program which sync is being done for. shipment_info_id: id of the shipment info object that task is running for. column_indexes: column indexes for specific columns in JSON format. sheet_rows: spreadsheets CSV chunk data in JSON format. """ timekeeper = Timekeeper(20000) params = dicts.merge(request.POST, request.GET) if 'program_key' not in params: logging.error("missing program_key in params: '%s'", params) return responses.terminateTask() if 'shipment_info_id' not in params: logging.error("missing shipment_info_id in params: '%s'", params) return responses.terminateTask() self.setProgram(params['program_key']) self.setShipmentInfo(int(params['shipment_info_id'])) if 'sheet_rows' not in params: logging.error("missing sheet_rows data in params: '%s'", params) return responses.terminateTask() if 'column_indexes' not in params: logging.error("missing column_indexes data in params: '%s'", params) return responses.terminateTask() column_indexes = json.loads(params['column_indexes']) sheet_rows = json.loads(params['sheet_rows']) try: for remain, row in timekeeper.iterate(sheet_rows): if len(row) < len(column_indexes): row.extend((len(column_indexes) - len(row)) * ['']) data = self.getRowData(row, column_indexes) username = data['username'] profile = profile_logic.getProfileForUsername(username, self.program_key) if not profile: logging.error("Profile with username '%s' for program '%s' is not found", username, self.ndb_program_key.id()) continue #continue to next row if not profile.is_student: logging.error("Profile with username '%s' is not a student", username) continue tracking = data['tracking'] self.updateShipmentDataForStudent(profile, tracking) except DeadlineExceededError: if remain: remaining_rows = sheet_rows[(-1 * remain):] params = { 'program_key': params.get('program_key'), 'sheet_rows': json.dumps(remaining_rows), 'column_indexes': params.get('column_indexes'), 'shipment_info_id': params.get('shipment_info_id'), } task_continue_url = links.SOC_LINKER.site(url_names.GSOC_SHIPMENT_TASK_CONTINUE) taskqueue.add(url=task_continue_url, params=params) return responses.terminateTask() self.finishSync() return responses.terminateTask()
def refreshConversationsForUserAndProgram(user_key, program_key): """Adds/removes the user to/from conversations that they should be involved in based on the conversation's criteria. For example, if there is a conversation that should include all program mentors, and this user is a program mentor who is involved with the program but isn't part of the converation, this function will add the user to that conversation. Likewise, it will remove the user from converstions they have no business being in, unless they're the creator of the conversation or the conversation is for specific users. This will only look at conversations that have auto_update_users set as True, and whoose, recipients_type is not 'User'. This function will not add a user to a conversation if the user does not fit the conversation's criteria, even if the user is the creator. If the user is _only_ the creator of the conversation, the user's GCIConversationUser entity should have been created when the conversation was initially created. Args: user_key: Key (ndb) of the User. program_key: Key (ndb) of the GCIProgram. """ profile = profile_logic.getProfileForUsername( user_key.id(), program_key.to_old_key()) if not profile: raise Exception('Could not find Profile for user and program.') def deleteConvUserIfDoesntBelong(conv_user): if not doesConversationUserBelong( conversation_user=conv_user.key, ignore_auto_update_users=False): conv_user.key.delete() # Remove user from any conversations they're in that they don't belong in conv_user_query = queryForProgramAndUser(user=user_key, program=program_key) map(deleteConvUserIfDoesntBelong, conv_user_query) def addToConversation(conversation): addUserToConversation(conversation=conversation.key, user=user_key) mentor_org_keys = profile.mentor_for admin_org_keys = profile.admin_for # Make sure user is added to program conversations they belong in as a # student if profile.is_student: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_students == True)) map(addToConversation, query) # Make sure user is added to program conversations they belong in as a # mentor if profile.is_mentor: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_mentors == True)) map(addToConversation, query) # Make sure user is added to program conversations they belong in as an # admin if profile.is_admin: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_admins == True)) map(addToConversation, query) # Make sure user is added to program conversations they belong in as a # winner if profile.student_data and profile.student_data.is_winner: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_winners == True)) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # mentor if profile.is_mentor and mentor_org_keys: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_mentors == True) .filter(gciconversation_model.GCIConversation.organization.IN( mentor_org_keys))) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # admin if profile.is_admin and admin_org_keys: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_admins == True) .filter(gciconversation_model.GCIConversation.organization.IN( admin_org_keys))) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # winner if profile.is_student and profile.student_data.is_winner: query = (queryConversationsForProgram(program_key) .filter(gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION) .filter(gciconversation_model.GCIConversation.auto_update_users == True) .filter(gciconversation_model.GCIConversation.include_winners == True) .filter(gciconversation_model.GCIConversation.organization == profile.student_data.winner_for)) map(addToConversation, query)
def testForExistingProfile(self): """Tests that profile is returned if exists.""" profile = profile_logic.getProfileForUsername('test', self.program_key) self.assertEqual(profile.key, self.profile.key)
def testForOtherProgram(self): """Tests that no entity is returned for a different program.""" other_program = seeder_logic.seed(program_model.Program) profile = profile_logic.getProfileForUsername('other', other_program.key()) self.assertIsNone(profile)
def testForNoProfile(self): """Tests that no entity is returned when a user does not have a profile.""" profile = profile_logic.getProfileForUsername('other', self.program_key) self.assertIsNone(profile)
def refreshConversationsForUserAndProgram(user_key, program_key): """Adds/removes the user to/from conversations that they should be involved in based on the conversation's criteria. For example, if there is a conversation that should include all program mentors, and this user is a program mentor who is involved with the program but isn't part of the converation, this function will add the user to that conversation. Likewise, it will remove the user from converstions they have no business being in, unless they're the creator of the conversation or the conversation is for specific users. This will only look at conversations that have auto_update_users set as True, and whoose, recipients_type is not 'User'. This function will not add a user to a conversation if the user does not fit the conversation's criteria, even if the user is the creator. If the user is _only_ the creator of the conversation, the user's GCIConversationUser entity should have been created when the conversation was initially created. Args: user_key: Key (ndb) of the User. program_key: Key (ndb) of the GCIProgram. """ profile = profile_logic.getProfileForUsername(user_key.id(), program_key.to_old_key()) if not profile: raise Exception('Could not find Profile for user and program.') def deleteConvUserIfDoesntBelong(conv_user): if not doesConversationUserBelong(conversation_user=conv_user.key, ignore_auto_update_users=False): conv_user.key.delete() # Remove user from any conversations they're in that they don't belong in conv_user_query = queryForProgramAndUser(user=user_key, program=program_key) map(deleteConvUserIfDoesntBelong, conv_user_query) def addToConversation(conversation): addUserToConversation(conversation=conversation.key, user=user_key) mentor_org_keys = profile.mentor_for admin_org_keys = profile.admin_for # Make sure user is added to program conversations they belong in as a # student if profile.is_student: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter( gciconversation_model.GCIConversation.include_students == True) ) map(addToConversation, query) # Make sure user is added to program conversations they belong in as a # mentor if profile.is_mentor: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter( gciconversation_model.GCIConversation.include_mentors == True)) map(addToConversation, query) # Make sure user is added to program conversations they belong in as an # admin if profile.is_admin: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter( gciconversation_model.GCIConversation.include_admins == True)) map(addToConversation, query) # Make sure user is added to program conversations they belong in as a # winner if profile.student_data and profile.student_data.is_winner: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.PROGRAM).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter( gciconversation_model.GCIConversation.include_winners == True)) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # mentor if profile.is_mentor and mentor_org_keys: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter(gciconversation_model.GCIConversation.include_mentors == True).filter( gciconversation_model.GCIConversation.organization.IN( mentor_org_keys))) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # admin if profile.is_admin and admin_org_keys: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter(gciconversation_model.GCIConversation.include_admins == True).filter( gciconversation_model.GCIConversation.organization.IN( admin_org_keys))) map(addToConversation, query) # Make sure user is added to org conversations they belong in as an org # winner if profile.is_student and profile.student_data.is_winner: query = (queryConversationsForProgram(program_key).filter( gciconversation_model.GCIConversation.recipients_type == conversation_model.ORGANIZATION).filter( gciconversation_model.GCIConversation.auto_update_users == True ).filter(gciconversation_model.GCIConversation.include_winners == True).filter( gciconversation_model.GCIConversation.organization == profile.student_data.winner_for)) map(addToConversation, query)
def doesUserBelongInConversation(user, conversation, ignore_auto_update_users=True): """Decides whether the user in a conversation belongs in the conversation. If ignore_auto_update_users is False, True will be returned if the conversation's auto_update_users is False. Args: user: Key (ndb) of a User. conversation: Key (ndb) of a GCIConversation. ignore_auto_update_users: Whether this should ignore the conversation's auto_update_users property. Returns: Whether the user belongs in the conversation. If the conversation's recipients_type is 'User', True is always returned. Also returns true if the user is the conversation's creator. """ conversation_ent = conversation.get() if not conversation_ent.auto_update_users and not ignore_auto_update_users: return True if conversation_ent.creator == user: return True profile = profile_logic.getProfileForUsername( user.id(), conversation_ent.program.to_old_key()) if not profile: raise Exception('Could not find GCIProfile for user and program.') if conversation_ent.recipients_type == conversation_model.PROGRAM: if conversation_ent.include_admins and profile.is_admin: return True elif conversation_ent.include_mentors and profile.is_mentor: return True elif conversation_ent.include_students and profile.is_student: return True elif (profile.is_student and conversation_ent.include_winners and profile.student_data.is_winner): return True else: return False elif conversation_ent.recipients_type == conversation_model.ORGANIZATION: if (conversation_ent.include_admins and conversation_ent.organization in profile.admin_for): return True elif (conversation_ent.include_mentors and conversation_ent.organization in profile.mentor_for): return True elif (profile.is_student and conversation_ent.include_winners and profile.student_data.is_winner and conversation_ent.organization == profile.student_data.winner_for): return True else: return False # This might be reached if conversation recipients_type is 'User' return True