Fix not working former_ids. Add support for "Invalid accounts". Now when id from former_ids tries to create a profile "This account is invalid." error message is displayed. Compare emails in lower cases to prevent changing User email to the same email with different character casing (needs some more testing).
authorPawel Solyga <Pawel.Solyga@gmail.com>
Fri, 07 Nov 2008 22:24:01 +0000
changeset 448 075360be6743
parent 447 83b49d60effd
child 449 a4dc4c9e7356
Fix not working former_ids. Add support for "Invalid accounts". Now when id from former_ids tries to create a profile "This account is invalid." error message is displayed. Compare emails in lower cases to prevent changing User email to the same email with different character casing (needs some more testing). Patch by: Pawel Solyga
app/soc/logic/models/user.py
app/soc/logic/site/id_user.py
app/soc/views/docs/edit.py
app/soc/views/helper/access.py
app/soc/views/helper/responses.py
app/soc/views/models/docs.py
app/soc/views/models/sponsor.py
app/soc/views/site/sponsor/profile.py
app/soc/views/site/user/profile.py
app/soc/views/user/profile.py
--- a/app/soc/logic/models/user.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/logic/models/user.py	Fri Nov 07 22:24:01 2008 +0000
@@ -22,7 +22,6 @@
   ]
 
 
-from soc.logic import key_name
 from soc.logic.models import base
 
 import soc.models.user
@@ -40,11 +39,22 @@
     self._model = soc.models.user.User
     self._skip_properties = ['former_ids']
 
+  def isFormerId(self, id):
+    """Returns true if id is in former ids"""
+    # TODO(pawel.solyga): replace 1000 with solution that works for any number of queries
+    users_with_former_ids = soc.models.user.User.gql('WHERE former_ids != :1', None).fetch(1000)
+    
+    for former_id_user in users_with_former_ids: 
+      if id in former_id_user.former_ids:
+        return True
+    
+    return False
+
   def getKeyValues(self, entity):
-    """See base.Logic.getKeyNameValues.
+    """See base.Logic.getKeyValues.
     """
-
-    return [entity.link_name]
+    
+    return [entity.id.email()]
 
   def getKeyValuesFromFields(self, fields):
     """See base.Logic.getKeyValuesFromFields.
@@ -63,6 +73,20 @@
 
     return ['email']
 
+  def updateOrCreateFromId(self, properties, id):
+    """Like updateOrCreateFromKeyName, but resolves id to a key_name first.
+    """
+
+    # attempt to retrieve the existing entity
+    user = soc.models.user.User.gql('WHERE id = :1', id).get()
+    
+    if user:
+      key_name = user.key().name()
+    else:
+      key_name  = self.getKeyNameForFields({'email': id.email()})
+
+    return self.updateOrCreateFromKeyName(properties, key_name)
+
   def _updateField(self, model, name, value):
     """Special case logic for id.
 
--- a/app/soc/logic/site/id_user.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/logic/site/id_user.py	Fri Nov 07 22:24:01 2008 +0000
@@ -85,7 +85,7 @@
   if not id:
     id = current_id
 
-  user = models.user.logic.getFromFields(email=id.email())
+  user = models.user.logic.getForFields({'id': id}, unique=True)
 
   if not user:
     # no User entity for this Google Account, and id is not the currently
@@ -114,12 +114,12 @@
   else:
     old_email = None
 
-  if new_id.email() == old_email:
+  if new_id.email().lower == old_email.lower:
     # "new" email is same as existing User wanting it, so it is "available"
     return True
   # else: "new" email truly is new to the existing User, so keep checking
 
-  if not models.user.logic.getFromFields(email=new_id.email()):
+  if not models.user.logic.getForFields({'id': new_id}, unique=True):
     # new email address also does not belong to any other User,
     # so it is available
     return True
@@ -165,7 +165,7 @@
     # link name cannot belong to an unspecified User
     return False
 
-  user = models.user.logic.getFromFields(email=id.email())
+  user = models.user.logic.getForFields({'id': id}, unique=True)
 
   if not user:
     # no User corresponding to id Google Account, so no link name at all 
--- a/app/soc/views/docs/edit.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/docs/edit.py	Fri Nov 07 22:24:01 2008 +0000
@@ -61,10 +61,6 @@
   """
 
   user = users.get_current_user()
-  if user:
-    email = user.email()
-  else:
-    email = None
 
   partial_path = form.cleaned_data.get('partial_path')
   link_name = form.cleaned_data.get('link_name')
@@ -75,7 +71,7 @@
   properties['title'] = form.cleaned_data.get('title')
   properties['short_name'] = form.cleaned_data.get('short_name')
   properties['content'] = form.cleaned_data.get('content')
-  properties['author'] = models.user.logic.getFromFields(email=email)
+  properties['author'] = models.user.logic.getForFields({'id': user}, unique=True)
   properties['is_featured'] = form.cleaned_data.get('is_featured')
 
   key_fields = document.logic.getKeyFieldsFromDict(properties)
--- a/app/soc/views/helper/access.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/helper/access.py	Fri Nov 07 22:24:01 2008 +0000
@@ -98,7 +98,7 @@
   checkIsLoggedIn(request)
 
   id = users.get_current_user()
-  user = models.user.logic.getFromFields(email=id.email())
+  user = models.user.logic.getForFields({'id': id}, unique=True)
 
   if user:
     return
