예제 #1
0
def test_minimal_question_serializer(answer):
    with scope(event=answer.question.event):
        data = MinimalQuestionSerializer(answer.question).data
    assert set(data.keys()) == {"id", "question"}
예제 #2
0
def other_accepted_submission(other_submission):
    with scope(event=other_submission.event):
        other_submission.accept()
        return other_submission
예제 #3
0
def deleted_submission(event, submission_data, other_speaker):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.speakers.add(other_speaker)
        sub.remove(force=True)
        return sub
예제 #4
0
def answer(event, submission, question):
    with scope(event=event):
        return Answer.objects.create(answer="11",
                                     submission=submission,
                                     question=question)
예제 #5
0
def submission_type(event):
    with scope(event=event):
        return SubmissionType.objects.create(name="Workshop",
                                             event=event,
                                             default_duration=60)
예제 #6
0
def track(event):
    with scope(event=event):
        event.settings.use_tracks = True
        return Track.objects.create(name="Test Track",
                                    color="00ff00",
                                    event=event)
예제 #7
0
def access_code(event):
    with scope(event=event):
        return SubmitterAccessCode.objects.create(event=event)
예제 #8
0
 def get_form_name(self, response, event):
     with scope(event=event):
         doc = bs4.BeautifulSoup(response.rendered_content, "lxml")
     input_hidden = doc.select("input[name^=submit_wizard]")[0]
     return input_hidden['name'], input_hidden['value']
예제 #9
0
def other_resource(submission):
    f = SimpleUploadedFile('testresource2.txt', b'another resource')
    with scope(event=submission.event):
        return Resource.objects.create(submission=submission,
                                       resource=f,
                                       description='Test resource 2')
예제 #10
0
def _default_context(request):
    try:
        url = resolve(request.path_info)
    except Resolver404:
        return {}

    if not request.path.startswith(get_script_prefix() + 'control'):
        return {}
    ctx = {
        'url_name': url.url_name,
        'settings': settings,
        'django_settings': settings,
        'DEBUG': settings.DEBUG,
    }
    _html_head = []
    if hasattr(request, 'event') and request.user.is_authenticated:
        for receiver, response in html_head.send(request.event,
                                                 request=request):
            _html_head.append(response)
    ctx['html_head'] = "".join(_html_head)

    _js_payment_weekdays_disabled = '[]'
    if getattr(request, 'event', None) and hasattr(
            request, 'organizer') and request.user.is_authenticated:
        ctx['nav_items'] = get_event_navigation(request)

        if request.event.settings.get('payment_term_weekdays'):
            _js_payment_weekdays_disabled = '[0,6]'

        ctx['has_domain'] = get_event_domain(request.event,
                                             fallback=True) is not None

        if not request.event.testmode:
            with scope(organizer=request.organizer):
                complain_testmode_orders = request.event.cache.get(
                    'complain_testmode_orders')
                if complain_testmode_orders is None:
                    complain_testmode_orders = request.event.orders.filter(
                        testmode=True).exists()
                    request.event.cache.set('complain_testmode_orders',
                                            complain_testmode_orders, 30)
            ctx['complain_testmode_orders'] = complain_testmode_orders
        else:
            ctx['complain_testmode_orders'] = False

        if not request.event.live and ctx['has_domain']:
            child_sess = request.session.get('child_session_{}'.format(
                request.event.pk))
            s = SessionStore()
            if not child_sess or not s.exists(child_sess):
                s['pretix_event_access_{}'.format(
                    request.event.pk)] = request.session.session_key
                s.create()
                ctx['new_session'] = s.session_key
                request.session['child_session_{}'.format(
                    request.event.pk)] = s.session_key
                request.session['event_access'] = True
            else:
                ctx['new_session'] = child_sess
                request.session['event_access'] = True

        if request.GET.get('subevent', ''):
            # Do not use .get() for lazy evaluation
            ctx['selected_subevents'] = request.event.subevents.filter(
                pk=request.GET.get('subevent'))
    elif getattr(request, 'organizer', None) and request.user.is_authenticated:
        ctx['nav_items'] = get_organizer_navigation(request)
    elif request.user.is_authenticated:
        ctx['nav_items'] = get_global_navigation(request)

    ctx['js_payment_weekdays_disabled'] = _js_payment_weekdays_disabled

    _nav_topbar = []
    if request.user.is_authenticated:
        for receiver, response in nav_topbar.send(request, request=request):
            _nav_topbar += response
    ctx['nav_topbar'] = sorted(_nav_topbar, key=lambda n: n['label'])

    ctx['js_datetime_format'] = get_javascript_format('DATETIME_INPUT_FORMATS')
    ctx['js_date_format'] = get_javascript_format('DATE_INPUT_FORMATS')
    ctx['js_long_date_format'] = get_javascript_output_format('DATE_FORMAT')
    ctx['js_time_format'] = get_javascript_format('TIME_INPUT_FORMATS')
    ctx['js_locale'] = get_moment_locale()
    ctx['select2locale'] = get_language()[:2]

    ctx['warning_update_available'] = False
    ctx['warning_update_check_active'] = False
    gs = GlobalSettingsObject()
    ctx['global_settings'] = gs.settings
    if request.user.is_staff:
        if gs.settings.update_check_result_warning:
            ctx['warning_update_available'] = True
        if not gs.settings.update_check_ack and 'runserver' not in sys.argv:
            ctx['warning_update_check_active'] = True

    if request.user.is_authenticated:
        ctx['staff_session'] = request.user.has_active_staff_session(
            request.session.session_key)
        ctx['staff_need_to_explain'] = (
            StaffSession.objects.filter(
                user=request.user, date_end__isnull=False).filter(
                    Q(comment__isnull=True) | Q(comment=""))
            if request.user.is_staff and settings.PRETIX_ADMIN_AUDIT_COMMENTS
            else StaffSession.objects.none())

    return ctx
