Example #1
0
 def test_team_admin_subscription(self):
     # Make a team subscription where the user is an admin, and see what
     # we record.
     user = self.factory.makePerson()
     target = self.factory.makeProduct()
     request = LaunchpadTestRequest()
     team = self.factory.makeTeam()
     with person_logged_in(team.teamowner):
         team.addMember(user,
                        team.teamowner,
                        status=TeamMembershipStatus.ADMIN)
         sub = target.addBugSubscription(team, team.teamowner)
     expose_user_subscriptions_to_js(user, [sub], request)
     info = IJSONRequestCache(request).objects['subscription_info']
     self.assertEqual(len(info), 1)  # One target.
     target_info = info[0]
     self.assertEqual(target_info['target_title'], target.title)
     self.assertEqual(target_info['target_url'],
                      canonical_url(target, rootsite='mainsite'))
     self.assertEqual(len(target_info['filters']), 1)  # One filter.
     filter_info = target_info['filters'][0]
     self.assertEqual(filter_info['filter'], sub.bug_filters[0])
     self.assertTrue(filter_info['subscriber_is_team'])
     self.assertTrue(filter_info['user_is_team_admin'])
     self.assertTrue(filter_info['can_mute'])
     self.assertFalse(filter_info['is_muted'])
     self.assertEqual(filter_info['subscriber_title'], team.title)
     self.assertEqual(filter_info['subscriber_link'],
                      absoluteURL(team, IWebServiceClientRequest(request)))
     self.assertEqual(filter_info['subscriber_url'],
                      canonical_url(team, rootsite='mainsite'))
Example #2
0
    def metadata_changes_text(self):
        """Textual representation of the changes to the question metadata."""
        question = self.question
        old_question = self.old_question
        indent = 4 * ' '
        info_fields = []
        if question.status != old_question.status:
            info_fields.append(indent + 'Status: %s => %s' % (
                old_question.status.title, question.status.title))
        if question.target != old_question.target:
            info_fields.append(
                indent + 'Project: %s => %s' % (
                old_question.target.displayname, question.target.displayname))

        if question.assignee != old_question.assignee:
            if old_question.assignee is None:
                old_assignee = None
            else:
                old_assignee = old_question.assignee.displayname
            if question.assignee is None:
                assignee = None
            else:
                assignee = question.assignee.displayname
            info_fields.append(indent + 'Assignee: %s => %s' % (
               old_assignee, assignee))

        old_bugs = set(old_question.bugs)
        bugs = set(question.bugs)
        for linked_bug in bugs.difference(old_bugs):
            info_fields.append(
                indent + 'Linked to bug: #%s\n' % linked_bug.id +
                indent + '%s\n' % canonical_url(linked_bug) +
                indent + '"%s"' % linked_bug.title)
        for unlinked_bug in old_bugs.difference(bugs):
            info_fields.append(
                indent + 'Removed link to bug: #%s\n' % unlinked_bug.id +
                indent + '%s\n' % canonical_url(unlinked_bug) +
                indent + '"%s"' % unlinked_bug.title)

        if question.faq != old_question.faq:
            if question.faq is None:
                info_fields.append(
                    indent + 'Related FAQ was removed:\n' +
                    indent + old_question.faq.title + '\n' +
                    indent + canonical_url(old_question.faq))
            else:
                info_fields.append(
                    indent + 'Related FAQ set to:\n' +
                    indent + question.faq.title + '\n' +
                    indent + canonical_url(question.faq))

        if question.title != old_question.title:
            info_fields.append('Summary changed to:\n%s' % question.title)
        if question.description != old_question.description:
            info_fields.append(
                'Description changed to:\n%s' % (
                    self.wrapper.format(question.description)))

        question_changes = '\n\n'.join(info_fields)
        return question_changes