--- a/app/soc/views/helper/responses.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/helper/responses.py	Fri Nov 07 22:24:01 2008 +0000
@@ -99,8 +99,8 @@
 
   if id:
     context['id'] = id
-    context['user'] = soc.logic.models.user.logic.getFromFields(
-        email=id.email())
+    context['user'] = soc.logic.models.user.logic.getForFields(
+        {'id': id}, unique=True)
     context['is_admin'] = id_user.isIdDeveloper(id=id)
 
   context['is_debug'] = system.isDebug()
--- a/app/soc/views/models/docs.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/models/docs.py	Fri Nov 07 22:24:01 2008 +0000
@@ -132,7 +132,7 @@
     """
 
     id = users.get_current_user()
-    user = soc.logic.models.user.logic.getFromFields(email=id.email())
+    user = soc.logic.models.user.logic.getForFields({'id': id}, unique=True)
     fields['author'] = user
 
   def _editGet(self, request, entity, form):
--- a/app/soc/views/models/sponsor.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/models/sponsor.py	Fri Nov 07 22:24:01 2008 +0000
@@ -137,7 +137,7 @@
     """
 
     id = users.get_current_user()
-    user = soc.logic.models.user.logic.getFromFields(email=id.email())
+    user = soc.logic.models.user.logic.getForFields({'id': id}, unique=True)
     fields['founder'] = user
 
 
--- a/app/soc/views/site/sponsor/profile.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/site/sponsor/profile.py	Fri Nov 07 22:24:01 2008 +0000
@@ -116,7 +116,7 @@
   context['page'] = page
 
   logged_in_id = users.get_current_user()
-  user = models.user.logic.getFromFields(email=logged_in_id.email())
+  user = models.user.logic.getForFields({'id': logged_in_id}, unique=True)
   sponsor_form = None
   existing_sponsor = None
 
--- a/app/soc/views/site/user/profile.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/site/user/profile.py	Fri Nov 07 22:24:01 2008 +0000
@@ -134,7 +134,7 @@
       
       if form_id:
         # email provided, so attempt to look up user by email
-        user = models.user.logic.getFromFields(email=form_id.email())
+        user = models.user.logic.getForFields({'id': form_id}, unique=True)
 
         if user:
           lookup_message = ugettext_lazy('User found by email.')
@@ -234,8 +234,9 @@
 
     key_name = self.data.get('key_name')
     user = models.user.logic.getFromKeyName(key_name)
-
-    if user and user.link_name != link_name:
+    
+    linkname_user_exist = id_user.getUserFromLinkName(link_name)
+    if (user and user.link_name != link_name) and linkname_user_exist:
       raise forms.ValidationError("This link name is already in use.")
 
     return link_name
@@ -245,6 +246,9 @@
     if not id_user.isIdAvailable(
         form_id, existing_key_name=self.data.get('key_name')):
       raise forms.ValidationError("This account is already in use.")
+    if models.user.logic.isFormerId(form_id):
+      raise forms.ValidationError("This account is invalid. "
+          "It exists as former id.")
     return form_id
 
 
@@ -398,8 +402,11 @@
   def clean_id(self):
     new_email = self.cleaned_data.get('id')
     form_id = users.User(email=new_email)
-    if models.user.logic.getFromFields(email=form_id.email()):
+    if models.user.logic.getForFields({'id': form_id}, unique=True):
       raise forms.ValidationError("This account is already in use.")
+    if models.user.logic.isFormerId(form_id):
+      raise forms.ValidationError("This account is invalid. "
+          "It exists as former id.")
     return form_id
 
 
--- a/app/soc/views/user/profile.py	Fri Nov 07 22:13:20 2008 +0000
+++ b/app/soc/views/user/profile.py	Fri Nov 07 22:24:01 2008 +0000
@@ -69,6 +69,7 @@
 
 
 DEF_USER_PROFILE_EDIT_TMPL = 'soc/user/edit_self.html'
+DEF_USER_ACCOUNT_INVALID_MSG = 'This account is invalid.'
 
 SUBMIT_MSG_PARAM_NAME = 's'
 
@@ -99,7 +100,7 @@
     be filled out, or a redirect to the correct view in the interface.
   """
   id = users.get_current_user()
-
+  
   # create default template context for use with any templates
   context = helper.responses.getUniversalContext(request)
 
@@ -145,17 +146,22 @@
         'id': id,
       }
 
-      key_fields = {'email': id.email()}
-      user = models.user.logic.updateOrCreateFromFields(properties, 
-                                                        key_fields)
-
+      # check if user account is not in former_ids
+      # if it is show error message that account is invalid
+      if models.user.logic.isFormerId(id):
+        msg = DEF_USER_ACCOUNT_INVALID_MSG
+        error = out_of_band.ErrorResponse(msg)
+        return simple.errorResponse(request, page, error, template, context)
+      
+      user = models.user.logic.updateOrCreateFromId(properties, id)
+      
       # redirect to /user/profile?s=0
       # (causes 'Profile saved' message to be displayed)
       return helper.responses.redirectToChangedSuffix(
           request, None, params=SUBMIT_PROFILE_SAVED_PARAMS)
   else: # request.method == 'GET'
     # try to fetch User entity corresponding to Google Account if one exists
-    user = models.user.logic.getFromFields(email=id.email())
+    user = models.user.logic.getForFields({'id': id}, unique=True)
 
     if user:
       # is 'Profile saved' parameter present, but referrer was not ourself?