Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 281 lines (248 sloc) 11.52 kB
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
1 import cgi
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
2 from google.appengine.ext import webapp, db
3 from google.appengine.ext.webapp import util, template
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
4 from google.appengine.api import urlfetch, memcache, users, mail
5
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
6 from django.utils import simplejson
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
7 from django.template.defaultfilters import slugify
5cd04ac Fixed iCalendar-related imports, and added the end date to the
Matt Hancher authored
8 from icalendar import Calendar
b4ea292 Handler to bug pending events
Brian Klug authored
9 import logging, urllib, os
7bdb866 Let all members staff events.
Brian Klug authored
10 from pprint import pprint
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
11 from datetime import datetime, timedelta
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
12
4d85afa @dustball Remove staffing requirement and make members more responsible
dustball authored
13 from models import Event, Feedback, ROOM_OPTIONS, PENDING_LIFETIME
5bf70d1 @christopherb Style Cleanup / Dead code removal
christopherb authored
14 from utils import username, human_username, set_cookie, local_today, is_phone_valid, UserRights
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
15 from notices import *
7742592 @progrium start of maintaining form state on errors
progrium authored
16
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
17 class ExpireCron(webapp.RequestHandler):
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
18 def post(self):
19 # Expire events marked to expire today
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
20 today = local_today()
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
21 events = Event.all() \
22 .filter('status IN', ['pending', 'understaffed']) \
23 .filter('expired >=', today) \
24 .filter('expired <', today + timedelta(days=1))
25 for event in events:
26 event.expire()
27 notify_owner_expired(event)
28
f1997e4 @christopherb Made misc style fixes
christopherb authored
29
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
30 class ExpireReminderCron(webapp.RequestHandler):
31 def post(self):
32 # Find events expiring in 10 days to warn owner
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
33 ten_days = local_today() + timedelta(days=10)
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
34 events = Event.all() \
35 .filter('status IN', ['pending', 'understaffed']) \
36 .filter('expired >=', ten_days) \
37 .filter('expired <', ten_days + timedelta(days=1))
38 for event in events:
39 notify_owner_expiring(event)
40
f1997e4 @christopherb Made misc style fixes
christopherb authored
41
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
42 class EventsHandler(webapp.RequestHandler):
43 def get(self, format):
44 if format == 'ics':
a493a39 @progrium changing the json events list to the approved list
progrium authored
45 events = Event.all().filter('status IN', ['approved', 'canceled']).order('start_time')
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
46 cal = Calendar()
47 for event in events:
48 cal.add_component(event.to_ical())
49 self.response.headers['content-type'] = 'text/calendar'
50 self.response.out.write(cal.as_string())
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
51 elif format == 'json':
52 self.response.headers['content-type'] = 'application/json'
a493a39 @progrium changing the json events list to the approved list
progrium authored
53 events = map(lambda x: x.to_dict(summarize=True), Event.get_approved_list())
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
54 self.response.out.write(simplejson.dumps(events))
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
55
f1997e4 @christopherb Made misc style fixes
christopherb authored
56
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
57 class EventHandler(webapp.RequestHandler):
58 def get(self, id):
59 event = Event.get_by_id(int(id))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
60 if self.request.path.endswith('json'):
61 self.response.headers['content-type'] = 'application/json'
62 self.response.out.write(simplejson.dumps(event.to_dict()))
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
63 else:
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
64 user = users.get_current_user()
65 if user:
766e87c @christopherb Added UserRights class.
christopherb authored
66 access_rights = UserRights(user, event)
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
67 logout_url = users.create_logout_url('/')
766e87c @christopherb Added UserRights class.
christopherb authored
68
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
69 else:
70 login_url = users.create_login_url('/')
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
71 event.details = db.Text(event.details.replace('\n','<br/>'))
72 event.notes = db.Text(event.notes.replace('\n','<br/>'))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
73 self.response.out.write(template.render('templates/event.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
74
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
75 def post(self, id):
76 event = Event.get_by_id(int(id))
77 user = users.get_current_user()
766e87c @christopherb Added UserRights class.
christopherb authored
78 access_rights = UserRights(user, event)
79
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
80 state = self.request.get('state')
81 if state:
766e87c @christopherb Added UserRights class.
christopherb authored
82 if state.lower() == 'approve' and access_rights.can_approve:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
83 event.approve()
b84b533 @dustball Fix one more staff logic bomb
dustball authored
84 if state.lower() == 'staff' and access_rights.can_staff:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
85 event.add_staff(user)
766e87c @christopherb Added UserRights class.
christopherb authored
86 if state.lower() == 'unstaff' and access_rights.can_unstaff:
72849c2 @billsaysthis added unstaff event, including email notification if event becomes un…
billsaysthis authored
87 event.remove_staff(user)
766e87c @christopherb Added UserRights class.
christopherb authored
88 # send notification is state changed to understaffed
89 if event.status == 'understaffed':
90 notify_unapproved_unstaff_event(event)
91 if state.lower() == 'cancel' and access_rights.can_cancel:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
92 event.cancel()
766e87c @christopherb Added UserRights class.
christopherb authored
93 if state.lower() == 'delete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
94 event.delete()
766e87c @christopherb Added UserRights class.
christopherb authored
95 if state.lower() == 'undelete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
96 event.undelete()
766e87c @christopherb Added UserRights class.
christopherb authored
97 if state.lower() == 'expire' and access_rights.is_admin:
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
98 event.expire()
99 if event.status == 'approved':
100 notify_owner_approved(event)
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
101 self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
102
f1997e4 @christopherb Made misc style fixes
christopherb authored
103
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
104 class ApprovedHandler(webapp.RequestHandler):
105 def get(self):
106 user = users.get_current_user()
107 if user:
108 logout_url = users.create_logout_url('/')
109 else:
110 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
111 today = local_today()
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
112 events = Event.get_approved_list()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
113 tomorrow = today + timedelta(days=1)
d63161a Add widget mode
Brian Klug authored
114 whichbase = 'base.html'
115 if self.request.get('base'):
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
116 whichbase = self.request.get('base') + '.html'
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
117 self.response.out.write(template.render('templates/approved.html', locals()))
118
f1997e4 @christopherb Made misc style fixes
christopherb authored
119
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
120 class MyEventsHandler(webapp.RequestHandler):
121 @util.login_required
122 def get(self):
123 user = users.get_current_user()
124 if user:
125 logout_url = users.create_logout_url('/')
126 else:
127 login_url = users.create_login_url('/')
128 events = Event.all().filter('member = ', user).order('start_time')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
129 today = local_today()
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
130 tomorrow = today + timedelta(days=1)
131 self.response.out.write(template.render('templates/myevents.html', locals()))
132
f1997e4 @christopherb Made misc style fixes
christopherb authored
133
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
134 class PastHandler(webapp.RequestHandler):
135 def get(self):
136 user = users.get_current_user()
137 if user:
138 logout_url = users.create_logout_url('/')
139 else:
140 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
141 today = local_today()
d75579f @progrium minor updates here and there to bills contributions.
progrium authored
142 events = Event.all().filter('start_time < ', today).order('-start_time')
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
143 self.response.out.write(template.render('templates/past.html', locals()))
144
f1997e4 @christopherb Made misc style fixes
christopherb authored
145
b4ea292 Handler to bug pending events
Brian Klug authored
146 class CronBugOwnersHandler(webapp.RequestHandler):
147 def get(self):
148 events = Event.get_pending_list()
149 for e in events:
150 bug_owner_pending(e)
151
f1997e4 @christopherb Made misc style fixes
christopherb authored
152
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
153 class PendingHandler(webapp.RequestHandler):
154 def get(self):
155 user = users.get_current_user()
156 if user:
157 logout_url = users.create_logout_url('/')
158 else:
159 login_url = users.create_login_url('/')
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
160 events = Event.get_pending_list()
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
161 today = local_today()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
162 tomorrow = today + timedelta(days=1)
163 self.response.out.write(template.render('templates/pending.html', locals()))
164
f1997e4 @christopherb Made misc style fixes
christopherb authored
165
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
166 class NewHandler(webapp.RequestHandler):
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
167 @util.login_required
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
168 def get(self):
169 user = users.get_current_user()
4d85afa @dustball Remove staffing requirement and make members more responsible
dustball authored
170 human = human_username(user)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
171 if user:
172 logout_url = users.create_logout_url('/')
173 else:
174 login_url = users.create_login_url('/')
175 rooms = ROOM_OPTIONS
176 self.response.out.write(template.render('templates/new.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
177
f1997e4 @christopherb Made misc style fixes
christopherb authored
178
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
179 def post(self):
180 user = users.get_current_user()
7742592 @progrium start of maintaining form state on errors
progrium authored
181 try:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
182 start_time = datetime.strptime('%s %s:%s %s' % (
7742592 @progrium start of maintaining form state on errors
progrium authored
183 self.request.get('date'),
184 self.request.get('start_time_hour'),
185 self.request.get('start_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
186 self.request.get('start_time_ampm')), '%m/%d/%Y %I:%M %p')
187 end_time = datetime.strptime('%s %s:%s %s' % (
7742592 @progrium start of maintaining form state on errors
progrium authored
188 self.request.get('date'),
189 self.request.get('end_time_hour'),
190 self.request.get('end_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
191 self.request.get('end_time_ampm')), '%m/%d/%Y %I:%M %p')
8615877 Fix validation for event size
Brian Klug authored
192 if not self.request.get('estimated_size').isdigit():
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
193 raise ValueError('Estimated number of people must be a number')
8615877 Fix validation for event size
Brian Klug authored
194 if not int(self.request.get('estimated_size')) > 0:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
195 raise ValueError('Estimated number of people must be greater then zero')
7742592 @progrium start of maintaining form state on errors
progrium authored
196 if (end_time-start_time).days < 0:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
197 raise ValueError('End time must be after start time')
d8e72b5 @chrismeyer Added checking for phone numbers as well as a unit testing framework.
chrismeyer authored
198 if ( not is_phone_valid( self.request.get( 'contact_phone' ) ) ):
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
199 raise ValueError( 'Phone number does not appear to be valid' )
7742592 @progrium start of maintaining form state on errors
progrium authored
200 else:
201 event = Event(
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
202 name = cgi.escape(self.request.get('name')),
7742592 @progrium start of maintaining form state on errors
progrium authored
203 start_time = start_time,
204 end_time = end_time,
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
205 type = cgi.escape(self.request.get('type')),
206 estimated_size = cgi.escape(self.request.get('estimated_size')),
207 contact_name = cgi.escape(self.request.get('contact_name')),
208 contact_phone = cgi.escape(self.request.get('contact_phone')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
209 details = cgi.escape(self.request.get('details')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
210 url = cgi.escape(self.request.get('url')),
211 fee = cgi.escape(self.request.get('fee')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
212 notes = cgi.escape(self.request.get('notes')),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
213 rooms = self.request.get_all('rooms'),
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
214 expired = local_today() + timedelta(days=PENDING_LIFETIME), # Set expected expiration date
7742592 @progrium start of maintaining form state on errors
progrium authored
215 )
216 event.put()
217 notify_owner_confirmation(event)
218 if not event.is_staffed():
219 notify_staff_needed(event)
220 notify_new_event(event)
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
221 set_cookie(self.response.headers, 'formvalues', None)
7742592 @progrium start of maintaining form state on errors
progrium authored
222 self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
223 except Exception, e:
224 message = str(e)
225 if 'match format' in message:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
226 message = 'Date is required.'
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
227 if message.startswith('Property'):
228 message = message[9:].replace('_', ' ').capitalize()
229 set_cookie(self.response.headers, 'formerror', message)
7742592 @progrium start of maintaining form state on errors
progrium authored
230 set_cookie(self.response.headers, 'formvalues', dict(self.request.POST))
231 self.redirect('/new')
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
232
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
233
234 class FeedbackHandler(webapp.RequestHandler):
235 @util.login_required
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
236 def get(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
237 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
238 event = Event.get_by_id(int(id))
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
239 if user:
240 logout_url = users.create_logout_url('/')
241 else:
242 login_url = users.create_login_url('/')
243 self.response.out.write(template.render('templates/feedback.html', locals()))
244
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
245 def post(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
246 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
247 event = Event.get_by_id(int(id))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
248 try:
249 if self.request.get('rating'):
250 feedback = Feedback(
251 event = event,
252 rating = int(self.request.get('rating')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
253 comment = cgi.escape(self.request.get('comment')))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
254 feedback.put()
255 self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
256 else:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
257 raise ValueError('Please select a rating')
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
258 except Exception:
259 set_cookie(self.response.headers, 'formvalues', dict(self.request.POST))
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
260 self.redirect('/feedback/new/' + id)
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
261
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
262 def main():
263 application = webapp.WSGIApplication([
264 ('/', ApprovedHandler),
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
265 ('/events\.(.+)', EventsHandler),
d75579f @progrium minor updates here and there to bills contributions.
progrium authored
266 ('/past', PastHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
267 ('/pending', PendingHandler),
b4ea292 Handler to bug pending events
Brian Klug authored
268 ('/cronbugowners', CronBugOwnersHandler),
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
269 ('/myevents', MyEventsHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
270 ('/new', NewHandler),
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
271 ('/event/(\d+).*', EventHandler),
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
272 ('/event/(\d+)\.json', EventHandler),
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
273 ('/expire', ExpireCron),
34d98f0 @billsaysthis moved feedback stuff to separate py file, small tweak to email notifi…
billsaysthis authored
274 ('/expiring', ExpireReminderCron),
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
275 ('/feedback/new/(\d+).*', FeedbackHandler) ],debug=True)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
276 util.run_wsgi_app(application)
277
f1997e4 @christopherb Made misc style fixes
christopherb authored
278
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
279 if __name__ == '__main__':
280 main()
Something went wrong with that request. Please try again.