def printed_badge_change(attendee): if attendee.badge_printed_name != attendee.orig_value_of('badge_printed_name') \ and not AdminAccount.admin_name() \ and localized_now() > c.get_printed_badge_deadline_by_type(attendee.badge_type_real): return '{} badges have already been ordered, so you cannot change the badge printed name.'.format( attendee.badge_type_label if attendee.badge_type in c.PREASSIGNED_BADGE_TYPES else "Supporter")
def internal(self, session, message=''): if c.HIDE_SCHEDULE and not AdminAccount.access_set( ) and not cherrypy.session.get('staffer_id'): return "The {} schedule is being developed and will be made public " \ "when it's closer to being finalized.".format(c.EVENT_NAME) schedule = defaultdict(lambda: defaultdict(list)) for event in session.query(Event).all(): schedule[event.start_time_local][event.location].append(event) for i in range(1, event.duration): half_hour = event.start_time_local + timedelta(minutes=30 * i) schedule[half_hour][event.location].append(c.EVENT_BOOKED) max_simul = {} for id, name in c.EVENT_LOCATION_OPTS: max_events = 1 for i in range(2 * c.CON_LENGTH): half_hour = c.EPOCH + timedelta(minutes=30 * i) max_events = max(max_events, len(schedule[half_hour][id])) max_simul[id] = max_events for half_hour in schedule: for location in schedule[half_hour]: for event in schedule[half_hour][location]: if isinstance(event, Event): simul = max( len(schedule[half_hour][event.location]) for half_hour in event.half_hours) event.colspan = 1 if simul > 1 else max_simul[ event.location] for i in range(1, event.duration): schedule[half_hour + timedelta( minutes=30 * i)][event.location].remove( c.EVENT_BOOKED) schedule[half_hour + timedelta( minutes=30 * i)][event.location].append( event.colspan) for half_hour in schedule: for id, name in c.EVENT_LOCATION_OPTS: span_sum = sum( getattr(e, 'colspan', e) for e in schedule[half_hour][id]) for i in range(max_simul[id] - span_sum): schedule[half_hour][id].append(c.EVENT_OPEN) schedule[half_hour] = sorted( schedule[half_hour].items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[0])) max_simul = [(id, c.EVENT_LOCATIONS[id], colspan) for id, colspan in max_simul.items()] return { 'message': message, 'schedule': sorted(schedule.items()), 'max_simul': sorted(max_simul, key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[0])) }
def update(self, session, password='', message='', **params): account = session.admin_account(params) if account.is_new: if c.AT_OR_POST_CON and not password: message = 'You must enter a password' else: password = password if c.AT_OR_POST_CON else genpasswd() account.hashed = bcrypt.hashpw(password, bcrypt.gensalt()) message = message or check(account) if not message: message = 'Account settings uploaded' attendee = session.attendee( account.attendee_id ) # dumb temporary hack, will fix later with tests account.attendee = attendee session.add(account) if account.is_new and not c.AT_OR_POST_CON: session.commit() body = render('emails/accounts/new_account.txt', { 'account': account, 'password': password, 'creator': AdminAccount.admin_name() }, encoding=None) send_email.delay(c.ADMIN_EMAIL, attendee.email, 'New ' + c.EVENT_NAME + ' Ubersystem Account', body, model=attendee.to_dict('id')) else: session.rollback() raise HTTPRedirect('index?message={}', message)
def test_email(self, session, subject=None, body=None, from_address=None, to_address=None, **params): """ Testing only: send a test email as a system user """ output_msg = "" if subject and body and from_address and to_address: send_email(from_address, to_address, subject, body) output_msg = "RAMS has attempted to send your email." right_now = str(datetime.now()) return { 'from_address': from_address or c.STAFF_EMAIL, 'to_address': (to_address or ("*****@*****.**" if c.DEV_BOX else AdminAccount.admin_email()) or ""), 'subject': c.EVENT_NAME_AND_YEAR + " test email " + right_now, 'body': body or "ignore this email, <b>it is a test</b> of the <u>RAMS email system</u> " + right_now, 'message': output_msg, }
def update(self, session, password='', message='', **params): account = session.admin_account(params, checkgroups=['access']) if account.is_new: if c.AT_OR_POST_CON and not password: message = 'You must enter a password' else: password = password if c.AT_OR_POST_CON else genpasswd() account.hashed = bcrypt.hashpw(password, bcrypt.gensalt()) message = message or check(account) if not message: message = 'Account settings uploaded' attendee = session.attendee(account.attendee_id) # dumb temporary hack, will fix later with tests account.attendee = attendee session.add(account) if account.is_new and not c.AT_OR_POST_CON: body = render('emails/accounts/new_account.txt', { 'account': account, 'password': password, 'creator': AdminAccount.admin_name() }, encoding=None) send_email.delay( c.ADMIN_EMAIL, attendee.email, 'New ' + c.EVENT_NAME + ' Ubersystem Account', body, model=attendee.to_dict('id')) else: session.rollback() raise HTTPRedirect('index?message={}', message)
def sitemap(self): site_sections = cherrypy.tree.apps[c.PATH].root modules = { name: getattr(site_sections, name) for name in dir(site_sections) if not name.startswith('_') } pages = defaultdict(list) access_set = AdminAccount.access_set() for module_name, module_root in modules.items(): for name in dir(module_root): method = getattr(module_root, name) if getattr(method, 'exposed', False): spec = inspect.getfullargspec(unwrap(method)) has_defaults = len([ arg for arg in spec.args[1:] if arg != 'session' ]) == len(spec.defaults or []) if set(getattr(method, 'restricted', []) or []).intersection(access_set) \ and not getattr(method, 'ajax', False) \ and (getattr(method, 'site_mappable', False) or has_defaults and not spec.varkw): pages[module_name].append({ 'name': name.replace('_', ' ').title(), 'path': '/{}/{}'.format(module_name, name) }) return {'pages': sorted(pages.items())}
def index(self, session, message='', decline=None, **params): if c.AFTER_ROOM_DEADLINE and c.STAFF_ROOMS not in AdminAccount.access_set(): raise HTTPRedirect('../signups/index?message={}', 'The room deadline has passed') attendee = session.logged_in_volunteer() if not attendee.hotel_eligible: raise HTTPRedirect('../signups/index?message={}', 'You have not been marked as eligible for hotel space') requests = session.hotel_requests(params, checkgroups=['nights'], restricted=True) if 'attendee_id' in params: requests.attendee = attendee # foreign keys are automatically admin-only session.add(requests) if decline or not requests.nights: requests.nights = '' raise HTTPRedirect( '../signups/index?message={}', "We've recorded that you've declined hotel room space") else: if requests.setup_teardown: days = ' / '.join( c.NIGHTS[day] for day in sorted(requests.nights_ints, key=c.NIGHT_DISPLAY_ORDER.index) if day not in c.CORE_NIGHTS) message = "Your hotel room request has been submitted. " \ "We'll let you know whether your offer to help on {} is accepted, " \ "and who your roommates will be, a few weeks after the deadline.".format(days) else: message = "You've accepted hotel room space for {}. " \ "We'll let you know your roommates a few weeks after the " \ "deadline.".format(requests.nights_display) raise HTTPRedirect('../signups/index?message={}', message) else: requests = attendee.hotel_requests or requests if requests.is_new: requests.nights = ','.join(map(str, c.CORE_NIGHTS)) nights = [] two_day_before = (c.EPOCH - timedelta(days=2)).strftime('%A') day_before = (c.EPOCH - timedelta(days=1)).strftime('%A') last_day = c.ESCHATON.strftime('%A').upper() day_after = (c.ESCHATON + timedelta(days=1)).strftime('%A') nights.append([getattr(c, two_day_before.upper()), getattr(requests, two_day_before.upper()), "I'd like to help set up on " + two_day_before]) nights.append([getattr(c, day_before.upper()), getattr(requests, day_before.upper()), "I'd like to help set up on " + day_before]) for night in c.CORE_NIGHTS: nights.append([night, night in requests.nights_ints, c.NIGHTS[night]]) nights.append([getattr(c, last_day), getattr(requests, last_day), "I'd like to help tear down on {} / {}".format(c.ESCHATON.strftime('%A'), day_after)]) return { 'nights': nights, 'message': message, 'requests': requests, 'attendee': attendee }
def create_judge(self, session, message='', first_name='', last_name='', email='', **params): judge = session.indie_judge(params, checkgroups=['genres', 'platforms']) if cherrypy.request.method == 'POST': message = check(judge) if not message and not first_name or not last_name or not email: message = 'First name, last name, and email address are all required to add a judge' if not message: # only match on last name and email, to prevent nickname issues; this could cause # problems if we had two judges with the same last name AND the same email address attendee = session.query(Attendee).filter_by(last_name=last_name, email=email).first() if attendee and attendee.admin_account: if attendee.admin_account.judge: raise HTTPRedirect( 'index?message={}{}', attendee.full_name, ' is already registered as a judge') else: attendee.admin_account.judge = judge attendee.admin_account.access = ','.join(map(str, set( attendee.admin_account.access_ints + [c.INDIE_JUDGE]))) raise HTTPRedirect('index?message={}{}', attendee.full_name, ' has been granted judge access') if not attendee: attendee = Attendee(first_name=first_name, last_name=last_name, email=email, placeholder=True, badge_type=c.ATTENDEE_BADGE, paid=c.NEED_NOT_PAY) session.add(attendee) password = genpasswd() attendee.admin_account = AdminAccount( judge=judge, access=str(c.INDIE_JUDGE), hashed=bcrypt.hashpw(password, bcrypt.gensalt()) ) email_body = render('emails/accounts/new_account.txt', { 'password': password, 'account': attendee.admin_account }, encoding=None) send_email.delay( c.MIVS_EMAIL, attendee.email, 'New {} Ubersystem Account'.format(c.EVENT_NAME), email_body, model=attendee.to_dict('id')) raise HTTPRedirect( 'index?message={}{}', attendee.full_name, ' has been given an admin account as an Indie Judge') return { 'message': message, 'judge': judge, 'first_name': first_name, 'last_name': last_name, 'email': email }
def test_check_admin_account_access_add(self, session, admin_account, admin_access, access_changes, expected): admin_access = ','.join(map(str, admin_access)) access_changes = ','.join(map(str, access_changes)) admin_account.access = admin_access session.commit() session.refresh(admin_account) test_attendee = Attendee(email='*****@*****.**') session.add(test_attendee) test_admin_account = AdminAccount( access='', attendee_id=test_attendee.id, hashed='<bcrypted>') session.add(test_admin_account) session.commit() session.refresh(test_admin_account) test_admin_account.access = access_changes message = check(test_admin_account) assert expected == message
def index(self, session, message=''): # show a public-facing view of the schedule # anything returned here should be cache-friendly and ready to be shown to the public. dont_allow_schedule_to_be_viewed = \ c.HIDE_SCHEDULE and not AdminAccount.access_set() and not cherrypy.session.get('staffer_id') if dont_allow_schedule_to_be_viewed: return "The {} schedule is being developed and will be made public " \ "when it's closer to being finalized.".format(c.EVENT_NAME) if c.ALT_SCHEDULE_URL: raise HTTPRedirect(c.ALT_SCHEDULE_URL) else: # external view attendees can look at with no admin menus/etc # we cache this view because it takes a while to generate return get_schedule_data(session, message)
def index(self, session, message=''): # show a public-facing view of the schedule # anything returned here should be cache-friendly and ready to be shown to the public. dont_allow_schedule_to_be_viewed = \ c.HIDE_SCHEDULE and not AdminAccount.access_set() and not cherrypy.session.get('staffer_id') if dont_allow_schedule_to_be_viewed: return "The {} schedule is being developed and will be made public " \ "when it's closer to being finalized.".format(c.EVENT_NAME) if c.ALT_SCHEDULE_URL: raise HTTPRedirect(c.ALT_SCHEDULE_URL) else: # external view attendees can look at with no admin menus/etc # we cache this view because it takes a while to generate return get_schedule_data(session, message)
def sitemap(self): site_sections = cherrypy.tree.apps[c.CHERRYPY_MOUNT_PATH].root modules = {name: getattr(site_sections, name) for name in dir(site_sections) if not name.startswith('_')} pages = defaultdict(list) access_set = AdminAccount.access_set() for module_name, module_root in modules.items(): for name in dir(module_root): method = getattr(module_root, name) if getattr(method, 'exposed', False): spec = inspect.getfullargspec(unwrap(method)) has_defaults = len([arg for arg in spec.args[1:] if arg != 'session']) == len(spec.defaults or []) if set(getattr(method, 'restricted', []) or []).intersection(access_set) \ and not getattr(method, 'ajax', False) \ and (getattr(method, 'site_mappable', False) or has_defaults and not spec.varkw): pages[module_name].append({ 'name': name.replace('_', ' ').title(), 'path': '/{}/{}'.format(module_name, name) }) return {'pages': sorted(pages.items())}
def test_email(self, session, subject=None, body=None, from_address=None, to_address=None, **params): """ Testing only: send a test email as a system user """ output_msg = "" if subject and body and from_address and to_address: send_email.delay(from_address, to_address, subject, body) output_msg = "RAMS has attempted to send your email." right_now = str(datetime.now()) return { 'from_address': from_address or c.STAFF_EMAIL, 'to_address': ( to_address or ("*****@*****.**" if c.DEV_BOX else AdminAccount.admin_email()) or ""), 'subject': c.EVENT_NAME_AND_YEAR + " test email " + right_now, 'body': body or "ignore this email, <b>it is a test</b> of the <u>RAMS email system</u> " + right_now, 'message': output_msg, }
def index(self, session, message='', decline=None, **params): if c.AFTER_ROOM_DEADLINE and c.STAFF_ROOMS not in AdminAccount.access_set( ): raise HTTPRedirect('../signups/index?message={}', 'The room deadline has passed') attendee = session.logged_in_volunteer() if not attendee.hotel_eligible: raise HTTPRedirect( '../signups/index?message={}', 'You have not been marked as eligible for hotel space') requests = session.hotel_requests(params, checkgroups=['nights'], restricted=True) if 'attendee_id' in params: requests.attendee = attendee # foreign keys are automatically admin-only session.add(requests) if decline or not requests.nights: requests.nights = '' raise HTTPRedirect( '../signups/index?message={}', "We've recorded that you've declined hotel room space") else: if requests.setup_teardown: days = ' / '.join(c.NIGHTS[day] for day in sorted( requests.nights_ints, key=c.NIGHT_DISPLAY_ORDER.index) if day not in c.CORE_NIGHTS) message = "Your hotel room request has been submitted. " \ "We'll let you know whether your offer to help on {} is accepted, " \ "and who your roommates will be, a few weeks after the deadline.".format(days) else: message = "You've accepted hotel room space for {}. " \ "We'll let you know your roommates a few weeks after the " \ "deadline.".format(requests.nights_display) raise HTTPRedirect('../signups/index?message={}', message) else: requests = attendee.hotel_requests or requests if requests.is_new: requests.nights = ','.join(map(str, c.CORE_NIGHTS)) nights = [] two_day_before = (c.EPOCH - timedelta(days=2)).strftime('%A') day_before = (c.EPOCH - timedelta(days=1)).strftime('%A') last_day = c.ESCHATON.strftime('%A').upper() day_after = (c.ESCHATON + timedelta(days=1)).strftime('%A') nights.append([ getattr(c, two_day_before.upper()), getattr(requests, two_day_before.upper()), "I'd like to help set up on " + two_day_before ]) nights.append([ getattr(c, day_before.upper()), getattr(requests, day_before.upper()), "I'd like to help set up on " + day_before ]) for night in c.CORE_NIGHTS: nights.append( [night, night in requests.nights_ints, c.NIGHTS[night]]) nights.append([ getattr(c, last_day), getattr(requests, last_day), "I'd like to help tear down on {} / {}".format( c.ESCHATON.strftime('%A'), day_after) ]) return { 'nights': nights, 'message': message, 'requests': requests, 'attendee': attendee }