def isStudentForSurvey(self): """Checks if the student can take survey for the project. """ assert access_checker.isSet(self.data.profile) assert access_checker.isSet(self.data.project) self.isProjectInURLValid() project = self.data.project # check if the project belongs to the current user and if so he # can access the survey expected_profile_key = project.parent_key() if expected_profile_key != self.data.profile.key(): raise AccessViolation(DEF_STUDENT_EVAL_DOES_NOT_BELONG_TO_YOU) # check if the project is still ongoing if project.status in ['invalid', 'withdrawn']: raise AccessViolation(DEF_EVAL_NOT_ACCESSIBLE_FOR_PROJECT) # check if the project has failed in a previous evaluation # TODO(Madhu): This still has a problem that when the project fails # in the final evaluation, the users will not be able to access the # midterm evaluation show page. Should be fixed. if project.status == 'failed' and project.failed_evaluations: failed_evals = db.get(project.failed_evaluations) fe_keynames = [f.grading_survey_group.grading_survey.key( ).id_or_name() for f in failed_evals] if self.data.student_evaluation.key().id_or_name() not in fe_keynames: raise AccessViolation(DEF_FAILED_PREVIOUS_EVAL % ( self.data.student_evaluation.short_name.lower()))
def isPossibleMentorForProposal(self): """Checks if the user is a possible mentor for the proposal in the data. """ assert isSet(self.profile) assert isSet(self.proposal) return self.profile.key() in self.proposal.possible_mentors
def newCommentContext(data, comment, to_emails): """Sends out a notification to alert the user of a new comment. Args: data: a RequestData object """ assert isSet(data.proposal) assert isSet(data.proposer) review_notification_url = data.redirect.comment(comment, full=True) edit_link = data.redirect.program().urlOf('edit_gsoc_profile', full=True) review_type = 'private' if comment.is_private else 'public' reviewed_name = data.proposal.title message_properties = { 'review_notification_url': review_notification_url, 'reviewer_name': comment.author.name(), 'reviewed_name': reviewed_name, 'review_content': comment.content, 'review_visibility': review_type, 'proposer_name': data.proposer.name(), 'org': data.proposal.org.name, 'profile_edit_link': edit_link, } # determine the subject subject = DEF_NEW_REVIEW_SUBJECT % message_properties template = DEF_NEW_REVIEW_NOTIFICATION_TEMPLATE if data.proposer.notify_public_comments and not comment.is_private: to_emails.append(data.proposer.email) return getContext(data, to_emails, message_properties, subject, template)
def context(self): assert isSet(self.data.program) assert isSet(self.data.timeline) assert isSet(self.data.student_evaluation_record) record = self.data.student_evaluation_record student = self.data.url_profile context = { 'page_name': 'Student evaluation - %s' % (student.name()), 'student': student.name(), 'organization': self.data.project.org.name, 'project': self.data.project.title, 'top_msg': LoggedInMsg(self.data, apply_link=False), 'css_prefix': GSoCStudentEvaluationReadOnlyTemplate.Meta.css_prefix, } if record: context['record'] = GSoCStudentEvaluationReadOnlyTemplate(record) if self.data.timeline.surveyPeriod(self.data.student_evaluation): if self.data.role == 'student': context['update_link'] = self.data.redirect.survey_record( self.data.student_evaluation.link_id).urlOf( 'gsoc_take_student_evaluation') else: context['submission_msg'] = ugettext( 'Bug your student to submit the evaluation.') return context
def canStudentUpdateProject(self): """Checks if the student can edit the project details.""" assert access_checker.isSet(self.data.program) assert access_checker.isSet(self.data.timeline) self.isProjectInURLValid() # check if the timeline allows updating project self.isProgramVisible() self.acceptedStudentsAnnounced() # check if the current used is an active student self.isActiveStudent() # check if the project belongs to the current user expected_profile_key = self.data.url_project.parent_key() if expected_profile_key != self.data.ndb_profile.key.to_old_key(): error_msg = access_checker.DEF_ENTITY_DOES_NOT_BELONG_TO_YOU % { 'name': 'project' } raise exception.Forbidden(message=error_msg) # check if the status allows the project to be updated if self.data.url_project.status in ['invalid', 'withdrawn', 'failed']: raise exception.Forbidden( message=access_checker.DEF_CANNOT_UPDATE_ENTITY % { 'name': 'project' })
def handledInviteContext(data): """Sends a message that the invite to obtain a role has been handled. Args: data: a RequestData object """ assert isSet(data.invite) assert isSet(data.invited_profile) # do not send notifications if the user has opted out if not data.invited_profile.notify_invite_handled: return {} status = data.invite.status action = 'resubmitted' if status == 'pending' else status edit_link = data.redirect.program().urlOf('edit_gsoc_profile', full=True) message_properties = { 'role_verbose' : data.invite.roleName(), 'org': data.invite.org.name, 'action': action, 'profile_edit_link': edit_link, } subject = DEF_HANDLED_INVITE_SUBJECT % message_properties template = DEF_HANDLED_INVITE_NOTIFICATION_TEMPLATE to_email = data.invited_profile.email # from user set to None to not leak who rejected it. return getContext(data, [to_email], message_properties, subject, template)
def context(self): """Handler to for GSoC Show Request Page HTTP get request. """ assert isSet(self.data.request_entity) assert isSet(self.data.can_respond) assert isSet(self.data.organization) assert isSet(self.data.requester) show_actions = self.data.request_entity.status in [ 'pending', 'withdrawn' ] if self.data.can_respond and self.data.request_entity.status == 'rejected': show_actions = True return { 'page_name': "Request to become a mentor", 'request': self.data.request_entity, 'org': self.data.organization, 'actions': self.ACTIONS, 'user_name': self.data.requester.name, 'user_email': accounts.denormalizeAccount(self.data.requester.account).email(), 'show_actions': show_actions, 'can_respond': self.data.can_respond, }
def getScores(self): """Gets all the scores for the proposal. """ assert isSet(self.data.private_comments_visible) assert isSet(self.data.proposal) if not self.data.private_comments_visible: return None total = 0 number = 0 user_score = 0 query = db.Query(GSoCScore).ancestor(self.data.proposal) for score in query: total += score.value number += 1 author_key = GSoCScore.author.get_value_for_datastore(score) if author_key == self.data.profile.key(): user_score = score.value return { 'average': total / number if number else 0, 'number': number, 'total': total, 'user_score': user_score, }
def context(self): assert isSet(self.data.url_user) assert isSet(self.data.url_profile) # TODO(nathaniel): Eliminate this state-setting call. self.data.redirect.profile() is_banned = self.data.url_profile.status == 'invalid' profile_banned = ToggleButtonTemplate( self.data, 'on_off', 'Banned', 'user-banned', self.data.redirect.urlOf(self._getActionURLName()), checked=is_banned, help_text=self._getHelpText(), labels={ 'checked': 'Yes', 'unchecked': 'No'}) self.toggle_buttons.append(profile_banned) context = { 'title': 'Host Actions', 'toggle_buttons': self.toggle_buttons, } return context
def context(self): assert isSet(self.data.url_user) assert isSet(self.data.url_profile) # TODO(nathaniel): Eliminate this state-setting call. self.data.redirect.profile() is_banned = self.data.url_profile.status == 'invalid' profile_banned = ToggleButtonTemplate(self.data, 'on_off', 'Banned', 'user-banned', self.data.redirect.urlOf( self._getActionURLName()), checked=is_banned, help_text=self._getHelpText(), labels={ 'checked': 'Yes', 'unchecked': 'No' }) self.toggle_buttons.append(profile_banned) context = { 'title': 'Host Actions', 'toggle_buttons': self.toggle_buttons, } return context
def handledRequestContext(data, status): """Sends a message that the request to get a role has been handled. Args: data: a RequestData object """ assert isSet(data.request_entity) assert isSet(data.requester_profile) # do not send notifications if the user has opted out if not data.requester_profile.notify_request_handled: return {} edit_link = data.redirect.program().urlOf('edit_gsoc_profile', full=True) message_properties = { 'role_verbose' : data.request_entity.roleName(), 'org': data.request_entity.org.name, 'action': status, 'profile_edit_link': edit_link, } subject = DEF_HANDLED_REQUEST_SUBJECT % message_properties template = DEF_HANDLED_REQUEST_NOTIFICATION_TEMPLATE to_email = data.requester_profile.email # from user set to None to not leak who rejected it. return getContext(data, [to_email], message_properties, subject, template)
def context(self, data, check, mutator): assert isSet(data.program) assert isSet(data.timeline) assert isSet(data.student_evaluation_record) record = data.student_evaluation_record student = data.url_ndb_profile org_key = project_model.GSoCProject.org.get_value_for_datastore( data.url_project) org = ndb.Key.from_old_key(org_key).get() context = { 'page_name': 'Student evaluation - %s' % (student.public_name), 'student': student.public_name, 'organization': org.name, 'project': data.url_project.title, 'css_prefix': GSoCStudentEvaluationReadOnlyTemplate.Meta.css_prefix, } if record: context['record'] = GSoCStudentEvaluationReadOnlyTemplate(record) if data.timeline.surveyPeriod(data.student_evaluation): if data.role == 'student': context['update_link'] = data.redirect.survey_record( data.student_evaluation.link_id).urlOf( 'gsoc_take_student_evaluation') else: context['submission_msg'] = ugettext( 'Bug your student to submit the evaluation.') return context
def canStudentUpdateProject(self): """Checks if the student can edit the project details.""" assert access_checker.isSet(self.data.program) assert access_checker.isSet(self.data.timeline) self.isProjectInURLValid() # check if the timeline allows updating project self.isProgramVisible() self.acceptedStudentsAnnounced() # check if the current used is an active student self.isActiveStudent() # check if the project belongs to the current user expected_profile_key = self.data.url_project.parent_key() if expected_profile_key != self.data.ndb_profile.key.to_old_key(): error_msg = access_checker.DEF_ENTITY_DOES_NOT_BELONG_TO_YOU % { 'name': 'project' } raise exception.Forbidden(message=error_msg) # check if the status allows the project to be updated if self.data.url_project.status in ['invalid', 'withdrawn', 'failed']: raise exception.Forbidden( message=access_checker.DEF_CANNOT_UPDATE_ENTITY % {'name': 'project'})
def _acceptRequest(self): """Accepts a request. """ assert isSet(self.data.organization) assert isSet(self.data.requester_profile) request_key = self.data.request_entity.key() profile_key = self.data.requester_profile.key() organization_key = self.data.organization.key() def accept_request_txn(): request = db.get(request_key) profile = db.get(profile_key) request.status = "accepted" profile.is_mentor = True profile.mentor_for.append(organization_key) profile.mentor_for = list(set(profile.mentor_for)) profile.put() request.put() context = notifications.handledRequestContext(self.data, request.status) sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request) # TODO(SRabbelier): just call as soon as we make User Request's parent db.run_in_transaction(sub_txn) accept_request_txn()
def context(self, data, check, mutator): assert access_checker.isSet(data.conversation) assert access_checker.isSet(data.user) # Marks the conversation as "read" for the user gciconversation_logic.markAllReadForConversationAndUser( data.conversation.key, ndb.Key.from_old_key(data.user.key()) ) num_users = gciconversation_logic.queryConversationUserForConversation(data.conversation.key).count() messages = gcimessage_logic.queryForConversation(data.conversation.key).order( gcimessage_model.GCIMessage.sent_on ) for message in messages: message.author_name = db.get(ndb.Key.to_old_key(message.author)).name message.sent_on_relative = timeformat_helper.relativeTime(message.sent_on) message.sent_on_ctime = message.sent_on.ctime() return { "page_name": data.conversation.subject, "conversation": data.conversation, "num_users": num_users, "messages": messages, "user_list": UserList(data), "user_actions": UserActions(data), "reply_action": urlresolvers.reverse(url_names.GCI_CONVERSATION_REPLY, kwargs=data.kwargs), }
def context(self): """See soc.views.template.Template.context for full specification.""" assert access_checker.isSet(self.data.conversation) assert access_checker.isSet(self.data.user) query = gciconversation_logic.queryConversationUserForConversationAndUser( self.data.conversation.key, ndb.Key.from_old_key(self.data.user.key()) ) conv_user_results = query.fetch(1) assert conv_user_results conv_user = conv_user_results[0] self.data.redirect.id() url = self.data.redirect.urlOf(url_names.GCI_CONVERSATION_NOTIFICATION_TOGGLE) enable_notifications = toggle_button_view.ToggleButtonTemplate( self.data, "on_off", translation.ugettext("Enable Notifications"), "notifications-enabled", url, checked=conv_user.enable_notifications, help_text=self.DEF_ENABLE_NOTIFICATIONS_HELP, labels={"checked": "Yes", "unchecked": "No"}, ) self.toggle_buttons.append(enable_notifications) return {"title": translation.ugettext("Conversation Actions"), "toggle_buttons": self.toggle_buttons}
def context(self): assert isSet(self.data.program) assert isSet(self.data.url_profile) assert isSet(self.data.url_user) user = self.data.url_user profile = self.data.url_profile program = self.data.program r = self.redirect.profile() links = [] for project in GSoCProject.all().ancestor(profile): r.project(project.key().id()) links.append(r.urlOf('gsoc_project_details', full=True)) r = self.redirect.profile() return { 'page_name': '%s Profile - %s' % (program.short_name, profile.name()), 'program_name': program.name, 'form_top_msg': LoggedInMsg(self.data, apply_link=False), 'user': profile_show.UserReadOnlyTemplate(user), 'profile': GSoCProfileReadOnlyTemplate(profile), 'links': links, 'css_prefix': GSoCProfileReadOnlyTemplate.Meta.css_prefix, 'submit_tax_link': r.urlOf('gsoc_tax_form_admin'), 'submit_enrollment_link': r.urlOf('gsoc_enrollment_form_admin'), }
def context(self): """Handler to for GSoC Show Request Page HTTP get request. """ assert isSet(self.data.request_entity) assert isSet(self.data.can_respond) assert isSet(self.data.organization) assert isSet(self.data.requester) # This code is dupcliated between request and invite status = self.data.request_entity.status can_accept = can_reject = can_withdraw = can_resubmit = False if self.data.can_respond: # admin speaking if status == "pending": can_accept = True can_reject = True if status == "rejected": can_accept = True else: # requester speaking if status == "withdrawn": can_resubmit = True if status == "pending": can_withdraw = True show_actions = can_accept or can_reject or can_withdraw or can_resubmit org_key = self.data.organization.key() status_msg = None if self.data.requester_profile.key() == self.data.profile.key(): if org_key in self.data.requester_profile.org_admin_for: status_msg = "You are now an organization administrator for this organization." elif org_key in self.data.requester_profile.mentor_for: status_msg = "You are now a mentor for this organization." else: if org_key in self.data.requester_profile.org_admin_for: status_msg = "This user is now an organization administrator with your organization." elif org_key in self.data.requester_profile.mentor_for: status_msg = "This user is now a mentor with your organization." return { "page_name": "Request to become a mentor", "request": self.data.request_entity, "org": self.data.organization, "actions": self.ACTIONS, "status_msg": status_msg, "user_name": self.data.requester_profile.name(), "user_link_id": self.data.requester.link_id, "user_email": accounts.denormalizeAccount(self.data.requester.account).email(), "show_actions": show_actions, "can_accept": can_accept, "can_reject": can_reject, "can_withdraw": can_withdraw, "can_resubmit": can_resubmit, }
def isPossibleMentorForProposal(self, mentor_profile=None): """Checks if the user is a possible mentor for the proposal in the data. """ assert isSet(self.profile) assert isSet(self.proposal) profile = mentor_profile if mentor_profile else self.profile return profile.key() in self.proposal.possible_mentors
def isUserInConversation(self): """Checks if the user is part of a conversation.""" assert access_checker.isSet(self.data.conversation) assert access_checker.isSet(self.data.user) query = gciconversation_logic.queryConversationUserForConversationAndUser( self.data.conversation.key, ndb.Key.from_old_key(self.data.user.key())) if query.count() == 0: raise exception.Forbidden(message=DEF_NOT_IN_CONVERSATION)
def checkAccess(self): self.mutator.projectFromKwargs() self.mutator.mentorEvaluationFromKwargs() self.mutator.mentorEvaluationRecordFromKwargs() assert isSet(self.data.project) assert isSet(self.data.mentor_evaluation) self.check.isProfileActive() self.check.isMentorForSurvey()
def mentorEvaluationRecordFromKwargs(self): """Sets the mentor evaluation record in RequestData object. """ assert access_checker.isSet(self.data.mentor_evaluation) assert access_checker.isSet(self.data.project) self.data.organization = self.data.project.org q = GSoCGradingProjectSurveyRecord.all() q.filter('project', self.data.project) q.filter('survey', self.data.mentor_evaluation) self.data.mentor_evaluation_record = q.get()
def post(self): assert isSet(self.data.proposer) assert isSet(self.data.proposal) comment = self.createCommentFromForm() if comment: self.redirect.review(self.data.proposal.key().id(), self.data.proposer.link_id) self.redirect.to('review_gsoc_proposal') else: # TODO: probably we want to handle an error somehow pass
def _acceptRequest(self): """Accepts a request. """ assert isSet(self.data.organization) assert isSet(self.data.requester_profile) self.data.request_entity.status = 'accepted' self.data.requester_profile.mentor_for.append(self.data.organization.key()) self.data.requester_profile.put() self.data.request_entity.put()
def createOrUpdateScore(self, value): """Creates a new score or updates a score if there is already one posted by the current user. If the value passed in is 0 then the Score of the user will be removed and None will be returned. Args: value: The value of the score the user gave as an integer. Returns: The score entity that was created/updated or None if value is 0. """ assert isSet(self.data.proposal) assert isSet(self.data.proposal_org) max_score = self.data.proposal_org.max_score if value < 0 or value > max_score: raise BadRequest("Score must not be higher than %d" % max_score) query = db.Query(GSoCScore) query.filter("author = ", self.data.profile) query.ancestor(self.data.proposal) def update_score_trx(): delta = 0 # update score entity score = query.get() if not score: if not value: return old_value = 0 score = GSoCScore(parent=self.data.proposal, author=self.data.profile, value=value) score.put() delta = 1 else: old_value = score.value if not value: delta = -1 score.delete() else: score.value = value score.put() # update total score for the proposal proposal = db.get(self.data.proposal.key()) proposal.score += value - old_value proposal.nr_scores += delta proposal.put() db.run_in_transaction(update_score_trx)
def _acceptRequest(self): """Accepts a request. """ assert isSet(self.data.organization) assert isSet(self.data.requester_profile) self.data.request_entity.status = 'accepted' self.data.requester_profile.mentor_for.append( self.data.organization.key()) self.data.requester_profile.put() self.data.request_entity.put()
def canUserEditTask(self): """Returns True/False depending on whether the currently logged in user can edit the task. """ assert access_checker.isSet(self.data.task) assert access_checker.isSet(self.data.mentor_for) task = self.data.task valid_org_keys = [o.key() for o in self.data.mentor_for] if task.org.key() not in valid_org_keys: return False return True
def canCreateTask(self): """Checks whether the currently logged in user can edit the task. """ assert access_checker.isSet(self.data.organization) assert access_checker.isSet(self.data.mentor_for) valid_org_keys = [o.key() for o in self.data.mentor_for] if self.data.organization.key() not in valid_org_keys: raise AccessViolation(DEF_NO_TASK_CREATE_PRIV % ( self.data.organization.name)) if (request_data.isBefore(self.data.timeline.orgsAnnouncedOn()) \ or self.data.timeline.tasksClaimEnded()): raise AccessViolation(access_checker.DEF_PAGE_INACTIVE)
def checkAccess(self): self.check.isProgramVisible() self.check.isProfileActive() self.mutator.proposalFromKwargs() self.mutator.commentVisible() assert isSet(self.data.proposer) assert isSet(self.data.proposal_org) # check if the comment is given by the author of the proposal if self.data.proposer.key() == self.data.profile.key(): self.data.public_only = True return self.data.public_only = False self.check.isMentorForOrganization(self.data.proposal_org)
def updatedProposalContext(data, proposal, to_emails): """Sends out a notification to alert the user of an updated proposal. Args: data: a RequestData object """ assert isSet(data.organization) proposal_notification_url = links.ABSOLUTE_LINKER.userId( data.ndb_profile.key, proposal.key().id(), url_names.PROPOSAL_REVIEW) edit_profile_url = links.ABSOLUTE_LINKER.program( data.program, urls.UrlNames.PROFILE_EDIT, secure=True) message_properties = { 'proposal_notification_url': proposal_notification_url, 'proposer_name': data.ndb_profile.public_name, 'proposal_name': proposal.title, 'proposal_content': proposal.content, 'org': data.organization.name, 'profile_edit_link': edit_profile_url, } # determine the subject subject = DEF_UPDATED_PROPOSAL_SUBJECT % message_properties template = DEF_UPDATED_PROPOSAL_NOTIFICATION_TEMPLATE return getContext(data.site, data.program, to_emails, message_properties, subject, template)
def checkAccess(self, data, check, mutator): mutator.studentEvaluationFromKwargs() mutator.studentEvaluationRecordFromKwargs() assert isSet(data.student_evaluation) if user_logic.isHostForProgram(data.ndb_user, data.program.key()): return show_url = data.redirect.survey_record( data.student_evaluation.link_id).urlOf( 'gsoc_show_student_evaluation') check.isStudentSurveyActive( data.student_evaluation, data.url_ndb_profile, show_url=show_url) check.isProfileActive() # TODO(dcrodman): When GSoCProject is converted to NDB, this Key # conversion will need to be removed. org_key = project_model.GSoCProject.org.get_value_for_datastore( data.url_project) org_key = ndb.Key.from_old_key(org_key) if data.orgAdminFor(org_key): raise exception.Redirect(show_url) check.canUserTakeSurvey(data.student_evaluation, 'student') check.isStudentForSurvey()
def context(self): """Handler to for GSoC Organization Home page HTTP get request. """ current_timeline = timeline_logic.getCurrentTimeline( self.data.program_timeline, self.data.org_app) assert isSet(self.data.organization) organization = self.data.organization context = { 'page_name': '%s - Homepage' % organization.short_name, 'organization': organization, 'contact': Contact(self.data), 'tags': organization.tags_string(organization.org_tag), 'apply': Apply(self.data, current_timeline), } if self.data.orgAdminFor(organization): r = self.redirect r.organization(organization) context['edit_link'] = r.urlOf('edit_gsoc_org_profile') context['invite_admin_link'] = r.invite('org_admin').urlOf('gsoc_invite') context['invite_mentor_link'] = r.invite('mentor').urlOf('gsoc_invite') if self.data.timeline.studentsAnnounced(): context['project_list'] = ProjectList(self.request, self.data) return context
def clean_link_id(self): """Accepts link_id of users which may be invited. """ assert isSet(self.request_data.organization) invited_user = None link_id_cleaner = cleaning.clean_link_id('link_id') try: link_id = link_id_cleaner(self) except djangoforms.ValidationError, e: if e.code != 'invalid': raise email_cleaner = cleaning.clean_email('link_id') try: email_address = email_cleaner(self) except djangoforms.ValidationError, e: if e.code != 'invalid': raise msg = ugettext(u'Enter a valid link_id or email address.') raise djangoforms.ValidationError(msg, code='invalid')
def post(self, data, check, mutator): """Get handler for the code sample delete file.""" assert isSet(data.url_project) try: id_value = int(data.request.POST['id']) code_sample = GSoCCodeSample.get_by_id(id_value, data.url_project) if not code_sample: raise exception.BadRequest(message='Requested code sample not found') upload_of_work = code_sample.upload_of_work def txn(): code_sample.delete() if upload_of_work: # this is executed outside of transaction upload_of_work.delete() if data.url_project.countCodeSamples() <= 1: project = GSoCProject.get(data.url_project.key()) project.code_samples_submitted = False project.put() db.run_in_transaction(txn) url = links.LINKER.userId( data.url_profile.key(), data.url_project.key().id(), url_names.GSOC_PROJECT_UPDATE) return http.HttpResponseRedirect(url) except KeyError: raise exception.BadRequest(message='id argument missing in POST data') except ValueError: raise exception.BadRequest( message='id argument in POST data is not a number')
def checkCanUserEditTask(self): """Checks whether the currently logged in user can edit the task. """ assert access_checker.isSet(self.data.task) if not self.canUserEditTask(): raise AccessViolation(DEF_NO_TASK_EDIT_PRIV % (self.data.task.org.name))
def updatedProposalContext(data, proposal, to_emails): """Sends out a notification to alert the user of an updated proposal. Args: data: a RequestData object """ assert isSet(data.organization) proposal_notification_url = links.ABSOLUTE_LINKER.userId( data.ndb_profile.key, proposal.key().id(), url_names.PROPOSAL_REVIEW) edit_profile_url = links.ABSOLUTE_LINKER.program( data.program, urls.UrlNames.PROFILE_EDIT, secure=True) message_properties = { 'proposal_notification_url': proposal_notification_url, 'proposer_name': data.ndb_profile.public_name, 'proposal_name': proposal.title, 'proposal_content': proposal.content, 'org': data.organization.name, 'profile_edit_link': edit_profile_url, } # determine the subject subject = DEF_UPDATED_PROPOSAL_SUBJECT % message_properties template = DEF_UPDATED_PROPOSAL_NOTIFICATION_TEMPLATE return getContext( data.site, data.program, to_emails, message_properties, subject, template)
def context(self, data, check, mutator): context = super(GCIProfileShowAdminPage, self).context(data, check, mutator) assert access_checker.isSet(data.url_profile.student_info) profile = data.url_profile student_info = profile.student_info if student_info: if student_info.consent_form_verified: context['verify_consent_form_init'] = 'unchecked' else: context['verify_consent_form_init'] = 'checked' if student_info.student_id_form_verified: context['verify_student_id_form_init'] = 'unchecked' else: context['verify_student_id_form_init'] = 'checked' # TODO(nathaniel): Eliminate this state-setting call. data.redirect.profile(profile.link_id) context['student_task_link'] = data.redirect.urlOf( url_names.GCI_STUDENT_TASKS) context['user'] = self._getUserReadOnlyTemplate(data.url_user) return context
def organization(self, organization=None): """Sets the kwargs for an url_patterns.ORG redirect.""" if not organization: assert access_checker.isSet(self._data.organization) organization = self._data.organization self.program() self.kwargs['organization'] = organization.link_id
def isTaskVisible(self): """Checks if the task is visible to the public. Returns: True if the task is visible, if the task is not visible but the user can edit the task, False. """ assert access_checker.isSet(self.data.task) # TODO(nathaniel): Yep, this is weird. can_edit = False try: self.checkCanUserEditTask() self.checkHasTaskEditableStatus() self.checkTimelineAllowsTaskEditing() can_edit = True except exception.UserError: pass if not self.data.timeline.tasksPubliclyVisible(): if can_edit: return False period = self.data.timeline.tasksPubliclyVisibleOn() raise exception.Forbidden( message=access_checker.DEF_PAGE_INACTIVE_BEFORE % period) if not self.data.task.isAvailable(): if can_edit: return False raise exception.Forbidden(message=access_checker.DEF_PAGE_INACTIVE) return True
def checkCanUserEditTask(self): """Checks whether the currently logged in user can edit the task.""" assert access_checker.isSet(self.data.task) if not self.canUserEditTask(): raise exception.Forbidden( message=DEF_NO_TASK_EDIT_PRIV % (self.data.task.org.name))
def post(self, data, check, mutator): """Handles the POST request when editing a GradingRecord.""" assert isSet(data.record) record_form = GradingRecordForm(data=data.POST) if not record_form.is_valid(): return self.get(data, check, mutator) decision = record_form.cleaned_data['grade_decision'] locked = record_form.cleaned_data['locked'] record = data.record record.grade_decision = decision record.locked = locked record.put() grading_record.updateProjectsForGradingRecords([record]) # pass along these params as POST to the new task task_params = {'record_key': str(record.key())} task_url = '/tasks/gsoc/grading_record/mail_result' mail_task = taskqueue.Task(params=task_params, url=task_url) mail_task.add('mail') data.redirect.id(record.grading_survey_group.key().id_or_name()) return data.redirect.to('gsoc_grading_record_overview')
def checkAccess(self, data, check, mutator): mutator.mentorEvaluationFromKwargs() mutator.mentorEvaluationRecordFromKwargs() assert isSet(data.mentor_evaluation) check.isProfileActive() check.isMentorForSurvey()
def getComments(self): """Gets all the comments for the proposal visible by the current user. """ assert isSet(self.data.private_comments_visible) assert isSet(self.data.proposal) public_comments = [] private_comments = [] query = db.Query(GSoCComment).ancestor(self.data.proposal) for comment in query: if not comment.is_private: public_comments.append(comment) elif self.data.private_comments_visible: private_comments.append(comment) return public_comments, private_comments
def checkAccess(self, data, check, mutator): if not data.org_app: raise exception.NotFound(message=access_checker.DEF_NO_ORG_APP % data.program.name) mutator.orgAppRecordIfIdInKwargs() assert access_checker.isSet(data.org_app_record) check.canViewOrgApp()
def post(self): """Handler to for GSoC Show Request Page HTTP post request. """ assert isSet(self.data.action) assert isSet(self.data.request_entity) if self.data.action == self.ACTIONS['accept']: self._acceptRequest() elif self.data.action == self.ACTIONS['reject']: self._rejectRequest() elif self.data.action == self.ACTIONS['resubmit']: self._resubmitRequest() elif self.data.action == self.ACTIONS['withdraw']: self._withdrawRequest() self.redirect.program() self.redirect.to('gsoc_dashboard')
def toggleNotificationsEnabled(self, data, value): """Makes email notifications enabled or disabled. Args: data: A RequestData describing the current request. value: can be either "checked" or "unchecked". """ assert access_checker.isSet(data.conversation) assert access_checker.isSet(data.user) query = gciconversation_logic.queryConversationUserForConversationAndUser( data.conversation.key, ndb.Key.from_old_key(data.user.key())) conv_user_results = query.fetch(1) assert conv_user_results conv_user = conv_user_results[0] if value != 'checked' and value != 'unchecked': raise exception.BadRequest( message='Invalid post data. Value must be checked or unchecked.' ) if value == 'checked' and not conv_user.enable_notifications: raise exception.BadRequest( message='Notifications were already disabled.') if value == 'unchecked' and conv_user.enable_notifications: raise exception.BadRequest( message='Notifications were already enabled.') conv_user_key = conv_user.key # TODO(nathaniel): Remove the suppression on the following line when # https://bitbucket.org/logilab/pylint.org/issue/6/false-positive-no # is fixed. @ndb.transactional(xg=True) # pylint: disable=no-value-for-parameter def set_notifications_enabled_txn(): # transactionally get latest GCIConversationUser conv_user = conv_user_key.get() if value == 'unchecked': conv_user.enable_notifications = True elif value == 'checked': conv_user.enable_notifications = False conv_user.put() set_notifications_enabled_txn()
def jsonContext(self): """Handler for JSON requests. """ assert isSet(self.data.organization) list_content = ProjectList(self.request, self.data).getListData() if not list_content: raise AccessViolation( 'You do not have access to this data') return list_content.content()
def program(self, program=None): """Sets kwargs for an url_patterns.PROGRAM redirect.""" if not program: assert access_checker.isSet(self._data.program) program = self._data.program self._clear() self.kwargs['sponsor'] = program_logic.getSponsorKey(program).name() self.kwargs['program'] = program.link_id
def context(self, data, check, mutator): """See soc.views.base.RequestHandler.context for specification.""" assert isSet(data.program) assert isSet(data.user) profile = self._getProfile(data) program = data.program user_template = self._getUserReadOnlyTemplate(data.user) profile_template = self._getProfileReadOnlyTemplate(profile) css_prefix = profile_template.Meta.css_prefix return { 'page_name': '%s Profile - %s' % (program.short_name, profile.name()), 'program_name': program.name, 'user': user_template, 'profile': profile_template, 'css_prefix': css_prefix, 'tabs': self._getTabs(data) }
def checkAccess(self, data, check, mutator): mutator.mentorEvaluationFromKwargs() mutator.mentorEvaluationRecordFromKwargs() assert isSet(data.mentor_evaluation) show_url = data.redirect.survey_record( data.mentor_evaluation.link_id).urlOf( 'gsoc_show_mentor_evaluation') check.isSurveyActive(data.mentor_evaluation, show_url) check.canUserTakeSurvey(data.mentor_evaluation, 'org') check.isMentorForSurvey()
def createReplyFromForm(self, data): """Creates a new message based on the data inserted into the form. Args: data: A RequestData object for the current request. Returns: A newly created message entity. """ assert access_checker.isSet(data.conversation) assert access_checker.isSet(data.user) content = cleaning.sanitize_html_string( data.request.POST['content'].strip()) if len(html.strip_tags(content).strip()) == 0: raise exception.Forbidden(message=DEF_BLANK_MESSAGE) author = ndb.Key.from_old_key(data.user.key()) return gciconversation_logic.createMessage(data.conversation.key, author, content)
def context(self, data, check, mutator): assert access_checker.isSet(data.conversation) assert access_checker.isSet(data.user) # Marks the conversation as "read" for the user gciconversation_logic.markAllReadForConversationAndUser( data.conversation.key, ndb.Key.from_old_key(data.user.key())) num_users = ( gciconversation_logic.queryConversationUserForConversation( data.conversation.key).count()) messages = gcimessage_logic.queryForConversation( data.conversation.key).order(gcimessage_model.GCIMessage.sent_on) for message in messages: message.author_name = db.get(ndb.Key.to_old_key( message.author)).name message.sent_on_relative = timeformat_helper.relativeTime( message.sent_on) message.sent_on_ctime = message.sent_on.ctime() return { 'page_name': data.conversation.subject, 'conversation': data.conversation, 'num_users': num_users, 'messages': messages, 'user_list': UserList(data), 'user_actions': UserActions(data), 'reply_action': urlresolvers.reverse(url_names.GCI_CONVERSATION_REPLY, kwargs=data.kwargs) }
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 comment_form.cleaned_data['author'] = self.data.profile return comment_form.create(commit=True, parent=self.data.proposal)
def mentorEvaluationRecordFromKwargs(self): """Sets the mentor evaluation record in RequestData object. """ assert access_checker.isSet(self.data.mentor_evaluation) # TODO(daniel): get rid of this ugly mutation! org_key = project_model.GSoCProject.org.get_value_for_datastore( self.data.url_project) self.data._url_ndb_org = ndb.Key.from_old_key(org_key).get() q = GSoCGradingProjectSurveyRecord.all() q.filter('project', self.data.url_project) q.filter('survey', self.data.mentor_evaluation) self.data.mentor_evaluation_record = q.get()
def userOrg(self, user=None, organization=None): """Sets args for an url_patterns.USER_ORG redirect.""" if not user: assert 'user' in self._data.kwargs user = self._data.kwargs['user'] if not organization: assert access_checker.isSet(self._data.organization) organization = self._data.organization self.program() self.kwargs['user'] = user self.kwargs['organization'] = organization.link_id return self
def canOrgAdminUpdateProject(self): """Checks if the organization admin can edit the project details.""" assert access_checker.isSet(self.data.program) assert access_checker.isSet(self.data.timeline) self.isProjectInURLValid() # check if the timeline allows updating project self.isProgramVisible() self.acceptedStudentsAnnounced() # check if the person is an organization admin for the organization # to which the project was assigned org_key = ndb.Key.from_old_key( project_model.GSoCProject.org.get_value_for_datastore( self.data.url_project)) self.isOrgAdminForOrganization(org_key) # check if the status allows the project to be updated if self.data.url_project.status in ['invalid', 'withdrawn', 'failed']: raise exception.Forbidden( message=access_checker.DEF_CANNOT_UPDATE_ENTITY % {'name': 'project'})