예제 #1
0
def printed_badge_change(attendee):
    if attendee.badge_printed_name != attendee.orig_value_of('badge_printed_name') \
            and not AdminAccount.admin_name() \
            and localized_now() > c.get_printed_badge_deadline_by_type(attendee.badge_type_real):

        return '{} badges have already been ordered, so you cannot change the badge printed name.'.format(
            attendee.badge_type_label if attendee.badge_type in c.PREASSIGNED_BADGE_TYPES else "Supporter")
예제 #2
0
    def internal(self, session, message=''):
        if c.HIDE_SCHEDULE and not AdminAccount.access_set(
        ) and not cherrypy.session.get('staffer_id'):
            return "The {} schedule is being developed and will be made public " \
                "when it's closer to being finalized.".format(c.EVENT_NAME)

        schedule = defaultdict(lambda: defaultdict(list))
        for event in session.query(Event).all():
            schedule[event.start_time_local][event.location].append(event)
            for i in range(1, event.duration):
                half_hour = event.start_time_local + timedelta(minutes=30 * i)
                schedule[half_hour][event.location].append(c.EVENT_BOOKED)

        max_simul = {}
        for id, name in c.EVENT_LOCATION_OPTS:
            max_events = 1
            for i in range(2 * c.CON_LENGTH):
                half_hour = c.EPOCH + timedelta(minutes=30 * i)
                max_events = max(max_events, len(schedule[half_hour][id]))
            max_simul[id] = max_events

        for half_hour in schedule:
            for location in schedule[half_hour]:
                for event in schedule[half_hour][location]:
                    if isinstance(event, Event):
                        simul = max(
                            len(schedule[half_hour][event.location])
                            for half_hour in event.half_hours)
                        event.colspan = 1 if simul > 1 else max_simul[
                            event.location]
                        for i in range(1, event.duration):
                            schedule[half_hour + timedelta(
                                minutes=30 * i)][event.location].remove(
                                    c.EVENT_BOOKED)
                            schedule[half_hour + timedelta(
                                minutes=30 * i)][event.location].append(
                                    event.colspan)

        for half_hour in schedule:
            for id, name in c.EVENT_LOCATION_OPTS:
                span_sum = sum(
                    getattr(e, 'colspan', e) for e in schedule[half_hour][id])
                for i in range(max_simul[id] - span_sum):
                    schedule[half_hour][id].append(c.EVENT_OPEN)

            schedule[half_hour] = sorted(
                schedule[half_hour].items(),
                key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[0]))

        max_simul = [(id, c.EVENT_LOCATIONS[id], colspan)
                     for id, colspan in max_simul.items()]
        return {
            'message':
            message,
            'schedule':
            sorted(schedule.items()),
            'max_simul':
            sorted(max_simul,
                   key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[0]))
        }
예제 #3
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)
예제 #4
0
    def test_email(self,
                   session,
                   subject=None,
                   body=None,
                   from_address=None,
                   to_address=None,
                   **params):
        """
        Testing only: send a test email as a system user
        """

        output_msg = ""

        if subject and body and from_address and to_address:
            send_email(from_address, to_address, subject, body)
            output_msg = "RAMS has attempted to send your email."

        right_now = str(datetime.now())

        return {
            'from_address':
            from_address or c.STAFF_EMAIL,
            'to_address': (to_address
                           or ("*****@*****.**" if c.DEV_BOX
                               else AdminAccount.admin_email()) or ""),
            'subject':
            c.EVENT_NAME_AND_YEAR + " test email " + right_now,
            'body':
            body or
            "ignore this email, <b>it is a test</b> of the <u>RAMS email system</u> "
            + right_now,
            'message':
            output_msg,
        }
예제 #5
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)
예제 #6
0
    def sitemap(self):
        site_sections = cherrypy.tree.apps[c.PATH].root
        modules = {
            name: getattr(site_sections, name)
            for name in dir(site_sections) if not name.startswith('_')
        }
        pages = defaultdict(list)
        access_set = AdminAccount.access_set()
        for module_name, module_root in modules.items():
            for name in dir(module_root):
                method = getattr(module_root, name)
                if getattr(method, 'exposed', False):
                    spec = inspect.getfullargspec(unwrap(method))
                    has_defaults = len([
                        arg for arg in spec.args[1:] if arg != 'session'
                    ]) == len(spec.defaults or [])
                    if set(getattr(method, 'restricted', []) or []).intersection(access_set) \
                            and not getattr(method, 'ajax', False) \
                            and (getattr(method, 'site_mappable', False)
                                 or has_defaults and not spec.varkw):

                        pages[module_name].append({
                            'name':
                            name.replace('_', ' ').title(),
                            'path':
                            '/{}/{}'.format(module_name, name)
                        })

        return {'pages': sorted(pages.items())}
