def test_minimal_question_serializer(answer): with scope(event=answer.question.event): data = MinimalQuestionSerializer(answer.question).data assert set(data.keys()) == {"id", "question"}
def other_accepted_submission(other_submission): with scope(event=other_submission.event): other_submission.accept() return other_submission
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
def answer(event, submission, question): with scope(event=event): return Answer.objects.create(answer="11", submission=submission, question=question)
def submission_type(event): with scope(event=event): return SubmissionType.objects.create(name="Workshop", event=event, default_duration=60)
def track(event): with scope(event=event): event.settings.use_tracks = True return Track.objects.create(name="Test Track", color="00ff00", event=event)
def access_code(event): with scope(event=event): return SubmitterAccessCode.objects.create(event=event)
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']
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')
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
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
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))
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()
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
def review(submission, review_user): with scope(event=submission.event): return Review.objects.create(score=1, submission=submission, user=review_user, text="Looks great!")
def personal_answer(personal_question, speaker): with scope(event=personal_question.event): return Answer.objects.create(answer='True', person=speaker, question=personal_question)
def information(event): with scope(event=event): return SpeakerInformation.objects.create(event=event, title="Information title", text="Important information")
def sent_mail(mail_template, speaker, event): with scope(event=event): mail = mail_template.to_mail(speaker, event) mail.send() return mail
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)
def room_availability(event, room, availability): with scope(event=event): availability.room = room availability.save() return availability
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")
def schedule(event): with scope(event=event): event.release_schedule('🍪 Version') return event.current_schedule
def impersonal_answer(question, speaker, submission): with scope(event=question.event): return Answer.objects.create(answer="True", submission=submission, person=speaker, question=question)
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
def submission(submission_data, speaker, event): with scope(event=event): sub = Submission.objects.create(**submission_data) sub.save() sub.speakers.add(speaker) return sub
def feedback(past_slot): with scope(event=past_slot.submission.event): return Feedback.objects.create(talk=past_slot.submission, review='I liked it!')
def other_confirmed_submission(other_accepted_submission, event): with scope(event=event): other_accepted_submission.confirm() return other_accepted_submission
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
def mail(mail_template, speaker, event): with scope(event=event): return mail_template.to_mail(speaker, event)
def test_slot_no_warnings_when_room_available(slot, room_availability): with scope(event=slot.event): assert not slot.warnings