示例#1
0
  def __init__(self, attach_pb, project_name):
    """Get IssueAttachmentContent PB and make its fields available as attrs.

    Args:
      attach_pb: Attachment part of IssueComment protocol buffer.
      project_name: string Name of the current project.
    """
    super(AttachmentView, self).__init__(attach_pb)
    self.filesizestr = template_helpers.BytesKbOrMb(attach_pb.filesize)
    self.downloadurl = 'attachment?aid=%s' % attach_pb.attachment_id

    self.url = None
    self.thumbnail_url = None
    self.video_url = None
    if IsViewableImage(attach_pb.mimetype, attach_pb.filesize):
      self.url = self.downloadurl + '&inline=1'
      self.thumbnail_url = self.url + '&thumb=1'
    elif IsViewableVideo(attach_pb.mimetype, attach_pb.filesize):
      self.url = self.downloadurl + '&inline=1'
      self.video_url = self.url
    elif IsViewableText(attach_pb.mimetype, attach_pb.filesize):
      self.url = tracker_helpers.FormatRelativeIssueURL(
          project_name, urls.ISSUE_ATTACHMENT_TEXT,
          aid=attach_pb.attachment_id)

    self.iconurl = '/images/paperclip.png'
示例#2
0
 def testBytesKbOrMb(self):
   self.assertEqual('1023 bytes', template_helpers.BytesKbOrMb(1023))
   self.assertEqual('1.0 KB', template_helpers.BytesKbOrMb(1024))
   self.assertEqual('1023 KB', template_helpers.BytesKbOrMb(1024 * 1023))
   self.assertEqual('1.0 MB', template_helpers.BytesKbOrMb(1024 * 1024))
   self.assertEqual('98.0 MB', template_helpers.BytesKbOrMb(98 * 1024 * 1024))
   self.assertEqual('99 MB', template_helpers.BytesKbOrMb(99 * 1024 * 1024))
示例#3
0
  def _BuildComponentQuota(self, used_bytes, quota_bytes, field_name):
    """Return an object to easily display quota info in EZT."""
    if quota_bytes:
      used_percent = 100 * used_bytes // quota_bytes
    else:
      used_percent = 0

    quota_mb = quota_bytes // 1024 // 1024

    return template_helpers.EZTItem(
        used=template_helpers.BytesKbOrMb(used_bytes),
        quota_mb=quota_mb,
        used_percent=used_percent,
        avail_percent=100 - used_percent,
        field_name=field_name)
示例#4
0
    def __init__(self, attach_pb, project_name):
        """Get IssueAttachmentContent PB and make its fields available as attrs.

    Args:
      attach_pb: Attachment part of IssueComment protocol buffer.
      project_name: string Name of the current project.
    """
        super(AttachmentView, self).__init__(attach_pb)
        self.filesizestr = template_helpers.BytesKbOrMb(attach_pb.filesize)
        self.downloadurl = attachment_helpers.GetDownloadURL(
            attach_pb.attachment_id)
        self.url = attachment_helpers.GetViewURL(attach_pb, self.downloadurl,
                                                 project_name)
        self.thumbnail_url = attachment_helpers.GetThumbnailURL(
            attach_pb, self.downloadurl)
        self.video_url = attachment_helpers.GetVideoURL(
            attach_pb, self.downloadurl)

        self.iconurl = '/images/paperclip.png'