def notify_message_held(message_approval, event):
    """Send a notification of a message hold to all team administrators."""
    message_details = getAdapter(message_approval, IHeldMessageDetails)
    team = message_approval.mailing_list.team
    from_address = format_address(
        team.displayname, config.canonical.noreply_from_address)
    subject = (
        'New mailing list message requiring approval for %s'
        % team.displayname)
    template = get_email_template('new-held-message.txt', app='registry')

    # Most of the replacements are the same for everyone.
    replacements = {
        'subject': message_details.subject,
        'author_name': message_details.author.displayname,
        'author_url': canonical_url(message_details.author),
        'date': message_details.date,
        'message_id': message_details.message_id,
        'review_url': '%s/+mailinglist-moderate' % canonical_url(team),
        'team': team.displayname,
        }

    # Don't wrap the paragraph with the url.
    def wrap_function(paragraph):
        return (paragraph.startswith('http:') or
                paragraph.startswith('https:'))

    # Send one message to every team administrator.
    person_set = getUtility(IPersonSet)
    for address in team.getTeamAdminsEmailAddresses():
        user = person_set.getByEmail(address)
        replacements['user'] = user.displayname
        body = MailWrapper(72).format(
            template % replacements, force_wrap=True, wrap_func=wrap_function)
        simple_sendmail(from_address, address, subject, body)
    def metadata_changes_text(self):
        """Textual representation of the changes to the question metadata."""
        question = self.question
        old_question = self.old_question
        indent = 4 * ' '
        info_fields = []
        if question.status != old_question.status:
            info_fields.append(indent + 'Status: %s => %s' % (
                old_question.status.title, question.status.title))
        if question.target != old_question.target:
            info_fields.append(
                indent + 'Project: %s => %s' % (
                old_question.target.displayname, question.target.displayname))

        if question.assignee != old_question.assignee:
            if old_question.assignee is None:
                old_assignee = None
            else:
                old_assignee = old_question.assignee.displayname
            if question.assignee is None:
                assignee = None
            else:
                assignee = question.assignee.displayname
            info_fields.append(indent + 'Assignee: %s => %s' % (
               old_assignee, assignee))

        old_bugs = set(old_question.bugs)
        bugs = set(question.bugs)
        for linked_bug in bugs.difference(old_bugs):
            info_fields.append(
                indent + 'Linked to bug: #%s\n' % linked_bug.id +
                indent + '%s\n' % canonical_url(linked_bug) +
                indent + '"%s"' % linked_bug.title)
        for unlinked_bug in old_bugs.difference(bugs):
            info_fields.append(
                indent + 'Removed link to bug: #%s\n' % unlinked_bug.id +
                indent + '%s\n' % canonical_url(unlinked_bug) +
                indent + '"%s"' % unlinked_bug.title)

        if question.faq != old_question.faq:
            if question.faq is None:
                info_fields.append(
                    indent + 'Related FAQ was removed:\n' +
                    indent + old_question.faq.title + '\n' +
                    indent + canonical_url(old_question.faq))
            else:
                info_fields.append(
                    indent + 'Related FAQ set to:\n' +
                    indent + question.faq.title + '\n' +
                    indent + canonical_url(question.faq))

        if question.title != old_question.title:
            info_fields.append('Summary changed to:\n%s' % question.title)
        if question.description != old_question.description:
            info_fields.append(
                'Description changed to:\n%s' % (
                    self.wrapper.format(question.description)))

        question_changes = '\n\n'.join(info_fields)
        return question_changes
 def test_view_with_source_package_recipe(self):
     # When a SourcePackageRelease is linked to a
     # SourcePackageRecipeBuild, the view shows which recipe was
     # responsible for creating the SPR.
     sprb = self.factory.makeSourcePackageRecipeBuild(
         archive=self.archive)
     recipe = sprb.recipe
     requester = sprb.requester
     spph = self.publisher.getPubSource(
         archive=self.archive, status=PackagePublishingStatus.PUBLISHED)
     spph.sourcepackagerelease.source_package_recipe_build = sprb
     recipe_link_matches = soupmatchers.HTMLContains(
         soupmatchers.Tag(
             'link to build', 'a', attrs={'href': canonical_url(sprb)},
             text='Built'),
         soupmatchers.Tag(
             'recipe name', 'a', attrs={'href': canonical_url(recipe)},
             text=recipe.name),
         soupmatchers.Tag(
             'requester', 'a',
             attrs={
                 'href': canonical_url(requester)},
             text=requester.displayname))
     browser = self.getViewBrowser(spph, '+listing-archive-extra')
     self.assertThat(browser.contents, recipe_link_matches)
 def assertWebhookDeliveries(self, snapbuild,
                             expected_store_upload_statuses):
     hook = snapbuild.snap.webhooks.one()
     deliveries = list(hook.deliveries)
     deliveries.reverse()
     expected_payloads = [{
         "snap_build":
         Equals(canonical_url(snapbuild, force_local_path=True)),
         "action":
         Equals("status-changed"),
         "snap":
         Equals(canonical_url(snapbuild.snap, force_local_path=True)),
         "build_request":
         Is(None),
         "status":
         Equals("Successfully built"),
         "store_upload_status":
         Equals(expected),
     } for expected in expected_store_upload_statuses]
     matchers = [
         MatchesStructure(event_type=Equals("snap:build:0.1"),
                          payload=MatchesDict(expected_payload))
         for expected_payload in expected_payloads
     ]
     self.assertThat(deliveries, MatchesListwise(matchers))
     with dbuser(config.IWebhookDeliveryJobSource.dbuser):
         for delivery in deliveries:
             self.assertEqual(
                 "<WebhookDeliveryJob for webhook %d on %r>" %
                 (hook.id, hook.target), repr(delivery))
Example #7
0
 def setUp(self):
     super(TestBugTrackerBreadcrumbs, self).setUp()
     self.bug_tracker_set = getUtility(IBugTrackerSet)
     self.bug_tracker_set_url = canonical_url(self.bug_tracker_set,
                                              rootsite='bugs')
     self.bug_tracker = self.factory.makeBugTracker()
     self.bug_tracker_url = canonical_url(self.bug_tracker, rootsite='bugs')
Example #8
0
 def test_scheduleStoreUpload_triggers_webhooks(self):
     # Scheduling a store upload triggers webhooks on the corresponding
     # snap.
     self.setUpStoreUpload()
     self.build.updateStatus(BuildStatus.FULLYBUILT)
     self.factory.makeSnapFile(
         snapbuild=self.build,
         libraryfile=self.factory.makeLibraryFileAlias(db_only=True))
     hook = self.factory.makeWebhook(target=self.build.snap,
                                     event_types=["snap:build:0.1"])
     self.build.scheduleStoreUpload()
     expected_payload = {
         "snap_build":
         Equals(canonical_url(self.build, force_local_path=True)),
         "action": Equals("status-changed"),
         "snap":
         Equals(canonical_url(self.build.snap, force_local_path=True)),
         "build_request": Is(None),
         "status": Equals("Successfully built"),
         "store_upload_status": Equals("Pending"),
     }
     delivery = hook.deliveries.one()
     self.assertThat(
         delivery,
         MatchesStructure(event_type=Equals("snap:build:0.1"),
                          payload=MatchesDict(expected_payload)))
     with dbuser(config.IWebhookDeliveryJobSource.dbuser):
         self.assertEqual(
             "<WebhookDeliveryJob for webhook %d on %r>" %
             (hook.id, hook.target), repr(delivery))
