def process_art_show_payment(self, session, payment_id, stripeToken):
     charge = Charge.get(payment_id)
     [attendee] = charge.attendees
     attendee = session.merge(attendee)
     apps = attendee.art_show_applications
     for app in apps:
         message = charge.charge_cc(session, stripeToken)
         if message:
             raise HTTPRedirect('edit?id={}&message={}', app.id, message)
         else:
             attendee.amount_paid += charge.dollar_amount
             app.status = c.PAID
             if attendee.paid == c.NOT_PAID:
                 attendee.paid = c.HAS_PAID
         session.add(attendee)
         send_email.delay(c.ADMIN_EMAIL,
                          c.ART_SHOW_EMAIL,
                          'Art Show Payment Received',
                          render('emails/art_show/payment_notification.txt',
                                 {'app': app},
                                 encoding=None),
                          model=app.to_dict('id'))
         send_email.delay(c.ART_SHOW_EMAIL,
                          app.email,
                          'Art Show Payment Received',
                          render('emails/art_show/payment_confirmation.txt',
                                 {'app': app},
                                 encoding=None),
                          model=app.to_dict('id'))
         raise HTTPRedirect('edit?id={}&message={}', app.id,
                            'Your payment has been accepted!')
Example #2
0
    def new_agent(self, session, **params):
        app = session.art_show_application(params['id'])
        promo_code = session.promo_code(code=app.agent_code)
        message = 'Agent code updated'
        page = "edit" if 'admin' not in params else "../art_show_admin/form"

        app.agent_code = app.new_agent_code()
        session.delete(promo_code)
        if app.agent:
            message = 'Agent removed and code updated'
            send_email.delay(
                c.ART_SHOW_EMAIL,
                [app.agent.email_to_address, app.attendee.email_to_address],
                '{} Art Show Agent Removed'.format(c.EVENT_NAME),
                render('emails/art_show/agent_removed.html', {'app': app},
                       encoding=None),
                'html',
                model=app.to_dict('id'))
            app.agent_id = None

        send_email.delay(
            c.ART_SHOW_EMAIL,
            app.attendee.email_to_address,
            'New Agent Code for the {} Art Show'.format(c.EVENT_NAME),
            render('emails/art_show/agent_code.html', {'app': app},
                   encoding=None),
            'html',
            model=app.to_dict('id'))

        raise HTTPRedirect('{}?id={}&message={}', page, app.id, message)
Example #3
0
 def process_art_show_payment(self, session, id):
     attendee = session.attendee(id)
     charge = Charge(attendee, description="Art show application payment")
     
     stripe_intent = charge.create_stripe_intent(session)
     message = stripe_intent if isinstance(stripe_intent, string_types) else ''
     if message:
         return {'error': message}
     else:
         for app in attendee.art_show_applications:
             app.status = c.PAID  # This needs to accommodate payment cancellations
             send_email.delay(
                 c.ADMIN_EMAIL,
                 c.ART_SHOW_EMAIL,
                 'Art Show Payment Received',
                 render('emails/art_show/payment_notification.txt',
                     {'app': app}, encoding=None),
                 model=app.to_dict('id'))
             send_email.delay(
                 c.ART_SHOW_EMAIL,
                 app.email,
                 'Art Show Payment Received',
                 render('emails/art_show/payment_confirmation.txt',
                     {'app': app}, encoding=None),
                 model=app.to_dict('id'))
         if attendee.paid == c.NOT_PAID:
             attendee.paid = c.HAS_PAID
         session.add(session.create_receipt_item(attendee, charge.amount, "Art show payment", charge.stripe_transaction))
         session.add(attendee)
         session.commit()
         
         return {'stripe_intent': stripe_intent,
                 'success_url': 'edit?id={}&message={}'.format(attendee.art_show_applications[0].id,
                                                               'Your payment has been accepted')}
Example #4
0
 def reset_problems(self, session, game_id):
     game = session.indie_game(game_id)
     for review in game.reviews:
         if review.has_video_issues:
             body = render('emails/video_fixed.txt', {'review': review},
                           encoding=None)
             send_email.delay(c.MIVS_EMAIL,
                              review.judge.email,
                              'MIVS: Video Problems Resolved for {}'.format(
                                  review.game.title),
                              body,
                              model=review.judge.to_dict('id'))
             review.video_status = c.PENDING
         if review.has_game_issues:
             body = render('emails/game_fixed.txt', {'review': review},
                           encoding=None)
             send_email.delay(c.MIVS_EMAIL,
                              review.judge.email,
                              'MIVS: Game Problems Resolved for {}'.format(
                                  review.game.title),
                              body,
                              model=review.judge.to_dict('id'))
             review.game_status = c.PENDING
     raise HTTPRedirect(
         'index?message={}{}', review.game.title,
         ' has been marked as having its judging issues fixed')
