app/soc/views/models/user_self.py
changeset 1043 5e15994b2033
parent 1017 6ad4fdb48840
child 1047 26fade94886b
equal deleted inserted replaced
1042:edd125206703 1043:5e15994b2033
    17 """Views for the User's own profiles.
    17 """Views for the User's own profiles.
    18 """
    18 """
    19 
    19 
    20 __authors__ = [
    20 __authors__ = [
    21     '"Sverre Rabbelier" <sverre@rabbelier.nl>',
    21     '"Sverre Rabbelier" <sverre@rabbelier.nl>',
       
    22     '"Lennard de Rijk" <ljvderijk@gmail.com>',
    22     '"Pawel Solyga" <pawel.solyga@gmail.com>',
    23     '"Pawel Solyga" <pawel.solyga@gmail.com>',
    23   ]
    24   ]
    24 
    25 
    25 
    26 
    26 from google.appengine.api import users
    27 from google.appengine.api import users
    27 
    28 
    28 from django import forms
       
    29 from django import http
    29 from django import http
    30 from django.utils.encoding import force_unicode
    30 from django.utils.encoding import force_unicode
    31 from django.utils.safestring import mark_safe
    31 from django.utils.safestring import mark_safe
    32 from django.utils.translation import ugettext
    32 from django.utils.translation import ugettext
    33 
    33 
       
    34 from soc.logic import cleaning
    34 from soc.logic import dicts
    35 from soc.logic import dicts
    35 from soc.logic import validate
       
    36 from soc.logic import models as model_logic
    36 from soc.logic import models as model_logic
    37 from soc.logic.models.site import logic as site_logic
       
    38 from soc.logic.models.user import logic as user_logic
    37 from soc.logic.models.user import logic as user_logic
    39 from soc.views import helper
    38 from soc.views import helper
    40 from soc.views import out_of_band
       
    41 from soc.views.helper import access
    39 from soc.views.helper import access
    42 from soc.views.helper import decorators
    40 from soc.views.helper import decorators
       
    41 from soc.views.helper import widgets
    43 from soc.views.models import base
    42 from soc.views.models import base
       
    43 from soc.views.models import user as user_view
    44 
    44 
    45 import soc.models.linkable
       
    46 import soc.models.user
    45 import soc.models.user
    47 import soc.views.helper
       
    48 
       
    49 
       
    50 class UserForm(helper.forms.BaseForm):
       
    51   """Django form displayed when creating or editing a User.
       
    52   """
       
    53   class Meta:
       
    54     """Inner Meta class that defines some behavior for the form.
       
    55     """
       
    56     #: db.Model subclass for which the form will gather information
       
    57     model = soc.models.user.User
       
    58 
       
    59     #: list of model fields which will *not* be gathered by the form
       
    60     exclude = ['account', 'former_accounts', 'is_developer']
       
    61 
       
    62   def clean_link_id(self):
       
    63     link_id = self.cleaned_data.get('link_id').lower()
       
    64     if not validate.isLinkIdFormatValid(link_id):
       
    65       raise forms.ValidationError("This link ID is in wrong format.")
       
    66 
       
    67     user = user_logic.getForFields({'link_id': link_id}, unique=True)
       
    68 
       
    69     # Get the currently logged in user account
       
    70     current_account = users.get_current_user()
       
    71 
       
    72     if user:
       
    73       if current_account != user.account:
       
    74         raise forms.ValidationError("This link ID is already in use.")
       
    75 
       
    76     return link_id
       
    77 
       
    78   def clean_agrees_to_tos(self):
       
    79     agrees_to_tos = self.cleaned_data.get('agrees_to_tos')
       
    80 
       
    81     if not site_logic.getToS(site_logic.getSingleton()):
       
    82       return agrees_to_tos
       
    83 
       
    84     # Site settings specify a site-wide ToS, so agreement is *required*
       
    85     if agrees_to_tos:
       
    86       return True
       
    87 
       
    88     raise forms.ValidationError(
       
    89         'The site-wide Terms of Service must be accepted to participate'
       
    90         ' on this site.')
       
    91 
    46 
    92 
    47 
    93 class View(base.View):
    48 class View(base.View):
    94   """View methods for the User model.
    49   """Views for User own profiles.
    95   """
    50   """
    96 
       
    97   DEF_USER_ACCOUNT_INVALID_MSG_FMT = ugettext(
       
    98     'The <b><i>%(email)s</i></b> account cannot be used with this site, for'
       
    99     ' one or more of the following reasons:'
       
   100     '<ul>'
       
   101     ' <li>the account is invalid</li>'
       
   102     ' <li>the account is already attached to a User profile and cannot be'
       
   103     ' used to create another one</li>'
       
   104     ' <li>the account is a former account that cannot be used again</li>'
       
   105     '</ul>')
       
   106 
    51 
   107   def __init__(self, params=None):
    52   def __init__(self, params=None):
   108     """Defines the fields and methods required for the base View class
    53     """Defines the fields and methods required for the base View class
   109     to provide the user with list, public, create, edit and delete views.
    54     to provide the user with list, public, create, edit and delete views.
   110 
    55 
   113     """
    58     """
   114 
    59 
   115     rights = access.Checker(params)
    60     rights = access.Checker(params)
   116     rights['unspecified'] = ['deny']
    61     rights['unspecified'] = ['deny']
   117     rights['any_access'] = ['allow']
    62     rights['any_access'] = ['allow']
   118     rights['edit'] = ['checkIsLoggedIn']
    63     rights['create_profile'] = ['checkIsUnusedAccount']
       
    64     rights['edit_profile'] = ['checkHasUserEntity']
   119     rights['roles'] = ['checkIsUser']
    65     rights['roles'] = ['checkIsUser']
   120     rights['signIn'] = ['checkNotLoggedIn']
    66     rights['signIn'] = ['checkNotLoggedIn']
   121     rights['notification'] = ['checkIsUser']
    67     rights['notification'] = ['checkIsUser']
   122 
    68 
   123     new_params = {}
    69     new_params = {}
   126 
    72 
   127     new_params['name'] = "User"
    73     new_params['name'] = "User"
   128     new_params['module_name'] = "user_self"
    74     new_params['module_name'] = "user_self"
   129     new_params['url_name'] = "user"
    75     new_params['url_name'] = "user"
   130 
    76 
   131     new_params['edit_template'] = 'soc/user/edit_self.html'
    77     new_params['create_template'] = 'soc/user/edit_profile.html'
       
    78     new_params['edit_template'] = 'soc/user/edit_profile.html'
       
    79     new_params['save_message'] = [ugettext('Profile saved.')]
       
    80     new_params['edit_redirect'] = '/%(url_name)s/edit_profile'
       
    81 
       
    82     # set the specific fields for the users profile page
       
    83     new_params['extra_dynaexclude'] = ['former_accounts', 
       
    84         'account', 'is_developer']
       
    85     new_params['create_extra_dynafields'] = {
       
    86         'clean_agrees_to_tos' : cleaning.clean_agrees_to_tos('agrees_to_tos'),
       
    87         'clean_link_id': cleaning.clean_user_not_exist('link_id'),}
       
    88 
       
    89     new_params['edit_extra_dynafields'] = {
       
    90         'clean_link_id': cleaning.clean_link_id
       
    91         }
   132 
    92 
   133     new_params['sidebar_heading'] = 'User (self)'
    93     new_params['sidebar_heading'] = 'User (self)'
   134     new_params['sidebar'] = [
    94     new_params['sidebar'] = [
   135         (users.create_login_url("/user/edit"), 'Sign In', 'signIn'),
    95         (users.create_login_url("/"), 'Sign In', 'signIn'),
   136         ('/' + new_params['url_name'] + '/edit', 'Profile', 'edit'),
    96         ('/' + new_params['url_name'] + '/create_profile', 'Create Profile', 'create_profile'),
       
    97         ('/' + new_params['url_name'] + '/edit_profile', 'Edit Profile', 'edit_profile'),
   137         ('/' + new_params['url_name'] + '/roles', 'Roles', 'roles'),
    98         ('/' + new_params['url_name'] + '/roles', 'Roles', 'roles'),
   138         ]
    99         ]
   139 
   100 
   140     patterns = []
   101     patterns = []
   141 
   102 
   142     page_name = "Profile"
   103     page_name = ugettext("Create your profile")
   143     patterns += [(r'^%(url_name)s/(?P<access_type>edit)$',
   104     patterns += [(r'^%(url_name)s/(?P<access_type>create_profile)$',
       
   105                   'soc.views.models.%(module_name)s.create', page_name)]
       
   106 
       
   107     page_name = ugettext("Edit your profile")
       
   108     patterns += [(r'^%(url_name)s/(?P<access_type>edit_profile)$',
   144                   'soc.views.models.%(module_name)s.edit', page_name)]
   109                   'soc.views.models.%(module_name)s.edit', page_name)]
   145 
   110 
   146     page_name = "Requests Overview"
   111     page_name = ugettext("List of your roles")
   147     patterns += [(r'^%(url_name)s/(?P<access_type>roles)$',
   112     patterns += [(r'^%(url_name)s/(?P<access_type>roles)$',
   148                    'soc.views.models.request.list_self', page_name)]
   113                    'soc.views.models.request.list_self', page_name)]
   149     
   114     
   150     new_params['django_patterns_defaults'] = patterns
   115     new_params['django_patterns_defaults'] = patterns
   151     
   116     
   152     params = dicts.merge(params, new_params)
   117     params = dicts.merge(params, new_params)
   153 
   118 
   154     super(View, self).__init__(params=params)
   119     super(View, self).__init__(params=params)
   155 
   120 
       
   121 
   156   @decorators.merge_params
   122   @decorators.merge_params
   157   @decorators.check_access
   123   @decorators.check_access
   158   def edit(self, request, access_type,
   124   def editProfile(self, request, access_type,
   159            page_name=None, params=None, seed=None, **kwargs):
   125            page_name=None, params=None, seed=None, **kwargs):
   160     """Displays User self edit page for the entity specified by **kwargs.
   126     """Displays User profile edit page for the current user.
   161 
   127 
   162     Args:
   128     Args:
   163       request: the standard Django HTTP request object
   129       request: the standard Django HTTP request object
   164       page_name: the page name displayed in templates as page and header title
   130       page_name: the page name displayed in templates as page and header title
   165       params: a dict with params for this View
   131       params: a dict with params for this View
   166       kwargs: The Key Fields for the specified entity
   132       kwargs: The Key Fields for the specified entity
   167     """
   133     """
   168 
   134 
   169     account = users.get_current_user()
   135     # set the link_id to the current user's link_id
   170     properties = {'account': account}
   136     user_entity = user_logic.getForCurrentAccount()
       
   137     link_id = user_entity.link_id
   171 
   138 
   172     user = user_logic.getForFields(properties, unique=True)
   139     return self.edit(request, access_type,
       
   140            page_name=page_name, params=params, seed=seed, link_id=link_id, **kwargs)
   173 
   141 
   174     # create default template context for use with any templates
       
   175     context = helper.responses.getUniversalContext(request)
       
   176 
   142 
   177     if request.method == 'POST':
       
   178       form = UserForm(request.POST)
       
   179 
       
   180       if form.is_valid():
       
   181         new_link_id = form.cleaned_data.get('link_id')
       
   182         properties = {
       
   183           'link_id': new_link_id,
       
   184           'name': form.cleaned_data.get('name'),
       
   185           'account': account,
       
   186           'agrees_to_tos': form.cleaned_data.get('agrees_to_tos'),
       
   187         }
       
   188 
       
   189         # check if user account is not in former_accounts
       
   190         # if it is show error message that account is invalid
       
   191         if user_logic.isFormerAccount(account):
       
   192           msg = self.DEF_USER_ACCOUNT_INVALID_MSG_FMT % {
       
   193             'email': account.email()}
       
   194           error = out_of_band.Error(msg)
       
   195           return helper.responses.errorResponse(
       
   196               error, request, template=params['edit_template'], context=context)
       
   197 
       
   198         user = user_logic.updateOrCreateFromFields(
       
   199             properties, {'link_id': new_link_id})
       
   200 
       
   201         # redirect to /user/profile?s=0
       
   202         # (causes 'Profile saved' message to be displayed)
       
   203         return helper.responses.redirectToChangedSuffix(
       
   204             request, None, params=params['edit_params'])
       
   205     else: # request.method == 'GET'
       
   206       if user:
       
   207         # is 'Profile saved' parameter present, but referrer was not ourself?
       
   208         # (e.g. someone bookmarked the GET that followed the POST submit)
       
   209         if (request.GET.get(params['submit_msg_param_name'])
       
   210             and (not helper.requests.isReferrerSelf(request))):
       
   211           # redirect to aggressively remove 'Profile saved' query parameter
       
   212           return http.HttpResponseRedirect(request.path)
       
   213 
       
   214         # referrer was us, so select which submit message to display
       
   215         # (may display no message if ?s=0 parameter is not present)
       
   216         context['notice'] = (
       
   217             helper.requests.getSingleIndexedParamValue(
       
   218                 request, params['submit_msg_param_name'],
       
   219                 values=params['save_message']))
       
   220 
       
   221         # populate form with the existing User entity
       
   222         form = UserForm(instance=user)
       
   223       else:
       
   224         if request.GET.get(params['submit_msg_param_name']):
       
   225           # redirect to aggressively remove 'Profile saved' query parameter
       
   226           return http.HttpResponseRedirect(request.path)
       
   227 
       
   228         # no User entity exists for this Google Account, so show a blank form
       
   229         form = UserForm()
       
   230 
       
   231     context['form'] = form
       
   232 
       
   233     template = params['edit_template']
       
   234 
       
   235     return helper.responses.respond(request, template, context)
       
   236   
       
   237   def _editGet(self, request, entity, form):
   143   def _editGet(self, request, entity, form):
   238     """See base.View._editGet().
   144     """See base.View._editGet().
   239     """
   145     """
   240 
   146 
   241     # fill in the email field with the data from the entity
   147     # set the ToS example text
   242     form.fields['email'].initial = entity.account.email()
   148     form.fields['agrees_to_tos'].example_text = user_view.view.getToSExampleText()
       
   149     form.fields['link_id'].initial = entity.link_id
   243 
   150 
   244     super(View, self)._editGet(request, entity, form)
   151     super(View, self)._editGet(request, entity, form)
   245 
   152 
   246   def _editPost(self, request, entity, fields):
   153   def _editPost(self, request, entity, fields):
   247     """See base.View._editPost().
   154     """See base.View._editPost().
   248     """
   155     """
   249 
   156 
   250     # fill in the account field with the user created from email
   157     # fill in the account field with the current User
   251     fields['account'] = users.User(fields['email'])
   158     fields['account'] = users.User() 
   252 
   159 
   253     super(View, self)._editPost(request, entity, fields)
   160     super(View, self)._editPost(request, entity, fields)
       
   161 
   254 
   162 
   255   def getSidebarMenus(self, id, user, params=None):
   163   def getSidebarMenus(self, id, user, params=None):
   256     """See base.View.getSidebarMenus().
   164     """See base.View.getSidebarMenus().
   257     """
   165     """
   258 
   166 
   280     return super(View, self).getSidebarMenus(id, user, params=params)
   188     return super(View, self).getSidebarMenus(id, user, params=params)
   281 
   189 
   282 
   190 
   283 view = View()
   191 view = View()
   284 
   192 
   285 edit = view.edit
   193 create = view.create
       
   194 edit = view.editProfile
   286 export = view.export
   195 export = view.export
   287 
   196