Example #9
0
 def test_view_with_source_package_recipe(self):
     # When a SourcePackageRelease is linked to a
     # SourcePackageRecipeBuild, the view shows which recipe was
     # responsible for creating the SPR.
     sprb = self.factory.makeSourcePackageRecipeBuild(archive=self.archive)
     recipe = sprb.recipe
     requester = sprb.requester
     spph = self.publisher.getPubSource(
         archive=self.archive, status=PackagePublishingStatus.PUBLISHED)
     spph.sourcepackagerelease.source_package_recipe_build = sprb
     recipe_link_matches = soupmatchers.HTMLContains(
         soupmatchers.Tag('link to build',
                          'a',
                          attrs={'href': canonical_url(sprb)},
                          text='Built'),
         soupmatchers.Tag('recipe name',
                          'a',
                          attrs={'href': canonical_url(recipe)},
                          text=recipe.name),
         soupmatchers.Tag('requester',
                          'a',
                          attrs={'href': canonical_url(requester)},
                          text=requester.displayname))
     browser = self.getViewBrowser(spph, '+listing-archive-extra')
     self.assertThat(browser.contents, recipe_link_matches)
Example #10
0
 def test_view_data_model(self):
     # Test that the json request cache contains the view data model.
     pillarperson = self.getPillarPerson()
     view = create_initialized_view(pillarperson, '+index')
     bugtask = list(view.bugtasks)[0]
     bug = bugtask.bug
     cache = IJSONRequestCache(view.request)
     request = get_current_web_service_request()
     self.assertEqual({
         'self_link': absoluteURL(pillarperson.person, request),
         'displayname': pillarperson.person.displayname
     }, cache.objects.get('grantee'))
     self.assertEqual({
         'self_link': absoluteURL(pillarperson.pillar, request),
     }, cache.objects.get('pillar'))
     self.assertEqual({
         'bug_id': bug.id,
         'bug_summary': bug.title,
         'bug_importance': bugtask.importance.title.lower(),
         'information_type': bug.information_type.title,
         'web_link': canonical_url(
             bugtask, path_only_if_possible=True),
         'self_link': absoluteURL(bug, request),
     }, cache.objects.get('bugs')[0])
     if self.pillar_type == 'product':
         branch = list(view.branches)[0]
         self.assertEqual({
             'branch_id': branch.id,
             'branch_name': branch.unique_name,
             'information_type': branch.information_type.title,
             'web_link': canonical_url(branch, path_only_if_possible=True),
             'self_link': absoluteURL(branch, request),
         }, cache.objects.get('branches')[0])
Example #11
0
 def test_updateStatus_triggers_webhooks(self):
     # Updating the status of a SnapBuild triggers webhooks on the
     # corresponding Snap.
     hook = self.factory.makeWebhook(target=self.build.snap,
                                     event_types=["snap:build:0.1"])
     self.build.updateStatus(BuildStatus.FULLYBUILT)
     expected_payload = {
         "snap_build":
         Equals(canonical_url(self.build, force_local_path=True)),
         "action": Equals("status-changed"),
         "snap":
         Equals(canonical_url(self.build.snap, force_local_path=True)),
         "build_request": Is(None),
         "status": Equals("Successfully built"),
         "store_upload_status": Equals("Unscheduled"),
     }
     delivery = hook.deliveries.one()
     self.assertThat(
         delivery,
         MatchesStructure(event_type=Equals("snap:build:0.1"),
                          payload=MatchesDict(expected_payload)))
     with dbuser(config.IWebhookDeliveryJobSource.dbuser):
         self.assertEqual(
             "<WebhookDeliveryJob for webhook %d on %r>" %
             (hook.id, hook.target), repr(delivery))
Example #12
0
 def _getTemplateParams(self, email, recipient):
     """See `BaseMailer`."""
     params = super(TeamMembershipMailer,
                    self)._getTemplateParams(email, recipient)
     params["recipient"] = recipient.displayname
     reason, _ = self._recipients.getReason(email)
     if reason.recipient_class is not None:
         params["recipient_class"] = reason.recipient_class
     params["member"] = self.member.unique_displayname
     params["membership_invitations_url"] = "%s/+invitation/%s" % (
         canonical_url(self.member), self.team.name)
     params["team"] = self.team.unique_displayname
     params["team_url"] = canonical_url(self.team)
     if self.membership is not None:
         params["membership_url"] = canonical_url(self.membership)
     if reason.recipient_class == "bulk" and self.reviewer == self.member:
         params["reviewer"] = "the user"
     elif self.reviewer is not None:
         params["reviewer"] = self.reviewer.unique_displayname
     if self.team.mailing_list is not None:
         template = get_email_template("team-list-subscribe-block.txt",
                                       app="registry")
         editemails_url = urlappend(
             canonical_url(getUtility(ILaunchpadRoot)),
             "~/+editmailinglists")
         list_instructions = template % {"editemails_url": editemails_url}
     else:
         list_instructions = ""
     params["list_instructions"] = list_instructions
     params.update(self.extra_params)
     return params
 def test_view_with_deleted_source_package_recipe(self):
     # If a SourcePackageRelease is linked to a deleted recipe, the text
     # 'deleted recipe' is displayed, rather than a link.
     sprb = self.factory.makeSourcePackageRecipeBuild(
         archive=self.archive)
     recipe = sprb.recipe
     requester = sprb.requester
     spph = self.publisher.getPubSource(
         archive=self.archive, status=PackagePublishingStatus.PUBLISHED)
     spph.sourcepackagerelease.source_package_recipe_build = sprb
     with person_logged_in(recipe.owner):
         recipe.destroySelf()
     recipe_link_matches = soupmatchers.HTMLContains(
         soupmatchers.Tag(
             'link to build', 'a',
             attrs={'href': canonical_url(sprb)},
             text='Built'),
         soupmatchers.Tag(
             'requester', 'a',
             attrs={
                 'href': canonical_url(requester)},
             text=requester.displayname))
     browser = self.getViewBrowser(spph, '+listing-archive-extra')
     self.assertThat(browser.contents, recipe_link_matches)
     self.assertIn('deleted recipe', browser.contents)