Example #5
0
    def process_marketplace_payment(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [attendee] = charge.attendees
        attendee = session.merge(attendee)
        apps = attendee.marketplace_applications

        message = charge.charge_cc(session, stripeToken)
        if message:
            raise HTTPRedirect('edit?id={}&message={}', apps[0].id, message)
        else:
            attendee_payment = charge.dollar_amount
            if attendee.marketplace_cost:
                for app in attendee.marketplace_applications:
                    attendee_payment -= app.amount_unpaid
                    app.amount_paid += app.amount_unpaid
            attendee.amount_paid += attendee_payment
            if attendee.paid == c.NOT_PAID:
                attendee.paid = c.HAS_PAID
        session.add(attendee)
        send_email.delay(c.ADMIN_EMAIL,
                         c.MARKETPLACE_APP_EMAIL,
                         'Marketplace Payment Received',
                         render('emails/marketplace/payment_notification.txt',
                                {'app': app},
                                encoding=None),
                         model=app.to_dict('id'))
        send_email.delay(c.MARKETPLACE_APP_EMAIL,
                         app.email,
                         'Marketplace Payment Received',
                         render('emails/marketplace/payment_confirmation.txt',
                                {'app': app},
                                encoding=None),
                         model=app.to_dict('id'))
        raise HTTPRedirect('edit?id={}&message={}', app.id,
                           'Your payment has been accepted!')
Example #6
0
    def process_marketplace_payment(self, session, id):
        attendee = session.attendee(id)
        charge = Charge(
            attendee,
            description="Marketplace application payment for {}".format(
                attendee.full_name))

        stripe_intent = charge.create_stripe_intent(session)
        message = stripe_intent if isinstance(stripe_intent,
                                              string_types) else ''
        if message:
            return {'error': message}
        else:
            if attendee.marketplace_cost:
                for app in attendee.marketplace_applications:
                    cancel_amt = app.amount_unpaid
                    app.amount_paid += app.amount_unpaid
                    send_email.delay(
                        c.ADMIN_EMAIL,
                        c.MARKETPLACE_APP_EMAIL,
                        'Marketplace Payment Received',
                        render('emails/marketplace/payment_notification.txt',
                               {'app': app},
                               encoding=None),
                        model=app.to_dict('id'))
                    send_email.delay(
                        c.MARKETPLACE_APP_EMAIL,
                        app.email_to_address,
                        'Marketplace Payment Received',
                        render('emails/marketplace/payment_confirmation.txt',
                               {'app': app},
                               encoding=None),
                        model=app.to_dict('id'))

            if attendee.paid == c.NOT_PAID:
                attendee.paid = c.HAS_PAID
            session.add(
                session.create_receipt_item(attendee, charge.amount,
                                            "Marketplace payment",
                                            charge.stripe_transaction))
        session.add(attendee)
        session.commit()

        return {
            'stripe_intent':
            stripe_intent,
            'success_url':
            'edit?id={}&message={}'.format(
                attendee.marketplace_applications[0].id,
                'Your payment has been accepted'),
            'cancel_url':
            '../preregistration/cancel_payment?model_id={}&cancel_amt={}'.
            format(attendee.marketplace_applications[0].id, cancel_amt)
        }
Example #7
0
    def index(self, session, message='', **params):
        attendee = None

        if cherrypy.request.method == 'GET' and params.get('attendee_id', ''):
            try:
                attendee = session.attendee(id=params['attendee_id'])
            except Exception:
                message = \
                    'We could not find you by your confirmation number. ' \
                    'Is the URL correct?'

        if attendee and attendee.group:
            for field in MarketplaceApplication.MATCHING_DEALER_FIELDS:
                params[field] = params[field] if field in params else getattr(
                    attendee.group, field, None)

        app = session.marketplace_application(params,
                                              restricted=True,
                                              ignore_csrf=True)

        if not (c.AFTER_MARKETPLACE_REG_START
                and c.BEFORE_MARKETPLACE_DEADLINE):
            return render('static_views/marketplace_closed.html') if c.AFTER_MARKETPLACE_DEADLINE \
                else render('static_views/marketplace_not_open.html')

        if cherrypy.request.method == 'POST':
            attendee, message = session.attendee_from_marketplace_app(**params)

            message = message or check(attendee) or check(app, prereg=True)
            if not message:
                if c.AFTER_MARKETPLACE_WAITLIST:
                    app.status = c.WAITLISTED
                session.add(attendee)
                app.attendee = attendee

                session.add(app)
                send_email(c.MARKETPLACE_APP_EMAIL,
                           c.MARKETPLACE_APP_EMAIL,
                           'Marketplace Application Received',
                           render('emails/marketplace/reg_notification.txt',
                                  {'app': app}),
                           model=app)
                session.commit()
                raise HTTPRedirect('confirmation?id={}', app.id)

        return {
            'message': message,
            'app': app,
            'attendee': attendee,
            'attendee_id': app.attendee_id or params.get('attendee_id', ''),
            'logged_in_account': session.current_attendee_account(),
            'new_badge': params.get('new_badge', '')
        }
Example #8
0
    def index(self, session, message='', **params):
        app = session.art_show_application(params,
                                           restricted=True,
                                           ignore_csrf=True)
        attendee = None

        if not c.ART_SHOW_OPEN:
            return render('static_views/art_show_closed.html') if c.AFTER_ART_SHOW_DEADLINE \
                else render('static_views/art_show_not_open.html')

        if cherrypy.request.method == 'GET' and params.get('attendee_id', ''):
            try:
                attendee = session.attendee(id=params['attendee_id'])
            except Exception:
                message = \
                    'We could not find you by your confirmation number. ' \
                    'Is the URL correct?'

        if cherrypy.request.method == 'POST':
            attendee, message = session.attendee_from_art_show_app(**params)

            if attendee and attendee.badge_status == c.NOT_ATTENDING \
                    and app.delivery_method == c.BRINGING_IN:
                message = 'You cannot bring your own art ' \
                          'if you are not attending.'

            message = message or check(attendee) or check(app, prereg=True)
            if not message:
                if c.AFTER_ART_SHOW_WAITLIST:
                    app.status = c.WAITLISTED
                session.add(attendee)
                app.attendee = attendee

                session.add(app)
                send_email(c.ART_SHOW_EMAIL,
                           c.ART_SHOW_EMAIL,
                           'Art Show Application Received',
                           render('emails/art_show/reg_notification.txt',
                                  {'app': app}),
                           model=app)
                session.commit()
                raise HTTPRedirect('confirmation?id={}', app.id)

        return {
            'message': message,
            'app': app,
            'attendee': attendee,
            'attendee_id': app.attendee_id or params.get('attendee_id', ''),
            'logged_in_account': session.current_attendee_account(),
            'not_attending': params.get('not_attending', ''),
            'new_badge': params.get('new_badge', '')
        }
Example #9
0
def check_pending_badges():
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        emails = [[
            'Staff', c.STAFF_EMAIL, Attendee.badge_type == c.STAFF_BADGE,
            'staffing_admin'
        ],
                  [
                      'Attendee', c.REGDESK_EMAIL,
                      Attendee.badge_type != c.STAFF_BADGE, 'registration'
                  ]]
        subject = c.EVENT_NAME + ' Pending {} Badge Report for ' + localized_now(
        ).strftime('%Y-%m-%d')
        with Session() as session:
            for badge_type, to, per_email_filter, site_section in emails:
                pending = session.query(Attendee).filter_by(
                    badge_status=c.PENDING_STATUS).filter(
                        per_email_filter).all()
                if pending and session.no_email(subject.format(badge_type)):
                    body = render('emails/daily_checks/pending.html', {
                        'pending': pending,
                        'site_section': site_section
                    })
                    send_email(c.ADMIN_EMAIL,
                               to,
                               subject.format(badge_type),
                               body,
                               format='html',
                               model='n/a')
Example #10
0
    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)
Example #11
0
    def reset(self, session, message='', email=None):
        if email is not None:
            try:
                account = session.get_account_by_email(email)
            except NoResultFound:
                message = 'No account exists for email address {!r}'.format(email)
            else:
                password = genpasswd()
                if account.password_reset:
                    session.delete(account.password_reset)
                    session.commit()
                session.add(PasswordReset(admin_account=account, hashed=bcrypt.hashpw(password, bcrypt.gensalt())))
                body = render('emails/accounts/password_reset.txt', {
                    'name': account.attendee.full_name,
                    'password':  password}, encoding=None)

                send_email.delay(
                    c.ADMIN_EMAIL,
                    account.attendee.email,
                    c.EVENT_NAME + ' Admin Password Reset',
                    body,
                    model=account.attendee.to_dict('id'))
                raise HTTPRedirect('login?message={}', 'Your new password has been emailed to you')

        return {
            'email':   email,
            'message': message
        }
    def allotments(self,
                   session,
                   department_id=None,
                   submitted=None,
                   csrf_token=None,
                   **params):
        if not department_id:
            raise HTTPRedirect('../dept_checklist/index')
        attendee = session.admin_attendee()
        department = session.query(Department).options(
            subqueryload(Department.dept_checklist_items)).get(department_id)

        if submitted:
            slug = 'allotments'
            item = department.checklist_item_for_slug(slug)
            if not item:
                item = DeptChecklistItem(attendee=attendee,
                                         department=department,
                                         slug=slug)

            # since this form doesn't use our normal utility methods, we need to do this manually
            check_csrf(csrf_token)
            item.comments = render('dept_checklist/allotments.txt',
                                   params).decode('utf-8')
            session.add(item)
            raise HTTPRedirect(
                '../dept_checklist/index?department_id={}&message={}',
                department_id, 'Treasury checklist data uploaded')

        return {'department': department}
