コード例 #1
0
ファイル: proposal.py プロジェクト: adviti/melange
  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)
コード例 #2
0
ファイル: request.py プロジェクト: adviti/melange
    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)
コード例 #3
0
ファイル: profile.py プロジェクト: adviti/melange
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)
コード例 #4
0
ファイル: proposal_review.py プロジェクト: adviti/melange
    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
コード例 #5
0
ファイル: seed_db.py プロジェクト: adviti/melange
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')
コード例 #6
0
ファイル: duplicates.py プロジェクト: adviti/melange
  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
コード例 #7
0
ファイル: proposal_review.py プロジェクト: adviti/melange
    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)
コード例 #8
0
ファイル: access_checker.py プロジェクト: adviti/melange
  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)
コード例 #9
0
ファイル: proposal.py プロジェクト: adviti/melange
  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)
コード例 #10
0
ファイル: stats.py プロジェクト: adviti/melange
 def getGSoC2011Profile(link_id):
   program = GSoCProgram.get_by_key_name('google/gsoc2011')
   return GSoCProfile.all().filter('scope', program).filter('link_id', link_id).get()
コード例 #11
0
ファイル: trackings.py プロジェクト: adviti/melange
  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()
コード例 #12
0
 def getGSoC2012Profile(link_id):
   program = GSoCProgram.get_by_key_name('google/gsoc2012')
   return GSoCProfile.all().filter('scope', program).filter('link_id', link_id).get()
コード例 #13
0
  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)
コード例 #14
0
ファイル: dashboard.py プロジェクト: SRabbelier/Melange
  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
コード例 #15
0
ファイル: survey_reminders.py プロジェクト: adviti/melange
  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()
コード例 #16
0
    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
コード例 #17
0
  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()