Example #14
0
def notify_message_held(message_approval, event):
    """Send a notification of a message hold to all team administrators."""
    message_details = getAdapter(message_approval, IHeldMessageDetails)
    team = message_approval.mailing_list.team
    from_address = format_address(team.displayname,
                                  config.canonical.noreply_from_address)
    subject = ('New mailing list message requiring approval for %s' %
               team.displayname)
    template = get_email_template('new-held-message.txt', app='registry')

    # Most of the replacements are the same for everyone.
    replacements = {
        'subject': message_details.subject,
        'author_name': message_details.author.displayname,
        'author_url': canonical_url(message_details.author),
        'date': message_details.date,
        'message_id': message_details.message_id,
        'review_url': '%s/+mailinglist-moderate' % canonical_url(team),
        'team': team.displayname,
    }

    # Don't wrap the paragraph with the url.
    def wrap_function(paragraph):
        return (paragraph.startswith('http:')
                or paragraph.startswith('https:'))

    # Send one message to every team administrator.
    person_set = getUtility(IPersonSet)
    for address in team.getTeamAdminsEmailAddresses():
        user = person_set.getByEmail(address)
        replacements['user'] = user.displayname
        body = MailWrapper(72).format(template % replacements,
                                      force_wrap=True,
                                      wrap_func=wrap_function)
        simple_sendmail(from_address, address, subject, body)
Example #15
0
 def test_team_admin_subscription(self):
     # Make a team subscription where the user is an admin, and see what
     # we record.
     user = self.factory.makePerson()
     target = self.factory.makeProduct()
     request = LaunchpadTestRequest()
     team = self.factory.makeTeam()
     with person_logged_in(team.teamowner):
         team.addMember(user, team.teamowner,
                        status=TeamMembershipStatus.ADMIN)
         sub = target.addBugSubscription(team, team.teamowner)
     expose_user_subscriptions_to_js(user, [sub], request)
     info = IJSONRequestCache(request).objects['subscription_info']
     self.assertEqual(len(info), 1)  # One target.
     target_info = info[0]
     self.assertEqual(target_info['target_title'], target.title)
     self.assertEqual(
         target_info['target_url'], canonical_url(
             target, rootsite='mainsite'))
     self.assertEqual(len(target_info['filters']), 1)  # One filter.
     filter_info = target_info['filters'][0]
     self.assertEqual(filter_info['filter'], sub.bug_filters[0])
     self.assertTrue(filter_info['subscriber_is_team'])
     self.assertTrue(filter_info['user_is_team_admin'])
     self.assertTrue(filter_info['can_mute'])
     self.assertFalse(filter_info['is_muted'])
     self.assertEqual(filter_info['subscriber_title'], team.title)
     self.assertEqual(
         filter_info['subscriber_link'],
         absoluteURL(team, IWebServiceClientRequest(request)))
     self.assertEqual(
         filter_info['subscriber_url'],
         canonical_url(team, rootsite='mainsite'))
Example #16
0
 def test_sharing_menu(self):
     url = canonical_url(self.pillar)
     sharing_url = canonical_url(self.pillar, view_name='+sharing')
     browser = setupBrowserForUser(user=self.driver)
     browser.open(url)
     soup = BeautifulSoup(browser.contents)
     sharing_menu = soup.find('a', {'href': sharing_url})
     self.assertIsNotNone(sharing_menu)
 def setUp(self):
     super(TestBugTrackerBreadcrumbs, self).setUp()
     self.bug_tracker_set = getUtility(IBugTrackerSet)
     self.bug_tracker_set_url = canonical_url(
         self.bug_tracker_set, rootsite='bugs')
     self.bug_tracker = self.factory.makeBugTracker()
     self.bug_tracker_url = canonical_url(
         self.bug_tracker, rootsite='bugs')
Example #18
0
 def setUp(self):
     super(TestHasSpecificationsBreadcrumbOnBlueprintsFacet, self).setUp()
     self.person = self.factory.makePerson()
     self.person_specs_url = canonical_url(self.person,
                                           rootsite='blueprints')
     self.product = self.factory.makeProduct(name='crumb-tester',
                                             displayname="Crumb Tester")
     self.product_specs_url = canonical_url(self.product,
                                            rootsite='blueprints')
 def test_excessive_comments_redirect_to_download(self):
     """View for excessive comments redirects to download page."""
     comment = make_bug_comment(self.factory, body='x ' * 5001)
     view_url = canonical_url(comment)
     download_url = canonical_url(comment, view_name='+download')
     browser = self.getUserBrowser(view_url)
     self.assertNotEqual(view_url, browser.url)
     self.assertEqual(download_url, browser.url)
     self.assertEqual('x ' * 5001, browser.contents)