Example #13
0
    def edit(self, session, message='', **params):
        app = session.marketplace_application(params,
                                              restricted=True,
                                              ignore_csrf=True)
        return_to = params['return_to'] \
            if 'return_to' in params else '/marketplace/edit'
        if 'id' not in params:
            message = 'Invalid marketplace application ID. ' \
                      'Please try going back in your browser.'

        if cherrypy.request.method == 'POST':
            message = check(app, prereg=True)
            if not message:
                session.add(app)
                session.commit(
                )  # Make sure we update the DB or the email will be wrong!
                send_email.delay(
                    c.MARKETPLACE_APP_EMAIL,
                    app.email,
                    'Marketplace Application Updated',
                    render('emails/marketplace/appchange_notification.html',
                           {'app': app},
                           encoding=None),
                    'html',
                    model=app.to_dict('id'))
                raise HTTPRedirect('..{}?id={}&message={}', return_to, app.id,
                                   'Your application has been updated')
            else:
                session.rollback()

        return {
            'message': message,
            'app': app,
            'return_to': 'edit',
        }
Example #14
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)
Example #15
0
def stripe_form(action, charge):
    payment_id = uuid4().hex
    cherrypy.session[payment_id] = charge.to_dict()

    email = None
    if charge.models and charge.models[0].email:
        email = charge.models[0].email[:255]

    if not charge.models:
        if c.AT_THE_CON:
            regtext = 'On-Site Charge'
        else:
            regtext = 'Charge'
    elif c.AT_THE_CON:
        regtext = 'Registration'
    else:
        regtext = 'Preregistration'

    params = {
        'action': action,
        'regtext': regtext,
        'email': email,
        'payment_id': payment_id,
        'charge': charge
    }

    return safe_string(render('preregistration/stripeForm.html', params).decode('utf-8'))
    def pay_for_extra_members(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        group_badge_price = c.DEALER_BADGE_PRICE if group.tables else c.GROUP_PRICE
        badges_to_add = charge.dollar_amount // group_badge_price
        if charge.dollar_amount % group_badge_price:
            message = 'Our preregistration price has gone up since you tried to add the badges; please try again'
        else:
            message = charge.charge_cc(session, stripeToken)

        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id, message)
        else:
            session.assign_badges(group, group.badges + badges_to_add)
            group.amount_paid_override += charge.dollar_amount
            session.add(session.create_receipt_item(
                group, charge.amount,
                "{} badge{} (${} each)".format(
                    badges_to_add,
                    "s" if badges_to_add > 1 else "",
                    group.new_badge_cost), charge.stripe_transaction, c.BADGE),
            )
            session.merge(group)
            if group.is_dealer:
                send_email.delay(
                    c.MARKETPLACE_EMAIL,
                    c.MARKETPLACE_EMAIL,
                    '{} Paid for Extra Members'.format(c.DEALER_TERM.title()),
                    render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None),
                    model=group.to_dict('id'))
            raise HTTPRedirect(
                'group_members?id={}&message={}',
                group.id,
                'You payment has been accepted and the badges have been added to your group')
Example #17
0
    def pay_for_extra_members(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        group_badge_price = c.DEALER_BADGE_PRICE if group.tables else c.GROUP_PRICE
        badges_to_add = charge.dollar_amount // group_badge_price
        if charge.dollar_amount % group_badge_price:
            message = 'Our preregistration price has gone up since you tried to add the badges; please try again'
        else:
            message = charge.charge_cc(session, stripeToken)

        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id, message)
        else:
            session.assign_badges(group, group.badges + badges_to_add)
            group.amount_paid += charge.dollar_amount
            session.merge(group)
            if group.is_dealer:
                send_email.delay(
                    c.MARKETPLACE_EMAIL,
                    c.MARKETPLACE_EMAIL,
                    'Dealer Paid for Extra Members',
                    render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None),
                    model=group.to_dict('id'))
            raise HTTPRedirect(
                'group_members?id={}&message={}',
                group.id,
                'You payment has been accepted and the badges have been added to your group')
    def pay_for_extra_members(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        badges_to_add = charge.dollar_amount // c.GROUP_PRICE
        if charge.dollar_amount % c.GROUP_PRICE:
            message = 'Our preregistration price has gone up since you tried to add the badges; please try again'
        else:
            message = charge.charge_cc(session, stripeToken)

        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               message)
        else:
            session.assign_badges(group, group.badges + badges_to_add)
            group.amount_paid += charge.dollar_amount
            session.merge(group)
            if group.is_dealer:
                send_email.delay(
                    c.MARKETPLACE_EMAIL,
                    c.MARKETPLACE_EMAIL,
                    'Dealer Paid for Extra Members',
                    render('emails/dealers/payment_notification.txt',
                           {'group': group},
                           encoding=None),
                    model=group.to_dict('id'))
            raise HTTPRedirect(
                'group_members?id={}&message={}', group.id,
                'You payment has been accepted and the badges have been added to your group'
            )
Example #19
0
    def reset(self, session, message='', email=None):
        if email is not None:
            try:
                account = session.get_account_by_email(email)
            except NoResultFound:
                message = 'No account exists for email address {!r}'.format(
                    email)
            else:
                password = genpasswd()
                if account.password_reset:
                    session.delete(account.password_reset)
                    session.commit()
                session.add(
                    PasswordReset(admin_account=account,
                                  hashed=bcrypt.hashpw(password,
                                                       bcrypt.gensalt())))
                body = render('emails/accounts/password_reset.txt', {
                    'name': account.attendee.full_name,
                    'password': password
                },
                              encoding=None)

                send_email.delay(c.ADMIN_EMAIL,
                                 account.attendee.email,
                                 c.EVENT_NAME + ' Admin Password Reset',
                                 body,
                                 model=account.attendee.to_dict('id'))
                raise HTTPRedirect(
                    'login?message={}',
                    'Your new password has been emailed to you')

        return {'email': email, 'message': message}
