# HG changeset patch # User Pawel Solyga # Date 1222090973 0 # Node ID 7c0b42aecd9b8fcfb9e9b5291aca2c303f06c0bb # Parent 37d98c3cefa5cb6d866debd0fb92197460c5ac35 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 diff -r 37d98c3cefa5 -r 7c0b42aecd9b app/soc/logic/site/id_user.py --- 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. diff -r 37d98c3cefa5 -r 7c0b42aecd9b app/soc/templates/soc/site/user/profile/edit.html --- 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 %}

+ {{ form.key_name }} {% 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 %} + + + + + + + {% endif %} diff -r 37d98c3cefa5 -r 7c0b42aecd9b app/soc/templates/soc/site/user/profile/lookup.html --- 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 @@ + + {% if found_user.former_ids %} + + + + + + + {% endif %} {% endif %} diff -r 37d98c3cefa5 -r 7c0b42aecd9b app/soc/views/site/user/profile.py --- 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: diff -r 37d98c3cefa5 -r 7c0b42aecd9b app/soc/views/user/profile.py --- 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)
Former ids + {% for former_id in existing_user.former_ids %} + {{ former_id }}
+ {% endfor %} +
  
 
   
Former ids + {% for former_id in found_user.former_ids %} + {{ former_id }}
+ {% endfor %} +