예제 #11
0
    def test_wizard_existing_user(
        self,
        event,
        client,
        question,
        user,
        speaker_question,
        choice_question,
        multiple_choice_question,
    ):
        with scope(event=event):
            submission_type = SubmissionType.objects.filter(
                event=event).first().pk
            answer_data = {
                f'questions-question_{question.pk}':
                '42',
                f'questions-question_{speaker_question.pk}':
                'green',
                f'questions-question_{choice_question.pk}':
                choice_question.options.first().pk,
                f'questions-question_{multiple_choice_question.pk}':
                multiple_choice_question.options.first().pk,
            }

        response, current_url = self.perform_init_wizard(client, event=event)
        response, current_url = self.perform_info_wizard(
            client,
            response,
            current_url + '?submission_type=123-helpful-slug',
            submission_type=submission_type,
            event=event,
        )
        response, current_url = self.perform_question_wizard(
            client,
            response,
            current_url,
            answer_data,
            next_step='user',
            event=event,
        )
        response, current_url = self.perform_user_wizard(
            client,
            response,
            current_url,
            email=user.email,
            password='******',
            event=event,
        )
        response, current_url = self.perform_profile_form(client,
                                                          response,
                                                          current_url,
                                                          event=event)

        doc = bs4.BeautifulSoup(response.rendered_content, "lxml")
        assert doc.select('.alert-success')
        assert doc.select('#user-dropdown-label')

        with scope(event=event):
            sub = Submission.objects.last()
            assert sub.title == 'Submission title'
            answ = sub.answers.filter(question__target='submission').first()
            assert answ.question == question
            assert answ.answer == '42'
            assert answ.submission == sub
            assert not answ.person
            answ = user.answers.filter(question__target='speaker').first()
            assert answ.question == speaker_question
            assert answ.person == user
            assert not answ.submission
            assert answ.answer == 'green'
            s_user = sub.speakers.first()
            assert s_user.pk == user.pk
            assert s_user.name == 'Jane Doe'
            assert s_user.profiles.get(event=event).biography == 'l337 hax0r'
            assert len(djmail.outbox) == 1
            mail = djmail.outbox[0]
            assert sub.title in mail.subject
            assert sub.title in mail.body
            assert s_user.email in mail.to