Example #20
0
    def email_promo_code(self, session, group_id, message='', **params):
        if cherrypy.request.method == 'POST':
            code = session.lookup_promo_or_group_code(params.get('code'))
            if not code:
                message = "This code is invalid. If it has not been claimed, please contact us at {}".format(
                    c.REGDESK_EMAIL)
            elif not params.get('email'):
                message = "Please enter an email address"
            else:
                try:
                    validate_email(params.get('email'))
                except EmailNotValidError as e:
                    message = str(e)
                    message = 'Enter a valid email address. ' + message

            if not message:
                send_email.delay(
                    c.REGDESK_EMAIL,
                    params.get('email'),
                    'Claim a {} badge in "{}"'.format(c.EVENT_NAME, code.group.name),
                    render('emails/reg_workflow/promo_code_invite.txt', {'code': code}, encoding=None),
                    model=code.to_dict('id'))
                raise HTTPRedirect('group_promo_codes?id={}&message={}'.format(group_id, "Email sent!"))
            else:
                raise HTTPRedirect('group_promo_codes?id={}&message={}'.format(group_id, message))
    def unset_group_member(self, session, id):
        attendee = session.attendee(id)
        try:
            send_email.delay(
                c.REGDESK_EMAIL,
                attendee.email,
                '{} group registration dropped'.format(c.EVENT_NAME),
                render('emails/reg_workflow/group_member_dropped.txt', {'attendee': attendee}, encoding=None),
                model=attendee.to_dict('id'))
        except Exception:
            log.error('unable to send group unset email', exc_info=True)

        session.assign_badges(
            attendee.group,
            attendee.group.badges + 1,
            new_badge_type=attendee.badge_type,
            new_ribbon_type=attendee.ribbon,
            registered=attendee.registered,
            paid=attendee.paid)

        session.delete_from_group(attendee, attendee.group)
        raise HTTPRedirect(
            'group_members?id={}&message={}',
            attendee.group_id,
            'Attendee unset; you may now assign their badge to someone else')
    def email_promo_code(self, session, group_id, message='', **params):
        if cherrypy.request.method == 'POST':
            code = session.lookup_promo_or_group_code(params.get('code'))
            if not code:
                message = "This code is invalid. If it has not been claimed, please contact us at {}".format(
                    c.REGDESK_EMAIL)
            elif not params.get('email'):
                message = "Please enter an email address"
            else:
                try:
                    validate_email(params.get('email'))
                except EmailNotValidError as e:
                    message = str(e)
                    message = 'Enter a valid email address. ' + message

            if not message:
                send_email.delay(
                    c.REGDESK_EMAIL,
                    params.get('email'),
                    'Claim a {} badge in "{}"'.format(c.EVENT_NAME, code.group.name),
                    render('emails/reg_workflow/promo_code_invite.txt', {'code': code}, encoding=None),
                    model=code.to_dict('id'))
                raise HTTPRedirect('group_promo_codes?id={}&message={}'.format(group_id, "Email sent!"))
            else:
                raise HTTPRedirect('group_promo_codes?id={}&message={}'.format(group_id, message))
Example #23
0
def notify_admins_of_pending_emails():
    """
    Generate and email a report which alerts admins that there are automated
    emails which are ready to send, but can't be sent until they are approved
    by an admin.

    This is important so we don't forget to let certain automated emails send.
    """
    if not c.ENABLE_PENDING_EMAILS_REPORT or not c.PRE_CON or not (c.DEV_BOX or c.SEND_EMAILS):
        return None

    with Session() as session:
        pending_emails = session.query(AutomatedEmail).filter(*AutomatedEmail.filters_for_pending).all()
        pending_emails_by_sender = groupify(pending_emails, ['sender', 'ident'])

        for sender, emails_by_ident in pending_emails_by_sender.items():
            if sender == c.STAFF_EMAIL:
                # STOPS receives a report on ALL the pending emails.
                emails_by_sender = pending_emails_by_sender
            else:
                emails_by_sender = {sender: emails_by_ident}

            subject = '{} Pending Emails Report for {}'.format(c.EVENT_NAME, utils.localized_now().strftime('%Y-%m-%d'))
            body = render('emails/daily_checks/pending_emails.html', {
                'pending_emails_by_sender': emails_by_sender,
                'primary_sender': sender,
            })
            send_email(c.STAFF_EMAIL, sender, subject, body, format='html', model='n/a', session=session)

        return groupify(pending_emails, 'sender', 'ident')
Example #24
0
def stripe_form(action, charge):
    payment_id = uuid4().hex
    cherrypy.session[payment_id] = charge.to_dict()

    email = None
    if charge.models and charge.models[0].email:
        email = charge.models[0].email[:255]

    if not charge.models:
        if c.AT_THE_CON:
            regtext = 'On-Site Charge'
        else:
            regtext = 'Charge'
    elif c.AT_THE_CON:
        regtext = 'Registration'
    else:
        regtext = 'Preregistration'

    params = {
        'action': action,
        'regtext': regtext,
        'email': email,
        'payment_id': payment_id,
        'charge': charge
    }

    return safe_string(
        render('preregistration/stripeForm.html', params).decode('utf-8'))
    def process_group_payment(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        message = charge.charge_cc(session, stripeToken)
        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               message)
        else:
            group.amount_paid += charge.dollar_amount

            session.merge(group)
            if group.is_dealer:
                try:
                    send_email.delay(
                        c.MARKETPLACE_EMAIL,
                        c.MARKETPLACE_EMAIL,
                        'Dealer Payment Completed',
                        render('emails/dealers/payment_notification.txt',
                               {'group': group},
                               encoding=None),
                        model=group.to_dict('id'))
                except Exception:
                    log.error(
                        'unable to send dealer payment confirmation email',
                        exc_info=True)
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               'Your payment has been accepted!')
Example #26
0
    def schedule_tsv(self, session):
        cherrypy.response.headers['Content-Type'] = 'text/tsv'
        cherrypy.response.headers[
            'Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format(
                int(localized_now().timestamp()))

        schedule = defaultdict(list)
        for event in session.query(Event).order_by('start_time').all():
            schedule[event.location_label].append(
                dict(
                    event.to_dict(), **{
                        'date':
                        event.start_time_local.strftime('%m/%d/%Y'),
                        'start_time':
                        event.start_time_local.strftime('%I:%M:%S %p'),
                        'end_time': (event.start_time_local + timedelta(
                            minutes=event.minutes)).strftime('%I:%M:%S %p'),
                        'description':
                        normalize_newlines(event.description).replace(
                            '\n', ' ')
                    }))

        return render(
            'schedule/schedule.tsv', {
                'schedule':
                sorted(schedule.items(),
                       key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0][
                           'location']))
            })
    def check_if_preregistered(self, session, message='', **params):
        if 'email' in params:
            attendee = session.query(Attendee).filter(
                func.lower(Attendee.email) == func.lower(
                    params['email'])).first()
            message = 'Thank you! You will receive a confirmation email if ' \
                'you are registered for {}.'.format(c.EVENT_NAME_AND_YEAR)

            subject = c.EVENT_NAME_AND_YEAR + ' Registration Confirmation'

            if attendee:
                last_email = (session.query(Email).filter_by(
                    to=attendee.email,
                    subject=subject).order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (localized_now() -
                                                        timedelta(days=7)):
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt',
                               {'attendee': attendee},
                               encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}