Example #20
0
def notify_new_ppa_subscription(subscription, event):
    """Notification that a new PPA subscription can be activated."""
    non_active_subscribers = subscription.getNonActiveSubscribers()

    archive = subscription.archive

    # We don't send notification emails for some PPAs, particularly those that
    # are purchased via the Software Centre, so that its users do not have to
    # learn about Launchpad.
    if archive.suppress_subscription_notifications:
        return

    registrant_name = subscription.registrant.displayname
    ppa_displayname = archive.displayname
    ppa_reference = "ppa:%s/%s" % (
        archive.owner.name, archive.name)
    ppa_description = archive.description
    subject = 'PPA access granted for ' + ppa_displayname

    template = get_email_template('ppa-subscription-new.txt', app='soyuz')

    for person, preferred_email in non_active_subscribers:
        to_address = [preferred_email.email]
        root = getUtility(ILaunchpadRoot)
        recipient_subscriptions_url = "%s~/+archivesubscriptions" % (
            canonical_url(root))
        description_blurb = '.'
        if ppa_description is not None and ppa_description != '':
            description_blurb = (
                ' and has the following description:\n\n%s' % ppa_description)
        replacements = {
            'recipient_name': person.displayname,
            'registrant_name': registrant_name,
            'registrant_profile_url': canonical_url(subscription.registrant),
            'ppa_displayname': ppa_displayname,
            'ppa_reference': ppa_reference,
            'ppa_description_blurb': description_blurb,
            'recipient_subscriptions_url': recipient_subscriptions_url,
            }
        body = MailWrapper(72).format(template % replacements,
                                      force_wrap=True)

        from_address = format_address(
            registrant_name, config.canonical.noreply_from_address)

        headers = {
            'Sender': config.canonical.bounce_address,
            }

        # If the registrant has a preferred email, then use it for the
        # Reply-To.
        if subscription.registrant.preferredemail:
            headers['Reply-To'] = format_address(
                registrant_name,
                subscription.registrant.preferredemail.email)

        simple_sendmail(from_address, to_address, subject, body, headers)
 def test_excessive_comments_redirect_to_download(self):
     """View for excessive comments redirects to download page."""
     comment = make_bug_comment(self.factory, body='x ' * 5001)
     view_url = canonical_url(comment)
     download_url = canonical_url(comment, view_name='+download')
     browser = self.getUserBrowser(view_url)
     self.assertNotEqual(view_url, browser.url)
     self.assertEqual(download_url, browser.url)
     self.assertEqual('x ' * 5001, browser.contents)
 def setUp(self):
     super(TestHasSpecificationsBreadcrumbOnBlueprintsVHost, self).setUp()
     self.person = self.factory.makePerson()
     self.person_specs_url = canonical_url(
         self.person, rootsite='blueprints')
     self.product = self.factory.makeProduct(
         name='crumb-tester', displayname="Crumb Tester")
     self.product_specs_url = canonical_url(
         self.product, rootsite='blueprints')
 def test_view_navigation_links(self):
     # Check the navigation links get get to the change owner page.
     owner = self.factory.makePerson()
     team = self.factory.makeTeam(owner=owner)
     edit_url = canonical_url(team, view_name='+edit')
     reassign_url = canonical_url(team, view_name='+reassign')
     browser = setupBrowserForUser(owner)
     browser.open(edit_url)
     browser.getLink('Change owner').click()
     self.assertEqual(reassign_url, browser.url)
 def test_view_navigation_links(self):
     # Check the navigation links get get to the change owner page.
     owner = self.factory.makePerson()
     team = self.factory.makeTeam(owner=owner)
     edit_url = canonical_url(team, view_name='+edit')
     reassign_url = canonical_url(team, view_name='+reassign')
     browser = setupBrowserForUser(owner)
     browser.open(edit_url)
     browser.getLink('Change owner').click()
     self.assertEqual(reassign_url, browser.url)
    def test_package_bugtask(self):
        target = self.package_bugtask.target
        distro_url = canonical_url(target.distribution)
        distroseries_url = canonical_url(target.distroseries)
        package_url = canonical_url(target)
        package_bugs_url = canonical_url(target, rootsite='bugs')

        self.assertBreadcrumbUrls(
            [distro_url, distroseries_url, package_url, package_bugs_url,
             self.package_bugtask_url],
            self.package_bugtask)
def setup(request, data):
    owner = factory.makePerson()
    with person_logged_in(owner):
        product = factory.makeProduct(name="my-test-project", owner=owner)
        product_series = factory.makeProductSeries(name="new-series",
                                                   product=product)
        data['product'] = product
        data['series_uri'] = canonical_url(product_series,
                                           path_only_if_possible=True)
        data['milestone_form_uri'] = (canonical_url(product_series) +
                                      '/+addmilestone/++form++')
    login_as_person(owner)
def setup(request, data):
    owner = factory.makePerson()
    with person_logged_in(owner):
        product = factory.makeProduct(name="my-test-project", owner=owner)
        product_series = factory.makeProductSeries(
            name="new-series", product=product)
        data['product'] = product
        data['series_uri'] = canonical_url(
            product_series, path_only_if_possible=True)
        data['milestone_form_uri'] = (
            canonical_url(product_series) + '/+addmilestone/++form++')
    login_as_person(owner)
 def setUp(self):
     super(TestQuestionTargetProjectAndPersonBreadcrumbOnAnswersVHost,
           self).setUp()
     self.person = self.factory.makePerson()
     self.person_questions_url = canonical_url(
         self.person, rootsite='answers')
     self.product = self.factory.makeProduct()
     self.product_questions_url = canonical_url(
         self.product, rootsite='answers')
     self.project = self.factory.makeProject()
     self.project_questions_url = canonical_url(
         self.project, rootsite='answers')