예제 #12
0
def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: str, sender: str,
                   event: int=None, position: int=None, headers: dict=None, bcc: List[str]=None,
                   invoices: List[int]=None, order: int=None, attach_tickets=False, user=None,
                   attach_ical=False) -> bool:
    email = CustomEmail(subject, body, sender, to=to, bcc=bcc, headers=headers)
    if html is not None:
        html_message = SafeMIMEMultipart(_subtype='related', encoding=settings.DEFAULT_CHARSET)
        html_with_cid, cid_images = replace_images_with_cid_paths(html)
        html_message.attach(SafeMIMEText(html_with_cid, 'html', settings.DEFAULT_CHARSET))
        attach_cid_images(html_message, cid_images, verify_ssl=True)
        email.attach_alternative(html_message, "multipart/related")

    if user:
        user = User.objects.get(pk=user)

    if event:
        with scopes_disabled():
            event = Event.objects.get(id=event)
        backend = event.get_mail_backend()
        cm = lambda: scope(organizer=event.organizer)  # noqa
    else:
        backend = get_connection(fail_silently=False)
        cm = lambda: scopes_disabled()  # noqa

    with cm():
        if invoices:
            invoices = Invoice.objects.filter(pk__in=invoices)
            for inv in invoices:
                if inv.file:
                    try:
                        with language(inv.order.locale):
                            email.attach(
                                pgettext('invoice', 'Invoice {num}').format(num=inv.number).replace(' ', '_') + '.pdf',
                                inv.file.file.read(),
                                'application/pdf'
                            )
                    except:
                        logger.exception('Could not attach invoice to email')
                        pass
        if event:
            if order:
                try:
                    order = event.orders.get(pk=order)
                except Order.DoesNotExist:
                    order = None
                else:
                    if position:
                        try:
                            position = order.positions.get(pk=position)
                        except OrderPosition.DoesNotExist:
                            attach_tickets = False
                    if attach_tickets:
                        args = []
                        attach_size = 0
                        for name, ct in get_tickets_for_order(order, base_position=position):
                            content = ct.file.read()
                            args.append((name, content, ct.type))
                            attach_size += len(content)

                        if attach_size < 4 * 1024 * 1024:
                            # Do not attach more than 4MB, it will bounce way to often.
                            for a in args:
                                try:
                                    email.attach(*a)
                                except:
                                    pass
                        else:
                            order.log_action(
                                'pretix.event.order.email.attachments.skipped',
                                data={
                                    'subject': 'Attachments skipped',
                                    'message': 'Attachment have not been send because {} bytes are likely too large to arrive.'.format(attach_size),
                                    'recipient': '',
                                    'invoices': [],
                                }
                            )
                    if attach_ical:
                        ical_events = set()
                        if event.has_subevents:
                            if position:
                                ical_events.add(position.subevent)
                            else:
                                for p in order.positions.all():
                                    ical_events.add(p.subevent)
                        else:
                            ical_events.add(order.event)

                        for i, e in enumerate(ical_events):
                            cal = get_ical([e])
                            email.attach('event-{}.ics'.format(i), cal.serialize(), 'text/calendar')

            email = email_filter.send_chained(event, 'message', message=email, order=order, user=user)

        email = global_email_filter.send_chained(event, 'message', message=email, user=user, order=order)

        try:
            backend.send_messages([email])
        except smtplib.SMTPResponseException as e:
            if e.smtp_code in (101, 111, 421, 422, 431, 442, 447, 452):
                self.retry(max_retries=5, countdown=2 ** (self.request.retries * 2))
            logger.exception('Error sending email')

            if order:
                order.log_action(
                    'pretix.event.order.email.error',
                    data={
                        'subject': 'SMTP code {}'.format(e.smtp_code),
                        'message': e.smtp_error.decode() if isinstance(e.smtp_error, bytes) else str(e.smtp_error),
                        'recipient': '',
                        'invoices': [],
                    }
                )

            raise SendMailException('Failed to send an email to {}.'.format(to))
        except Exception as e:
            if order:
                order.log_action(
                    'pretix.event.order.email.error',
                    data={
                        'subject': 'Internal error',
                        'message': str(e),
                        'recipient': '',
                        'invoices': [],
                    }
                )
            logger.exception('Error sending email')
            raise SendMailException('Failed to send an email to {}.'.format(to))
예제 #13
0
def process_banktransfers(self, job: int, data: list) -> None:
    with language("en"):  # We'll translate error messages at display time
        with scopes_disabled():
            job = BankImportJob.objects.get(pk=job)
        with scope(organizer=job.organizer or job.event.organizer):
            job.state = BankImportJob.STATE_RUNNING
            job.save()

            try:
                # Delete left-over transactions from a failed run before so they can reimported
                BankTransaction.objects.filter(
                    state=BankTransaction.STATE_UNCHECKED,
                    **job.owner_kwargs).delete()

                transactions = _get_unknown_transactions(
                    job, data, **job.owner_kwargs)

                code_len_agg = Order.objects.filter(
                    event__organizer=job.organizer).annotate(
                        clen=Length('code')).aggregate(min=Min('clen'),
                                                       max=Max('clen'))
                if job.event:
                    prefixes = [job.event.slug.upper()]
                else:
                    prefixes = [
                        e.slug.upper().replace(".",
                                               r"\.").replace("-", r"[\- ]*")
                        for e in job.organizer.events.all()
                    ]
                pattern = re.compile("(%s)[ \\-_]*([A-Z0-9]{%s,%s})" %
                                     ("|".join(prefixes), code_len_agg['min']
                                      or 0, code_len_agg['max'] or 5))

                for trans in transactions:
                    matches = pattern.findall(
                        trans.reference.replace(" ", "").replace("\n",
                                                                 "").upper())

                    if matches:
                        if job.event:
                            _handle_transaction(trans,
                                                matches,
                                                event=job.event)
                        else:
                            _handle_transaction(trans,
                                                matches,
                                                organizer=job.organizer)
                    else:
                        trans.state = BankTransaction.STATE_NOMATCH
                        trans.save()
            except LockTimeoutException:
                try:
                    self.retry()
                except MaxRetriesExceededError:
                    logger.exception(
                        'Maximum number of retries exceeded for task.')
                    job.state = BankImportJob.STATE_ERROR
                    job.save()
            except Exception as e:
                job.state = BankImportJob.STATE_ERROR
                job.save()
                raise e
            else:
                job.state = BankImportJob.STATE_COMPLETED
                job.save()
