def _updateFromForm(self): """Updates a proposal based on the data inserted in the form. Returns: an updated proposal entity or None """ proposal_form = ProposalForm(self.data.POST, instance=self.data.proposal) if not proposal_form.is_valid(): return None q = GSoCProfile.all().filter('mentor_for', self.data.proposal.org) q = q.filter('status', 'active') q.filter('notify_proposal_updates', True) mentors = q.fetch(1000) to_emails = [i.email for i in mentors] proposal_key = self.data.proposal.key() def update_proposal_txn(): proposal = db.get(proposal_key) proposal_form.instance = proposal proposal = proposal_form.save(commit=True) context = notifications.updatedProposalContext(self.data, proposal, to_emails) sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal) sub_txn() return proposal return db.run_in_transaction(update_proposal_txn)
def _createFromForm(self): """Creates a new request based on the data inserted in the form. Returns: a newly created Request entity or None """ assert isSet(self.data.organization) request_form = RequestForm(self.data.POST) if not request_form.is_valid(): return None # create a new invitation entity request_form.cleaned_data["user"] = self.data.user request_form.cleaned_data["org"] = self.data.organization request_form.cleaned_data["role"] = "mentor" request_form.cleaned_data["type"] = "Request" q = GSoCProfile.all().filter("org_admin_for", self.data.organization) q = q.filter("status", "active").filter("notify_new_requests", True) admins = q.fetch(1000) admin_emails = [i.email for i in admins] def create_request_txn(): request = request_form.create(commit=True) context = notifications.requestContext(self.data, request, admin_emails) sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request) sub_txn() return request return db.run_in_transaction(create_request_txn)
def queryAllMentorsKeysForOrg(org, limit=1000): """Returns a list of keys of all the mentors for the organization Args: org: the organization entity for which we need to get all the mentors limit: the maximum number of entities that must be fetched returns: List of all the mentors for the organization """ # get all mentors keys first query = GSoCProfile.all(keys_only=True) query.filter("mentor_for", org) mentors_keys = query.fetch(limit=limit) # get all org admins keys first query = GSoCProfile.all(keys_only=True) query.filter("org_admin_for", org) oa_keys = query.fetch(limit=limit) return set(mentors_keys + oa_keys)
def context(self): """The context for this template used in render(). """ r = self.data.redirect orgs = [] for org in db.get(self.duplicate.orgs): q = GSoCProfile.all() q.filter("org_admin_for", org) q.filter("status", "active") admins = q.fetch(1000) data = {"name": org.name, "link": r.organization(org).urlOf("gsoc_org_home"), "admins": admins} orgs.append(data) context = {"orgs": orgs} return context
def clear(*args, **kwargs): """Removes all entities from the datastore. """ # TODO(dbentley): If there are more than 1000 instances of any model, # this method will not clear all instances. Instead, it should continually # call .all(), delete all those, and loop until .all() is empty. entities = itertools.chain(*[ Notification.all(), GCIStudent.all(), Survey.all(), SurveyRecord.all(), StudentProposal.all(), GSoCOrganization.all(), GCIOrganization.all(), GSoCTimeline.all(), GCITimeline.all(), GSoCProgram.all(), GSoCProfile.all(), GCIProfile.all(), GSoCProposal.all(), GCIProgram.all(), GCIScore.all(), GSoCStudentInfo.all(), GCIStudentInfo.all(), GCITask.all(), Host.all(), Sponsor.all(), User.all(), Site.all(), Document.all(), ]) try: for entity in entities: entity.delete() except db.Timeout: return http.HttpResponseRedirect('#') # pylint: disable=E1101 memcache.flush_all() return http.HttpResponse('Done')
def context(self): """Returns the context for the current template. """ r = self.data.redirect context = {'duplicate': self.duplicate} orgs = db.get(self.duplicate.orgs) proposals = db.get(self.duplicate.duplicates) orgs_details = {} for org in orgs: orgs_details[org.key().id_or_name()] = { 'name': org.name, 'link': r.organization(org).urlOf('gsoc_org_home') } q = GSoCProfile.all() q.filter('org_admin_for', org) q.filter('status', 'active') org_admins = q.fetch(1000) orgs_details[org.key().id_or_name()]['admins'] = [] for org_admin in org_admins: orgs_details[org.key().id_or_name()]['admins'].append({ 'name': org_admin.name(), 'email': org_admin.email }) orgs_details[org.key().id_or_name()]['proposals'] = [] for proposal in proposals: if proposal.org.key() == org.key(): orgs_details[org.key().id_or_name()]['proposals'].append({ 'key': proposal.key().id_or_name(), 'title': proposal.title, 'link': r.review(proposal.key().id_or_name(), proposal.parent().link_id).urlOf( 'review_gsoc_proposal') }) context['orgs'] = orgs_details return context
def createCommentFromForm(self): """Creates a new comment based on the data inserted in the form. Returns: a newly created comment entity or None """ assert isSet(self.data.public_only) assert isSet(self.data.proposal) if self.data.public_only: comment_form = CommentForm(self.data.request.POST) else: # this form contains checkbox for indicating private/public comments comment_form = PrivateCommentForm(self.data.request.POST) if not comment_form.is_valid(): return None if self.data.public_only: comment_form.cleaned_data["is_private"] = False comment_form.cleaned_data["author"] = self.data.profile q = GSoCProfile.all().filter("mentor_for", self.data.proposal.org) q = q.filter("status", "active") if comment_form.cleaned_data.get("is_private"): q.filter("notify_private_comments", True) else: q.filter("notify_public_comments", True) mentors = q.fetch(1000) to_emails = [i.email for i in mentors if i.key() != self.data.profile.key()] def create_comment_txn(): comment = comment_form.create(commit=True, parent=self.data.proposal) context = notifications.newCommentContext(self.data, comment, to_emails) sub_txn = mailer.getSpawnMailTaskTxn(context, parent=comment) sub_txn() return comment return db.run_in_transaction(create_comment_txn)
def canTakeOrgApp(self): """A user can take the GCI org app if he/she participated in GSoC or GCI as a non-student. """ from soc.modules.gsoc.models.profile import GSoCProfile self.isUser() q = GSoCProfile.all() q.filter('is_student', False) q.filter('status', 'active') q.filter('user', self.data.user) gsoc_profile = q.get() q = GCIProfile.all() q.filter('is_student', False) q.filter('status', 'active') q.filter('user', self.data.user) gci_profile = q.get() if not (gsoc_profile or gci_profile): raise AccessViolation(DEF_NO_PREV_ORG_MEMBER)
def createFromForm(self): """Creates a new proposal based on the data inserted in the form. Returns: a newly created proposal entity or None """ proposal_form = ProposalForm(self.data.POST) if not proposal_form.is_valid(): return None # set the organization and program references proposal_form.cleaned_data['org'] = self.data.organization proposal_form.cleaned_data['program'] = self.data.program student_info_key = self.data.student_info.key() q = GSoCProfile.all().filter('mentor_for', self.data.organization) q = q.filter('status', 'active') q.filter('notify_new_proposals', True) mentors = q.fetch(1000) to_emails = [i.email for i in mentors] def create_proposal_trx(): student_info = db.get(student_info_key) student_info.number_of_proposals += 1 student_info.put() proposal = proposal_form.create(commit=True, parent=self.data.profile) context = notifications.newProposalContext(self.data, proposal, to_emails) sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal) sub_txn() return proposal return db.run_in_transaction(create_proposal_trx)
def getGSoC2011Profile(link_id): program = GSoCProgram.get_by_key_name('google/gsoc2011') return GSoCProfile.all().filter('scope', program).filter('link_id', link_id).get()
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) redirect = RedirectHelper(None, None) 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 = simplejson.loads(params['column_indexes']) sheet_rows = simplejson.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) link_id = data['link_id'] q = GSoCProfile.all().filter('scope', self.__program) q.filter('link_id', link_id) profile = q.get() if not profile: logging.error("Profile link_id '%s' for program '%s' is not found" % (link_id, self.__program.name)) continue #continue to next row if not profile.is_student: logging.error("Profile link_id '%s' is not a student" % link_id) continue tracking = data['tracking'] date_shipped = data['date_shipped'] notes = data['notes'] full_address = " ".join([ data['address_1'], data['address_2'], data['city'], data.get('state', ''), data.get('zip', ''), data.get('zippostal_code', ''), data.get('country', '') ]) self.updateShipmentDataForStudent( profile, tracking, date_shipped, notes, full_address) except DeadlineExceededError: if remain: remaining_rows = sheet_rows[(-1 * remain):] params = { 'program_key': params.get('program_key'), 'sheet_rows': simplejson.dumps(remaining_rows), 'column_indexes': params.get('column_indexes'), 'shipment_info_id': params.get('shipment_info_id'), } taskqueue.add( url=redirect.urlOf('shipment_sync_task_continue'), params=params) return responses.terminateTask() self.finishSync() return responses.terminateTask()
def getGSoC2012Profile(link_id): program = GSoCProgram.get_by_key_name('google/gsoc2012') return GSoCProfile.all().filter('scope', program).filter('link_id', link_id).get()
def testCreateProfile(self): from soc.modules.gsoc.models.profile import GSoCProfile from soc.modules.gsoc.models.profile import GSoCStudentInfo self.timeline.studentSignup() self.data.createUser() suffix = "%(program)s" % { 'program': self.gsoc.key().name(), } role_suffix = "%(role)s/%(suffix)s" % { 'role': 'student', 'suffix': suffix, } url = '/gsoc/profile/' + suffix role_url = '/gsoc/profile/' + role_suffix # we do not want to seed the data in the datastore, we just # want to get the properties generated for seeding. The post # test will actually do the entity creation, so we reuse the # seed_properties method from the seeder to get the most common # values for Profile and StudentInfo postdata = seeder_logic.seed_properties(GSoCProfile) props = seeder_logic.seed_properties(GSoCStudentInfo, properties={ 'tax_form': None, 'enrollment_form': None, }) props.pop('tax_form') props.pop('enrollment_form') postdata.update(props) postdata.update({ 'link_id': self.data.user.link_id, 'student_info': None, 'user': self.data.user, 'parent': self.data.user, 'scope': self.gsoc, 'status': 'active', 'email': self.data.user.account.email(), 'mentor_for': [], 'org_admin_for': [], 'is_org_admin': False, 'is_mentor': False, }) response = self.post(role_url, postdata) self.assertResponseRedirect(response, url + '?validated') # hacky profile = GSoCProfile.all().get() profile.delete() postdata.update({ 'email': 'somerandominvalid@emailid', }) response = self.post(role_url, postdata) # yes! this is the protocol for form posts. We get an OK response # with the response containing the form's GET request page whenever # the form has an error and could not be posted. This is the architecture # chosen in order to save the form error state's while rendering the # error fields. self.assertResponseOK(response) error_dict = response.context['error'] self.assertTrue('email' in error_dict)
def getListData(self): idx = lists.getListIndex(self.request) def starter(start_key, q): if not start_key: q.filter('org_admin_for IN', self.data.org_admin_for) return True split = start_key.split(':', 1) if len(split) != 2: return False cls, start_key = split if cls == 'org_admin': q.filter('org_admin_for IN', self.data.org_admin_for) elif cls == 'mentor': q.filter('mentor_for IN', self.data.org_admin_for) else: return False if not start_key: return True start_entity = db.get(start_key) if not start_entity: return False q.filter('__key__ >=', start_entity.key()) return True def ender(entity, is_last, start): if not start: if is_last: return 'mentor:' else: return 'org_admin:' + str(entity.key()) split = start.split(':', 1) if len(split) != 2: return False cls, _ = split if is_last: return 'done' return '%s:%s' % (cls, str(entity.key())) def skipper(entity, start): if start.startswith('mentor:'): return False return any(self.data.orgAdminFor(i) for i in entity.mentor_for) q = GSoCProfile.all() if idx == 9: fields = {'mentor_for': self.data.user} response_builder = lists.RawQueryContentResponseBuilder( self.request, self._list_config, q, starter, ender=ender, skipper=skipper, prefetch=['user']) return response_builder.build() else: return None
def sendSurveyReminderForProject(self, request, *args, **kwargs): """Sends a reminder mail for a given StudentProject and Survey. A reminder is only send if no record is on file for the given Survey and StudentProject. Expects the following to be present in the POST dict: survey_key: specifies the key name for the ProjectSurvey to send reminders for survey_type: either project or grading depending on the type of Survey project_key: encoded Key which specifies the project to send a reminder for Args: request: Django Request object """ post_dict = request.POST project_key = post_dict.get('project_key') survey_key = post_dict.get('survey_key') survey_type = post_dict.get('survey_type') if not (project_key and survey_key and survey_type): # invalid task data, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid sendSurveyReminderForProject data: %s' % post_dict) # set model depending on survey type specified in POST if survey_type == 'project': survey_model = ProjectSurvey record_model = GSoCProjectSurveyRecord elif survey_type == 'grading': survey_model = GradingProjectSurvey record_model = GSoCGradingProjectSurveyRecord else: return error_handler.logErrorAndReturnOK( '%s is an invalid survey_type' %survey_type) # retrieve the project and survey project_key = db.Key(project_key) project = GSoCProject.get(project_key) if not project: # no existing project found, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid project specified %s:' % project_key) survey = survey_model.get_by_key_name(survey_key) if not survey: # no existing survey found, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid survey specified %s:' % survey_key) # try to retrieve an existing record q = record_model.all() q.filter('project', project) q.filter('survey', survey) record = q.get() if not record: # send reminder email because we found no record student_profile = project.parent() site_entity = site.singleton() if survey_type == 'project': url_name = 'gsoc_take_student_evaluation' to_name = student_profile.name() to_address = student_profile.email mail_template = 'v2/modules/gsoc/reminder/student_eval_reminder.html' elif survey_type == 'grading': url_name = 'gsoc_take_mentor_evaluation' mentors = db.get(project.mentors) to_address = [m.email for m in mentors] to_name = 'mentor(s) for project "%s"' %(project.title) mail_template = \ 'v2/modules/gsoc/reminder/mentor_eval_reminder.html' program = project.program hostname = system.getHostname() url_kwargs = { 'sponsor': program.scope.link_id, 'program': program.link_id, 'survey': survey.link_id, 'user': student_profile.link_id, 'id': str(project.key().id()), } url = reverse(url_name, kwargs=url_kwargs) survey_url = '%s://%s%s' % ('http', hostname, url) # set the context for the mail template mail_context = { 'student_name': student_profile.name(), 'project_title': project.title, 'survey_url': survey_url, 'survey_end': survey.survey_end, 'to_name': to_name, 'site_name': site_entity.site_name, 'sender_name': "The %s Team" % site_entity.site_name, } # set the sender (_, sender_address) = mail_dispatcher.getDefaultMailSender() mail_context['sender'] = sender_address # set the receiver and subject mail_context['to'] = to_address mail_context['subject'] = \ 'Evaluation Survey "%s" Reminder' %(survey.title) # find all org admins for the project's organization org = project.org q = GSoCProfile.all() q.filter('status', 'active') q.filter('org_admin_for', org) org_admins = q.fetch(1000) # collect email addresses for all found org admins org_admin_addresses = [] for org_admin in org_admins: org_admin_addresses.append(org_admin.email) if org_admin_addresses: mail_context['cc'] = org_admin_addresses # send out the email mail_dispatcher.sendMailFromTemplate(mail_template, mail_context) # return OK return http.HttpResponse()
def sendMailAboutGradingRecordResult(self, request, *args, **kwargs): """Sends out a mail about the result of one GradingRecord. Expects the following to be present in the POST dict: record_key: Specifies the key for the record to process. Args: request: Django Request object """ post_dict = request.POST record_key = post_dict.get('record_key') if not record_key: # no GradingRecord key specified, log and return OK error_handler.logErrorAndReturnOK( 'No valid record_key specified in POST data: %s' % request.POST) record = GSoCGradingRecord.get(db.Key(record_key)) if not record: # no valid GradingRecord key specified, log and return OK error_handler.logErrorAndReturnOK( 'No valid GradingRecord key specified: %s' % record_key) survey_group_entity = record.grading_survey_group project_entity = record.parent() student_entity = project_entity.parent() org_entity = project_entity.org site_entity = site.singleton() mail_context = { 'survey_group': survey_group_entity, 'grading_record': record, 'project': project_entity, 'organization': org_entity, 'site_name': site_entity.site_name, 'to_name': student_entity.name() } # set the sender (_, sender_address) = mail_dispatcher.getDefaultMailSender() mail_context['sender'] = sender_address # set the receiver and subject mail_context['to'] = student_entity.email mail_context['cc'] = [] mail_context['subject'] = '%s results processed for %s' %( survey_group_entity.name, project_entity.title) q = GSoCProfile.all() q.filter('org_admin_for', org_entity) org_admins = q.fetch(1000) # collect all mentors mentors = db.get(project_entity.mentors) # add them all to the cc list for org_member in org_admins + mentors: mail_context['cc'].append(org_member.email) # send out the email using a template mail_template = 'modules/gsoc/grading_record/mail/result.html' mail_dispatcher.sendMailFromTemplate(mail_template, mail_context) # return OK return http.HttpResponse()