19 |
19 |
20 __authors__ = [ |
20 __authors__ = [ |
21 '"Todd Larsen" <tlarsen@google.com>', |
21 '"Todd Larsen" <tlarsen@google.com>', |
22 ] |
22 ] |
23 |
23 |
24 import re |
|
25 import logging |
|
26 |
24 |
27 from google.appengine.api import users |
25 from google.appengine.api import users |
|
26 |
28 from django import http |
27 from django import http |
29 from django import shortcuts |
|
30 from django import newforms as forms |
28 from django import newforms as forms |
|
29 from django.utils.translation import ugettext_lazy |
31 |
30 |
32 from soc.logic import out_of_band |
31 from soc.logic import out_of_band |
33 from soc.logic.site import id_user |
32 from soc.logic.site import id_user |
34 from soc.views import simple |
33 from soc.views import simple |
35 from soc.views.helpers import forms_helpers |
34 from soc.views.helpers import forms_helpers |
36 from soc.views.helpers import response_helpers |
35 from soc.views.helpers import response_helpers |
37 from soc.views.helpers import template_helpers |
36 from soc.views.helpers import template_helpers |
|
37 from soc.views.user import profile |
38 |
38 |
39 import soc.models.user |
39 import soc.models.user |
40 |
40 |
41 |
41 |
42 class LookupForm(forms_helpers.DbModelForm): |
42 class LookupForm(forms_helpers.DbModelForm): |
43 """Django form displayed for a Developer to look up a User. |
43 """Django form displayed for a Developer to look up a User. |
|
44 |
|
45 This form is manually specified, instead of using |
|
46 model = soc.models.user.User |
|
47 in the Meta class, because the form behavior is unusual and normally |
|
48 required Properties of the User model need to sometimes be omitted. |
|
49 |
|
50 Also, this form only permits entry and editing of some of the User entity |
|
51 Properties, not all of them. |
44 """ |
52 """ |
45 id = forms.EmailField(required=False) |
53 id = forms.EmailField(required=False, |
46 link_name = forms.CharField(required=False) |
54 label=soc.models.user.User.id.verbose_name, |
|
55 help_text=soc.models.user.User.id.help_text) |
|
56 |
|
57 link_name = forms.CharField(required=False, |
|
58 label=soc.models.user.User.link_name.verbose_name, |
|
59 help_text=soc.models.user.User.link_name.help_text) |
47 |
60 |
48 class Meta: |
61 class Meta: |
49 model = None |
62 model = None |
50 |
63 |
51 def clean_link_name(self): |
64 def clean_link_name(self): |
88 be filled out, or a redirect to the correct view in the interface. |
101 be filled out, or a redirect to the correct view in the interface. |
89 """ |
102 """ |
90 # create default template context for use with any templates |
103 # create default template context for use with any templates |
91 context = response_helpers.getUniversalContext(request) |
104 context = response_helpers.getUniversalContext(request) |
92 |
105 |
93 logged_in_id = users.get_current_user() |
106 alt_response = simple.getAltResponseIfNotDeveloper(request, |
94 |
107 context=context) |
95 alt_response = simple.getAltResponseIfNotDeveloper(request, context, |
|
96 id = logged_in_id) |
|
97 if alt_response: |
108 if alt_response: |
98 # not a developer |
|
99 return alt_response |
|
100 |
|
101 alt_response = simple.getAltResponseIfNotLoggedIn(request, context, |
|
102 id = logged_in_id) |
|
103 if alt_response: |
|
104 # not logged in |
|
105 return alt_response |
109 return alt_response |
106 |
110 |
107 user = None # assume that no User entity will be found |
111 user = None # assume that no User entity will be found |
108 form = None # assume blank form needs to be displayed |
112 form = None # assume blank form needs to be displayed |
109 lookup_message = 'Enter information to look up a User.' |
113 lookup_message = ugettext_lazy('Enter information to look up a User.') |
110 lookup_error = None # assume no look-up errors |
114 email_error = None # assume no email look-up errors |
111 edit_link = None # assume no User entity found to be edited |
|
112 |
115 |
113 if request.method == 'POST': |
116 if request.method == 'POST': |
114 form = LookupForm(request.POST) |
117 form = LookupForm(request.POST) |
115 |
118 |
116 if form.is_valid(): |
119 if form.is_valid(): |
119 if form_id: |
122 if form_id: |
120 # email provided, so attempt to look up user by email |
123 # email provided, so attempt to look up user by email |
121 user = id_user.getUserFromId(form_id) |
124 user = id_user.getUserFromId(form_id) |
122 |
125 |
123 if user: |
126 if user: |
124 lookup_message = 'User found by email.' |
127 lookup_message = ugettext_lazy('User found by email.') |
125 else: |
128 else: |
126 lookup_error = 'User with that email not found.' |
129 email_error = ugettext_lazy('User with that email not found.') |
127 |
130 |
128 if not user: |
131 if not user: |
129 # user not found yet, so see if link name was provided |
132 # user not found yet, so see if link name was provided |
130 linkname = form.cleaned_data.get('link_name') |
133 linkname = form.cleaned_data.get('link_name') |
131 |
134 |
132 if linkname: |
135 if linkname: |
133 # link name provided, so try to look up by link name |
136 # link name provided, so try to look up by link name |
134 user = id_user.getUserFromLinkName(linkname) |
137 user = id_user.getUserFromLinkName(linkname) |
135 |
138 |
136 if user: |
139 if user: |
137 lookup_message = 'User found by link name.' |
140 lookup_message = ugettext_lazy('User found by link name.') |
138 lookup_error = None # clear previous error, now that User was found |
141 email_error = None # clear previous error, since User was found |
139 else: |
142 else: |
140 if form_id: |
143 context['linkname_error'] = ugettext_lazy( |
141 # email was provided, so look up failure is due to both |
144 'User with that link name not found.') |
142 lookup_error = 'User with that email or link name not found.' |
|
143 else: |
|
144 # email was not provided, so look up failure is due to link name |
|
145 lookup_error = 'User with that link name not found.' |
|
146 # else: form was not valid |
145 # else: form was not valid |
147 # else: # method == 'GET' |
146 # else: # method == 'GET' |
148 |
147 |
149 if user: |
148 if user: |
150 # User entity found, so populate form with existing User information |
149 # User entity found, so populate form with existing User information |
152 form = LookupForm(initial={'id': user.id, |
151 form = LookupForm(initial={'id': user.id, |
153 'link_name': user.link_name}) |
152 'link_name': user.link_name}) |
154 |
153 |
155 if request.path.endswith('lookup'): |
154 if request.path.endswith('lookup'): |
156 # convert /lookup path into /profile/link_name path |
155 # convert /lookup path into /profile/link_name path |
157 edit_link = '%sprofile/%s' % (request.path[:-len('lookup')], |
156 context['edit_link'] = response_helpers.replaceSuffix( |
158 user.link_name) |
157 request.path, 'lookup', 'profile/%s' % user.link_name) |
159 # else: URL is not one that was expected, so do not display edit link |
158 # else: URL is not one that was expected, so do not display edit link |
160 elif not form: |
159 elif not form: |
161 # no pre-populated form was constructed, so show the empty look-up form |
160 # no pre-populated form was constructed, so show the empty look-up form |
162 form = LookupForm() |
161 form = LookupForm() |
163 |
162 |
164 context.update({'form': form, |
163 context.update({'form': form, |
165 'edit_link': edit_link, |
|
166 'found_user': user, |
164 'found_user': user, |
167 'lookup_error': lookup_error, |
165 'email_error': email_error, |
168 'lookup_message': lookup_message}) |
166 'lookup_message': lookup_message}) |
169 |
167 |
170 return response_helpers.respond(request, template, context) |
168 return response_helpers.respond(request, template, context) |
|
169 |
|
170 |
|
171 class EditForm(forms_helpers.DbModelForm): |
|
172 """Django form displayed when Developer creates or edits a User. |
|
173 |
|
174 This form is manually specified, instead of using |
|
175 model = soc.models.user.User |
|
176 in the Meta class, because the form behavior is unusual and normally |
|
177 required Properties of the User model need to sometimes be omitted. |
|
178 """ |
|
179 id = forms.EmailField( |
|
180 label=soc.models.user.User.id.verbose_name, |
|
181 help_text=soc.models.user.User.id.help_text) |
|
182 |
|
183 link_name = forms.CharField( |
|
184 label=soc.models.user.User.link_name.verbose_name, |
|
185 help_text=soc.models.user.User.link_name.help_text) |
|
186 |
|
187 nick_name = forms.CharField( |
|
188 label=soc.models.user.User.nick_name.verbose_name) |
|
189 |
|
190 is_developer = forms.BooleanField(required=False, |
|
191 label=soc.models.user.User.is_developer.verbose_name, |
|
192 help_text=soc.models.user.User.is_developer.help_text) |
|
193 |
|
194 class Meta: |
|
195 model = None |
|
196 |
|
197 def clean_link_name(self): |
|
198 link_name = self.cleaned_data.get('link_name') |
|
199 if not id_user.isLinkNameFormatValid(link_name): |
|
200 raise forms.ValidationError("This link name is in wrong format.") |
|
201 else: |
|
202 if not id_user.isLinkNameAvailableForId( |
|
203 link_name, id=self.cleaned_data.get('id')): |
|
204 raise forms.ValidationError("This link name is already in use.") |
|
205 return link_name |
|
206 |
|
207 def clean_id(self): |
|
208 try: |
|
209 return users.User(email=self.cleaned_data.get('id')) |
|
210 except users.UserNotFoundError: |
|
211 raise forms.ValidationError('Account not found.') |
|
212 |
|
213 |
|
214 DEF_SITE_USER_PROFILE_EDIT_TMPL = 'soc/site/user/profile/edit.html' |
|
215 |
|
216 def edit(request, linkname=None, template=DEF_SITE_USER_PROFILE_EDIT_TMPL): |
|
217 """View for a Developer to modify the properties of a User Model entity. |
|
218 |
|
219 Args: |
|
220 request: the standard django request object |
|
221 linkname: the User's site-unique "linkname" extracted from the URL |
|
222 template: the "sibling" template (or a search list of such templates) |
|
223 from which to construct the public.html template name (or names) |
|
224 |
|
225 Returns: |
|
226 A subclass of django.http.HttpResponse which either contains the form to |
|
227 be filled out, or a redirect to the correct view in the interface. |
|
228 """ |
|
229 # create default template context for use with any templates |
|
230 context = response_helpers.getUniversalContext(request) |
|
231 |
|
232 alt_response = simple.getAltResponseIfNotDeveloper(request, |
|
233 context=context) |
|
234 if alt_response: |
|
235 return alt_response |
|
236 |
|
237 user = None # assume that no User entity will be found |
|
238 |
|
239 if request.method == 'POST': |
|
240 form = EditForm(request.POST) |
|
241 |
|
242 if form.is_valid(): |
|
243 form_id = form.cleaned_data.get('id') |
|
244 new_linkname = form.cleaned_data.get('link_name') |
|
245 nickname = form.cleaned_data.get('nick_name') |
|
246 is_developer = form.cleaned_data.get('is_developer') |
|
247 |
|
248 user = id_user.updateOrCreateUserFromId( |
|
249 form_id, link_name=new_linkname, nick_name=nickname, |
|
250 is_developer=is_developer) |
|
251 |
|
252 # redirect to new /site/user/profile/new_linkname&s=0 |
|
253 # (causes 'Profile saved' message to be displayed) |
|
254 return response_helpers.redirectToChangedSuffix( |
|
255 request, linkname, new_linkname, |
|
256 params=profile.SUBMIT_PROFILE_SAVED_PARAMS) |
|
257 else: # method == 'GET': |
|
258 # try to fetch User entity corresponding to link name if one exists |
|
259 if linkname: |
|
260 user = id_user.getUserFromLinkName(linkname) |
|
261 |
|
262 if user: |
|
263 # is 'Profile saved' parameter present, but referrer was not ourself? |
|
264 # (e.g. someone bookmarked the GET that followed the POST submit) |
|
265 if (request.GET.get(profile.SUBMIT_MSG_PARAM_NAME) |
|
266 and (not response_helpers.isReferrerSelf(request, |
|
267 suffix=linkname))): |
|
268 # redirect to aggressively remove 'Profile saved' query parameter |
|
269 return http.HttpResponseRedirect(request.path) |
|
270 |
|
271 # referrer was us, so select which submit message to display |
|
272 # (may display no message if ?s=0 parameter is not present) |
|
273 context['submit_message'] = ( |
|
274 template_helpers.getSingleIndexedParamValue( |
|
275 request, profile.SUBMIT_MSG_PARAM_NAME, |
|
276 values=profile.SUBMIT_MESSAGES)) |
|
277 |
|
278 # populate form with the existing User entity |
|
279 form = EditForm(initial={ |
|
280 'id': user.id, 'link_name': user.link_name, |
|
281 'nick_name': user.nick_name, 'is_developer': user.is_developer}) |
|
282 else: |
|
283 if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME): |
|
284 # redirect to aggressively remove 'Profile saved' query parameter |
|
285 return http.HttpResponseRedirect(request.path) |
|
286 |
|
287 context['lookup_error'] = ugettext_lazy( |
|
288 'User with that link name not found.') |
|
289 form = EditForm(initial={'link_name': linkname}) |
|
290 else: # no link name specified in the URL |
|
291 if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME): |
|
292 # redirect to aggressively remove 'Profile saved' query parameter |
|
293 return http.HttpResponseRedirect(request.path) |
|
294 |
|
295 # no link name specified, so start with an empty form |
|
296 form = EditForm() |
|
297 |
|
298 context.update({'form': form, |
|
299 'existing_user': user}) |
|
300 |
|
301 return response_helpers.respond(request, template, context) |