示例#5
0
    def GatherPageData(self, mr):
        """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
        with mr.profiler.Phase('getting config'):
            config = self.services.config.GetProjectConfig(
                mr.cnxn, mr.project_id)

        # In addition to checking perms, we adjust some default field values for
        # project members.
        is_member = framework_bizobj.UserIsInProject(mr.project,
                                                     mr.auth.effective_ids)
        page_perms = self.MakePagePerms(
            mr, None, permissions.CREATE_ISSUE, permissions.SET_STAR,
            permissions.EDIT_ISSUE, permissions.EDIT_ISSUE_SUMMARY,
            permissions.EDIT_ISSUE_STATUS, permissions.EDIT_ISSUE_OWNER,
            permissions.EDIT_ISSUE_CC)

        with work_env.WorkEnv(mr, self.services) as we:
            userprefs = we.GetUserPrefs(mr.auth.user_id)
            code_font = any(
                pref for pref in userprefs.prefs
                if pref.name == 'code_font' and pref.value == 'true')

        template = self._GetTemplate(mr.cnxn, config, mr.template_name,
                                     is_member)

        if template.summary:
            initial_summary = template.summary
            initial_summary_must_be_edited = template.summary_must_be_edited
        else:
            initial_summary = PLACEHOLDER_SUMMARY
            initial_summary_must_be_edited = True

        if template.status:
            initial_status = template.status
        elif is_member:
            initial_status = 'Accepted'
        else:
            initial_status = 'New'  # not offering meta, only used in hidden field.

        component_paths = []
        for component_id in template.component_ids:
            component_paths.append(
                tracker_bizobj.FindComponentDefByID(component_id, config).path)
        initial_components = ', '.join(component_paths)

        if template.owner_id:
            initial_owner = framework_views.MakeUserView(
                mr.cnxn, self.services.user, template.owner_id)
        elif template.owner_defaults_to_member and page_perms.EditIssue:
            initial_owner = mr.auth.user_view
        else:
            initial_owner = None

        if initial_owner:
            initial_owner_name = initial_owner.email
            owner_avail_state = initial_owner.avail_state
            owner_avail_message_short = initial_owner.avail_message_short
        else:
            initial_owner_name = ''
            owner_avail_state = None
            owner_avail_message_short = None

        # Check whether to allow attachments from the entry page
        allow_attachments = tracker_helpers.IsUnderSoftAttachmentQuota(
            mr.project)

        config_view = tracker_views.ConfigView(mr, self.services, config,
                                               template)
        # If the user followed a link that specified the template name, make sure
        # that it is also in the menu as the current choice.
        # TODO(jeffcarp): Unit test this.
        config_view.template_view.can_view = ezt.boolean(True)

        # TODO(jeffcarp): Unit test this.
        offer_templates = len(config_view.template_names) > 1
        restrict_to_known = config.restrict_to_known
        enum_field_name_set = {
            fd.field_name.lower()
            for fd in config.field_defs
            if fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
            and not fd.is_deleted
        }  # TODO(jrobbins): restrictions
        link_or_template_labels = mr.GetListParam('labels', template.labels)
        labels = [
            lab for lab in link_or_template_labels if
            not tracker_bizobj.LabelIsMaskedByField(lab, enum_field_name_set)
        ]

        # Corp-mode users automatically add R-V-G.
        with work_env.WorkEnv(mr, self.services) as we:
            userprefs = we.GetUserPrefs(mr.auth.user_id)
            corp_mode = any(
                up.name == 'restrict_new_issues' and up.value == 'true'
                for up in userprefs.prefs)
            if corp_mode:
                if not any(lab.lower().startswith('restrict-view-')
                           for lab in labels):
                    labels.append(CORP_RESTRICTION_LABEL)

        field_user_views = tracker_views.MakeFieldUserViews(
            mr.cnxn, template, self.services.user)
        approval_ids = [av.approval_id for av in template.approval_values]
        field_views = tracker_views.MakeAllFieldValueViews(
            config,
            link_or_template_labels, [],
            template.field_values,
            field_user_views,
            parent_approval_ids=approval_ids,
            phases=template.phases)
        # TODO(jojwang): monorail:6305, remove this hack when Edit perms for field
        # values are implemented.
        field_views = [
            view for view in field_views
            if view.field_name.lower() not in RESTRICTED_FLT_FIELDS
        ]

        # TODO(jrobbins): remove "or []" after next release.
        (prechecked_approvals, required_approval_ids,
         phases) = issue_tmpl_helpers.GatherApprovalsPageData(
             template.approval_values or [], template.phases, config)
        approvals = [
            view for view in field_views if view.field_id in approval_ids
        ]

        page_data = {
            'issue_tab_mode':
            'issueEntry',
            'initial_summary':
            initial_summary,
            'template_summary':
            initial_summary,
            'clear_summary_on_click':
            ezt.boolean(initial_summary_must_be_edited
                        and 'initial_summary' not in mr.form_overrides),
            'must_edit_summary':
            ezt.boolean(initial_summary_must_be_edited),
            'initial_description':
            template.content,
            'template_name':
            template.name,
            'component_required':
            ezt.boolean(template.component_required),
            'initial_status':
            initial_status,
            'initial_owner':
            initial_owner_name,
            'owner_avail_state':
            owner_avail_state,
            'owner_avail_message_short':
            owner_avail_message_short,
            'initial_components':
            initial_components,
            'initial_cc':
            '',
            'initial_blocked_on':
            '',
            'initial_blocking':
            '',
            'initial_hotlists':
            '',
            'labels':
            labels,
            'fields':
            field_views,
            'any_errors':
            ezt.boolean(mr.errors.AnyErrors()),
            'page_perms':
            page_perms,
            'allow_attachments':
            ezt.boolean(allow_attachments),
            'max_attach_size':
            template_helpers.BytesKbOrMb(
                framework_constants.MAX_POST_BODY_SIZE),
            'offer_templates':
            ezt.boolean(offer_templates),
            'config':
            config_view,
            'restrict_to_known':
            ezt.boolean(restrict_to_known),
            'is_member':
            ezt.boolean(is_member),
            'code_font':
            ezt.boolean(code_font),
            # The following are necessary for displaying phases that come with
            # this template. These are read-only.
            'allow_edit':
            ezt.boolean(False),
            'initial_phases':
            phases,
            'approvals':
            approvals,
            'prechecked_approvals':
            prechecked_approvals,
            'required_approval_ids':
            required_approval_ids,
            # See monorail:4692 and the use of PHASES_WITH_MILESTONES
            # in elements/flt/mr-launch-overview/mr-phase.js
            'issue_phase_names':
            list({
                phase.name.lower()
                for phase in phases if phase.name in PHASES_WITH_MILESTONES
            }),
        }

        return page_data
示例#6
0
  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
    with self.profiler.Phase('getting config'):
      config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    # In addition to checking perms, we adjust some default field values for
    # project members.
    is_member = framework_bizobj.UserIsInProject(
        mr.project, mr.auth.effective_ids)
    page_perms = self.MakePagePerms(
        mr, None,
        permissions.CREATE_ISSUE,
        permissions.SET_STAR,
        permissions.EDIT_ISSUE,
        permissions.EDIT_ISSUE_SUMMARY,
        permissions.EDIT_ISSUE_STATUS,
        permissions.EDIT_ISSUE_OWNER,
        permissions.EDIT_ISSUE_CC)

    wkp = _SelectTemplate(mr.template_name, config, is_member)

    if wkp.summary:
      initial_summary = wkp.summary
      initial_summary_must_be_edited = wkp.summary_must_be_edited
    else:
      initial_summary = PLACEHOLDER_SUMMARY
      initial_summary_must_be_edited = True

    if wkp.status:
      initial_status = wkp.status
    elif is_member:
      initial_status = 'Accepted'
    else:
      initial_status = 'New'  # not offering meta, only used in hidden field.

    component_paths = []
    for component_id in wkp.component_ids:
      component_paths.append(
          tracker_bizobj.FindComponentDefByID(component_id, config).path)
    initial_components = ', '.join(component_paths)

    if wkp.owner_id:
      initial_owner = framework_views.MakeUserView(
          mr.cnxn, self.services.user, wkp.owner_id)
    elif wkp.owner_defaults_to_member and page_perms.EditIssue:
      initial_owner = mr.auth.user_view
    else:
      initial_owner = None

    if initial_owner:
      initial_owner_name = initial_owner.email
      owner_avail_state = initial_owner.avail_state
      owner_avail_message_short = initial_owner.avail_message_short
    else:
      initial_owner_name = ''
      owner_avail_state = None
      owner_avail_message_short = None

    # Check whether to allow attachments from the entry page
    allow_attachments = tracker_helpers.IsUnderSoftAttachmentQuota(mr.project)

    config_view = tracker_views.ConfigView(mr, self.services, config)
    # If the user followed a link that specified the template name, make sure
    # that it is also in the menu as the current choice.
    for template_view in config_view.templates:
      if template_view.name == mr.template_name:
        template_view.can_view = ezt.boolean(True)

    offer_templates = len(list(
        tmpl for tmpl in config_view.templates if tmpl.can_view)) > 1
    restrict_to_known = config.restrict_to_known
    field_name_set = {fd.field_name.lower() for fd in config.field_defs
                      if not fd.is_deleted}  # TODO(jrobbins): restrictions
    link_or_template_labels = mr.GetListParam('labels', wkp.labels)
    labels = [lab for lab in link_or_template_labels
              if not tracker_bizobj.LabelIsMaskedByField(lab, field_name_set)]

    field_user_views = tracker_views.MakeFieldUserViews(
        mr.cnxn, wkp, self.services.user)
    field_views = [
        tracker_views.MakeFieldValueView(
            fd, config, link_or_template_labels, [], wkp.field_values,
            field_user_views)
        # TODO(jrobbins): field-level view restrictions, display options
        for fd in config.field_defs
        if not fd.is_deleted]

    page_data = {
        'issue_tab_mode': 'issueEntry',
        'initial_summary': initial_summary,
        'template_summary': initial_summary,
        'clear_summary_on_click': ezt.boolean(
            initial_summary_must_be_edited and
            'initial_summary' not in mr.form_overrides),
        'must_edit_summary': ezt.boolean(initial_summary_must_be_edited),

        'initial_description': wkp.content,
        'template_name': wkp.name,
        'component_required': ezt.boolean(wkp.component_required),
        'initial_status': initial_status,
        'initial_owner': initial_owner_name,
        'owner_avail_state': owner_avail_state,
        'owner_avail_message_short': owner_avail_message_short,
        'initial_components': initial_components,
        'initial_cc': '',
        'initial_blocked_on': '',
        'initial_blocking': '',
        'labels': labels,
        'fields': field_views,

        'any_errors': ezt.boolean(mr.errors.AnyErrors()),
        'page_perms': page_perms,
        'allow_attachments': ezt.boolean(allow_attachments),
        'max_attach_size': template_helpers.BytesKbOrMb(
            framework_constants.MAX_POST_BODY_SIZE),

        'offer_templates': ezt.boolean(offer_templates),
        'config': config_view,

        'restrict_to_known': ezt.boolean(restrict_to_known),
        }

    return page_data
示例#7
0
    def GatherPageData(self, mr):
        """Parse the attachment ID from the request and serve its content.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering almost the page.
    """
        with mr.profiler.Phase('get issue, comment, and attachment'):
            try:
                attachment, issue = tracker_helpers.GetAttachmentIfAllowed(
                    mr, self.services)
            except exceptions.NoSuchIssueException:
                webapp2.abort(404, 'issue not found')
            except exceptions.NoSuchAttachmentException:
                webapp2.abort(404, 'attachment not found')
            except exceptions.NoSuchCommentException:
                webapp2.abort(404, 'comment not found')

        content = []
        if attachment.gcs_object_id:
            bucket_name = app_identity.get_default_gcs_bucket_name()
            full_path = '/' + bucket_name + attachment.gcs_object_id
            logging.info("reading gcs: %s" % full_path)
            with cloudstorage.open(full_path, 'r') as f:
                content = f.read()

        filesize = len(content)

        # This servlet only displays safe textual attachments. The user should
        # not have been given a link to this servlet for any other kind.
        if not attachment_helpers.IsViewableText(attachment.mimetype,
                                                 filesize):
            self.abort(400, 'not a text file')

        u_text, is_binary, too_large = filecontent.DecodeFileContents(content)
        lines = prettify.PrepareSourceLinesForHighlighting(
            u_text.encode('utf8'))

        config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
        granted_perms = tracker_bizobj.GetGrantedPerms(issue,
                                                       mr.auth.effective_ids,
                                                       config)
        page_perms = self.MakePagePerms(mr,
                                        issue,
                                        permissions.DELETE_ISSUE,
                                        permissions.CREATE_ISSUE,
                                        granted_perms=granted_perms)

        page_data = {
            'issue_tab_mode': 'issueDetail',
            'local_id': issue.local_id,
            'filename': attachment.filename,
            'filesize': template_helpers.BytesKbOrMb(filesize),
            'file_lines': lines,
            'is_binary': ezt.boolean(is_binary),
            'too_large': ezt.boolean(too_large),
            'code_reviews': None,
            'page_perms': page_perms,
        }
        if is_binary or too_large:
            page_data['should_prettify'] = ezt.boolean(False)
        else:
            page_data.update(
                prettify.BuildPrettifyData(len(lines), attachment.filename))

        return page_data