def register_group_member(self, session, group_id, message='', **params): # Safe to ignore csrf tokens here, because an attacker would need to know the group id a priori group = session.group(group_id, ignore_csrf=True) attendee = session.attendee(params, restricted=True, ignore_csrf=True) must_be_staffing = False if group.unassigned[0].staffing: must_be_staffing = True attendee.staffing = True params['staffing'] = True message = check_pii_consent(params, attendee) or message if not message and 'first_name' in params: message = check(attendee, prereg=True) if not message and not params['first_name']: message = 'First and Last Name are required fields' if not message: if not group.unassigned: raise HTTPRedirect( 'register_group_member?group_id={}&message={}', group_id, 'No more unassigned badges exist in this group') attrs_to_preserve_from_unassigned_group_member = [ 'id', 'group_id', 'badge_type', 'badge_num', 'base_badge_price', 'ribbon', 'paid', 'overridden_price', 'requested_hotel_info'] attendee = group.unassigned[0] for attr in attrs_to_preserve_from_unassigned_group_member: if attr in params: del params[attr] attendee.apply(params, restricted=True) # Free group badges are considered registered' when they are actually claimed. if group.cost == 0: attendee.registered = localized_now() if attendee.amount_unpaid: raise HTTPRedirect('attendee_donation_form?id={}', attendee.id) else: raise HTTPRedirect('badge_updated?id={}&message={}', attendee.id, 'Badge registered successfully') return { 'message': message, 'group_id': group_id, 'group': group, 'attendee': attendee, 'affiliates': session.affiliates(), 'badge_cost': 0, 'must_be_staffing': must_be_staffing, }
def register_group_member(self, session, group_id, message='', **params): # Safe to ignore csrf tokens here, because an attacker would need to know the group id a priori group = session.group(group_id, ignore_csrf=True) attendee = session.attendee(params, restricted=True, ignore_csrf=True) message = check_pii_consent(params, attendee) or message if not message and 'first_name' in params: message = check(attendee, prereg=True) if not message and not params['first_name']: message = 'First and Last Name are required fields' if not message: if not group.unassigned: raise HTTPRedirect( 'register_group_member?group_id={}&message={}', group_id, 'No more unassigned badges exist in this group') attrs_to_preserve_from_unassigned_group_member = [ 'id', 'group_id', 'badge_type', 'badge_num', 'base_badge_price', 'ribbon', 'paid', 'overridden_price', 'requested_hotel_info'] attendee = group.unassigned[0] for attr in attrs_to_preserve_from_unassigned_group_member: if attr in params: del params[attr] attendee.apply(params, restricted=True) # Free group badges are considered registered' when they are actually claimed. if group.cost == 0: attendee.registered = localized_now() if attendee.amount_unpaid: raise HTTPRedirect('attendee_donation_form?id={}', attendee.id) else: raise HTTPRedirect('badge_updated?id={}&message={}', attendee.id, 'Badge registered successfully') return { 'message': message, 'group_id': group_id, 'group': group, 'attendee': attendee, 'affiliates': session.affiliates(), 'badge_cost': 0 }
def register(self, session, message='', error_message='', **params): params['id'] = 'None' attendee = session.attendee(params, restricted=True, ignore_csrf=True) error_message = check_pii_consent(params, attendee) or error_message if not error_message and 'first_name' in params: if not attendee.payment_method and (not c.BADGE_PRICE_WAIVED or c.BEFORE_BADGE_PRICE_WAIVED): error_message = 'Please select a payment type' elif attendee.payment_method == c.MANUAL and not re.match( c.EMAIL_RE, attendee.email): error_message = 'Email address is required to pay with a credit card at our registration desk' elif attendee.badge_type not in [ badge for badge, desc in c.AT_THE_DOOR_BADGE_OPTS ]: error_message = 'No hacking allowed!' else: error_message = check(attendee) if not error_message and c.BADGE_PROMO_CODES_ENABLED and 'promo_code' in params: error_message = session.add_promo_code_to_attendee( attendee, params.get('promo_code')) if not error_message: session.add(attendee) session.commit() if c.AFTER_BADGE_PRICE_WAIVED: message = c.AT_DOOR_WAIVED_MSG attendee.paid = c.NEED_NOT_PAY elif attendee.payment_method == c.STRIPE: raise HTTPRedirect('pay?id={}', attendee.id) elif attendee.payment_method == c.CASH: message = c.AT_DOOR_CASH_MSG.format('${}'.format( attendee.total_cost)) elif attendee.payment_method == c.MANUAL: message = c.AT_DOOR_MANUAL_MSG raise HTTPRedirect( 'register?message={}', message or "Thanks! Please proceed to the registration desk to pick up your badge." ) return { 'message': message, 'error_message': error_message, 'attendee': attendee, 'promo_code': params.get('promo_code', ''), }
def register(self, session, message='', error_message='', **params): params['id'] = 'None' attendee = session.attendee(params, restricted=True, ignore_csrf=True) error_message = check_pii_consent(params, attendee) or error_message if not error_message and 'first_name' in params: if not attendee.payment_method and (not c.BADGE_PRICE_WAIVED or c.BEFORE_BADGE_PRICE_WAIVED): error_message = 'Please select a payment type' elif attendee.payment_method == c.MANUAL and not re.match(c.EMAIL_RE, attendee.email): error_message = 'Email address is required to pay with a credit card at our registration desk' elif attendee.badge_type not in [badge for badge, desc in c.AT_THE_DOOR_BADGE_OPTS]: error_message = 'No hacking allowed!' else: error_message = check(attendee) if not error_message and c.BADGE_PROMO_CODES_ENABLED and 'promo_code' in params: error_message = session.add_promo_code_to_attendee(attendee, params.get('promo_code')) if not error_message: session.add(attendee) session.commit() if c.AFTER_BADGE_PRICE_WAIVED: message = c.AT_DOOR_WAIVED_MSG attendee.paid = c.NEED_NOT_PAY elif attendee.payment_method == c.STRIPE: raise HTTPRedirect('pay?id={}', attendee.id) elif attendee.payment_method == c.CASH: message = c.AT_DOOR_CASH_MSG.format('${}'.format(attendee.total_cost)) elif attendee.payment_method == c.MANUAL: message = c.AT_DOOR_MANUAL_MSG raise HTTPRedirect('register?message={}', message) return { 'message': message, 'error_message': error_message, 'attendee': attendee, 'promo_code': params.get('promo_code', ''), }
def form(self, session, message='', edit_id=None, **params): """ Our production NGINX config caches the page at /preregistration/form. Since it's cached, we CAN'T return a session cookie with the page. We must POST to a different URL in order to bypass the cache and get a valid session cookie. Thus, this page is also exposed as "post_form". """ params['id'] = 'None' # security! group = Group() if edit_id is not None: attendee = self._get_unsaved( edit_id, if_not_found=HTTPRedirect('form?message={}', 'That preregistration has already been finalized')) attendee.apply(params, restricted=True) params.setdefault('pii_consent', True) else: attendee = session.attendee(params, ignore_csrf=True, restricted=True) if attendee.badge_type == c.PSEUDO_DEALER_BADGE: if not c.DEALER_REG_OPEN: return render('static_views/dealer_reg_closed.html') if c.AFTER_DEALER_REG_START \ else render('static_views/dealer_reg_not_open.html') # Both the Attendee class and Group class have identically named # address fields. In order to distinguish the two sets of address # fields in the params, the Group fields are prefixed with "group_" # when the form is submitted. To prevent instantiating the Group object # with the Attendee's address fields, we must clone the params and # rename all the "group_" fields. group_params = dict(params) for field_name in ['country', 'region', 'zip_code', 'address1', 'address2', 'city']: group_params[field_name] = params.get('group_{}'.format(field_name), '') if params.get('copy_address'): params[field_name] = group_params[field_name] attendee.apply(params) group = session.group(group_params, ignore_csrf=True, restricted=True) if c.PAGE == 'post_dealer': attendee.badge_type = c.PSEUDO_DEALER_BADGE elif not attendee.badge_type: attendee.badge_type = c.ATTENDEE_BADGE if cherrypy.request.method == 'POST' or edit_id is not None: message = check_pii_consent(params, attendee) or message if not message and attendee.badge_type not in c.PREREG_BADGE_TYPES: message = 'Invalid badge type!' if not message and c.BADGE_PROMO_CODES_ENABLED and params.get('promo_code'): if session.lookup_promo_or_group_code(params.get('promo_code'), PromoCodeGroup): Charge.universal_promo_codes[attendee.id] = params.get('promo_code') message = session.add_promo_code_to_attendee(attendee, params.get('promo_code')) if message: return { 'message': message, 'attendee': attendee, 'group': group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), 'name': params.get('name', ''), 'badges': params.get('badges', 0), } if 'first_name' in params: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: message = check(group, prereg=True) message = message or check(attendee, prereg=True) if attendee.badge_type in [c.PSEUDO_GROUP_BADGE, c.PSEUDO_DEALER_BADGE]: message = "Please enter a group name" if not params.get('name') else message else: params['badges'] = 0 params['name'] = '' if not message: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: attendee.paid = c.PAID_BY_GROUP group.attendees = [attendee] session.assign_badges(group, params['badges']) group.status = c.WAITLISTED if c.DEALER_REG_SOFT_CLOSED else c.UNAPPROVED attendee.ribbon = add_opt(attendee.ribbon_ints, c.DEALER_RIBBON) attendee.badge_type = c.ATTENDEE_BADGE session.add_all([attendee, group]) session.commit() try: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, '{} Received'.format(c.DEALER_APP_TERM.title()), render('emails/dealers/reg_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) send_email.delay( c.MARKETPLACE_EMAIL, attendee.email, '{} Received'.format(c.DEALER_APP_TERM.title()), render('emails/dealers/application.html', {'group': group}, encoding=None), 'html', model=group.to_dict('id')) except Exception: log.error('unable to send marketplace application confirmation email', exc_info=True) raise HTTPRedirect('dealer_confirmation?id={}', group.id) else: track_type = c.UNPAID_PREREG if attendee.id in Charge.unpaid_preregs: track_type = c.EDITED_PREREG # Clear out any previously cached targets, in case the unpaid badge # has been edited and changed from a single to a group or vice versa. del Charge.unpaid_preregs[attendee.id] Charge.unpaid_preregs[attendee.id] = Charge.to_sessionized(attendee, params.get('name'), params.get('badges')) Tracking.track(track_type, attendee) if session.attendees_with_badges().filter_by( first_name=attendee.first_name, last_name=attendee.last_name, email=attendee.email).count(): raise HTTPRedirect('duplicate?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if attendee.banned: raise HTTPRedirect('banned?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if c.PREREG_REQUEST_HOTEL_INFO_OPEN: hotel_page = 'hotel?edit_id={}' if edit_id else 'hotel?id={}' raise HTTPRedirect(hotel_page, group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) else: raise HTTPRedirect('index') else: if edit_id is None: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: # All new dealer signups should default to receiving the # hotel info email, even if the deadline has passed. # There's a good chance some dealers will apply for a table # AFTER the hotel booking deadline, but BEFORE the hotel # booking is sent out. This ensures they'll still receive # the email, as requested by the Marketplace Department. attendee.requested_hotel_info = True if attendee.badge_type == c.PSEUDO_DEALER_BADGE and c.DEALER_REG_SOFT_CLOSED: message = '{} is closed, but you can ' \ 'fill out this form to add yourself to our waitlist'.format(c.DEALER_REG_TERM.title()) promo_code_group = None if attendee.promo_code: promo_code_group = session.query(PromoCode).filter_by(code=attendee.promo_code.code).first().group return { 'message': message, 'attendee': attendee, 'badges': params.get('badges', 0), 'name': params.get('name', ''), 'group': group, 'promo_code_group': promo_code_group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), }
def form(self, session, message='', edit_id=None, **params): """ Our production NGINX config caches the page at /preregistration/form. Since it's cached, we CAN'T return a session cookie with the page. We must POST to a different URL in order to bypass the cache and get a valid session cookie. Thus, this page is also exposed as "post_form". """ params['id'] = 'None' # security! group = Group() if edit_id is not None: attendee = self._get_unsaved( edit_id, if_not_found=HTTPRedirect('form?message={}', 'That preregistration has already been finalized')) attendee.apply(params, restricted=True) params.setdefault('pii_consent', True) else: attendee = session.attendee(params, ignore_csrf=True, restricted=True) if attendee.badge_type == c.PSEUDO_DEALER_BADGE: if not c.DEALER_REG_OPEN: return render('static_views/dealer_reg_closed.html') if c.AFTER_DEALER_REG_START \ else render('static_views/dealer_reg_not_open.html') # Both the Attendee class and Group class have identically named # address fields. In order to distinguish the two sets of address # fields in the params, the Group fields are prefixed with "group_" # when the form is submitted. To prevent instantiating the Group object # with the Attendee's address fields, we must clone the params and # rename all the "group_" fields. group_params = dict(params) for field_name in ['country', 'region', 'zip_code', 'address1', 'address2', 'city']: group_params[field_name] = params.get('group_{}'.format(field_name), '') if params.get('copy_address'): params[field_name] = group_params[field_name] group = session.group(group_params, ignore_csrf=True, restricted=True) if c.PAGE == 'post_dealer': attendee.badge_type = c.PSEUDO_DEALER_BADGE elif not attendee.badge_type: attendee.badge_type = c.ATTENDEE_BADGE if cherrypy.request.method == 'POST' or edit_id is not None: message = check_pii_consent(params, attendee) or message if not message and attendee.badge_type not in c.PREREG_BADGE_TYPES: message = 'Invalid badge type!' if not message and c.BADGE_PROMO_CODES_ENABLED and params.get('promo_code'): message = session.add_promo_code_to_attendee(attendee, params.get('promo_code')) if message: return { 'message': message, 'attendee': attendee, 'group': group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), } if 'first_name' in params: message = check(attendee, prereg=True) if not message and attendee.badge_type == c.PSEUDO_DEALER_BADGE: message = check(group, prereg=True) if attendee.badge_type in [c.PSEUDO_GROUP_BADGE, c.PSEUDO_DEALER_BADGE]: message = "Please enter a group name" if not params.get('name') else '' else: params['badges'] = 0 params['name'] = '' if not message: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: attendee.paid = c.PAID_BY_GROUP group.attendees = [attendee] session.assign_badges(group, params['badges']) group.status = c.WAITLISTED if c.DEALER_REG_SOFT_CLOSED else c.UNAPPROVED attendee.ribbon = add_opt(attendee.ribbon_ints, c.DEALER_RIBBON) attendee.badge_type = c.ATTENDEE_BADGE session.add_all([attendee, group]) session.commit() try: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Application Received', render('emails/dealers/reg_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) send_email.delay( c.MARKETPLACE_EMAIL, attendee.email, 'Dealer Application Received', render('emails/dealers/application.html', {'group': group}, encoding=None), 'html', model=group.to_dict('id')) except Exception: log.error('unable to send marketplace application confirmation email', exc_info=True) raise HTTPRedirect('dealer_confirmation?id={}', group.id) else: track_type = c.UNPAID_PREREG if attendee.id in Charge.unpaid_preregs: track_type = c.EDITED_PREREG # Clear out any previously cached targets, in case the unpaid badge # has been edited and changed from a single to a group or vice versa. del Charge.unpaid_preregs[attendee.id] Charge.unpaid_preregs[attendee.id] = Charge.to_sessionized(attendee, params.get('name'), params.get('badges')) Tracking.track(track_type, attendee) if session.attendees_with_badges().filter_by( first_name=attendee.first_name, last_name=attendee.last_name, email=attendee.email).count(): raise HTTPRedirect('duplicate?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if attendee.banned: raise HTTPRedirect('banned?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if c.PREREG_REQUEST_HOTEL_INFO_OPEN: hotel_page = 'hotel?edit_id={}' if edit_id else 'hotel?id={}' raise HTTPRedirect(hotel_page, group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) else: raise HTTPRedirect('index') else: if edit_id is None: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: # All new dealer signups should default to receiving the # hotel info email, even if the deadline has passed. # There's a good chance some dealers will apply for a table # AFTER the hotel booking deadline, but BEFORE the hotel # booking is sent out. This ensures they'll still receive # the email, as requested by the Marketplace Department. attendee.requested_hotel_info = True if attendee.badge_type == c.PSEUDO_DEALER_BADGE and c.DEALER_REG_SOFT_CLOSED: message = 'Dealer registration is closed, but you can ' \ 'fill out this form to add yourself to our waitlist' promo_code_group = None if attendee.promo_code: promo_code_group = session.query(PromoCode).filter_by(code=attendee.promo_code.code).first().group return { 'message': message, 'attendee': attendee, 'group': group, 'promo_code_group': promo_code_group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), }