← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~bac/launchpad/bug-186660 into lp:launchpad

 

Brad Crittenden has proposed merging lp:~bac/launchpad/bug-186660 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #186660 in Launchpad itself: "Launchpad shouldn't store wiki names"
  https://bugs.launchpad.net/launchpad/+bug/186660

For more details, see:
https://code.launchpad.net/~bac/launchpad/bug-186660/+merge/63029

= Summary =

It has been determined (see the bug discussion) that wiki_names are not
a useful thing to be associated with a Person in Launchpad.

== Proposed fix ==

This branch removes the wiki names from the web UI.

Subsequent branches will remove wiki_names from the webservice (while
attempting to maintain backwards compatibility) and another branch
removes them from the database.

== Pre-implementation notes ==

Chats with Gary.

== Implementation details ==

As above.

== Tests ==

None, as the test has been removed.

== Demo and Q/A ==

Visit http://launchpad.dev/~name12 and see that the wiki name is not
shown.  Visit http://launchpad.dev/~name12/+editwikinames
= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/registry/browser/configure.zcml
  lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt
  lib/lp/registry/templates/product-rdf.pt
  lib/lp/registry/templates/person-portlet-contact-details.pt
  lib/lp/registry/browser/person.py

./lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt
   Lots of known, annoying lint.
-- 
https://code.launchpad.net/~bac/launchpad/bug-186660/+merge/63029
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~bac/launchpad/bug-186660 into lp:launchpad.
=== modified file 'lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt'
--- lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt	2011-05-13 03:46:29 +0000
+++ lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt	2011-05-31 18:45:59 +0000
@@ -388,7 +388,6 @@
 >>> check("/~name16/+related-software")
 >>> check("/~name16/+editsshkeys", auth=True)
 >>> check("/~name16/+editpgpkeys", auth=True)
->>> check("/~name16/+editwikinames", auth=True)
 >>> check("/~name16/+editjabberids", auth=True)
 >>> check("/~name16/+codesofconduct", auth=True)
 >>> check("/~name16/+edithomepage", auth=True)

=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml	2011-05-27 21:03:22 +0000
+++ lib/lp/registry/browser/configure.zcml	2011-05-31 18:45:59 +0000
@@ -1040,12 +1040,6 @@
             class="lp.registry.browser.person.PersonCodeOfConductEditView"
             template="../templates/person-codesofconduct.pt"/>
         <browser:page
-            name="+editwikinames"
-            for="lp.registry.interfaces.person.IPerson"
-            permission="launchpad.Edit"
-            class="lp.registry.browser.person.PersonEditWikiNamesView"
-            template="../templates/person-editwikinames.pt"/>
-        <browser:page
             name="+editircnicknames"
             for="lp.registry.interfaces.person.IPerson"
             permission="launchpad.Edit"

=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py	2011-05-27 21:12:25 +0000
+++ lib/lp/registry/browser/person.py	2011-05-31 18:45:59 +0000
@@ -28,7 +28,6 @@
     'PersonEditLocationView',
     'PersonEditSSHKeysView',
     'PersonEditView',
-    'PersonEditWikiNamesView',
     'PersonFacets',
     'PersonGPGView',
     'PersonIndexMenu',
@@ -100,10 +99,7 @@
 from lazr.delegates import delegates
 from lazr.restful.interface import copy_field
 from lazr.restful.interfaces import IWebServiceClientRequest
-from lazr.uri import (
-    InvalidURIError,
-    URI,
-    )
+from lazr.uri import URI
 import pytz
 from storm.expr import Join
 from storm.zope.interfaces import IResultSet
@@ -228,7 +224,6 @@
     )
 from lp.app.widgets.location import LocationWidget
 from lp.app.widgets.password import PasswordChangeWidget
-from lp.app.widgets.textwidgets import URIWidget
 from lp.blueprints.browser.specificationtarget import HasSpecificationsView
 from lp.blueprints.enums import SpecificationFilter
 from lp.bugs.browser.bugtask import BugTaskSearchListingView
@@ -297,11 +292,14 @@
     ITeamMembershipSet,
     TeamMembershipStatus,
     )
+<<<<<<< TREE
 from lp.registry.interfaces.wikiname import (
     IWikiName,
     IWikiNameSet,
     )
 from lp.registry.mail.notification import send_direct_contact_email