예제 #7
0
    def index(self, session, message='', decline=None, **params):
        if c.AFTER_ROOM_DEADLINE and c.STAFF_ROOMS not in AdminAccount.access_set():
            raise HTTPRedirect('../signups/index?message={}', 'The room deadline has passed')
        attendee = session.logged_in_volunteer()
        if not attendee.hotel_eligible:
            raise HTTPRedirect('../signups/index?message={}', 'You have not been marked as eligible for hotel space')
        requests = session.hotel_requests(params, checkgroups=['nights'], restricted=True)
        if 'attendee_id' in params:
            requests.attendee = attendee  # foreign keys are automatically admin-only
            session.add(requests)
            if decline or not requests.nights:
                requests.nights = ''
                raise HTTPRedirect(
                    '../signups/index?message={}', "We've recorded that you've declined hotel room space")
            else:
                if requests.setup_teardown:
                    days = ' / '.join(
                        c.NIGHTS[day] for day in sorted(requests.nights_ints, key=c.NIGHT_DISPLAY_ORDER.index)
                        if day not in c.CORE_NIGHTS)

                    message = "Your hotel room request has been submitted. " \
                        "We'll let you know whether your offer to help on {} is accepted, " \
                        "and who your roommates will be, a few weeks after the deadline.".format(days)

                else:
                    message = "You've accepted hotel room space for {}. " \
                        "We'll let you know your roommates a few weeks after the " \
                        "deadline.".format(requests.nights_display)

                raise HTTPRedirect('../signups/index?message={}', message)
        else:
            requests = attendee.hotel_requests or requests
            if requests.is_new:
                requests.nights = ','.join(map(str, c.CORE_NIGHTS))

        nights = []
        two_day_before = (c.EPOCH - timedelta(days=2)).strftime('%A')
        day_before = (c.EPOCH - timedelta(days=1)).strftime('%A')
        last_day = c.ESCHATON.strftime('%A').upper()
        day_after = (c.ESCHATON + timedelta(days=1)).strftime('%A')
        nights.append([getattr(c, two_day_before.upper()), getattr(requests, two_day_before.upper()),
                       "I'd like to help set up on " + two_day_before])
        nights.append([getattr(c, day_before.upper()), getattr(requests, day_before.upper()),
                       "I'd like to help set up on " + day_before])
        for night in c.CORE_NIGHTS:
            nights.append([night, night in requests.nights_ints, c.NIGHTS[night]])
        nights.append([getattr(c, last_day), getattr(requests, last_day),
                       "I'd like to help tear down on {} / {}".format(c.ESCHATON.strftime('%A'), day_after)])

        return {
            'nights':   nights,
            'message':  message,
            'requests': requests,
            'attendee': attendee
        }
예제 #8
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
        }
예제 #9
0
    def test_check_admin_account_access_add(self, session, admin_account, admin_access, access_changes, expected):
        admin_access = ','.join(map(str, admin_access))
        access_changes = ','.join(map(str, access_changes))

        admin_account.access = admin_access
        session.commit()
        session.refresh(admin_account)

        test_attendee = Attendee(email='*****@*****.**')
        session.add(test_attendee)

        test_admin_account = AdminAccount(
            access='',
            attendee_id=test_attendee.id,
            hashed='<bcrypted>')
        session.add(test_admin_account)
        session.commit()
        session.refresh(test_admin_account)

        test_admin_account.access = access_changes
        message = check(test_admin_account)
        assert expected == message
예제 #10
0
    def index(self, session, message=''):
        # show a public-facing view of the schedule
        # anything returned here should be cache-friendly and ready to be shown to the public.

        dont_allow_schedule_to_be_viewed = \
            c.HIDE_SCHEDULE and not AdminAccount.access_set() and not cherrypy.session.get('staffer_id')

        if dont_allow_schedule_to_be_viewed:
            return "The {} schedule is being developed and will be made public " \
                   "when it's closer to being finalized.".format(c.EVENT_NAME)

        if c.ALT_SCHEDULE_URL:
            raise HTTPRedirect(c.ALT_SCHEDULE_URL)
        else:
            # external view attendees can look at with no admin menus/etc
            # we cache this view because it takes a while to generate
            return get_schedule_data(session, message)
예제 #11
0
    def index(self, session, message=''):
        # show a public-facing view of the schedule
        # anything returned here should be cache-friendly and ready to be shown to the public.

        dont_allow_schedule_to_be_viewed = \
            c.HIDE_SCHEDULE and not AdminAccount.access_set() and not cherrypy.session.get('staffer_id')

        if dont_allow_schedule_to_be_viewed:
            return "The {} schedule is being developed and will be made public " \
                   "when it's closer to being finalized.".format(c.EVENT_NAME)

        if c.ALT_SCHEDULE_URL:
            raise HTTPRedirect(c.ALT_SCHEDULE_URL)
        else:
            # external view attendees can look at with no admin menus/etc
            # we cache this view because it takes a while to generate
            return get_schedule_data(session, message)