Example #28
0
    def unset_group_member(self, session, id):
        attendee = session.attendee(id)
        try:
            send_email.delay(
                c.REGDESK_EMAIL,
                attendee.email,
                '{} group registration dropped'.format(c.EVENT_NAME),
                render('emails/reg_workflow/group_member_dropped.txt', {'attendee': attendee}, encoding=None),
                model=attendee.to_dict('id'))
        except Exception:
            log.error('unable to send group unset email', exc_info=True)

        session.assign_badges(
            attendee.group,
            attendee.group.badges + 1,
            new_badge_type=attendee.badge_type,
            new_ribbon_type=attendee.ribbon,
            registered=attendee.registered,
            paid=attendee.paid)

        session.delete_from_group(attendee, attendee.group)
        raise HTTPRedirect(
            'group_members?id={}&message={}',
            attendee.group_id,
            'Attendee unset; you may now assign their badge to someone else')
Example #29
0
    def game_review(self, session, message='', **params):
        review = session.indie_game_review(params, bools=['game_content_bad'])
        if cherrypy.request.method == 'POST':
            if review.game_status == c.PENDING:
                message = 'You must select a Game Status to tell us ' \
                    'whether or not you were able to download and run the game'
            elif review.game_status == c.PLAYABLE and not review.game_score:
                message = "You must indicate the game's readiness, design, and enjoyment"
            elif review.game_status != c.PLAYABLE and review.game_score:
                message = 'If the game is not playable, please leave the score fields blank'
            else:
                if review.game_status in c.MIVS_PROBLEM_STATUSES\
                        and review.game_status != review.orig_value_of('game_status'):
                    body = render('emails/mivs/admin_game_broken.txt',
                                  {'review': review},
                                  encoding=None)
                    send_email.delay(c.MIVS_EMAIL, c.MIVS_EMAIL,
                                     'MIVS Game Submission Marked as Broken',
                                     body)
                raise HTTPRedirect('index?message={}{}', review.game.title,
                                   ' game review has been uploaded')

        return {
            'review': review,
            'message': message,
            'game_code': session.code_for(review.game)
        }
Example #30
0
def check_duplicate_registrations():
    """
    This function looks through registered attendees for attendees with the
    same names and email addresses. It first deletes any unpaid duplicates,
    then sets paid duplicates from "Completed" to "New" and sends an email to
    the registration email address. This allows us to see new duplicate
    attendees without repetitive emails.
    """
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        subject = c.EVENT_NAME + ' Duplicates Report for ' + localized_now().strftime('%Y-%m-%d')
        with Session() as session:
            if session.no_email(subject):
                grouped = defaultdict(list)
                for a in session.query(Attendee).filter(Attendee.first_name != '') \
                        .filter(Attendee.badge_status == c.COMPLETED_STATUS).options(joinedload(Attendee.group)) \
                        .order_by(Attendee.registered):
                    if not a.group or a.group.status not in [c.WAITLISTED, c.UNAPPROVED]:
                        grouped[a.full_name, a.email.lower()].append(a)

                dupes = {k: v for k, v in grouped.items() if len(v) > 1}

                for who, attendees in dupes.items():
                    paid = [a for a in attendees if a.paid == c.HAS_PAID]
                    unpaid = [a for a in attendees if a.paid == c.NOT_PAID]
                    if len(paid) == 1 and len(attendees) == 1 + len(unpaid):
                        for a in unpaid:
                            session.delete(a)
                        del dupes[who]
                    for a in paid:
                        a.badge_status = c.NEW_STATUS

                if dupes:
                    body = render('emails/daily_checks/duplicates.html', {'dupes': sorted(dupes.items())})
                    send_email(c.ADMIN_EMAIL, c.REGDESK_EMAIL, subject, body, format='html', model='n/a')
Example #31
0
def stripe_form(action, model=None, **params):
    new_params = {'params': {}}
    for key, val in params.items():
        new_params['params'][key] = val
    new_params['action'] = action
    new_params['id'] = model.id if model else None

    return safe_string(render('preregistration/stripeForm.html', new_params).decode('utf-8'))
Example #32
0
 def index(self, session, message=''):
     if c.UBER_SHUT_DOWN or c.AT_THE_CON:
         return render('signups/printable.html', {'attendee': session.logged_in_volunteer()})
     else:
         return {
             'message': message,
             'attendee': session.logged_in_volunteer()
         }
Example #33
0
 def xml(self, session):
     cherrypy.response.headers['Content-type'] = 'text/xml'
     schedule = defaultdict(list)
     for event in session.query(Event).order_by('start_time').all():
         schedule[event.location_label].append(event)
     return render('schedule/schedule.xml', {
         'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0].location))
     })
Example #34
0
def check_near_cap():
    actual_badges_left = c.ATTENDEE_BADGE_STOCK - c.ATTENDEE_BADGE_COUNT
    for badges_left in [int(num) for num in c.BADGES_LEFT_ALERTS]:
        subject = "BADGES SOLD ALERT: {} BADGES LEFT!".format(badges_left)
        with Session() as session:
            if not session.query(Email).filter_by(subject=subject).first() and actual_badges_left <= badges_left:
                body = render('emails/badges_sold_alert.txt', {'badges_left': actual_badges_left})
                send_email(c.ADMIN_EMAIL, [c.REGDESK_EMAIL, c.ADMIN_EMAIL], subject, body, model='n/a')
Example #35
0
 def xml(self, session):
     cherrypy.response.headers['Content-type'] = 'text/xml'
     schedule = defaultdict(list)
     for event in session.query(Event).order_by('start_time').all():
         schedule[event.location_label].append(event)
     return render('schedule/schedule.xml', {
         'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0].location))
     })
