Add support for changing User id (Google Account email) in User Profile Developer view. Now user profile developer edit view includes hidden key_name field. Fix typo in user/profile.py. Show former user ids in lookup and edit User Profile Developer views.
Patch by: Pawel Solyga
Reviewed by: to-be-reviewed
--- a/app/soc/logic/site/id_user.py Sun Sep 21 08:59:11 2008 +0000
+++ b/app/soc/logic/site/id_user.py Mon Sep 22 13:42:53 2008 +0000
@@ -44,7 +44,7 @@
return 'User:%s' % id.email()
-def getIdIfMissing(id):
+def getIdIfMissing(id=None):
"""Gets Google Account of logged-in user (possibly None) if id is false.
This is a convenience function that simplifies a lot of view code that
@@ -66,6 +66,17 @@
return id
+def getUsersForOffsetAndLimit(offset=0, limit=0):
+ """Returns Users entities for given offset and limit or None if not found.
+
+ Args:
+ offset: offset in entities list which defines first entity to return
+ limit: max amount of entities to return
+ """
+ query = db.GqlQuery('SELECT * FROM User ORDER BY id')
+
+ # Fetch one more to see if there should be a 'next' link
+ return query.fetch(limit+1, offset)
def getUserFromId(id):
"""Returns User entity for a Google Account, or None if not found.
@@ -73,29 +84,8 @@
Args:
id: a Google Account (users.User) object
"""
- # first, attempt a lookup by User:id key name
- key_name = getUserKeyNameFromId(id)
-
- if key_name:
- user = soc.models.user.User.get_by_key_name(key_name)
- else:
- user = None
-
- if user:
- return user
+ return soc.models.user.User.gql('WHERE id = :1', id).get()
- # email address may have changed, so query the id property
- user = soc.models.user.User.gql('WHERE id = :1', id).get()
-
- if user:
- return user
-
- # last chance: perhaps the User changed their email address at some point
- user = soc.models.user.User.gql('WHERE former_ids = :1', id).get()
-
- return user
-
-
def getUserIfMissing(user, id):
"""Conditionally returns User entity for a Google Account.
@@ -227,6 +217,13 @@
"""
return soc.models.user.User.gql('WHERE link_name = :1', link_name).get()
+def getUserFromKeyName(key_name):
+ """Returns User entity for key_name or None if not found.
+
+ Args:
+ key_name: key name of User entity
+ """
+ return soc.models.user.User.get_by_key_name(key_name)
def getUserIfLinkName(link_name):
"""Returns User entity for supplied link_name if one exists.
@@ -349,6 +346,29 @@
# in a transaction
return updateUserProperties(user, **user_properties)
+def updateUserForKeyName(key_name, **user_properties):
+ """Update existing User entity for keyname with supplied properties.
+
+ Args:
+ key_name: key name of User entity
+ **user_properties: keyword arguments that correspond to User entity
+ properties and their values
+
+ Returns:
+ the User entity corresponding to the Google Account, with any supplied
+ properties changed, or a new User entity now associated with the Google
+ Account and with the supplied properties
+ """
+ # attempt to retrieve the existing User
+ user = getUserFromKeyName(key_name)
+
+ if not user:
+ return None
+
+ # there is no way to be sure if get_or_insert() returned a new User or
+ # got an existing one due to a race, so update with user_properties anyway,
+ # in a transaction
+ return updateUserProperties(user, **user_properties)
def updateUserProperties(user, **user_properties):
"""Update existing User entity using supplied User properties.
--- a/app/soc/templates/soc/site/user/profile/edit.html Sun Sep 21 08:59:11 2008 +0000
+++ b/app/soc/templates/soc/site/user/profile/edit.html Mon Sep 22 13:42:53 2008 +0000
@@ -36,6 +36,7 @@
{% endblock %}
</p>
<form method="POST">
+ {{ form.key_name }}
<table>
{% field_as_table_row form.id %}
{% if lookup_error %}
@@ -49,6 +50,18 @@
{% field_as_table_row form.link_name %}
{% field_as_table_row form.nick_name %}
{% field_as_table_row form.is_developer %}
+ {% if existing_user.former_ids %}
+ <tr>
+ <td class="formfieldlabel">Former ids</td>
+ <td>
+ {% for former_id in existing_user.former_ids %}
+ {{ former_id }}<br />
+ {% endfor %}
+ </td>
+ <td class="formfieldrequired"> </td>
+ <td class="formfieldhelptext"> </td>
+ </tr>
+ {% endif %}
<tr>
<td colspan="4"> </td>
</tr>
--- a/app/soc/templates/soc/site/user/profile/lookup.html Sun Sep 21 08:59:11 2008 +0000
+++ b/app/soc/templates/soc/site/user/profile/lookup.html Mon Sep 22 13:42:53 2008 +0000
@@ -59,6 +59,19 @@
<td class="formfieldrequired"> </td>
<td class="formfieldhelptext"> </td>
</tr>
+
+ {% if found_user.former_ids %}
+ <tr>
+ <td class="formfieldlabel">Former ids</td>
+ <td>
+ {% for former_id in found_user.former_ids %}
+ {{ former_id }}<br />
+ {% endfor %}
+ </td>
+ <td class="formfieldrequired"> </td>
+ <td class="formfieldhelptext"> </td>
+ </tr>
+ {% endif %}
{% endif %}
<tr>
<td colspan="4"> </td>
--- a/app/soc/views/site/user/profile.py Sun Sep 21 08:59:11 2008 +0000
+++ b/app/soc/views/site/user/profile.py Mon Sep 22 13:42:53 2008 +0000
@@ -191,6 +191,8 @@
label=soc.models.user.User.is_developer.verbose_name,
help_text=soc.models.user.User.is_developer.help_text)
+ key_name = forms.CharField(widget=forms.HiddenInput)
+
class Meta:
model = None
@@ -199,17 +201,22 @@
if not id_user.isLinkNameFormatValid(link_name):
raise forms.ValidationError("This link name is in wrong format.")
else:
+ key_name = self.data.get('key_name')
if not id_user.isLinkNameAvailableForId(
- link_name, id=self.cleaned_data.get('id')):
+ link_name, id=id_user.getUserFromKeyName(key_name).id) :
raise forms.ValidationError("This link name is already in use.")
return link_name
def clean_id(self):
- try:
- return users.User(email=self.cleaned_data.get('id'))
- except users.UserNotFoundError:
- raise forms.ValidationError('Account not found.')
-
+ new_email = self.cleaned_data.get('id')
+ form_id = users.User(email=new_email)
+ key_name = self.data.get('key_name')
+ old_email = id_user.getUserFromKeyName(key_name).id.email()
+ if new_email != old_email:
+ if id_user.isIdUser(form_id):
+ raise forms.ValidationError("This account is already in use.")
+ return form_id
+
DEF_SITE_USER_PROFILE_EDIT_TMPL = 'soc/site/user/profile/edit.html'
DEF_CREATE_NEW_USER_MSG = ' You can create a new user by visiting' \
@@ -255,11 +262,15 @@
new_linkname = form.cleaned_data.get('link_name')
nickname = form.cleaned_data.get('nick_name')
is_developer = form.cleaned_data.get('is_developer')
+ key_name = form.cleaned_data.get('key_name')
- user = id_user.updateOrCreateUserFromId(
- form_id, link_name=new_linkname, nick_name=nickname,
- is_developer=is_developer)
+ user = id_user.updateUserForKeyName(key_name=key_name, id=form_id,
+ link_name=new_linkname, nick_name=nickname,
+ is_developer=is_developer)
+ if not user:
+ return http.HttpResponseRedirect('/')
+
# redirect to new /site/user/profile/new_linkname?s=0
# (causes 'Profile saved' message to be displayed)
return response_helpers.redirectToChangedSuffix(
@@ -285,7 +296,7 @@
values=profile.SUBMIT_MESSAGES))
# populate form with the existing User entity
- form = EditForm(initial={
+ form = EditForm(initial={ 'key_name': user.key().name(),
'id': user.id.email, 'link_name': user.link_name,
'nick_name': user.nick_name, 'is_developer': user.is_developer})
else:
--- a/app/soc/views/user/profile.py Sun Sep 21 08:59:11 2008 +0000
+++ b/app/soc/views/user/profile.py Mon Sep 22 13:42:53 2008 +0000
@@ -126,7 +126,7 @@
user = id_user.updateOrCreateUserFromId(
id, link_name=new_linkname, nick_name=nickname)
- # redirect to new /user/profile/new_linkname&s=0
+ # redirect to new /user/profile/new_linkname?s=0
# (causes 'Profile saved' message to be displayed)
return response_helpers.redirectToChangedSuffix(
request, linkname, new_linkname, params=SUBMIT_PROFILE_SAVED_PARAMS)