예제 #14
0
    def build_event(self, end_stage):
        administrators = User.objects.filter(is_administrator=True)
        if not administrators:
            self.stdout.write(
                self.style.ERROR(
                    'Please run the "init" command to create an administrator user.'
                ))
            return
        organiser, team = create_organiser_with_team(
            name='DemoCon Org',
            slug='democonorg',
            users=administrators,
        )
        if end_stage == 'cfp':
            event_start = now() + dt.timedelta(days=35)
        elif end_stage == 'review':
            event_start = now() + dt.timedelta(days=25)
        elif end_stage == 'over':
            event_start = now() - dt.timedelta(days=10)
        else:  # end_stage == 'schedule'
            event_start = now() - dt.timedelta(days=1)
        self.bs = self.fake.bs()
        self.catch_phrase = self.fake.catch_phrase()
        intro = f'We provide a {self.catch_phrase.lower()} to {self.bs}.'
        disclaimer = '''This is an automatically generated event to test and showcase pretalx features.
Feel free to look around, but don\'t be alarmed if something doesn\'t quite make sense. You can always create your own free test event at [pretalx.com](https://pretalx.com)!'''
        with scopes_disabled():
            event = Event.objects.create(
                name='DemoCon',
                slug='democon',
                organiser=organiser,
                is_public=True,
                date_from=event_start.date(),
                date_to=event_start.date() + dt.timedelta(days=2),
                timezone='Europe/Berlin',
                email=self.fake.user_name() + '@example.org',
                primary_color=self.fake.hex_color(),
                locale_array='en',
                locale='en',
                landing_page_text=
                f'# Welcome to DemoCon!\n\n{intro}\n\n{disclaimer}',
            )
        with scope(event=event):
            event.build_initial_data()
            team.limit_events.add(event)
            SubmissionType.objects.create(event=event,
                                          name='Workshop',
                                          default_duration=90)

            event.settings.use_tracks = True
            for _ in range(self.fake.random_int(min=2, max=5)):
                Track.objects.create(
                    event=event,
                    name=self.fake.catch_phrase().split()[0],
                    color=self.fake.hex_color(),
                )
            event.cfp.headline = 'DemoCon submissions are {}!'.format(
                'open' if end_stage == 'cfp' else 'closed')
            track_text = '\n'.join(f'- {track.name}'
                                   for track in event.tracks.all())
            event.cfp.text = f'''This is the Call for Participation for DemoCon!\n\n{intro}\n\n

We are always on the look-out for speakers who can provide {self.fake.bs()} – if that is you, please submit a talk or a workshop! We accept submissions for the following tracks:

{track_text}

We explicitly encourage new speakers and multiple submissions per person.
If you have any interest in {self.fake.catch_phrase().lower()}, {self.fake.catch_phrase().lower()}, {self.fake.catch_phrase().lower()} – or something else you think matches our conference, please submit your proposal!

{disclaimer}
'''
            event.cfp.deadline = event.datetime_from - dt.timedelta(days=60)
            event.cfp.save()
            event.settings.display_header_pattern = random.choice(
                ('', 'pcb', 'bubbles', 'signal', 'topo', 'graph'))
            event.settings.review_max_score = 2
            self.event = event
            self.build_room()
            self.build_room()
            regenerate_css(event.pk)
        return event
예제 #15
0
def review(submission, review_user):
    with scope(event=submission.event):
        return Review.objects.create(score=1,
                                     submission=submission,
                                     user=review_user,
                                     text="Looks great!")
