def __call__(self, request, *args, **kwargs): """Custom call implementation that avoids looking up unneeded data.""" try: data, _, _ = self.initializer.initialize(request, args, kwargs) self.checkMaintenanceMode(data) action = args[0] if args else '' if action == 'login': return data.redirect.toUrl(users.create_login_url('/')) elif action == 'logout': return data.redirect.toUrl(users.create_logout_url('/')) else: settings = site_logic.singleton() program = settings.active_program if program: program_url = self.linker.program(program, program.homepage_url_name) return http.HttpResponseRedirect(program_url) else: return data.redirect.to('edit_site_settings') except exception.UserError as user_error: return self.error_handler.handleUserError(user_error, data) except exception.ServerError as server_error: return self.error_handler.handleServerError(server_error, data)
def sendRequestTaskNotification(org_admins, message): """Sends notifications to org admins that there is a student who requested more tasks from them. Args: org_admins: a list of org admins who the notification should be sent to message: a short message that will be included to the notification """ from soc.logic import site # get the default mail sender default_sender = mail_dispatcher.getDefaultMailSender() if not default_sender: # no valid sender found, abort return else: (sender_name, sender) = default_sender # get site name site_entity = site.singleton() template = DEF_TASK_REQUEST_TEMPLATE properties = { 'message': message, 'sender_name': sender_name, } for org_admin in org_admins: to = org_admin.user properties['to'] = to properties['to_name'] = to.name notifications.sendNotification(to, None, properties, subject, template)
def populate(self, redirect, request, args, kwargs): """Populates the fields in the RequestData object. Args: request: Django HTTPRequest object. args & kwargs: The args and kwargs django sends along. """ self.redirect = redirect self.request = request self.args = args self.kwargs = kwargs self.GET = request.GET self.POST = request.POST self.path = request.path.encode('utf-8') self.full_path = request.get_full_path().encode('utf-8') # XSRF middleware already retrieved it for us if not hasattr(request, 'site'): request.site = site.singleton() self.site = request.site self.user = user.current() if users.is_current_user_admin(): self.is_developer = True if self.user and self.user.is_developer: self.is_developer = True self.gae_user = users.get_current_user()
def __call__(self, request, *args, **kwargs): """Custom call implementation that avoids looking up unneeded data.""" try: data, _, _ = self.initializer.initialize(request, args, kwargs) self.checkMaintenanceMode(data) action = args[0] if args else '' if action == 'login': return data.redirect.toUrl(users.create_login_url('/')) elif action == 'logout': return data.redirect.toUrl(users.create_logout_url('/')) else: settings = site_logic.singleton() program = settings.active_program if program: program_url = self.linker.program( program, program.homepage_url_name) return http.HttpResponseRedirect(program_url) else: return data.redirect.to('edit_site_settings') except exception.UserError as user_error: return self.error_handler.handleUserError(user_error, data) except exception.ServerError as server_error: return self.error_handler.handleServerError(server_error, data)
def getTaskConversationMessageContext(message, to_emails, is_reply): """Sends out notifications to the conversation's participants. Args: message: Key (ndb) of GCIMessage to send. to_emails: List of recipients for the notification. is_reply: Whether this message is a reply to an existing conversation. Returns: Context dictionary for a mailer task. """ message_ent = message.get() conversation_ent = message_ent.conversation.get() program_ent = db.get(ndb.Key.to_old_key(conversation_ent.program)) author_ent = message_ent.author.get() url_kwargs = { 'sponsor': program_logic.getSponsorKey(program_ent).name(), 'program': program_ent.link_id, 'id': conversation_ent.key.integer_id(), } conversation_url = 'http://%(host)s%(conversation)s' % { 'host': site.getHostname(), 'conversation': reverse(url_names.GCI_CONVERSATION, kwargs=url_kwargs) } message_url = 'http://%(host)s%(conversation)s#m%(message_id)s' % { 'host': site.getHostname(), 'conversation': reverse(url_names.GCI_CONVERSATION, kwargs=url_kwargs), 'message_id': message.integer_id() } message_by = author_ent.user_id if author_ent else 'Melange' message_properties = { 'author_name': message_by, 'conversation_subject': conversation_ent.subject, 'message_content': message_ent.content, 'sender_name': 'The %s Team' % site.singleton().site_name, 'conversation_url': conversation_url, 'message_url': message_url, 'program_name': program_ent.name, 'is_reply': is_reply, } subject = ((DEF_NEW_MESSAGE_SUBJECT if is_reply else DEF_NEW_CONVERSATION_SUBJECT) % message_properties) template = (DEF_NEW_MESSAGE_NOTIFICATION_TEMPLATE if is_reply else DEF_NEW_CONVERSATION_NOTIFICATION_TEMPLATE) body = loader.render_to_string(template, dictionary=message_properties) return mailer.getMailContext(to=[], subject=subject, html=body, bcc=to_emails)
def getHostname(data=None): """Returns the hostname, taking in account site hostname settings. """ settings = data.site if data else site.singleton() if settings.hostname: return settings.hostname return getRawHostname()
def isSecondaryHostname(data=None): """Returns if the current request is from the secondary hostname. """ settings = data.site if data else site.singleton() if not settings.hostname: return False return getRawHostname().find(settings.hostname) >= 0
def site(self): """Returns the site field.""" if not self._isSet(self._site): # XSRF middleware might have already retrieved it for us if not hasattr(self.request, 'site'): # populate site.Site singleton to request field self.request.site = site_logic.singleton() self._site = self.request.site return self._site
def process(org_key): """Processes a single organization. Organization status is updated to ACCEPTED or REJECTED if the current status has been set to PRE_ACCEPTED or PRE_REJECTED, respectively, by program administrators. Args: org_key: Organization key. """ context = mapreduce_context.get() program_key = db.Key(context.mapreduce_spec.mapper.params['program_key']) if program_key.kind() == 'GSoCProgram': url_names = soc_urls.UrlNames elif program_key.kind() == 'GCIProgram': url_names = ci_urls.UrlNames else: raise ValueError('Invalid program type %s' % program_key.kind()) program = db.get(program_key) site = site_logic.singleton() org_key = ndb.Key.from_old_key(org_key) org_admins = profile_logic.getOrgAdmins(org_key) # We are "prefetching" the ProgramMessages entity here instead of fetching # it where it is required i.e. when the message templates are required # to build the email message body. We do this because we perform the # operation of fetching the ProgramMessages entity if it exists or create # it if it doesn't in a Appengine regular "db" transation whereas rest # of the updating of organization entities happen within an ndb transaction # because Organization model is an ndb model and such cross API nested # transactions are incompatible in Appengine. program_messages = program.getProgramMessages() @ndb.transactional def updateOrganizationStatus(): """Transactionally updates organization status.""" # only organizations defined for the specified program should be processed organization = org_key.get() if organization.program.to_old_key() == program_key: if organization.status == org_model.Status.PRE_ACCEPTED: org_logic.setStatus( organization, program, site, program_messages, org_model.Status.ACCEPTED, links.ABSOLUTE_LINKER, url_names, org_admins=org_admins) elif organization.status == org_model.Status.PRE_REJECTED: org_logic.setStatus( organization, program, site, program_messages, org_model.Status.REJECTED, links.ABSOLUTE_LINKER, url_names, org_admins=org_admins) updateOrganizationStatus()
def getTaskConversationMessageContext(message, to_emails, is_reply): """Sends out notifications to the conversation's participants. Args: message: Key (ndb) of GCIMessage to send. to_emails: List of recipients for the notification. is_reply: Whether this message is a reply to an existing conversation. Returns: Context dictionary for a mailer task. """ message_ent = message.get() conversation_ent = message_ent.conversation.get() program_ent = db.get(ndb.Key.to_old_key(conversation_ent.program)) author_ent = message_ent.author.get() url_kwargs = { 'sponsor': program_logic.getSponsorKey(program_ent).name(), 'program': program_ent.link_id, 'id': conversation_ent.key.integer_id(), } conversation_url = 'http://%(host)s%(conversation)s' % { 'host': site.getHostname(), 'conversation': reverse(url_names.GCI_CONVERSATION, kwargs=url_kwargs)} message_url = 'http://%(host)s%(conversation)s#m%(message_id)s' % { 'host': site.getHostname(), 'conversation': reverse(url_names.GCI_CONVERSATION, kwargs=url_kwargs), 'message_id': message.integer_id()} message_by = author_ent.user_id if author_ent else 'Melange' message_properties = { 'author_name': message_by, 'conversation_subject': conversation_ent.subject, 'message_content': message_ent.content, 'sender_name': 'The %s Team' % site.singleton().site_name, 'conversation_url': conversation_url, 'message_url': message_url, 'program_name': program_ent.name, 'is_reply': is_reply, } subject = (( DEF_NEW_MESSAGE_SUBJECT if is_reply else DEF_NEW_CONVERSATION_SUBJECT) % message_properties) template = ( DEF_NEW_MESSAGE_NOTIFICATION_TEMPLATE if is_reply else DEF_NEW_CONVERSATION_NOTIFICATION_TEMPLATE) body = loader.render_to_string(template, dictionary=message_properties) return mailer.getMailContext(to=[], subject=subject, html=body, bcc=to_emails)
def _GetSecretKey(request): """Gets the XSRF secret key from the request context. This function sets the key if it is not present. Args: request: A django.http.HttpRequest. Returns: The XSRF secret key for the request. """ if not hasattr(request, 'site'): request.site = site.singleton() return site.xsrfSecretKey(request.site)
def getDefaultMailSender(site=None): """Returns the sender that currently can be used to send emails. Args: site: Optional site_model.Site entity. If not supplied, it will be retrieved from the datastore or created. Returns: - A tuple containing (sender_name, sender_address) """ if not site: site = site_logic.singleton() # check if there is a noreply email address set no_reply_email = system.getApplicationNoReplyEmail() return (site.site_name, no_reply_email)
def getTaskCommentContext(task, comment, to_emails): """Sends out notifications to the subscribers. Args: task: task entity that comment made on. comment: comment entity. to_emails: list of recepients for the notification. """ url_kwargs = { 'sponsor': program_logic.getSponsorKey(task.program).name(), 'program': task.program.link_id, 'id': task.key().id(), } task_url = 'http://%(host)s%(task)s' % { 'host': site.getHostname(), 'task': reverse('gci_view_task', kwargs=url_kwargs) } author_key = ( comment_model.GCIComment.created_by.get_value_for_datastore(comment)) author = ndb.Key.from_old_key(author_key).get() if author_key else None commented_by = author.user_id if author else 'Melange' message_properties = { 'commented_by': commented_by, 'comment_title': comment.title, 'comment_content': comment.content, 'group': task.org.name, 'program_name': task.program.name, 'sender_name': 'The %s Team' % site.singleton().site_name, 'task_title': task.title, 'task_url': task_url, } subject = DEF_NEW_TASK_COMMENT_SUBJECT % message_properties template = DEF_NEW_TASK_COMMENT_NOTIFICATION_TEMPLATE body = loader.render_to_string(template, dictionary=message_properties) return mailer.getMailContext(to=[], subject=subject, html=body, bcc=to_emails)
def sendMail(to_user, subject, message_properties, template): """Sends an email with the specified properties and mail content Args: to_user: user entity to whom the mail should be sent subject: subject of the mail message_properties: contains those properties that need to be customized template: template that holds the content of the mail """ from soc.logic import site site_entity = site.singleton() site_name = site_entity.site_name # get the default mail sender default_sender = mail_dispatcher.getDefaultMailSender() if not default_sender: # no valid sender found, abort return else: (sender_name, sender) = default_sender to = accounts.denormalizeAccount(to_user.account).email() # create the message contents new_message_properties = { 'to_name': to_user.name, 'sender_name': sender_name, 'to': to, 'sender': sender, 'site_name': site_name, 'subject': force_unicode(subject) } messageProperties = dicts.merge(message_properties, new_message_properties) # send out the message using the default new notification template mail_dispatcher.sendMailFromTemplate(template, messageProperties)
def getTaskCommentContext(task, comment, to_emails): """Sends out notifications to the subscribers. Args: task: task entity that comment made on. comment: comment entity. to_emails: list of recepients for the notification. """ url_kwargs = { 'sponsor': program_logic.getSponsorKey(task.program).name(), 'program': task.program.link_id, 'id': task.key().id(), } task_url = 'http://%(host)s%(task)s' % { 'host': site.getHostname(), 'task': reverse('gci_view_task', kwargs=url_kwargs)} author_key = ( comment_model.GCIComment.created_by .get_value_for_datastore(comment)) author = ndb.Key.from_old_key(author_key).get() if author_key else None commented_by = author.user_id if author else 'Melange' message_properties = { 'commented_by': commented_by, 'comment_title': comment.title, 'comment_content': comment.content, 'group': task.org.name, 'program_name': task.program.name, 'sender_name': 'The %s Team' % site.singleton().site_name, 'task_title': task.title, 'task_url': task_url, } subject = DEF_NEW_TASK_COMMENT_SUBJECT % message_properties template = DEF_NEW_TASK_COMMENT_NOTIFICATION_TEMPLATE body = loader.render_to_string(template, dictionary=message_properties) return mailer.getMailContext(to=[], subject=subject, html=body, bcc=to_emails)
def sendMail(to_user, subject, message_properties, template): """Sends an email with the specified properties and mail content Args: to_user: user entity to whom the mail should be sent subject: subject of the mail message_properties: contains those properties that need to be customized template: template that holds the content of the mail """ site_entity = site.singleton() site_name = site_entity.site_name # get the default mail sender default_sender = mail_dispatcher.getDefaultMailSender(site=site_entity) if not default_sender: # no valid sender found, abort return else: (sender_name, sender) = default_sender to = accounts.denormalizeAccount(to_user.account).email() # create the message contents new_message_properties = { 'to_name': to_user.name, 'sender_name': sender_name, 'to': to, 'sender': sender, 'site_name': site_name, 'subject': force_unicode(subject) } messageProperties = dicts.merge(message_properties, new_message_properties) # send out the message using the default new notification template mail_dispatcher.sendMailFromTemplate(template, messageProperties)
def getDefaultMailSender(data=None): """Returns the sender that currently can be used to send emails. Args: data: an option RequestData object Returns: - A tuple containing (sender_name, sender_address) Consisting of: """ from soc.logic import system from soc.logic import site # check if there is a noreply email address set if data: site_entity = data.site else: site_entity = site.singleton() no_reply_email = system.getApplicationNoReplyEmail() return (site_entity.site_name, no_reply_email)
def __call__(self, request, *args, **kwargs): """Custom call implementation. This avoids looking up unneeded data. """ self.response = Response() self.init(request, args, kwargs) action = args[0] if args else '' if action == 'login': self.redirect.toUrl(users.create_login_url('/')) elif action == 'logout': self.redirect.toUrl(users.create_logout_url('/')) else: settings = site.singleton() program = settings.active_program if program: self.redirect.program(program).to(program.homepage_url_name) else: self.redirect.to('edit_site_settings') return self.response
def getTaskCommentContext(task, comment, to_emails): """Sends out notifications to the subscribers. Args: task: task entity that comment made on. comment: comment entity. to_emails: list of recepients for the notification. """ url_kwargs = { 'sponsor': task.program.scope_path, 'program': task.program.link_id, 'id': task.key().id(), } task_url = 'http://%(host)s%(task)s' % { 'host': system.getHostname(), 'task': reverse('gci_view_task', kwargs=url_kwargs)} commented_by = comment.created_by.name if comment.created_by else "Melange" message_properties = { 'commented_by': commented_by, 'comment_title': comment.title, 'comment_content': comment.content, 'group': task.org.name, 'program_name': task.program.name, 'sender_name': 'The %s Team' % site.singleton().site_name, 'task_title': task.title, 'task_url': task_url, } subject = DEF_NEW_TASK_COMMENT_SUBJECT % message_properties template = DEF_NEW_TASK_COMMENT_NOTIFICATION_TEMPLATE body = loader.render_to_string(template, dictionary=message_properties) return mailer.getMailContext(to=[], subject=subject, html=body, bcc=to_emails)
def _getSecretKey(self, request): """Gets the XSRF secret key from the request context.""" if not hasattr(request, 'site'): request.site = site.singleton() return site.xsrfSecretKey(request.site)
def sendSurveyReminderForProject(self, request, *args, **kwargs): """Sends a reminder mail for a given GSoCProject and Survey. A reminder is only send if no record is on file for the given Survey and GSoCProject. 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 = ndb.Key.from_old_key(project.parent_key()).get() site_entity = site.singleton() if survey_type == 'project': url_name = 'gsoc_take_student_evaluation' to_name = student.public_name to_address = student.contact.email mail_template = 'modules/gsoc/reminder/student_eval_reminder.html' elif survey_type == 'grading': url_name = 'gsoc_take_mentor_evaluation' mentors = ndb.get_multi( map(ndb.Key.from_old_key, project.mentors)) to_address = [mentor.contact.email for mentor in mentors] to_name = 'mentor(s) for project "%s"' % (project.title) mail_template = ( 'modules/gsoc/reminder/mentor_eval_reminder.html') program = project.program hostname = site.getHostname() url_kwargs = { 'sponsor': program_logic.getSponsorKey(program).name(), 'program': program.link_id, 'survey': survey.link_id, 'user': student.profile_id, 'id': str(project.key().id()), } url_path_and_query = reverse(url_name, kwargs=url_kwargs) survey_url = '%s://%s%s' % ('http', hostname, url_path_and_query) # set the context for the mail template mail_context = { 'student_name': student.public_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 "%s" Reminder' % survey.title) # find all org admins for the project's organization org_key = ndb.Key.from_old_key( GSoCProject.org.get_value_for_datastore(project)) org_admins = profile_logic.getOrgAdmins(org_key) # collect email addresses for all found org admins org_admin_addresses = [] for org_admin in org_admins: org_admin_addresses.append(org_admin.contact.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()
def process(org_key): """Processes a single organization. Organization status is updated to ACCEPTED or REJECTED if the current status has been set to PRE_ACCEPTED or PRE_REJECTED, respectively, by program administrators. Args: org_key: Organization key. """ context = mapreduce_context.get() program_key = db.Key(context.mapreduce_spec.mapper.params['program_key']) if program_key.kind() == 'GSoCProgram': url_names = soc_urls.UrlNames elif program_key.kind() == 'GCIProgram': url_names = ci_urls.UrlNames else: raise ValueError('Invalid program type %s' % program_key.kind()) program = db.get(program_key) site = site_logic.singleton() org_key = ndb.Key.from_old_key(org_key) org_admins = profile_logic.getOrgAdmins(org_key) # We are "prefetching" the ProgramMessages entity here instead of fetching # it where it is required i.e. when the message templates are required # to build the email message body. We do this because we perform the # operation of fetching the ProgramMessages entity if it exists or create # it if it doesn't in a Appengine regular "db" transation whereas rest # of the updating of organization entities happen within an ndb transaction # because Organization model is an ndb model and such cross API nested # transactions are incompatible in Appengine. program_messages = program.getProgramMessages() @ndb.transactional def updateOrganizationStatus(): """Transactionally updates organization status.""" # only organizations defined for the specified program should be processed organization = org_key.get() if organization.program.to_old_key() == program_key: if organization.status == org_model.Status.PRE_ACCEPTED: org_logic.setStatus(organization, program, site, program_messages, org_model.Status.ACCEPTED, links.ABSOLUTE_LINKER, url_names, org_admins=org_admins) elif organization.status == org_model.Status.PRE_REJECTED: org_logic.setStatus(organization, program, site, program_messages, org_model.Status.REJECTED, links.ABSOLUTE_LINKER, url_names, org_admins=org_admins) updateOrganizationStatus()
def sendSurveyReminderForProject(self, request, *args, **kwargs): """Sends a reminder mail for a given GSoCProject and Survey. A reminder is only send if no record is on file for the given Survey and GSoCProject. 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 = ndb.Key.from_old_key(project.parent_key()).get() site_entity = site.singleton() if survey_type == 'project': url_name = 'gsoc_take_student_evaluation' to_name = student.public_name to_address = student.contact.email mail_template = 'modules/gsoc/reminder/student_eval_reminder.html' elif survey_type == 'grading': url_name = 'gsoc_take_mentor_evaluation' mentors = ndb.get_multi(map(ndb.Key.from_old_key, project.mentors)) to_address = [mentor.contact.email for mentor in mentors] to_name = 'mentor(s) for project "%s"' % (project.title) mail_template = ( 'modules/gsoc/reminder/mentor_eval_reminder.html') program = project.program hostname = site.getHostname() url_kwargs = { 'sponsor': program_logic.getSponsorKey(program).name(), 'program': program.link_id, 'survey': survey.link_id, 'user': student.profile_id, 'id': str(project.key().id()), } url_path_and_query = reverse(url_name, kwargs=url_kwargs) survey_url = '%s://%s%s' % ('http', hostname, url_path_and_query) # set the context for the mail template mail_context = { 'student_name': student.public_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 "%s" Reminder' % survey.title) # find all org admins for the project's organization org_key = ndb.Key.from_old_key( GSoCProject.org.get_value_for_datastore(project)) org_admins = profile_logic.getOrgAdmins(org_key) # collect email addresses for all found org admins org_admin_addresses = [] for org_admin in org_admins: org_admin_addresses.append(org_admin.contact.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()
from soc.views.helper import context as context_helper from soc.views.helper import lists from soc.views.helper import url_patterns as soc_url_patterns from soc.modules.gsoc.views import forms from soc.modules.gsoc.views.helper import url_names from soc.modules.gsoc.views.helper import url_patterns from soc.modules.gsoc.views.helper.url_patterns import url from soc.modules.gsoc.views import base from summerofcode.request import links from summerofcode.models import shipment_tracking # TODO(daniel): once Site has been migrated to ndb, update this to make sure # it benefits from ndbs caching mechanisms. site = site_logic.singleton() decorator = OAuth2Decorator(client_id=site.google_client_id, client_secret=site.google_client_secret, scope='https://www.googleapis.com/auth/drive.file') URL_FMT = ("https://docs.google.com/feeds/download/spreadsheets/Export" + "?key=%s&exportFormat=csv&gid=%d") def redirect(self, uri): raise exception.Redirect(uri) class CallbackPage(base.GSoCRequestHandler): """View with the document picker. """
from soc.views.helper import context as context_helper from soc.views.helper import lists from soc.views.helper import url_patterns as soc_url_patterns from soc.modules.gsoc.views import forms from soc.modules.gsoc.views.helper import url_names from soc.modules.gsoc.views.helper import url_patterns from soc.modules.gsoc.views.helper.url_patterns import url from soc.modules.gsoc.views import base from summerofcode.request import links from summerofcode.models import shipment_tracking # TODO(daniel): once Site has been migrated to ndb, update this to make sure # it benefits from ndbs caching mechanisms. site = site_logic.singleton() decorator = OAuth2Decorator( client_id=site.google_client_id, client_secret=site.google_client_secret, scope='https://www.googleapis.com/auth/drive.file') URL_FMT = ("https://docs.google.com/feeds/download/spreadsheets/Export" + "?key=%s&exportFormat=csv&gid=%d") def redirect(self, uri): raise exception.Redirect(uri) class CallbackPage(base.GSoCRequestHandler): """View with the document picker.