+=======
+>>>>>>> MERGE-SOURCE
 from lp.registry.model.milestone import (
     Milestone,
     milestone_sort_key,
@@ -506,14 +504,6 @@
             return None
         return email
 
-    @stepthrough('+wikiname')
-    def traverse_wikiname(self, id):
-        """Traverse to this person's WikiNames on the webservice layer."""
-        wiki = getUtility(IWikiNameSet).get(id)
-        if wiki is None or wiki.person != self.context:
-            return None
-        return wiki
-
     @stepthrough('+jabberid')
     def traverse_jabberid(self, jabber_id):
         """Traverse to this person's JabberIDs on the webservice layer."""
@@ -1054,7 +1044,6 @@
         'common_edithomepage',
         'editemailaddresses',
         'editlanguages',
-        'editwikinames',
         'editircnicknames',
         'editjabberids',
         'editsshkeys',
@@ -1104,12 +1093,6 @@
         return Link(target, text, icon='edit')
 
     @enabled_with_permission('launchpad.Edit')
-    def editwikinames(self):
-        target = '+editwikinames'
-        text = 'Update wiki names'
-        return Link(target, text, icon='edit')
-
-    @enabled_with_permission('launchpad.Edit')
     def editircnicknames(self):
         target = '+editircnicknames'
         text = 'Update IRC nicknames'
@@ -2789,16 +2772,6 @@
             check_permission('launchpad.Edit', self.context))
 
     @property
