Browse files

Added UserRights class.

UserRights is a helper class that allowd for a centralized place
to perform user rights validation.
  • Loading branch information...
1 parent 4a7ab61 commit 766e87c8a679f2d519a3ad7d49d8a6997b5b070b @christopherb christopherb committed with Hacker Dojo Jun 26, 2010
Showing with 99 additions and 70 deletions.
  1. +15 −19 main.py
  2. +48 −48 templates/event.html
  3. +36 −3 utils.py
View
34 main.py
@@ -11,7 +11,7 @@
from datetime import datetime, timedelta
from models import Event, Feedback, ROOM_OPTIONS, GUESTS_PER_STAFF, PENDING_LIFETIME
-from utils import dojo, username, human_username, set_cookie, local_today, is_phone_valid
+from utils import dojo, username, human_username, set_cookie, local_today, is_phone_valid, UserRights
from notices import *
class ExpireCron(webapp.RequestHandler):
@@ -63,13 +63,9 @@ def get(self, id):
else:
user = users.get_current_user()
if user:
- is_admin = username(user) in dojo('/groups/events')
- is_staff = username(user) in dojo('/groups/staff')
- can_approve = (event.status in ['pending'] and is_admin and not user == event.member)
- can_staff = (event.status in ['pending', 'understaffed', 'approved'] and is_staff and not user in event.staff)
- can_unstaff = (not event.status in ['canceled', 'deleted'] and is_staff and user in event.staff)
+ access_rights = UserRights(user, event)
logout_url = users.create_logout_url('/')
- can_cancel = is_admin or user == event.member
+
else:
login_url = users.create_login_url('/')
event.details = db.Text(event.details.replace('\n','<br/>'))
@@ -79,26 +75,26 @@ def get(self, id):
def post(self, id):
event = Event.get_by_id(int(id))
user = users.get_current_user()
- is_admin = username(user) in dojo('/groups/events')
- is_staff = True
+ access_rights = UserRights(user, event)
+
state = self.request.get('state')
if state:
- if state.lower() == 'approve' and is_admin:
+ if state.lower() == 'approve' and access_rights.can_approve:
event.approve()
- if state.lower() == 'staff' and is_staff:
+ if state.lower() == 'staff' and access_rights.is_staff:
event.add_staff(user)
- if state.lower() == 'unstaff' and is_staff:
+ if state.lower() == 'unstaff' and access_rights.can_unstaff:
event.remove_staff(user)
- # send notification is state changed to understaffed
- if event.status == 'understaffed':
- notify_unapproved_unstaff_event(event)
- if state.lower() == 'cancel' and is_admin or event.member == user:
+ # send notification is state changed to understaffed
+ if event.status == 'understaffed':
+ notify_unapproved_unstaff_event(event)
+ if state.lower() == 'cancel' and access_rights.can_cancel:
event.cancel()
- if state.lower() == 'delete' and is_admin:
+ if state.lower() == 'delete' and access_rights.is_admin:
event.delete()
- if state.lower() == 'undelete' and is_admin:
+ if state.lower() == 'undelete' and access_rights.is_admin:
event.undelete()
- if state.lower() == 'expire' and is_admin:
+ if state.lower() == 'expire' and access_rights.is_admin:
event.expire()
if event.status == 'approved':
notify_owner_approved(event)
View
96 templates/event.html
@@ -1,60 +1,60 @@
{% extends 'base.html' %}
{% block content %}
<div id="menu" style="float: right; margin: 10px; font-size: smaller;">
- <a href="/">Approved</a> | <a href="/pending">Pending</a> | <a href="/new" style="font-weight: bold;">New Event</a>
+ <a href="/">Approved</a> | <a href="/pending">Pending</a> | <a href="/new" style="font-weight: bold;">New Event</a>
</div>
<div id="primary">
- <h3>{{event.name|title}}</h3>
- {% if not event.is_past %}<p>
- <form method="post" style="display: inline;">
- {% if event.is_deleted %}
- {% if is_admin %}<input type="submit" name="state" value="Undelete" />{% endif %}
- (This will return the event to the &ldquo;pending&rdquo; status.)
- {% else %}
- {% if can_approve %}<input type="submit" name="state" value="Approve" />{% endif %}
- {% if can_cancel %}<input type="submit" name="state" value="Cancel" />{% endif %}
- {% if is_admin %}<input type="submit" name="state" value="Delete" />{% endif %}
- {% if can_staff %}<input type="submit" name="state" value="Staff" />{% endif %}
- {% if can_unstaff %}<input type="submit" name="state" value="Unstaff" />{% endif %}
- {% endif %}
- </form>
- </p>{% endif %}
+ <h3>{{event.name|title}}</h3>
+ {% if not event.is_past %}<p>
+ <form method="post" style="display: inline;">
+ {% if event.is_deleted %}
+ {% if access_rights.is_admin %}<input type="submit" name="state" value="Undelete" />{% endif %}
+ (This will return the event to the &ldquo;pending&rdquo; status.)
+ {% else %}
+ {% if access_rights.can_approve %}<input type="submit" name="state" value="Approve" />{% endif %}
+ {% if access_rights.can_cancel and not event.is_canceled %}<input type="submit" name="state" value="Cancel" />{% endif %}
+ {% if access_rights.is_admin %}<input type="submit" name="state" value="Delete" />{% endif %}
+ {% if access_rights.can_staff %}<input type="submit" name="state" value="Staff" />{% endif %}
+ {% if access_rights.can_unstaff %}<input type="submit" name="state" value="Unstaff" />{% endif %}
+ {% endif %}
+ </form>
+ </p>{% endif %}
- {% if not event.is_staffed %}<p>
- <span style="color: red; font-weight: bold">This event is currently understaffed.</span><br/>
- Due to this size of the event, at least {{ event.staff_needed }} more Dojo member{{ event.staff_needed|pluralize }} must volunteer to staff it. It will not appear on the public calendar until {% if not event.is_approved %}it has been approved and {% endif %}enough people volunteer.
- </p>{% else %}{% if not event.is_approved %}<p>
- <span style="color: red; font-weight: bold">This event is not yet visible.</span><br/>
- This event will not appear on the public calendar until it has been approved. If this does not happen soon, contact <a href="email:events@hackerdojo.com">events@hackerdojo.com</a> for assistance.
+ {% if not event.is_staffed %}<p>
+ <span style="color: red; font-weight: bold">This event is currently understaffed.</span><br/>
+ Due to this size of the event, at least {{ event.staff_needed }} more Dojo member{{ event.staff_needed|pluralize }} must volunteer to staff it. It will not appear on the public calendar until {% if not event.is_approved %}it has been approved and {% endif %}enough people volunteer.
+ </p>{% else %}{% if not event.is_approved %}<p>
+ <span style="color: red; font-weight: bold">This event is not yet visible.</span><br/>
+ This event will not appear on the public calendar until it has been approved. If this does not happen soon, contact <a href="email:events@hackerdojo.com">events@hackerdojo.com</a> for assistance.
</p>{% endif %}{% endif %}
-
- <div class='b-block'><div class='b-label'>Status:</div><div class='b-data'>{{event.status|title}}</div></div>
- <div class='b-block'><div class='b-label'>Date:</div><div class='b-data'>{{event.start_time|date:"l, F j Y"}}</div></div>
- <div class='b-block'><div class='b-label'>Time:</div><div class='b-data'>{{event.start_time|date:"g:iA"|lower}} to {{event.end_time|date:"g:iA"|lower}}</div></div>
- <div class='b-block'><div class='b-label'>Member:</div><div class='b-data'>{{event.member}}</div></div>
- <div class='b-block'><div class='b-label'>Type:</div><div class='b-data'>{{event.type}}</div></div>
- <div class='b-block'><div class='b-label'>Estimated size:</div><div class='b-data'>{{event.estimated_size}}</div></div>
- <div class='b-block'><div class='b-label'>Contact:</div><div class='b-data'>{{event.contact_name}}{% if user %}, {{event.contact_phone}}{% endif %}</div></div>
- <div class='b-block'><div class='b-label'>URL:</div><div class='b-data'><a href='{{event.url}}'>{{event.url}}</a></div></div>
- <div class='b-block'><div class='b-label'>Fee:</div><div class='b-data'>{{event.fee}}</div></div>
- <div class='b-block'><div class='b-label'>Rooms:</div><div class='b-data'>{{event.roomlist}}</div></div>
- <div class='b-block'><div class='b-label'>Staff:</div><div class='b-data'>{{event.stafflist}}</div></div>
- <div class='thin-border'></div>
- <div class='b-block'><div class='b-label'>Details:</div><div class='b-data'>{{event.details}}</div></div>
- <br />
- <div class='b-block'><div class='b-label'>Notes:</div><div class='b-data'>{{event.notes}}</div></div>
- {% if event.feedback_set.count %}
- <div class='thin-border'></div>
- <div id='secondary'>
- <h3>Feedback</h3>
- {% for feedback in event.feedback_set %}
- <div class='b-block'><div class='b-label'>Submitted by:</div><div class='b-data'>{{feedback.user}} on {{feedback.created|date:"F j"}} at {{feedback.created|date:"g:iA"|lower}}</div></div>
- <div class='b-block'><div class='b-label'>Rating:</div><div class='b-data'>{{feedback.rating}}</div></div>
- <div class='b-block'><div class='b-label'>Comment:</div><div class='b-data'>{{feedback.comment}}</div></div>
- <div class='thinner-border'></div>
+
+ <div class='b-block'><div class='b-label'>Status:</div><div class='b-data'>{{event.status|title}}</div></div>
+ <div class='b-block'><div class='b-label'>Date:</div><div class='b-data'>{{event.start_time|date:"l, F j Y"}}</div></div>
+ <div class='b-block'><div class='b-label'>Time:</div><div class='b-data'>{{event.start_time|date:"g:iA"|lower}} to {{event.end_time|date:"g:iA"|lower}}</div></div>
+ <div class='b-block'><div class='b-label'>Member:</div><div class='b-data'>{{event.member}}</div></div>
+ <div class='b-block'><div class='b-label'>Type:</div><div class='b-data'>{{event.type}}</div></div>
+ <div class='b-block'><div class='b-label'>Estimated size:</div><div class='b-data'>{{event.estimated_size}}</div></div>
+ <div class='b-block'><div class='b-label'>Contact:</div><div class='b-data'>{{event.contact_name}}{% if user %}, {{event.contact_phone}}{% endif %}</div></div>
+ <div class='b-block'><div class='b-label'>URL:</div><div class='b-data'><a href='{{event.url}}'>{{event.url}}</a></div></div>
+ <div class='b-block'><div class='b-label'>Fee:</div><div class='b-data'>{{event.fee}}</div></div>
+ <div class='b-block'><div class='b-label'>Rooms:</div><div class='b-data'>{{event.roomlist}}</div></div>
+ <div class='b-block'><div class='b-label'>Staff:</div><div class='b-data'>{{event.stafflist}}</div></div>
+ <div class='thin-border'></div>
+ <div class='b-block'><div class='b-label'>Details:</div><div class='b-data'>{{event.details}}</div></div>
+ <br />
+ <div class='b-block'><div class='b-label'>Notes:</div><div class='b-data'>{{event.notes}}</div></div>
+ {% if event.feedback_set.count %}
+ <div class='thin-border'></div>
+ <div id='secondary'>
+ <h3>Feedback</h3>
+ {% for feedback in event.feedback_set %}
+ <div class='b-block'><div class='b-label'>Submitted by:</div><div class='b-data'>{{feedback.user}} on {{feedback.created|date:"F j"}} at {{feedback.created|date:"g:iA"|lower}}</div></div>
+ <div class='b-block'><div class='b-label'>Rating:</div><div class='b-data'>{{feedback.rating}}</div></div>
+ <div class='b-block'><div class='b-label'>Comment:</div><div class='b-data'>{{feedback.comment}}</div></div>
+ <div class='thinner-border'></div>
{% endfor %}
- </div>
+ </div>
{% endif %}
</div>
View
39 utils.py
@@ -67,9 +67,9 @@ def get_phone_parts( in_phone, international_okay=False ):
phone_pattern = '(\+?\d{1-3})?\D*' + phone_pattern
phone_re = re.compile( '^' + phone_pattern )
try:
- seg = phone_re.search( in_phone ).groups()
+ seg = phone_re.search( in_phone ).groups()
except AttributeError:
- return [ None, None, None, None, None ]
+ return [ None, None, None, None, None ]
if international_okay:
return [ seg[ 2 ], seg[ 3 ], seg[ 4 ], seg[ 6 ], seg[ 0 ] ]
else:
@@ -84,4 +84,37 @@ def is_phone_valid( in_phone, area_code_required=True, international_okay=True )
out = False
if parts[ 1 ] == None or parts[ 2 ] == None or len( parts[ 1 ] ) != 3 or len( parts[ 2 ] ) != 4:
out = False
- return out
+ return out
+
+class UserRights(object):
+ def __init__(self, user=None, event=None):
+ """Constructor.
+
+ Args:
+ user: User() object that you want to perform the check on.
+ event: Event() object that you want to perform the check against if applicable.
+ """
+ self.user = user
+ self.event = event
+ self.is_admin = False
+ self.is_staff = False
+ self.is_owner = False
+ self.can_approve = False
+ self.can_cancel = False
+ self.can_edit = False
+ self.can_staff = False
+ self.can_unstaff = False
+
+ if self.user:
+ self.is_admin = username(self.user) in dojo('/groups/events')
+ self.is_staff = username(user) in dojo('/groups/staff')
+ if self.event:
+ self.is_owner = (self.user == self.event.member)
+ self.can_approve = (self.event.status in ['pending'] and self.is_admin
+ and not self.is_owner)
+ self.can_cancel = self.is_admin or self.is_owner
+ self.can_edit = self.is_admin or self.is_owner
+ self.can_staff = (self.event.status in ['pending', 'understaffed', 'approved']
+ and self.is_staff and self.user not in self.event.staff)
+ self.can_unstaff = (self.event.status not in ['canceled', 'deleted']
+ and self.is_staff and self.user in self.event.staff)

0 comments on commit 766e87c

Please sign in to comment.