예제 #16
0
def personal_answer(personal_question, speaker):
    with scope(event=personal_question.event):
        return Answer.objects.create(answer='True',
                                     person=speaker,
                                     question=personal_question)
예제 #17
0
def information(event):
    with scope(event=event):
        return SpeakerInformation.objects.create(event=event,
                                                 title="Information title",
                                                 text="Important information")
예제 #18
0
def sent_mail(mail_template, speaker, event):
    with scope(event=event):
        mail = mail_template.to_mail(speaker, event)
        mail.send()
        return mail
예제 #19
0
def other_track(event):
    with scope(event=event):
        event.settings.use_tracks = True
        return Track.objects.create(name="Second Test Track",
                                    color="ff0000",
                                    event=event)
예제 #20
0
def room_availability(event, room, availability):
    with scope(event=event):
        availability.room = room
        availability.save()
        return availability
예제 #21
0
def other_resource(submission):
    f = SimpleUploadedFile("testresource2.txt", b"another resource")
    with scope(event=submission.event):
        return Resource.objects.create(submission=submission,
                                       resource=f,
                                       description="Test resource 2")
예제 #22
0
def schedule(event):
    with scope(event=event):
        event.release_schedule('🍪 Version')
        return event.current_schedule
예제 #23
0
def impersonal_answer(question, speaker, submission):
    with scope(event=question.event):
        return Answer.objects.create(answer="True",
                                     submission=submission,
                                     person=speaker,
                                     question=question)
예제 #24
0
def canceled_talk(past_slot):
    with scope(event=past_slot.submission.event):
        past_slot.submission.cancel(force=True)
        past_slot.submission.event.wip_schedule.freeze('vcanceled')
        return past_slot
예제 #25
0
def submission(submission_data, speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        return sub
예제 #26
0
def feedback(past_slot):
    with scope(event=past_slot.submission.event):
        return Feedback.objects.create(talk=past_slot.submission,
                                       review='I liked it!')
예제 #27
0
def other_confirmed_submission(other_accepted_submission, event):
    with scope(event=event):
        other_accepted_submission.confirm()
        return other_accepted_submission
예제 #28
0
def env():
    o = Organizer.objects.create(name='Dummy', slug='dummy')
    with scope(organizer=o):
        event = Event.objects.create(
            organizer=o, name='Dummy', slug='dummy',
            date_from=now(), plugins='pretix.plugins.banktransfer'
        )
        o = Order.objects.create(
            code='FOO', event=event, email='*****@*****.**',
            status=Order.STATUS_PENDING,
            datetime=now(), expires=now() + timedelta(days=10),
            total=0, locale='en'
        )
        tr = event.tax_rules.create(rate=Decimal('19.00'))
        o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
                      tax_value=Decimal('0.05'), tax_rule=tr)
        ticket = Item.objects.create(event=event, name='Early-bird ticket',
                                     category=None, default_price=23, tax_rule=tr,
                                     admission=True)
        t_shirt = Item.objects.create(event=event, name='T-Shirt',
                                      category=None, default_price=42, tax_rule=tr,
                                      admission=True)
        variation = ItemVariation.objects.create(value='M', item=t_shirt)
        OrderPosition.objects.create(
            order=o,
            item=ticket,
            variation=None,
            price=Decimal("23.00"),
            positionid=1,
        )
        OrderPosition.objects.create(
            order=o,
            item=t_shirt,
            variation=variation,
            price=Decimal("42.00"),
            positionid=2,
        )
        OrderPosition.objects.create(
            order=o,
            item=t_shirt,
            variation=variation,
            price=Decimal("42.00"),
            positionid=3,
            canceled=True
        )
        gs = GlobalSettingsObject()
        gs.settings.ecb_rates_date = date.today()
        gs.settings.ecb_rates_dict = json.dumps({
            "USD": "1.1648",
            "RON": "4.5638",
            "CZK": "26.024",
            "BGN": "1.9558",
            "HRK": "7.4098",
            "EUR": "1.0000",
            "NOK": "9.3525",
            "HUF": "305.15",
            "DKK": "7.4361",
            "PLN": "4.2408",
            "GBP": "0.89350",
            "SEK": "9.5883"
        }, cls=DjangoJSONEncoder)
        yield event, o
예제 #29
0
def mail(mail_template, speaker, event):
    with scope(event=event):
        return mail_template.to_mail(speaker, event)
예제 #30
0
def test_slot_no_warnings_when_room_available(slot, room_availability):
    with scope(event=slot.event):
        assert not slot.warnings