Example #29
0
 def test_delete_sprint_owner(self):
     # A sprint can be deleted by its owner, even if it has attendees and
     # specifications.
     self.useFixture(FakeLogger())
     sprint = self.makePopulatedSprint()
     sprint_url = canonical_url(sprint)
     owner_url = canonical_url(sprint.owner)
     browser = self.getViewBrowser(sprint, user=sprint.owner)
     browser.getLink("Delete sprint").click()
     browser.getControl("Delete sprint").click()
     self.assertEqual(owner_url, browser.url)
     self.assertRaises(NotFound, browser.open, sprint_url)
Example #30
0
 def setUp(self):
     super(TestQuestionTargetProjectAndPersonBreadcrumbOnAnswersFacet,
           self).setUp()
     self.person = self.factory.makePerson()
     self.person_questions_url = canonical_url(
         self.person, rootsite='answers')
     self.product = self.factory.makeProduct()
     self.product_questions_url = canonical_url(
         self.product, rootsite='answers')
     self.project = self.factory.makeProject()
     self.project_questions_url = canonical_url(
         self.project, rootsite='answers')
 def setUp(self):
     super(TestExtraFacetBreadcrumbsOnHierarchyView, self).setUp()
     login('*****@*****.**')
     self.product = self.factory.makeProduct(name='crumb-tester')
     self.product_url = canonical_url(self.product)
     self.product_bugs_url = canonical_url(self.product, rootsite='bugs')
     product_bug = self.factory.makeBug(target=self.product)
     self.product_bugtask = product_bug.default_bugtask
     self.product_bugtask_url = canonical_url(self.product_bugtask)
     self.source_package = self.factory.makeSourcePackage()
     self.package_bugtask = self.factory.makeBugTask(
         target=self.source_package)
     self.package_bugtask_url = canonical_url(self.package_bugtask)
 def setUp(self):
     super(TestExtraVHostBreadcrumbsOnHierarchyView, self).setUp()
     login('*****@*****.**')
     self.product = self.factory.makeProduct(name='crumb-tester')
     self.product_url = canonical_url(self.product)
     self.product_bugs_url = canonical_url(self.product, rootsite='bugs')
     product_bug = self.factory.makeBug(target=self.product)
     self.product_bugtask = product_bug.default_bugtask
     self.product_bugtask_url = canonical_url(self.product_bugtask)
     self.source_package = self.factory.makeSourcePackage()
     self.package_bugtask = self.factory.makeBugTask(
         target=self.source_package)
     self.package_bugtask_url = canonical_url(self.package_bugtask)
 def getBody(self):
     """See QuestionNotification."""
     return get_email_template(
         'question-linked-bug-status-updated.txt') % {
             'bugtask_target_name': self.bugtask.target.displayname,
             'question_id': self.question.id,
             'question_title': self.question.title,
             'question_url': canonical_url(self.question),
             'bugtask_url': canonical_url(self.bugtask),
             'bug_id': self.bugtask.bug.id,
             'bugtask_title': self.bugtask.bug.title,
             'old_status': self.old_bugtask.status.title,
             'new_status': self.bugtask.status.title}
 def test_notification_shown_if_marking_private_and_not_subscribed(self):
     # If a user who is not subscribed to a bug marks that bug as
     # private, the user will be subscribed to the bug. This allows
     # them to un-mark the bug if they choose to, rather than being
     # blocked from doing so.
     view = self.createInitializedSecrecyView()
     bug = view.context.bug
     task = removeSecurityProxy(bug).default_bugtask
     self.assertEqual(1, len(view.request.response.notifications))
     notification = view.request.response.notifications[0].message
     mute_url = canonical_url(task, view_name='+mute')
     subscribe_url = canonical_url(task, view_name='+subscribe')
     self.assertIn(mute_url, notification)
     self.assertIn(subscribe_url, notification)
Example #35
0
 def test_notification_shown_if_marking_private_and_not_subscribed(self):
     # If a user who is not subscribed to a bug marks that bug as
     # private, the user will be subscribed to the bug. This allows
     # them to un-mark the bug if they choose to, rather than being
     # blocked from doing so.
     view = self.createInitializedSecrecyView()
     bug = view.context.bug
     task = removeSecurityProxy(bug).default_bugtask
     self.assertEqual(1, len(view.request.response.notifications))
     notification = view.request.response.notifications[0].message
     mute_url = canonical_url(task, view_name='+mute')
     subscribe_url = canonical_url(task, view_name='+subscribe')
     self.assertIn(mute_url, notification)
     self.assertIn(subscribe_url, notification)
Example #36
0
 def test_traversal_to_nonexistent_bugtask(self):
     # Test that a traversing to a non-existent bugtask redirects to the
     # bug's default bugtask.
     bug = self.factory.makeBug()
     bugtask = self.factory.makeBugTask(bug=bug)
     bugtask_url = canonical_url(bugtask, rootsite='bugs')
     login_person(bugtask.owner)
     bugtask.delete()
     obj, view, request = test_traverse(bugtask_url)
     view()
     naked_view = removeSecurityProxy(view)
     self.assertEqual(301, request.response.getStatus())
     self.assertEqual(naked_view.target,
                      canonical_url(bug.default_bugtask, rootsite='bugs'))
