blob: 2e620a1922ae517e157f9e7c6c577d3bf10f2035 [file] [log] [blame]
#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module for the profile page.
"""
from google.appengine.api import users
from google.appengine.ext import db
from django.forms import fields
from soc.logic import accounts
from soc.logic import cleaning
from soc.views import forms
from soc.views.helper import url_patterns
class EmptyForm(forms.ModelForm):
"""Empty form that is always valid.
"""
def __init__(self, *args, **kwargs):
super(EmptyForm, self).__init__(forms.BoundField, *args, **kwargs)
def render(self):
return ''
def is_valid(self):
return True
PROFILE_EXCLUDE = [
# identification fields
'link_id', 'user', 'scope', 'scope_path', 'status',
'agreed_to_tos_on', 'name_on_documents',
# notification fields
'notify_new_requests', 'notify_new_invites',
'notify_invite_handled', 'notify_request_handled',
# role data fields
'student_info', 'mentor_for', 'org_admin_for',
'is_student', 'is_mentor', 'is_org_admin',
]
class ProfileForm(forms.ModelForm):
"""Django form for profile page.
"""
TWO_LETTER_STATE_REQ = ['United States', 'Canada']
def __init__(self, bound_field_class=None, request_data=None,
*args, **kwargs):
super(ProfileForm, self).__init__(bound_field_class, *args, **kwargs)
self.fields['given_name'].group = "2. Contact Info (Private)"
self.fields['surname'].group = "2. Contact Info (Private)"
self.request_data = request_data
self.program = request_data.program if request_data else None
public_name = fields.CharField(required=True)
clean_given_name = cleaning.clean_valid_shipping_chars('given_name')
clean_surname = cleaning.clean_valid_shipping_chars('surname')
clean_email = cleaning.clean_email('email')
clean_phone = cleaning.clean_phone_number('phone')
clean_res_street = cleaning.clean_valid_shipping_chars('res_street')
clean_res_street_extra = cleaning.clean_valid_shipping_chars(
'res_street_extra')
clean_res_city = cleaning.clean_valid_shipping_chars('res_city')
clean_res_state = cleaning.clean_valid_shipping_chars('res_state')
clean_res_postalcode = cleaning.clean_valid_shipping_chars(
'res_postalcode')
clean_ship_name = cleaning.clean_valid_shipping_chars('ship_name')
clean_ship_street = cleaning.clean_valid_shipping_chars('ship_street')
clean_ship_street_extra = cleaning.clean_valid_shipping_chars(
'ship_street_extra')
clean_ship_city = cleaning.clean_valid_shipping_chars('ship_city')
clean_ship_state = cleaning.clean_valid_shipping_chars('ship_state')
clean_ship_postalcode = cleaning.clean_valid_shipping_chars(
'ship_postalcode')
clean_home_page = cleaning.clean_url('home_page')
clean_blog = cleaning.clean_url('blog')
clean_photo_url = cleaning.clean_url('photo_url')
def clean(self):
country = self.cleaned_data.get('res_country')
state = self.cleaned_data.get('res_state')
if country in self.TWO_LETTER_STATE_REQ and (not state or len(state) != 2):
self._errors['res_state'] = ["Please use a 2-letter state/province name"]
country = self.cleaned_data.get('ship_country')
state = self.cleaned_data.get('ship_state')
if country in self.TWO_LETTER_STATE_REQ and (not state or len(state) != 2):
self._errors['ship_state'] = ["Please use a 2-letter state/province name"]
return self.cleaned_data
class ProfilePage(object):
"""View for the participant profile.
"""
def djangoURLPatterns(self):
return [
url_patterns.url(
self._getModulePrefix(),
r'profile/%s$' % self._getEditProfileURLPattern(),
self, name=self._getEditProfileURLName()),
url_patterns.url(
self._getModulePrefix(),
r'profile/%s$' % self._getCreateProfileURLPattern(),
self, name=self._getCreateProfileURLName()),
]
def _getTOSContent(self):
"""Convenience method to obtain the relevant Terms of Service content
for the role in the program.
"""
tos_content = None
role = self.data.kwargs.get('role')
program = self.data.program
if role == 'student' and program.student_agreement:
tos_content = program.student_agreement.content
elif role == 'mentor' and program.mentor_agreement:
tos_content = program.mentor_agreement.content
elif role == 'org_admin' and program.org_admin_agreement:
tos_content = program.org_admin_agreement.content
return tos_content
def isCreateProfileRequest(self):
"""Returns True if the current request is supposed to create a new profile.
Otherwise, the result is false.
"""
return self.data.kwargs.get('role') is not None
def isStudentRequest(self):
"""Returns True if the current request refers to a student which means it
is either Create or Edit Student Profile.
"""
role = self.data.kwargs.get('role')
return self.data.student_info or role == 'student'
def context(self):
role = self.data.kwargs.get('role')
if self.data.student_info or role == 'student':
student_info_form = self._getStudentInfoForm()
# student's age should be checked
is_student = True
else:
student_info_form = EmptyForm()
is_student = False
if not role:
page_name = 'Edit your Profile'
elif role == 'student':
page_name = 'Register as a Student'
elif role == 'mentor':
page_name = 'Register as a Mentor'
elif role == 'org_admin':
page_name = 'Register as Org Admin'
if self.data.user:
user_form = EmptyForm(self.data.POST or None, instance=self.data.user)
else:
user_form = self._getCreateUserForm()
if self.data.profile:
self.data.profile._fix_name()
profile_form = self._getEditProfileForm(is_student)
else:
profile_form = self._getCreateProfileForm(is_student)
error = user_form.errors or profile_form.errors or student_info_form.errors
form = self._getNotificationForm()
notification_form = form(self.data.POST or None,
instance=self.data.profile)
forms = [user_form, profile_form, notification_form, student_info_form]
context = {
'page_name': page_name,
'forms': forms,
'error': error,
}
return context
def validateUser(self, dirty):
if self.data.user:
return EmptyForm()
else:
user_form = self._getCreateUserForm()
if not user_form.is_valid():
return user_form
key_name = user_form.cleaned_data['link_id']
account = self.data.gae_user
norm_account = accounts.normalizeAccount(account)
user_form.cleaned_data['account'] = norm_account
user_form.cleaned_data['user_id'] = account.user_id()
# set the new user entity in self.data.user
self.data.user = user_form.create(commit=False, key_name=key_name)
dirty.append(self.data.user)
return user_form
def validateProfile(self, dirty):
if self.data.student_info or self.data.kwargs.get('role') == 'student':
# student's age should be checked
check_age = True
else:
check_age = False
if self.data.profile:
profile_form = self._getEditProfileForm(check_age)
else:
profile_form = self._getCreateProfileForm(check_age, save=True)
if not profile_form.is_valid():
return profile_form, None
key_name = '%s/%s' % (self.data.program.key().name(),
self.data.user.link_id)
user = self.data.user
profile_form.cleaned_data['user'] = user
profile_form.cleaned_data['link_id'] = user.link_id
profile_form.cleaned_data['scope'] = self.data.program
if self.data.profile:
profile = profile_form.save(commit=False)
else:
profile = profile_form.create(commit=False, key_name=key_name,
parent=self.data.user)
dirty.append(profile)
# synchronize the public name in the profile with the one in user
user.name = profile_form.cleaned_data['public_name']
dirty.append(user)
return profile_form, profile
def validateNotifications(self, dirty, profile):
if not profile:
return EmptyForm(self.data.POST)
form = self._getNotificationForm()
notification_form = form(self.data.POST, instance=profile)
if not notification_form.is_valid():
return notification_form
notification_form.save(commit=False)
if profile not in dirty:
dirty.append(profile)
return notification_form
def validateStudent(self, dirty, profile):
if not (self.data.student_info or
self.data.kwargs.get('role') == 'student'):
return EmptyForm(self.data.POST)
student_form = self._getStudentInfoForm()
if not profile or not student_form.is_valid():
return student_form
key_name = profile.key().name()
if self.data.student_info:
student_info = student_form.save(commit=False)
else:
student_info = student_form.create(
commit=False, key_name=key_name, parent=profile)
profile.is_student = True
profile.student_info = student_info
dirty.append(student_info)
return student_form
def validate(self):
dirty = []
user_form = self.validateUser(dirty)
if not user_form.is_valid():
return False
profile_form, profile = self.validateProfile(dirty)
notification_form = self.validateNotifications(dirty, profile)
student_form = self.validateStudent(dirty, profile)
if (user_form.is_valid() and profile_form.is_valid() and
notification_form.is_valid() and student_form.is_valid()):
db.run_in_transaction(db.put, dirty)
return True
else:
return False
def _getModulePrefix(self):
raise NotImplementedError
def _getEditProfileURLName(self):
raise NotImplementedError
def _getCreateProfileURLName(self):
raise NotImplementedError
def _getEditProfileURLPattern(self):
raise NotImplementedError
def _getCreateProfileURLPattern(self):
raise NotImplementedError
def _getEditProfileForm(self, check_age):
raise NotImplementedError
def _getCreateProfileForm(self, check_age):
raise NotImplementedError
def _getNotificationForm(self):
raise NotImplementedError
def _getStudentInfoForm(self):
raise NotImplementedError