Example #36
0
def check_unassigned_volunteers():
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        with Session() as session:
            unassigned = session.query(Attendee).filter(
                Attendee.staffing == True,
                not_(Attendee.dept_memberships.any())).order_by(Attendee.full_name).all()  # noqa: E712
            subject = c.EVENT_NAME + ' Unassigned Volunteer Report for ' + localized_now().strftime('%Y-%m-%d')
            if unassigned and session.no_email(subject):
                body = render('emails/daily_checks/unassigned.html', {'unassigned': unassigned})
                send_email(c.STAFF_EMAIL, c.STAFF_EMAIL, subject, body, format='html', model='n/a')
    def transfer_badge(self, session, message='', **params):
        old = session.attendee(params['id'])

        assert old.is_transferable, 'This badge is not transferrable.'
        session.expunge(old)
        attendee = session.attendee(params, restricted=True)

        if 'first_name' in params:
            message = check(attendee, prereg=True)
            if (old.first_name == attendee.first_name and old.last_name == attendee.last_name) \
                    or (old.legal_name and old.legal_name == attendee.legal_name):
                message = 'You cannot transfer your badge to yourself.'
            elif not message and (not params['first_name']
                                  and not params['last_name']):
                message = check(attendee, prereg=True)
            if not message and (not params['first_name']
                                and not params['last_name']):
                message = 'First and Last names are required.'

            if not message:
                subject = c.EVENT_NAME + ' Registration Transferred'
                body = render('emails/reg_workflow/badge_transfer.txt', {
                    'new': attendee,
                    'old': old
                },
                              encoding=None)

                try:
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        [old.email, attendee.email, c.REGDESK_EMAIL],
                        subject,
                        body,
                        model=attendee.to_dict('id'))
                except Exception:
                    log.error('unable to send badge change email',
                              exc_info=True)

                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}',
                                       attendee.id)
                else:
                    raise HTTPRedirect(
                        'badge_updated?id={}&message={}', attendee.id,
                        'Your registration has been transferred')
        else:
            for attr in c.UNTRANSFERABLE_ATTRS:
                setattr(attendee, attr, getattr(Attendee(), attr))

        return {
            'old': old,
            'attendee': attendee,
            'message': message,
            'affiliates': session.affiliates()
        }
Example #38
0
    def default(self, *path_args, **kwargs):
        content_filename = self.get_filename_from_path_args(path_args)

        template_name = self.get_full_path_from_path_args(path_args)
        try:
            content = render(template_name)
        except jinja2.exceptions.TemplateNotFound as e:
            self.raise_not_found(template_name, e)

        guessed_content_type = mimetypes.guess_type(content_filename)[0]
        return cherrypy.lib.static.serve_fileobj(content, name=content_filename, content_type=guessed_content_type)
Example #39
0
    def default(self, *path_args, **kwargs):
        content_filename = self.get_filename_from_path_args(path_args)

        template_name = self.get_full_path_from_path_args(path_args)
        try:
            content = render(template_name)
        except jinja2.exceptions.TemplateNotFound as e:
            self.raise_not_found(template_name, e)

        guessed_content_type = mimetypes.guess_type(content_filename)[0]
        return cherrypy.lib.static.serve_fileobj(content, name=content_filename, content_type=guessed_content_type)
Example #40
0
    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
        }
Example #41
0
 def invalid_notification(self):
     if self.staffing and self.badge_status == c.INVALID_STATUS \
             and self.badge_status != self.orig_value_of('badge_status'):
         try:
             send_email.delay(
                 c.STAFF_EMAIL,
                 c.STAFF_EMAIL,
                 'Volunteer invalidated',
                 render('emails/invalidated_volunteer.txt', {'attendee': self}, encoding=None),
                 model=self.to_dict('id'))
         except Exception:
             log.error('unable to send invalid email', exc_info=True)
Example #42
0
 def reset_problems(self, session, game_id):
     game = session.indie_game(game_id)
     for review in game.reviews:
         if review.has_video_issues:
             body = render('emails/mivs/video_fixed.txt', {'review': review}, encoding=None)
             send_email.delay(
                 c.MIVS_EMAIL,
                 review.judge.email,
                 'MIVS: Video Problems Resolved for {}'.format(review.game.title),
                 body,
                 model=review.judge.to_dict('id'))
             review.video_status = c.PENDING
         if review.has_game_issues:
             body = render('emails/mivs/game_fixed.txt', {'review': review}, encoding=None)
             send_email.delay(
                 c.MIVS_EMAIL,
                 review.judge.email,
                 'MIVS: Game Problems Resolved for {}'.format(review.game.title),
                 body,
                 model=review.judge.to_dict('id'))
             review.game_status = c.PENDING
     raise HTTPRedirect(
         'index?message={}{}', review.game.title, ' has been marked as having its judging issues fixed')
Example #43
0
    def schedule_tsv(self, session):
        cherrypy.response.headers['Content-Type'] = 'text/tsv'
        cherrypy.response.headers['Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format(
            int(localized_now().timestamp()))

        schedule = defaultdict(list)
        for event in session.query(Event).order_by('start_time').all():
            schedule[event.location_label].append(dict(event.to_dict(), **{
                'date': event.start_time_local.strftime('%m/%d/%Y'),
                'start_time': event.start_time_local.strftime('%I:%M:%S %p'),
                'end_time': (event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'),
                'description': normalize_newlines(event.description).replace('\n', ' ')
            }))

        return render('schedule/schedule.tsv', {
            'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0]['location']))
        })
Example #44
0
    def transfer_badge(self, session, message='', **params):
        old = session.attendee(params['id'])

        assert old.is_transferable, 'This badge is not transferrable.'
        session.expunge(old)
        attendee = session.attendee(params, restricted=True)

        if 'first_name' in params:
            message = check(attendee, prereg=True)
            if (old.first_name == attendee.first_name and old.last_name == attendee.last_name) \
                    or (old.legal_name and old.legal_name == attendee.legal_name):
                message = 'You cannot transfer your badge to yourself.'
            elif not message and (not params['first_name'] and not params['last_name']):
                message = check(attendee, prereg=True)
            if not message and (not params['first_name'] and not params['last_name']):
                message = 'First and Last names are required.'

            if not message:
                subject = c.EVENT_NAME + ' Registration Transferred'
                body = render('emails/reg_workflow/badge_transfer.txt', {'new': attendee, 'old': old}, encoding=None)

                try:
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        [old.email, attendee.email, c.REGDESK_EMAIL],
                        subject,
                        body,
                        model=attendee.to_dict('id'))
                except Exception:
                    log.error('unable to send badge change email', exc_info=True)

                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}', attendee.id)
                else:
                    raise HTTPRedirect(
                        'badge_updated?id={}&message={}', attendee.id, 'Your registration has been transferred')
        else:
            for attr in c.UNTRANSFERABLE_ATTRS:
                setattr(attendee, attr, getattr(Attendee(), attr))

        return {
            'old':      old,
            'attendee': attendee,
            'message':  message,
            'affiliates': session.affiliates()
        }
Example #45
0
    def video_review(self, session, message='', **params):
        review = session.indie_game_review(params)
        if cherrypy.request.method == 'POST':
            if review.video_status == c.PENDING:
                message = 'You must select a Video Status to tell us whether or not you were able to view the video'
            elif review.video_status == c.VIDEO_REVIEWED and review.video_score == c.PENDING:
                message = 'You must indicate whether or not you believe the game should pass to round 2'
            else:
                if review.video_status in c.MIVS_PROBLEM_STATUSES\
                        and review.video_status != review.orig_value_of('video_status'):
                    body = render('emails/mivs/admin_video_broken.txt', {'review': review}, encoding=None)
                    send_email.delay(c.MIVS_EMAIL, c.MIVS_EMAIL, 'MIVS Video Submission Marked as Broken', body)
                raise HTTPRedirect('index?message={}{}', review.game.title, ' video review has been uploaded')

        return {
            'message': message,
            'review': review
        }
