Merge lp:~sinzui/launchpad/location-bug-262193 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Eleanor Berger
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~sinzui/launchpad/location-bug-262193
Merge into: lp:launchpad
Diff against target: 459 lines (+57/-212)
10 files modified
lib/canonical/launchpad/emailtemplates/person-location-modified.txt (+0/-19)
lib/canonical/launchpad/permissions.zcml (+0/-4)
lib/canonical/launchpad/security.py (+0/-32)
lib/lp/registry/browser/configure.zcml (+1/-1)
lib/lp/registry/browser/person.py (+2/-14)
lib/lp/registry/configure.zcml (+1/-1)
lib/lp/registry/doc/personlocation.txt (+15/-53)
lib/lp/registry/model/person.py (+0/-14)
lib/lp/registry/stories/location/personlocation-edit.txt (+27/-59)
lib/lp/registry/stories/location/personlocation.txt (+11/-15)
To merge this branch: bzr merge lp:~sinzui/launchpad/location-bug-262193
Reviewer Review Type Date Requested Status
Eleanor Berger (community) code Approve
Review via email: mp+14878@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (3.1 KiB)

This is my branch to only permit users to edit their own location.

    lp:~sinzui/launchpad/location-bug-262193
    Diff size: 460
    Launchpad bug: https://bugs.launchpad.net/bugs/262193
    Test command: ./bin/test -vvt "personlocation"
    Pre-implementation: my conscience
    Target release: 3.1.11

= Only permit users to edit their own location. =

After much debate about allowing users to set someone else's location, it
is clear from the usage statistics that the feature is rarely used.
Removing the feature will not have a significant impact on Launchpad.

== Rules ==

    * Restrict the permissions to edit a location to the owner or admin:
      launchpad.Edit
    * Remove the launchpad.Editlocation permission.
      \o/ one less exception permission in security.py
    * Remove any UI that suggests that a user can edit someone else's
      location. Most, maybe all the UI elements suggesting that a person
      can set another person's location was removed in 3.0.
    * Remove the notification email set when some edits another person's
      location.

== QA ==

    * On staging, verify that the page does not prompt you to set someone's
      location.
    * Verify that you cannot access the user's +editlocation page.

== Lint ==

Linting changed files:
  lib/canonical/launchpad/permissions.zcml
  lib/canonical/launchpad/security.py
  lib/lp/registry/configure.zcml
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/person.py
  lib/lp/registry/doc/personlocation.txt
  lib/lp/registry/model/person.py
  lib/lp/registry/stories/location/personlocation-edit.txt
  lib/lp/registry/stories/location/personlocation.txt

== Test ==

    * lib/lp/registry/doc/personlocation.txt
      * Revised the test to show that a user's location is only editable
        by himself or an admin.
      * Removed all tests that showed that a user could set someone else's
        location if the location was unset.
    * lib/lp/registry/stories/location/personlocation-edit.txt
      * Removed the tests that demonstrated a user could set another user's
        location if the location was unset.
    * lib/lp/registry/stories/location/personlocation.txt
      * Removed the test that implied a user could set another user's
        location.
      * Revised to the test to show that any user can see another user's
        location if it is public (the previous test implied the user had
        to be logged in).

== Implementation ==

    * lib/canonical/launchpad/emailtemplates/person-location-modified.txt
      * Deleted because it is not possible to set another user's location.

    * lib/canonical/launchpad/permissions.zcml
    * lib/canonical/launchpad/security.py
      * Removed launchpad.EditLocation.

    * lib/lp/registry/configure.zcml
    * lib/lp/registry/browser/configure.zcml
      * Replaced launchpad.EditLocation with launchpad.Edit.

    * lib/lp/registry/browser/person.py
      * Replaced launchpad.EditLocation with launchpad.Edit.
      * Since there is only one permission to access +editlocation, the
        field_names never change.

    * lib/lp/registry/model/person.py
      * Removed the notification about a user setting an...

Read more...

Revision history for this message
Eleanor Berger (intellectronica) wrote :