def expose_user_subscriptions_to_js(user, subscriptions, request):
    """Make the user's subscriptions available to JavaScript."""
    api_request = IWebServiceClientRequest(request)
    info = {}
    if user is None:
        administered_teams = []
    else:
        administered_teams = user.administrated_teams

    for subscription in subscriptions:
        target = subscription.target
        record = info.get(target)
        if record is None:
            record = dict(target_title=target.title,
                          target_url=canonical_url(
                            target, rootsite='mainsite'),
                          filters=[])
            info[target] = record
        subscriber = subscription.subscriber
        for filter in subscription.bug_filters:
            is_team = subscriber.is_team
            user_is_team_admin = (
                is_team and subscriber in administered_teams)
            team_has_contact_address = (
                is_team and subscriber.preferredemail is not None)
            mailing_list = subscriber.mailing_list
            user_is_on_team_mailing_list = (
                team_has_contact_address and
                mailing_list is not None and
                mailing_list.is_usable and
                mailing_list.getSubscription(subscriber) is not None)
            record['filters'].append(dict(
                filter=filter,
                subscriber_link=absoluteURL(subscriber, api_request),
                subscriber_url=canonical_url(
                    subscriber, rootsite='mainsite'),
                target_bugs_url=canonical_url(
                    target, rootsite='bugs'),
                subscriber_title=subscriber.title,
                subscriber_is_team=is_team,
                user_is_team_admin=user_is_team_admin,
                team_has_contact_address=team_has_contact_address,
                user_is_on_team_mailing_list=user_is_on_team_mailing_list,
                can_mute=filter.isMuteAllowed(user),
                is_muted=filter.muted(user) is not None,
                target_title=target.title))
    info = info.values()
    info.sort(key=itemgetter('target_url'))
    IJSONRequestCache(request).objects['subscription_info'] = info
    def test_constructs_correct_urls(self):
        # The view classes can override constructTemplateURL with
        # optimized versions.  These can produce either an absolute URL
        # that exactly matches the template's canonical_url, or a
        # relative one starting from the series' canonical_url.
        template = self._makeTemplate()
        view = self._makeView(template)

        series_url = canonical_url(
            self._getSeries(template), rootsite='translations')
        constructed_url = view.constructTemplateURL(template)

        self.assertIn(
            canonical_url(template),
            (constructed_url, '/'.join([series_url, constructed_url])))
    def test_constructs_correct_urls(self):
        # The view classes can override constructTemplateURL with
        # optimized versions.  These can produce either an absolute URL
        # that exactly matches the template's canonical_url, or a
        # relative one starting from the series' canonical_url.
        template = self._makeTemplate()
        view = self._makeView(template)

        series_url = canonical_url(self._getSeries(template),
                                   rootsite='translations')
        constructed_url = view.constructTemplateURL(template)

        self.assertIn(
            canonical_url(template),
            (constructed_url, '/'.join([series_url, constructed_url])))
 def test_traversal_to_nonexistent_bugtask(self):
     # Test that a traversing to a non-existent bugtask redirects to the
     # bug's default bugtask.
     bug = self.factory.makeBug()
     bugtask = self.factory.makeBugTask(bug=bug)
     bugtask_url = canonical_url(bugtask, rootsite='bugs')
     login_person(bugtask.owner)
     bugtask.delete()
     obj, view, request = test_traverse(bugtask_url)
     view()
     naked_view = removeSecurityProxy(view)
     self.assertEqual(301, request.response.getStatus())
     self.assertEqual(
         naked_view.target,
         canonical_url(bug.default_bugtask, rootsite='bugs'))
Example #41
0
def notify_bugtask_edited(modified_bugtask, event):
    """Notify CC'd subscribers of this bug that something has changed
    on this task.

    modified_bugtask must be an IBugTask. event must be an
    IObjectModifiedEvent.
    """
    bugtask_delta = event.object.getDelta(event.object_before_modification)
    bug_delta = BugDelta(
        bug=event.object.bug,
        bugurl=canonical_url(event.object.bug),
        bugtask_deltas=bugtask_delta,
        user=IPerson(event.user))

    event_creator = IPerson(event.user)
    previous_subscribers = event.object_before_modification.bug_subscribers
    current_subscribers = event.object.bug_subscribers
    prev_subs_set = set(previous_subscribers)
    cur_subs_set = set(current_subscribers)
    new_subs = cur_subs_set.difference(prev_subs_set)

    add_bug_change_notifications(
        bug_delta, old_bugtask=event.object_before_modification,
        new_subscribers=new_subs)

    send_bug_details_to_new_bug_subscribers(
        event.object.bug, previous_subscribers, current_subscribers,
        event_creator=event_creator)
 def test_items_for_field_vocabulary(self):
     widget = self._getWidget(attribute_type="reference")
     vocab = getVocabularyRegistry().get(None, 'BuildableDistroSeries')
     value_fn = lambda item: canonical_url(
         item.value, force_local_path=True)
     expected_items = self._makeExpectedItems(vocab, value_fn=value_fn)
     self.assertEqual(simplejson.dumps(expected_items), widget.json_items)