예제 #12
0
    def sitemap(self):
        site_sections = cherrypy.tree.apps[c.CHERRYPY_MOUNT_PATH].root
        modules = {name: getattr(site_sections, name) for name in dir(site_sections) if not name.startswith('_')}
        pages = defaultdict(list)
        access_set = AdminAccount.access_set()
        for module_name, module_root in modules.items():
            for name in dir(module_root):
                method = getattr(module_root, name)
                if getattr(method, 'exposed', False):
                    spec = inspect.getfullargspec(unwrap(method))
                    has_defaults = len([arg for arg in spec.args[1:] if arg != 'session']) == len(spec.defaults or [])
                    if set(getattr(method, 'restricted', []) or []).intersection(access_set) \
                            and not getattr(method, 'ajax', False) \
                            and (getattr(method, 'site_mappable', False)
                                 or has_defaults and not spec.varkw):

                        pages[module_name].append({
                            'name': name.replace('_', ' ').title(),
                            'path': '/{}/{}'.format(module_name, name)
                        })

        return {'pages': sorted(pages.items())}
예제 #13
0
    def test_email(self, session, subject=None, body=None, from_address=None, to_address=None, **params):
        """
        Testing only: send a test email as a system user
        """

        output_msg = ""

        if subject and body and from_address and to_address:
            send_email.delay(from_address, to_address, subject, body)
            output_msg = "RAMS has attempted to send your email."

        right_now = str(datetime.now())

        return {
            'from_address': from_address or c.STAFF_EMAIL,
            'to_address': (
                to_address or
                ("*****@*****.**" if c.DEV_BOX else AdminAccount.admin_email())
                or ""),
            'subject':  c.EVENT_NAME_AND_YEAR + " test email " + right_now,
            'body': body or "ignore this email, <b>it is a test</b> of the <u>RAMS email system</u> " + right_now,
            'message': output_msg,
        }
예제 #14
0
    def index(self, session, message='', decline=None, **params):
        if c.AFTER_ROOM_DEADLINE and c.STAFF_ROOMS not in AdminAccount.access_set(
        ):
            raise HTTPRedirect('../signups/index?message={}',
                               'The room deadline has passed')
        attendee = session.logged_in_volunteer()
        if not attendee.hotel_eligible:
            raise HTTPRedirect(
                '../signups/index?message={}',
                'You have not been marked as eligible for hotel space')
        requests = session.hotel_requests(params,
                                          checkgroups=['nights'],
                                          restricted=True)
        if 'attendee_id' in params:
            requests.attendee = attendee  # foreign keys are automatically admin-only
            session.add(requests)
            if decline or not requests.nights:
                requests.nights = ''
                raise HTTPRedirect(
                    '../signups/index?message={}',
                    "We've recorded that you've declined hotel room space")
            else:
                if requests.setup_teardown:
                    days = ' / '.join(c.NIGHTS[day] for day in sorted(
                        requests.nights_ints, key=c.NIGHT_DISPLAY_ORDER.index)
                                      if day not in c.CORE_NIGHTS)

                    message = "Your hotel room request has been submitted. " \
                        "We'll let you know whether your offer to help on {} is accepted, " \
                        "and who your roommates will be, a few weeks after the deadline.".format(days)

                else:
                    message = "You've accepted hotel room space for {}. " \
                        "We'll let you know your roommates a few weeks after the " \
                        "deadline.".format(requests.nights_display)

                raise HTTPRedirect('../signups/index?message={}', message)
        else:
            requests = attendee.hotel_requests or requests
            if requests.is_new:
                requests.nights = ','.join(map(str, c.CORE_NIGHTS))

        nights = []
        two_day_before = (c.EPOCH - timedelta(days=2)).strftime('%A')
        day_before = (c.EPOCH - timedelta(days=1)).strftime('%A')
        last_day = c.ESCHATON.strftime('%A').upper()
        day_after = (c.ESCHATON + timedelta(days=1)).strftime('%A')
        nights.append([
            getattr(c, two_day_before.upper()),
            getattr(requests, two_day_before.upper()),
            "I'd like to help set up on " + two_day_before
        ])
        nights.append([
            getattr(c, day_before.upper()),
            getattr(requests, day_before.upper()),
            "I'd like to help set up on " + day_before
        ])
        for night in c.CORE_NIGHTS:
            nights.append(
                [night, night in requests.nights_ints, c.NIGHTS[night]])
        nights.append([
            getattr(c, last_day),
            getattr(requests, last_day),
            "I'd like to help tear down on {} / {}".format(
                c.ESCHATON.strftime('%A'), day_after)
        ])

        return {
            'nights': nights,
            'message': message,
            'requests': requests,
            'attendee': attendee
        }