simplicity rocks!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed file 'lib/canonical/launchpad/emailtemplates/person-location-modified.txt'
--- lib/canonical/launchpad/emailtemplates/person-location-modified.txt 2008-06-18 13:06:54 +0000
+++ lib/canonical/launchpad/emailtemplates/person-location-modified.txt 1970-01-01 00:00:00 +0000
@@ -1,19 +0,0 @@
1
2%(actor_browsername)s has updated your location and time zone information in
3Launchpad. This lets us present dates and times in your local time, and
4helps to coordinate team events that will span multiple time zones.
5
6Your information can be updated by any other user until you provide
7definitive data yourself, at which point the information is locked
8so that only you can edit it.
9
10Your details (now with map!): https://launchpad.net/~%(person)s
11%(actor_browsername)s's details: https://launchpad.net/~%(actor)s
12
13You can edit the location and time zone information for yourself at:
14
15 https://launchpad.net/~%(person)s/+editlocation
16
17Regards,
18
19The Launchpad team
200
=== modified file 'lib/canonical/launchpad/permissions.zcml'
--- lib/canonical/launchpad/permissions.zcml 2009-08-13 15:12:16 +0000
+++ lib/canonical/launchpad/permissions.zcml 2009-11-15 01:25:23 +0000
@@ -16,10 +16,6 @@
16 <permission16 <permission
17 id="launchpad.Edit" title="Editing something" access_level="write" />17 id="launchpad.Edit" title="Editing something" access_level="write" />
1818
19 <permission
20 id="launchpad.EditLocation" title="Editing an object's location"
21 access_level="write" />
22
23 <!-- Request large downloads, or other heavyweight jobs that are not19 <!-- Request large downloads, or other heavyweight jobs that are not
24 semantically like "editing" and are not restricted to administrators.20 semantically like "editing" and are not restricted to administrators.
25 -->21 -->
2622
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2009-11-13 05:13:07 +0000
+++ lib/canonical/launchpad/security.py 2009-11-15 01:25:23 +0000
@@ -624,38 +624,6 @@
624 return person == user or user.inTeam(admins)624 return person == user or user.inTeam(admins)
625625
626626
627class EditPersonLocation(AuthorizationBase):
628 permission = 'launchpad.EditLocation'
629 usedfor = IPerson
630
631 def checkAuthenticated(self, user):
632 """Anybody can edit a person's location until that person sets it.
633
634 Once a person sets his own location that information can only be
635 changed by the person himself or admins.
636 """
637 location = self.obj.location
638 if location is None:
639 # No PersonLocation entry exists for this person, so anybody can
640 # change this person's location.
641 return True
642
643 # There is a PersonLocation entry for this person, so we'll check its
644 # details to find out whether or not the user can edit them.
645 if (location.visible
646 and (location.latitude is None
647 or location.last_modified_by != self.obj)):
648 # No location has been specified yet or it has been specified
649 # by a non-authoritative source (not the person himself), so
650 # anybody can change it.
651 return True
652 else:
653 admins = getUtility(ILaunchpadCelebrities).admin
654 # The person himself and LP admins can always change that person's
655 # location.
656 return user == self.obj or user.inTeam(admins)
657
658
659class ViewPersonLocation(AuthorizationBase):627class ViewPersonLocation(AuthorizationBase):
660 permission = 'launchpad.View'628 permission = 'launchpad.View'
661 usedfor = IPersonLocation629 usedfor = IPersonLocation
662630
=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2009-11-11 10:30:23 +0000
+++ lib/lp/registry/browser/configure.zcml 2009-11-15 01:25:23 +0000
@@ -830,7 +830,7 @@
830 name="+editlocation"830 name="+editlocation"
831 for="lp.registry.interfaces.person.IPerson"831 for="lp.registry.interfaces.person.IPerson"
832 class="lp.registry.browser.person.PersonEditLocationView"832 class="lp.registry.browser.person.PersonEditLocationView"
833 permission="launchpad.EditLocation"833 permission="launchpad.Edit"
834 template="../templates/person-editlocation.pt"/>834 template="../templates/person-editlocation.pt"/>
835 <browser:page835 <browser:page
836 name="+contactuser"836 name="+contactuser"
837837
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2009-11-09 04:24:09 +0000
+++ lib/lp/registry/browser/person.py 2009-11-15 01:25:23 +0000
@@ -954,7 +954,7 @@
954 text = 'Update Jabber IDs'954 text = 'Update Jabber IDs'
955 return Link(target, text, icon='edit')955 return Link(target, text, icon='edit')
956956
957 @enabled_with_permission('launchpad.EditLocation')957 @enabled_with_permission('launchpad.Edit')
958 def editlocation(self):958 def editlocation(self):
959 target = '+editlocation'959 target = '+editlocation'
960 text = 'Set location and time zone'960 text = 'Set location and time zone'
@@ -5333,6 +5333,7 @@
5333 """Edit a person's location."""5333 """Edit a person's location."""
53345334
5335 schema = PersonLocationForm5335 schema = PersonLocationForm
5336 field_names = ['location', 'hide']
5336 custom_widget('location', LocationWidget)5337 custom_widget('location', LocationWidget)
53375338
5338 @property5339 @property
@@ -5343,19 +5344,6 @@
5343 label = page_title5344 label = page_title
53445345
5345 @property5346 @property
5346 def field_names(self):
5347 """See `LaunchpadFormView`.
5348
5349 If the user has launchpad.Edit on this context, then allow him to set
5350 whether or not the location should be visible. The field for setting
5351 the person's location is always shown.
5352 """
5353 if check_permission('launchpad.Edit', self.context):
5354 return ['location', 'hide']
5355 else:
5356 return ['location']
5357
5358 @property
5359 def initial_values(self):5347 def initial_values(self):
5360 """See `LaunchpadFormView`.5348 """See `LaunchpadFormView`.
53615349
53625350
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2009-11-12 12:01:22 +0000
+++ lib/lp/registry/configure.zcml 2009-11-15 01:25:23 +0000
@@ -805,7 +805,7 @@
805 permission="launchpad.View"805 permission="launchpad.View"
806 interface="lp.registry.interfaces.person.IPersonViewRestricted"/>806 interface="lp.registry.interfaces.person.IPersonViewRestricted"/>
807 <require807 <require
808 permission="launchpad.EditLocation"808 permission="launchpad.Edit"
809 interface="lp.registry.interfaces.location.ISetLocation"/>809 interface="lp.registry.interfaces.location.ISetLocation"/>
810 <require810 <require
811 permission="launchpad.Edit"811 permission="launchpad.Edit"
812812
=== modified file 'lib/lp/registry/doc/personlocation.txt'
--- lib/lp/registry/doc/personlocation.txt 2009-04-17 10:32:16 +0000
+++ lib/lp/registry/doc/personlocation.txt 2009-11-15 01:25:23 +0000
@@ -38,53 +38,22 @@
38requires that the user providing the information is passed as a38requires that the user providing the information is passed as a
39parameter.39parameter.
4040
41We'll use jdub as a prolific source of location information for41A user cannot set another user's location.
42community members.
4342
44 >>> jdub = personset.getByName('jdub')43 >>> jdub = personset.getByName('jdub')
45 >>> login_person(jdub)44 >>> login_person(jdub)
46
47First, jdub will provide information about cprov, who doesn't have any
48location data in the sampledata.
49
50 >>> cprov = personset.getByName('cprov')45 >>> cprov = personset.getByName('cprov')
51 >>> print cprov.latitude
52 None
53 >>> print cprov.time_zone
54 None
55 >>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)46 >>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)
56 >>> print cprov.time_zone47 Traceback (most recent call last):
57 America/Sao_Paulo48 ...
5849 Unauthorized:...
59When a person's location is changed by somebody else, we notify the50
60person through email.51A user can set his own location.
61
62 >>> from canonical.launchpad.database import PersonNotification
63 >>> notification = PersonNotification.selectOneBy(person=cprov)
64 >>> print notification.subject
65 Jeff Waugh updated your location and time zone
66
67 # Delete the notification so that it doesn't interfere in other tests.
68 >>> notification.destroySelf()
69
70And once cprov provides data for himself, jdub won't be able to edit it
71any more.
7252
73 >>> login_person(cprov)53 >>> login_person(cprov)
74 >>> cprov.setLocation(-43.2, -61.93, 'America/Sao_Paulo', cprov)54 >>> cprov.setLocation(-43.2, -61.93, 'America/Sao_Paulo', cprov)
7555
76 >>> login_person(jdub)56cprov can change his location information. We need to deal
77 >>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)
78 Traceback (most recent call last):
79 ...
80 Unauthorized:...
81
82When a user changes his own location, no notification is sent, though.
83
84 >>> PersonNotification.selectBy(person=cprov).count()
85 0
86
87But cprov can obviously still edit his own information. We need to deal
88with some floating point precision issues here, hence the rounding.57with some floating point precision issues here, hence the rounding.
8958
90 >>> login_person(cprov)59 >>> login_person(cprov)
@@ -92,7 +61,7 @@
92 >>> abs(cprov.latitude + 43.52) < 0.00161 >>> abs(cprov.latitude + 43.52) < 0.001
93 True62 True
9463
95And admins can, too.64Admins can set a user's location.
9665
97 >>> admin = personset.getByName('name16')66 >>> admin = personset.getByName('name16')
98 >>> login_person(admin)67 >>> login_person(admin)
@@ -100,20 +69,6 @@
100 >>> abs(cprov.longitude + 62.1) < 0.00169 >>> abs(cprov.longitude + 62.1) < 0.001
101 True70 True
10271
103If a user had provided only his time zone but not his location, other
104people would still be able to set his location. That's the case of
105most our existing users, who set their time zone but hadn't set their
106locations (since there was no UI for that).
107
108 >>> salgado = personset.getByName('salgado')
109 >>> login_person(salgado)
110 >>> salgado.setLocation(None, None, 'America/Sao_Paulo', salgado)
111
112 >>> login_person(jdub)
113 >>> salgado.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)
114 >>> print salgado.latitude
115 -43.0
116
117We cannot store a location for a team, though.72We cannot store a location for a team, though.
11873
119 >>> guadamen = personset.getByName('guadamen')74 >>> guadamen = personset.getByName('guadamen')
@@ -214,11 +169,18 @@
214we provide a way for them to hide their location from other users. By169we provide a way for them to hide their location from other users. By
215default a person's location is visible.170default a person's location is visible.
216171
172 >>> salgado = personset.getByName('salgado')
173 >>> login_person(salgado)
174 >>> salgado.setLocation(-43.0, -62.1, 'America/Sao_Paulo', salgado)
217 >>> salgado.location.visible175 >>> salgado.location.visible
218 True176 True
219 >>> salgado.location.latitude177 >>> salgado.location.latitude
220 -43...178 -43...
221179
180 >>> login_person(jdub)
181 >>> salgado.location.latitude
182 -43...
183
222But it can be changed through the setLocationVisibility() method. If the184But it can be changed through the setLocationVisibility() method. If the
223visibility is set to False, only the person himself will be able to see185visibility is set to False, only the person himself will be able to see
224the location data except for time zone.186the location data except for time zone.
225187
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2009-11-12 20:55:43 +0000
+++ lib/lp/registry/model/person.py 2009-11-15 01:25:23 +0000
@@ -551,20 +551,6 @@
551 person=self, time_zone=time_zone, latitude=latitude,551 person=self, time_zone=time_zone, latitude=latitude,
552 longitude=longitude, last_modified_by=user)552 longitude=longitude, last_modified_by=user)
553553
554 # Make a note that we need to tell this person that their
555 # information was updated by the user. We can only do this if we
556 # have a validated email address for this person.
557 if user != self and self.preferredemail is not None:
558 mail_text = get_email_template('person-location-modified.txt')
559 mail_text = mail_text % {
560 'actor': user.name,
561 'actor_browsername': user.displayname,
562 'person': self.name}
563 subject = '%s updated your location and time zone' % (
564 user.displayname)
565 getUtility(IPersonNotificationSet).addNotification(
566 self, subject, mail_text)
567
568 # specification-related joins554 # specification-related joins
569 @property555 @property
570 def assigned_specs(self):556 def assigned_specs(self):
571557
=== modified file 'lib/lp/registry/stories/location/personlocation-edit.txt'
--- lib/lp/registry/stories/location/personlocation-edit.txt 2009-03-24 12:43:49 +0000
+++ lib/lp/registry/stories/location/personlocation-edit.txt 2009-11-15 01:25:23 +0000
@@ -1,9 +1,7 @@
1== Edit person location information ==1== Edit person location information ==
22
3The location information is editable by anybody (like a wiki), until the3A person's location is only editable by people who have launchpad.Edit on
4person provides location data for themselves. At that point it is only4the person, which is that person and admins.
5editable by people who have launchpad.Edit on the person, which is that
6person and admins.
75
8 >>> login('test@canonical.com')6 >>> login('test@canonical.com')
9 >>> zzz = factory.makePerson(7 >>> zzz = factory.makePerson(
@@ -11,37 +9,15 @@
11 ... latitude=None, longitude=None, password='test')9 ... latitude=None, longitude=None, password='test')
12 >>> logout()10 >>> logout()
1311
14Anybody logged in can see the Location widget for a person who has no12A user cannot set another user's location.
15location set.
1613
17 >>> nopriv_browser = setupBrowser(auth="Basic no-priv@canonical.com:test")14 >>> nopriv_browser = setupBrowser(auth="Basic no-priv@canonical.com:test")
18 >>> nopriv_browser.open('http://launchpad.dev/~zzz/+editlocation')15 >>> nopriv_browser.open('http://launchpad.dev/~zzz/+editlocation')
19 >>> find_tag_by_id(nopriv_browser.contents, "field.location.latitude")16 Traceback (most recent call last):
20 <input...name="field.location.latitude" type="hidden"...17 ...
2118 Unauthorized:...
22Not only can we see the widgets, but anybody logged in can actually provide19
23new location information. Here we need to provide the location and time20A user can set his own location:
24zone, but when accessed through a real browser the page will use Javascript
25to infer the time zone based on the location given.
26
27 >>> nopriv_browser.getControl(name='field.location.latitude').value = (
28 ... '13.0')
29 >>> nopriv_browser.getControl(name='field.location.longitude').value = (
30 ... '17.0')
31 >>> nopriv_browser.getControl(name='field.location.time_zone').value = [
32 ... 'Europe/Madrid']
33 >>> nopriv_browser.getControl('Update').click()
34 >>> login('test@canonical.com')
35 >>> zzz.latitude
36 13.0
37 >>> zzz.longitude
38 17.0
39 >>> zzz.time_zone
40 u'Europe/Madrid'
41 >>> logout()
42
43If the person provides his own location information, then the data is
44locked, and random people can no longer edit it.
4521
46 >>> self_browser = setupBrowser(auth="Basic zzz@foo.com:test")22 >>> self_browser = setupBrowser(auth="Basic zzz@foo.com:test")
47 >>> self_browser.open('http://launchpad.dev/~zzz/+editlocation')23 >>> self_browser.open('http://launchpad.dev/~zzz/+editlocation')
@@ -53,12 +29,16 @@
53 ... 'Europe/Madrid']29 ... 'Europe/Madrid']
54 >>> self_browser.getControl('Update').click()30 >>> self_browser.getControl('Update').click()
5531
56 >>> nopriv_browser.open('http://launchpad.dev/~zzz/+editlocation')32 >>> login('zzz@foo.com')
57 Traceback (most recent call last):33 >>> zzz.latitude
58 ...34 39.4...
59 Unauthorized:...35 >>> zzz.longitude
36 -0.4...
37 >>> zzz.time_zone
38 u'Europe/Madrid'
39 >>> logout()
6040
61Of course, the person himself can continue to edit it:41The user can change his location:
6242
63 >>> self_browser.open('http://launchpad.dev/~zzz/+editlocation')43 >>> self_browser.open('http://launchpad.dev/~zzz/+editlocation')
64 >>> self_browser.getControl(name='field.location.latitude').value44 >>> self_browser.getControl(name='field.location.latitude').value
@@ -71,33 +51,21 @@
71 '39.48'51 '39.48'
7252
73The +editlocation page also allows a person to change his location53The +editlocation page also allows a person to change his location
74visibility, that is, whether or not others can see it. Unlike the actual54visibility, that is, whether or not others can see it.
75location (which can be changed by anybody until the person himself sets55
76it), the visibility can only be changed by the person himself.56 >>> nopriv_browser.open('http://launchpad.dev/~no-priv/+editlocation')
57 >>> nopriv_browser.getControl(
58 ... 'Hide my location details from others.').selected = True
59 >>> nopriv_browser.getControl('Update').click()
60 >>> nopriv_browser.url
61 'http://launchpad.dev/~no-priv'
62
63Once hidden, other users can't see it.
7764
78 >>> name12_browser = setupBrowser(auth="Basic test@canonical.com:test")65 >>> name12_browser = setupBrowser(auth="Basic test@canonical.com:test")
79 >>> name12_browser.open('http://launchpad.dev/~no-priv/+editlocation')
80 >>> name12_browser.getControl('Hide my location details from others.')
81 Traceback (most recent call last):
82 ...
83 LookupError:...
84
85 >>> nopriv_browser.open('http://launchpad.dev/~no-priv/+editlocation')
86 >>> nopriv_browser.getControl(
87 ... 'Hide my location details from others.').selected = True
88 >>> nopriv_browser.getControl('Update').click()
89 >>> nopriv_browser.url
90 'http://launchpad.dev/~no-priv'
91
92Once hidden, other users can't see nor change it.
93
94 >>> name12_browser.open('http://launchpad.dev/~no-priv')66 >>> name12_browser.open('http://launchpad.dev/~no-priv')
95 >>> print str(find_tag_by_id(name12_browser.contents, 'person_map_div'))67 >>> print str(find_tag_by_id(name12_browser.contents, 'person_map_div'))
96 None68 None
97 >>> name12_browser.open('http://launchpad.dev/~no-priv/+editlocation')
98 Traceback (most recent call last):
99 ...
100 Unauthorized:...
10169
102The person himself can still see and change it, though.70The person himself can still see and change it, though.
10371
10472
=== modified file 'lib/lp/registry/stories/location/personlocation.txt'
--- lib/lp/registry/stories/location/personlocation.txt 2009-09-16 17:56:17 +0000
+++ lib/lp/registry/stories/location/personlocation.txt 2009-11-15 01:25:23 +0000
@@ -8,30 +8,26 @@
8 >>> zzz = factory.makePerson(name='zzz', time_zone='Africa/Maseru',8 >>> zzz = factory.makePerson(name='zzz', time_zone='Africa/Maseru',
9 ... latitude=None, longitude=None)9 ... latitude=None, longitude=None)
10 >>> logout()10 >>> logout()
11 >>> nopriv_browser = setupBrowser(auth='Basic no-priv@canonical.com:test')11
12 >>> nopriv_browser.open('http://launchpad.dev/~zzz')12Any person can see another person's time zone.
1313
14They should see a link to the +editlocation page (around the map image)14 >>> anon_browser.open('http://launchpad.dev/~zzz')
15and the person's time zone.15 >>> print extract_text(
1616 ... find_tag_by_id(anon_browser.contents, 'portlet-map'))
17 >>> editlink = nopriv_browser.getLink(url='+editlocation', index=1)
18 >>> editlink.text
19 '[IMG]'
20 >>> print extract_text(find_tag_by_id(nopriv_browser.contents, 'portlet-map'))
21 Location17 Location
22 Time zone: Africa/Maseru18 Time zone: Africa/Maseru
2319
24If a person has a location, they should have a little map portlet in their20If a person has a location, there is a little map portlet in their
25home page. We can't test all the google javascript, but we can make sure21profile page. We can't test all the google javascript, but we can make sure
26there's a map, and the scripts are loaded.22there's a map, and the scripts are loaded.
2723
28 >>> login('test@canonical.com')24 >>> login('test@canonical.com')
29 >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',25 >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',
30 ... latitude=52.2, longitude=0.3)26 ... latitude=52.2, longitude=0.3)
31 >>> logout()27 >>> logout()
32 >>> nopriv_browser = setupBrowser(auth='Basic no-priv@canonical.com:test')28
33 >>> nopriv_browser.open('http://launchpad.dev/~yyy')29 >>> anon_browser.open('http://launchpad.dev/~yyy')
34 >>> markup = str(nopriv_browser.contents)30 >>> markup = str(anon_browser.contents)
35 >>> print extract_text(find_tag_by_id(markup, 'portlet-map'), skip_tags=[])31 >>> print extract_text(find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
36 Location32 Location
37 Time zone: Europe/London...33 Time zone: Europe/London...