Example #43
0
 def send(self):
     """Send a message to the user about the product's licence."""
     if not self.needs_notification(self.product):
         # The project has a common licence.
         return False
     maintainer = self.product.owner
     if maintainer.is_team:
         user_address = maintainer.getTeamAdminsEmailAddresses()
     else:
         user_address = format_address_for_person(maintainer)
     from_address = format_address(
         "Launchpad", config.canonical.noreply_from_address)
     commercial_address = format_address(
         'Commercial', '*****@*****.**')
     substitutions = dict(
         user_displayname=maintainer.displayname,
         user_name=maintainer.name,
         product_name=self.product.name,
         product_url=canonical_url(self.product),
         commercial_use_expiration=self.getCommercialUseMessage(),
         )
     # Email the user about licence policy.
     subject = (
         "Licence information for %(product_name)s "
         "in Launchpad" % substitutions)
     template = get_email_template(
         self.getTemplateName(), app='registry')
     message = template % substitutions
     simple_sendmail(
         from_address, user_address,
         subject, message, headers={'Reply-To': commercial_address})
     # Inform that Launchpad recognized the licence change.
     self._addLicenseChangeToReviewWhiteboard()
     return True
 def test_bug_page_user_with_aag_proprietary_product(self):
     # A user with an artifact grant for a bug targeted to a private
     # product can view the bug page.
     with person_logged_in(self.user):
         url = canonical_url(self.bug)
         # No exception is raised when the page is rendered.
         self.getUserBrowser(url, user=self.user)
 def test_bugtarget(self):
     project = self.factory.makeProduct(name='fnord')
     project_bugs_url = canonical_url(project, rootsite='bugs')
     crumbs = self.getBreadcrumbsForObject(project, rootsite='bugs')
     last_crumb = crumbs[-1]
     self.assertEquals(project_bugs_url, last_crumb.url)
     self.assertEquals("Bugs", last_crumb.text)
 def setUp(self):
     super(TestMilestoneBreadcrumb, self).setUp()
     self.project = self.factory.makeProduct()
     self.series = self.factory.makeProductSeries(product=self.project)
     self.milestone = self.factory.makeMilestone(
         productseries=self.series, name="1.1")
     self.milestone_url = canonical_url(self.milestone)
 def test_personal_archive_subscription(self):
     subscription_url = canonical_url(self.personal_archive_subscription)
     crumbs = self.getBreadcrumbsForObject(
         self.personal_archive_subscription)
     self.assertEquals(subscription_url, crumbs[-1].url)
     self.assertEquals("Access to %s" % self.ppa.displayname,
                       crumbs[-1].text)
 def setUp(self):
     super(TestDistroseriesBreadcrumb, self).setUp()
     self.distribution = self.factory.makeDistribution(
         name='youbuntu', displayname='Youbuntu')
     self.distroseries = self.factory.makeDistroSeries(
         name='groovy', version="1.06", distribution=self.distribution)
     self.distroseries_url = canonical_url(self.distroseries)
Example #49
0
 def _assert_getBugData(self, related_bug=None):
     # The getBugData method works as expected.
     owner = self.factory.makePerson()
     product = self.factory.makeProduct()
     bug = self.factory.makeBug(
         target=product,
         owner=owner,
         status=BugTaskStatus.INPROGRESS,
         title='title', description='description',
         information_type=InformationType.PRIVATESECURITY)
     with person_logged_in(owner):
         bug_data = getUtility(IMaloneApplication).getBugData(
             owner, bug.id, related_bug)
         expected_bug_data = {
                 'id': bug.id,
                 'information_type': 'Private Security',
                 'is_private': True,
                 'importance': 'Undecided',
                 'importance_class': 'importanceUNDECIDED',
                 'status': 'In Progress',
                 'status_class': 'statusINPROGRESS',
                 'bug_summary': 'title',
                 'description': 'description',
                 'bug_url': canonical_url(bug.default_bugtask),
                 'different_pillars': related_bug is not None
     }
     self.assertEqual([expected_bug_data], bug_data)
 def test_non_owner_unauthorised(self):
     # Only team owners can reassign team ownership.
     team = self.factory.makeTeam()
     any_person = self.factory.makePerson()
     reassign_url = canonical_url(team, view_name='+reassign')
     browser = setupBrowserForUser(any_person)
     self.assertRaises(Unauthorized, browser.open, reassign_url)
Example #51
0
 def composeWebhookPayload(branch, old_revid, new_revid):
     return {
         "bzr_branch": canonical_url(branch, force_local_path=True),
         "bzr_branch_path": branch.shortened_path,
         "old": {"revision_id": old_revid},
         "new": {"revision_id": new_revid},
         }
Example #52
0
 def createDelta(self, user=None, **kwargs):
     if user is None:
         user = self.user
     return BugDelta(bug=self.bug,
                     bugurl=canonical_url(self.bug),
                     user=user,
                     **kwargs)
 def test_distroarchseriesbinarypackagerelease(self):
     pmount_hoary_i386 = self.hoary_i386.getBinaryPackage("pmount")
     pmount_release = pmount_hoary_i386['0.1-1']
     pmount_release_url = canonical_url(pmount_release)
     crumbs = self.getBreadcrumbsForObject(pmount_release)
     self.assertEquals(crumbs[-1].url, pmount_release_url)
     self.assertEquals(crumbs[-1].text, "0.1-1")
Example #54
0
    def submitForcedEmptySuggestion(self):
        """Submit an empty suggestion for `self.current_translation`."""
        empty_translation = u''

        msgset_id = 'msgset_' + str(self.current_translation.potmsgset.id)
        msgset_id_lang = msgset_id + '_' + self.pofile.language.code
        widget_id_base = msgset_id_lang + '_translation_0_'

        form = {
            'lock_timestamp': datetime.now(pytz.utc).isoformat(),
            'alt': None,
            msgset_id: None,
            widget_id_base + 'radiobutton': widget_id_base + 'new',
            widget_id_base + 'new': empty_translation,
            'submit_translations': 'Save &amp; Continue',
            msgset_id_lang + '_needsreview': 'force_suggestion',
        }

        url = canonical_url(self.current_translation) + '/+translate'
        view = create_view(self.current_translation,
                           '+translate',
                           form=form,
                           server_url=url)
        view.request.method = 'POST'
        view.initialize()
 def test_non_owner_unauthorised(self):
     # Only team owners can reassign team ownership.
     team = self.factory.makeTeam()
     any_person = self.factory.makePerson()
     reassign_url = canonical_url(team, view_name='+reassign')
     browser = setupBrowserForUser(any_person)
     self.assertRaises(Unauthorized, browser.open, reassign_url)