Example #46
0
    def check_if_applied(self, session, message='', **params):
        if cherrypy.request.method == 'POST':
            subject = c.EVENT_NAME_AND_YEAR + ' MITS Team Confirmation'

            if 'email' not in params:
                message = "Please enter an email address."

            if not message:
                last_email = (session.query(Email)
                              .filter(Email.to.ilike(params['email']))
                              .filter_by(subject=subject)
                              .order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (
                            localized_now() - timedelta(days=7)):
                    can_send_email = True
                else:
                    can_send_email = False

                mits_teams = session.query(MITSTeam).all()

                match_counter = 0
                for team in mits_teams:
                    if params['email'] in team.email:
                        match_counter += 1

                        if can_send_email:
                            send_email.delay(
                                c.MITS_EMAIL,
                                params['email'],
                                subject,
                                render('emails/mits/mits_check.txt',
                                       {'team': team}, encoding=None),
                                cc=team.email,
                                model=team.to_dict('id'))

                if match_counter:
                    message = 'We found {} team{}.{}'\
                        .format(match_counter, 's' if match_counter > 1 else '',
                                ' Please check your email for a link to your application.'
                                if can_send_email else ' Please check your spam or junk folder.')

        return {'message': message}
Example #47
0
    def check_if_preregistered(self, session, message='', **params):
        if 'email' in params:
            attendee = session.query(Attendee).filter(func.lower(Attendee.email) == func.lower(params['email'])).first()
            message = 'Thank you! You will receive a confirmation email if ' \
                'you are registered for {}.'.format(c.EVENT_NAME_AND_YEAR)

            subject = c.EVENT_NAME_AND_YEAR + ' Registration Confirmation'

            if attendee:
                last_email = (session.query(Email)
                                     .filter_by(to=attendee.email, subject=subject)
                                     .order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (localized_now() - timedelta(days=7)):
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt', {'attendee': attendee}, encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}
Example #48
0
    def process_group_payment(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        message = charge.charge_cc(session, stripeToken)
        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id, message)
        else:
            group.amount_paid += charge.dollar_amount

            session.merge(group)
            if group.is_dealer:
                try:
                    send_email.delay(
                        c.MARKETPLACE_EMAIL,
                        c.MARKETPLACE_EMAIL,
                        'Dealer Payment Completed',
                        render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None),
                        model=group.to_dict('id'))
                except Exception:
                    log.error('unable to send dealer payment confirmation email', exc_info=True)
            raise HTTPRedirect('group_members?id={}&message={}', group.id, 'Your payment has been accepted!')
Example #49
0
    def game_review(self, session, message='', **params):
        review = session.indie_game_review(params, bools=['game_content_bad'])
        if cherrypy.request.method == 'POST':
            if review.game_status == c.PENDING:
                message = 'You must select a Game Status to tell us ' \
                    'whether or not you were able to download and run the game'
            elif review.game_status == c.PLAYABLE and not review.game_score:
                message = "You must indicate the game's readiness, design, and enjoyment"
            elif review.game_status != c.PLAYABLE and review.game_score:
                message = 'If the game is not playable, please leave the score fields blank'
            else:
                if review.game_status in c.MIVS_PROBLEM_STATUSES\
                        and review.game_status != review.orig_value_of('game_status'):
                    body = render('emails/mivs/admin_game_broken.txt', {'review': review}, encoding=None)
                    send_email.delay(c.MIVS_EMAIL, c.MIVS_EMAIL, 'MIVS Game Submission Marked as Broken', body)
                raise HTTPRedirect('index?message={}{}', review.game.title, ' game review has been uploaded')

        return {
            'review': review,
            'message': message,
            'game_code': session.code_for(review.game)
        }
Example #50
0
    def group_members(self, session, id, message='', **params):
        group = session.group(id)
        charge = Charge(group)
        if cherrypy.request.method == 'POST':
            # 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), '')

            group.apply(group_params, restricted=True)
            message = check(group, prereg=True)
            if message:
                session.rollback()
            else:
                session.commit()
                if group.is_dealer:
                    send_email.delay(
                        c.MARKETPLACE_EMAIL,
                        c.MARKETPLACE_EMAIL,
                        'Dealer Application Changed',
                        render('emails/dealers/appchange_notification.html', {'group': group}, encoding=None),
                        'html',
                        model=group.to_dict('id'))

                message = 'Thank you! Your application has been updated.'

            raise HTTPRedirect('group_members?id={}&message={}', group.id, message)
        return {
            'group':   group,
            'upgraded_badges': len([a for a in group.attendees if a.badge_type in c.BADGE_TYPE_PRICES]),
            'charge':  charge,
            'message': message
        }
Example #51
0
    def allotments(self, session, department_id=None, submitted=None, csrf_token=None, **params):
        if not department_id:
            raise HTTPRedirect('../dept_checklist/index')
        attendee = session.admin_attendee()
        department = session.query(Department).options(
            subqueryload(Department.dept_checklist_items)).get(department_id)

        if submitted:
            slug = 'allotments'
            item = department.checklist_item_for_slug(slug)
            if not item:
                item = DeptChecklistItem(attendee=attendee, department=department, slug=slug)

            # since this form doesn't use our normal utility methods, we need to do this manually
            check_csrf(csrf_token)
            item.comments = render('dept_checklist/allotments.txt', params).decode('utf-8')
            session.add(item)
            raise HTTPRedirect(
                '../dept_checklist/index?department_id={}&message={}',
                department_id,
                'Treasury checklist data uploaded')

        return {'department': department}
Example #52
0
    def add_bulk_admin_accounts(self, session, message='', **params):
        ids = params.get('ids')
        if isinstance(ids, str):
            ids = str(ids).split(",")
        success_count = 0
        for id in ids:
            try:
                uuid.UUID(id)
            except ValueError:
                pass
            else:
                match = session.query(Attendee).filter(Attendee.id == id).first()
                if match:
                    account = session.admin_account(params, checkgroups=['access'])
                    if account.is_new:
                        password = genpasswd()
                        account.hashed = bcrypt.hashpw(password, bcrypt.gensalt())
                        account.attendee = match
                        session.add(account)
                        body = render('emails/accounts/new_account.txt', {
                            'account': account,
                            'password': password
                        }, encoding=None)
                        send_email.delay(
                            c.ADMIN_EMAIL,
                            match.email,
                            'New ' + c.EVENT_NAME + ' Ubersystem Account',
                            body,
                            model=match.to_dict('id'))

                        success_count += 1
        if success_count == 0:
            message = 'No new accounts were created.'
        else:
            session.commit()
            message = '%d new accounts have been created, and emailed their passwords.' % success_count
        return message
Example #53
0
def attractions_send_notifications():
    twilio_client = get_twilio_client(c.PANELS_TWILIO_SID, c.PANELS_TWILIO_TOKEN)

    with Session() as session:
        for attraction in session.query(Attraction):
            now = datetime.now(pytz.UTC)
            from_time = now - timedelta(seconds=300)
            to_time = now + timedelta(seconds=300)
            signups = attraction.signups_requiring_notification(session, from_time, to_time, [
                subqueryload(
                    AttractionSignup.attendee).subqueryload(
                        Attendee.attraction_notifications),
                subqueryload(
                    AttractionSignup.event).subqueryload(
                        AttractionEvent.feature)])

            for signup, advance_notices in signups.items():
                attendee = signup.attendee
                if not attendee.first_name or not attendee.email:
                    try:
                        log.error(
                            'ERROR: Unassigned attendee signed up for an attraction, deleting signup:\n'
                            '\tAttendee.id: {}\n'
                            '\tAttraction.id: {}\n'
                            '\tAttractionEvent.id: {}\n'
                            '\tAttractionSignup.id: {}'.format(
                                attendee.id,
                                signup.attraction_id,
                                signup.attraction_event_id,
                                signup.id))

                        session.delete(signup)
                        session.commit()
                    except Exception:
                        log.error('ERROR: Failed to delete signup with unassigned attendee', exc_info=True)
                    continue

                # The first time someone signs up for an attractions, they always
                # receive the welcome email (even if they've chosen SMS or None
                # for their notification prefs). If they've chosen to receive SMS
                # notifications, they'll also get a text message.
                is_first_signup = not(attendee.attraction_notifications)

                if not is_first_signup and attendee.notification_pref == Attendee._NOTIFICATION_NONE:
                    continue

                use_text = twilio_client \
                    and c.PANELS_TWILIO_NUMBER \
                    and attendee.cellphone \
                    and attendee.notification_pref == Attendee._NOTIFICATION_TEXT

                event = signup.event

                # If we overlap multiple notices, we only want to send a single
                # notification. So if we have both "5 minutes before checkin" and
                # "when checkin starts", we only want to send the notification
                # for "when checkin starts".
                advance_notice = min(advance_notices)
                if advance_notice == -1 or advance_notice > 1800:
                    checkin = 'is at {}'.format(event.checkin_start_time_label)
                else:
                    checkin = humanize_timedelta(
                        event.time_remaining_to_checkin,
                        granularity='minutes',
                        separator=' ',
                        prefix='is in ',
                        now='is right now',
                        past_prefix='was ',
                        past_suffix=' ago')

                ident = AttractionEvent.get_ident(event.id, advance_notice)
                try:
                    if use_text:
                        type_ = Attendee._NOTIFICATION_TEXT
                        type_str = 'TEXT'
                        from_ = c.PANELS_TWILIO_NUMBER
                        to_ = attendee.cellphone
                        body = TEXT_TEMPLATE.format(signup=signup, checkin=checkin)
                        subject = ''
                        sid = send_sms_with_client(twilio_client, to_, body, from_)

                    if not use_text or is_first_signup:
                        type_ = Attendee._NOTIFICATION_EMAIL
                        type_str = 'EMAIL'
                        from_ = c.ATTRACTIONS_EMAIL
                        to_ = attendee.email
                        if is_first_signup:
                            template = 'emails/panels/attractions_welcome.html'
                            subject = 'Welcome to {} Attractions'.format(c.EVENT_NAME)
                        else:
                            template = 'emails/panels/attractions_notification.html'
                            subject = 'Checkin for {} is at {}'.format(event.name, event.checkin_start_time_label)

                        body = render(template, {
                            'signup': signup,
                            'checkin': checkin,
                            'c': c}).decode('utf-8')
                        sid = ident
                        send_email(from_, to_, subject=subject, body=body, format='html', model=attendee, ident=ident)
                except Exception:
                    log.error(
                        'Error sending notification\n'
                        '\tfrom: {}\n'
                        '\tto: {}\n'
                        '\tsubject: {}\n'
                        '\tbody: {}\n'
                        '\ttype: {}\n'
                        '\tattendee: {}\n'
                        '\tident: {}\n'.format(
                            from_,
                            to_,
                            subject,
                            body,
                            type_str,
                            attendee.id,
                            ident), exc_info=True)
                else:
                    session.add(AttractionNotification(
                        attraction_event_id=event.id,
                        attraction_id=event.attraction_id,
                        attendee_id=attendee.id,
                        notification_type=type_,
                        ident=ident,
                        sid=sid,
                        sent_time=datetime.now(pytz.UTC),
                        subject=subject,
                        body=body))
                    session.commit()
Example #54
0
def _decline_and_convert_dealer_group(session, group, status=c.DECLINED):
    """
    Deletes the waitlisted dealer group and converts all of the group members
    to the appropriate badge type. Unassigned, unpaid badges will be deleted.
    """
    admin_note = 'Converted badge from waitlisted dealer group "{}".'.format(group.name)
    group.status = status

    if not group.is_unpaid:
        group.tables = 0
        for attendee in group.attendees:
            attendee.append_admin_note(admin_note)
            attendee.ribbon = remove_opt(attendee.ribbon_ints, c.DEALER_RIBBON)
        return 'Group dealer status removed'

    message = ['Group declined']
    emails_failed = 0
    emails_sent = 0
    badges_converted = 0

    for attendee in list(group.attendees):
        if _is_dealer_convertible(attendee):
            attendee.badge_status = c.INVALID_STATUS

            if not attendee.is_unassigned:
                new_attendee = Attendee()
                for attr in c.UNTRANSFERABLE_ATTRS:
                    setattr(new_attendee, attr, getattr(attendee, attr))
                new_attendee.overridden_price = attendee.overridden_price
                new_attendee.base_badge_price = attendee.base_badge_price
                new_attendee.append_admin_note(admin_note)
                session.add(new_attendee)

                try:
                    send_email.delay(
                        c.MARKETPLACE_EMAIL,
                        new_attendee.email,
                        'Do you still want to come to {}?'.format(c.EVENT_NAME),
                        render('emails/dealers/badge_converted.html', {
                            'attendee': new_attendee,
                            'group': group}, encoding=None),
                        format='html',
                        model=attendee.to_dict('id'))
                    emails_sent += 1
                except Exception:
                    emails_failed += 1

                badges_converted += 1
        else:
            if attendee.paid not in [c.HAS_PAID, c.NEED_NOT_PAY]:
                attendee.paid = c.NOT_PAID

            attendee.append_admin_note(admin_note)
            attendee.ribbon = remove_opt(attendee.ribbon_ints, c.DEALER_RIBBON)

    for count, template in [
            (badges_converted, '{} badge{} converted'),
            (emails_sent, '{} email{} sent'),
            (emails_failed, '{} email{} failed to send')]:

        if count > 0:
            message.append(template.format(count, pluralize(count)))

    return ', '.join(message)
Example #55
0
    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'),
        }