-    def should_show_wikinames_section(self):
-        """Should the 'Wiki names' section be shown?
-
-        It's shown when the person has Wiki names registered or has rights
-        to register new ones.
-        """
-        return not self.context.wiki_names.is_empty() or (
-            check_permission('launchpad.Edit', self.context))
-
-    @property
     def should_show_jabberids_section(self):
         """Should the 'Jabber IDs' section be shown?
 
@@ -3560,161 +3533,6 @@
                 sCoC_util.modifySignature(sig_id, self.user, comment, False)
 
 
-class PersonEditWikiNamesView(LaunchpadFormView):
-    """View for ~person/+editwikinames"""
-
-    schema = IWikiName
-    fields = ['wiki', 'wikiname']
-    # Use custom widgets solely to get the width correct.  The URIWidget has a
-    # CSS class that does not respect the displayWidth, thus the need to use a
-    # different cssClass.
-    custom_widget('wiki', URIWidget, displayWidth=40, cssClass="textType")
-    custom_widget('wikiname', TextWidget, displayWidth=40)
-
-    @property
-    def label(self):
-        return smartquote("%s's wiki names" % self.context.displayname)
-
-    @property
-    def next_url(self):
-        return canonical_url(self.context)
-
-    cancel_url = next_url
-
-    def setUpFields(self):
-        super(PersonEditWikiNamesView, self).setUpFields()
-        if self.context.wiki_names.count() > 0:
-            # Make the wiki and wiki_name entries optional on the edit page if
-            # one or more ids already exist, which allows the removal of ids
-            # without filling out the new wiki fields.
-            wiki_field = self.form_fields['wiki']
-            wikiname_field = self.form_fields['wikiname']
-            # Copy the fields so as not to modify the interface.
-            wiki_field.field = copy_field(wiki_field.field)
-            wiki_field.field.required = False
-            wikiname_field.field = copy_field(wikiname_field.field)
-            wikiname_field.field.required = False
-
-    def _validateWikiURL(self, url):
-        """Validate the URL.
-
-        Make sure that the result is a valid URL with only the
-        appropriate schemes.  The url is assumed to be a string.
-        """
-        if url is None:
-            return
-        try:
-            uri = URI(url)
-            if uri.scheme not in ('http', 'https'):
-                self.setFieldError(
-                    'wiki',
-                    structured(
-                        'The URL scheme "%(scheme)s" is not allowed.  '
-                        'Only http or https URLs may be used.',
-                        scheme=uri.scheme))
-        except InvalidURIError:
-            self.setFieldError(
-                'wiki',
-                structured(
-                    '"%(url)s" is not a valid URL.', url=url))
-
-    def _validateWikiName(self, name):
-        """Ensure the wikiname is valid.
-
-        It must not be longer than 100 characters.  Name is assumed to be a
-        string.
-        """
-        max_len = 100
-        if len(name) > max_len:
-            self.setFieldError(
-                'wikiname',
-                structured(
-                    'The wiki name cannot exceed %d characters.' % max_len))
-
-    def _sanitizeWikiURL(self, url):
-        """Strip whitespaces and make sure :url ends in a single '/'."""
-        if not url:
-            return url
-        return '%s/' % url.strip().rstrip('/')
-
-    def validate(self, data):
-        # If there are already form errors then just show them.
-        if self.errors:
-            return
-        wikiurl = self._sanitizeWikiURL(data.get('wiki'))
-        wikiname = data.get('wikiname')
-        if wikiurl or wikiname:
-            if not wikiurl:
-                self.setFieldError(
-                    'wiki',
-                    structured(
-                        'The Wiki URL must be specified.'))
-            if not wikiname:
-                self.setFieldError(
-                    'wikiname',
-                    structured(
-                        'The Wiki name must be specified.'))
-
-        if self.errors:
-            return
-
-        if wikiurl is not None:
-            self._validateWikiURL(wikiurl)
-        if wikiname is not None:
-            self._validateWikiName(wikiname)
-
-        if self.errors:
-            return
-
-        wikinameset = getUtility(IWikiNameSet)
-        existingwiki = wikinameset.getByWikiAndName(wikiurl, wikiname)
-        if existingwiki:
-            if existingwiki.person != self.context:
-                owner_name = urllib.quote(existingwiki.person.name)
-                merge_url = (
-                    '%s/+requestmerge?field.dupe_person=%s'
-                    % (canonical_url(getUtility(IPersonSet)), owner_name))
-                self.setFieldError(
-                    'wikiname',
-                    structured(
-                        'The WikiName %s%s is already registered by '
-                        '<a href="%s">%s</a>. If you think this is a '
-                        'duplicated account, you can <a href="%s">merge it'
-                        '</a> into your account.',
-                        wikiurl, wikiname,
-                        canonical_url(existingwiki.person),
-                        existingwiki.person.displayname, merge_url))
-            else:
-                # The person already has this wiki.
-                self.setFieldError(
-                    'wikiname',
-                    'The WikiName %s%s already belongs to you.' %
-                    (wikiurl, wikiname))
-
-    def _save(self, wikiurl, wikiname):
-        """Given a wikiurl and wikiname, attempt to save it.
-
-        Verify someone else doesn't have it already.
-        """
-
-    @action(_("Save Changes"), name="save")
-    def save(self, action, data):
-        """Process the wiki names form."""
-        form = self.request.form
-        for obj in self.context.wiki_names:
-            if form.get('remove_%s' % obj.id):
-                obj.destroySelf()
-
-        if not self.errors:
-            wikiurl = self._sanitizeWikiURL(data.get('wiki'))
-            wikiname = data.get('wikiname')
-            # If either url or name are present then they both must be
-            # entered.
-            if wikiurl and wikiname:
-                wikinameset = getUtility(IWikiNameSet)
-                wikinameset.new(self.context, wikiurl, wikiname)
-
-
 class PersonEditIRCNicknamesView(LaunchpadFormView):
 
     schema = Interface

=== removed file 'lib/lp/registry/stories/person/xx-person-edit-wikis.txt'
--- lib/lp/registry/stories/person/xx-person-edit-wikis.txt	2010-08-31 14:00:54 +0000
+++ lib/lp/registry/stories/person/xx-person-edit-wikis.txt	1970-01-01 00:00:00 +0000
@@ -1,134 +0,0 @@
-Person's wikinames
-==================
-
-A person can have any number of WikiNames registered in Launchpad, and
-they can be managed on the +editwikinames page.
-
-    # A helper function for printing all wikinames of a person.
-    >>> def print_existing_wikiurls(contents):
-    ...     trs = find_tags_by_class(contents, 'wikiurl')
-    ...     wikis = []
-    ...     for tr in trs:
-    ...         td = tr.find('td')
-    ...         wikis.append(td.contents[0])
-    ...     print '\n'.join(wikis)
-
-    >>> def print_feedback(browser):
-    ...     print "\n".join(get_feedback_messages(browser.contents))
-
-Mark already has one WikiName registered.
-
-    >>> browser.addHeader('Authorization', 'Basic mark@xxxxxxxxxxx:test')
-    >>> browser.open('http://launchpad.dev/~mark/+editwikinames')
-    >>> print_existing_wikiurls(browser.contents)
-    https://wiki.ubuntu.com/MarkShuttleworth
-
-But he wants to register another one.
-
-    >>> browser.getControl(name='field.wiki').value = 'http://foo.bar/wiki/'
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print_feedback(browser)
-    >>> print browser.url
-    http://launchpad.dev/~mark
-    >>> browser.open('http://launchpad.dev/~mark/+editwikinames')
-    >>> print_existing_wikiurls(browser.contents)
-    http://foo.bar/wiki/FooBar
-    https://wiki.ubuntu.com/MarkShuttleworth
-
-He can't have two identical wiki names, though.
-
-    >>> browser.getControl(name='field.wiki').value = 'http://foo.bar/wiki/'
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> for message in find_tags_by_class(browser.contents, 'message'):
-    ...     print message.renderContents()
-    There is 1 error.
-    The WikiName http://foo.bar/wiki/FooBar already belongs to you.
-
-Nor can he have a WikiName that is already registered in Launchpad.
-
-    >>> browser.getControl(name='field.wiki').value = (
-    ...     'https://wiki.ubuntu.com/')
-    >>> browser.getControl(name='field.wikiname').value = 'GuilhermeSalgado'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    The WikiName https://wiki.ubuntu.com/GuilhermeSalgado is already
-    registered by Guilherme Salgado. If you think this is a duplicated
-    account, you can merge it into your account.
-
-A WikiName's URL can't be empty nor invalid.
-
-    >>> browser.getControl(name='field.wiki').value = ''
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    The Wiki URL must be specified.
-
-    >>> browser.getControl(name='field.wiki').value = '/this-is-not-a-url/'
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    "/this-is-not-a-url/" is not a valid URI
-
-And it can't be incredibly long.
-
-    >>> browser.getControl(name='field.wiki').value = (
-    ...     'https://wiki.ubuntu.com/')
-    >>> wikiname = "z" * 101
-    >>> browser.getControl(name='field.wikiname').value = wikiname
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    The wiki name cannot exceed 100 characters.
-
-The invalid value is escaped using HTML entities when displayed back to
-the user.
-
-    >>> browser.getControl(name='field.wiki').value = (
-    ...     '<script>alert(1);</script>')
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    "&lt;script&gt;alert(1);&lt;/script&gt;" is not a valid URI
-
-Only http and https URLs are allowed for wikis.
-
-    >>> browser.getControl(name='field.wiki').value = "javascript:void"
-    >>> browser.getControl(name='field.wikiname').value = 'FooBar'
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/%7Emark/+editwikinames
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    There is 1 error.
-    The URI scheme "javascript" is not allowed. Only URIs with the following
-    schemes may be used: http, https
-
-Mark can remove any of his wiki names.
-
-    >>> browser.getControl(name='field.wiki').value = ""
-    >>> browser.getControl(name='field.wikiname').value = ''
-    >>> browser.getControl('Remove', index=0).selected = True
-    >>> browser.getControl('Save Changes').click()
-    >>> print browser.url
-    http://launchpad.dev/~mark
-    >>> print "\n".join(get_feedback_messages(browser.contents))
-    >>> browser.open('http://launchpad.dev/~mark/+editwikinames')
-    >>> print_existing_wikiurls(browser.contents)
-    https://wiki.ubuntu.com/MarkShuttleworth

=== removed file 'lib/lp/registry/templates/person-editwikinames.pt'
--- lib/lp/registry/templates/person-editwikinames.pt	2010-08-30 22:41:41 +0000
+++ lib/lp/registry/templates/person-editwikinames.pt	1970-01-01 00:00:00 +0000
@@ -1,75 +0,0 @@
-<html
-  xmlns="http://www.w3.org/1999/xhtml";
-  xmlns:tal="http://xml.zope.org/namespaces/tal";
-  xmlns:metal="http://xml.zope.org/namespaces/metal";
-  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
-  metal:use-macro="view/macro:page/main_only"
-  i18n:domain="launchpad"
->
-<body>
-
-<div metal:fill-slot="main">
-<div metal:use-macro="context/@@launchpad_form/form">
-
-  <div metal:fill-slot="widgets">
-    <table id="wikinames">
-
-      <tal:XXX condition="nothing">
-        # XXX: salgado, 2008-11-25 bug=296739: We should use
-        # context/wiki_names/is_empty here, but we can't do that because
-        # there's a bug preventing us from # updating our version of storm
-        # to trunk.
-      </tal:XXX>
-
-      <tal:existing_wiki condition="context/wiki_names/any">
-
-        <tr>
-          <td><label>Existing wiki names</label></td>
-        </tr>
-
-        <tr>
-          <td><label>Wiki URL</label></td>
-        </tr>
-
-        <tr tal:repeat="wiki context/wiki_names" class="wikiurl">
-          <td tal:content="wiki/url"></td>
-          <td>
-            <label>
-              <input type="checkbox" value="Remove"
-                     tal:attributes="name string:remove_${wiki/id}" />
-              Remove
-            </label>
-          </td>
-        </tr>
-        <tr style="height:2em;"><td></td></tr>
-      </tal:existing_wiki>
-
-
-      <tr>
-        <td><label>New wiki name</label></td>
-      </tr>
-
-      <tal:widget define="widget nocall:view/widgets/wiki">
-        <metal:block use-macro="context/@@launchpad_form/widget_row" />
-      </tal:widget>
-
-      <tr>
-        <td class="formHelp">Example: https://wiki.ubuntu.com/</td>
-      </tr>
-
-      <tal:widget define="widget nocall:view/widgets/wikiname">
-        <metal:block use-macro="context/@@launchpad_form/widget_row" />
-      </tal:widget>
-
-      <tr>
-        <td class="formHelp">Example: YourName.</td>
-      </tr>
-
-    </table>
-  </div>
-
-</div>
-</div>
-
-</body>
-</html>

=== modified file 'lib/lp/registry/templates/person-portlet-contact-details.pt'
--- lib/lp/registry/templates/person-portlet-contact-details.pt	2011-05-27 17:28:16 +0000
+++ lib/lp/registry/templates/person-portlet-contact-details.pt	2011-05-31 18:45:59 +0000
@@ -93,6 +93,9 @@
       /></a>
     </div>
 
+  </div>
+
+  <div class="yui-u two-column-list">
     <dl tal:condition="view/should_show_ubuntu_coc_section" id="ubuntu-coc">
       <dt>Signed Ubuntu Code of Conduct:</dt>
       <dd tal:condition="context/is_ubuntu_coc_signer">
@@ -111,24 +114,7 @@
             ><img src="/@@/edit" alt="Sign the Ubuntu Code of Conduct" /></a>
       </dd>
     </dl>
-  </div>
 
-  <div class="yui-u two-column-list">
-    <dl tal:condition="view/should_show_wikinames_section">
-      <dt>Wiki:
-        <a tal:replace="structure overview_menu/editwikinames/fmt:icon" />
-      </dt>
-      <dd>
-        <div tal:repeat="wiki context/wiki_names">
-          <a tal:content="wiki/url"
-             tal:attributes="href wiki/url"
-           >WikiName</a>
-        </div>
-        <div tal:condition="context/wiki_names/is_empty">
-          No Wiki names registered.
-        </div>
-      </dd>
-    </dl>
     <dl tal:condition="view/should_show_ircnicknames_section">
       <dt>IRC:
         <a tal:replace="structure overview_menu/editircnicknames/fmt:icon" />

=== modified file 'lib/lp/registry/templates/product-rdf.pt'
--- lib/lp/registry/templates/product-rdf.pt	2010-10-15 16:28:56 +0000
+++ lib/lp/registry/templates/product-rdf.pt	2011-05-31 18:45:59 +0000
@@ -25,8 +25,6 @@
             1970-01-01 00:00:00
         </lp:creationDate>
         <lp:homepage tal:attributes="rdf:resource context/homepageurl" />
-        <lp:wiki tal:condition="context/wikiurl"
-                 tal:attributes="rdf:resource context/wikiurl" />
         <lp:freshmeatProject tal:condition="context/freshmeatproject"
                              tal:content="context/freshmeatproject">
             freshmeatproject