def retry(request, order): try: order = Order.objects.current.get( user=request.user, code=order, ) except Order.DoesNotExist: return # TODO: Handle this provider = Paypal(order.event) provider.init_api() if 'token' in request.GET: if 'PayerID' in request.GET: payment = paypalrestsdk.Payment.find(request.session.get('payment_paypal_id')) provider._execute_payment(payment, request, order) else: messages.error(request, _('It looks like you cancelled the PayPal payment')) else: payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri('plugins:paypal:retry', kwargs={ 'order': order.code }), "cancel_url": build_absolute_uri('plugins:paypal:retry', kwargs={ 'order': order.code }), }, "transactions": [ { "item_list": { "items": [ { "name": 'Order %s' % order.code, "quantity": 1, "price": str(order.total), "currency": order.event.currency } ] }, "amount": { "currency": order.event.currency, "total": str(order.total) }, "description": __('Event tickets for %s') % order.event.name } ] }) resp = provider._create_payment(request, payment) if resp: return redirect(resp) return redirect(eventreverse(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }) + '?paid=yes')
def get_context_data(self, **kwargs): ctx = super().get_context_data() url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug }) if self.object.subevent: url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug, 'subevent': self.object.subevent.pk }) data = { 'version': API_VERSION, 'url': url[:-7], # the slice removes the redeem/ part at the end 'key': self.object.key, 'allow_search': self.object.allow_search, 'show_info': self.object.show_info } ctx['config'] = self.object ctx['query'] = urllib.parse.urlencode(data, safe=':/') ctx['qrdata'] = json.dumps(data) return ctx
def send_notification_mail(notification: Notification, user: User): ctx = { 'site': settings.PRETIX_INSTANCE_NAME, 'site_url': settings.SITE_URL, 'color': '#8E44B3', 'notification': notification, 'settings_url': build_absolute_uri( 'control:user.settings.notifications', ), 'disable_url': build_absolute_uri( 'control:user.settings.notifications.off', kwargs={ 'token': user.notifications_token, 'id': user.pk } ) } tpl_html = get_template('pretixbase/email/notification.html') body_html = inline_css(tpl_html.render(ctx)) tpl_plain = get_template('pretixbase/email/notification.txt') body_plain = tpl_plain.render(ctx) mail_send_task.apply_async(kwargs={ 'to': [user.email], 'subject': '[{}] {}: {}'.format( settings.PRETIX_INSTANCE_NAME, notification.event.settings.mail_prefix or notification.event.slug.upper(), notification.title ), 'body': body_plain, 'html': body_html, 'sender': settings.MAIL_FROM, 'headers': {}, })
def get_context_data(self, **kwargs): ctx = super().get_context_data() key = self.request.event.settings.get('pretixdroid_key') if not key or 'flush_key' in self.request.GET: key = get_random_string(length=32, allowed_chars=string.ascii_uppercase + string.ascii_lowercase + string.digits) self.request.event.settings.set('pretixdroid_key', key) subevent = None url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug }) if self.request.event.has_subevents: if self.request.GET.get('subevent'): subevent = get_object_or_404(SubEvent, event=self.request.event, pk=self.request.GET['subevent']) url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug, 'subevent': subevent.pk }) ctx['subevent'] = subevent ctx['qrdata'] = json.dumps({ 'version': API_VERSION, 'url': url[:-7], # the slice removes the redeem/ part at the end 'key': key, }) return ctx
def retry(request, order): try: order = Order.objects.current.get(user=request.user, code=order) except Order.DoesNotExist: return # TODO: Handle this provider = Paypal(order.event) provider.init_api() if "token" in request.GET: if "PayerID" in request.GET: payment = paypalrestsdk.Payment.find(request.session.get("payment_paypal_id")) provider._execute_payment(payment, request, order) else: messages.error(request, _("It looks like you cancelled the PayPal payment")) else: payment = paypalrestsdk.Payment( { "intent": "sale", "payer": {"payment_method": "paypal"}, "redirect_urls": { "return_url": build_absolute_uri("plugins:paypal:retry", kwargs={"order": order.code}), "cancel_url": build_absolute_uri("plugins:paypal:retry", kwargs={"order": order.code}), }, "transactions": [ { "item_list": { "items": [ { "name": "Order %s" % order.code, "quantity": 1, "price": str(order.total), "currency": order.event.currency, } ] }, "amount": {"currency": order.event.currency, "total": str(order.total)}, "description": __("Event tickets for %s") % order.event.name, } ], } ) resp = provider._create_payment(request, payment) if resp: return redirect(resp) return redirect( "presale:event.order", event=order.event.slug, organizer=order.event.organizer.slug, order=order.code )
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data['user'] if settings.HAS_REDIS: from django_redis import get_redis_connection rc = get_redis_connection("redis") if rc.exists('pretix_pwreset_%s' % (user.id)): user.log_action('pretix.control.auth.user.forgot_password.denied.repeated') messages.error(request, _('We already sent you an email in the last 24 hours.')) return redirect('control:auth.forgot') else: rc.setex('pretix_pwreset_%s' % (user.id), 3600 * 24, '1') try: mail( user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', { 'user': user, 'url': (build_absolute_uri('control:auth.forgot.recover') + '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user))) }, None, locale=user.locale ) except SendMailException: messages.error(request, _('There was an error sending the mail. Please try again later.')) return self.get(request, *args, **kwargs) user.log_action('pretix.control.auth.user.forgot_password.mail_sent') messages.success(request, _('We sent you an e-mail containing further instructions.')) return redirect('control:auth.forgot') else: return self.get(request, *args, **kwargs)
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data["user"] if user.email: mail( user, _("Password recovery"), "pretixpresale/email/forgot.txt", { "user": user, "event": self.request.event, "url": build_absolute_uri( "presale:event.forgot.recover", kwargs={"event": self.request.event.slug, "organizer": self.request.event.organizer.slug}, ) + "?token=" + self.generate_token(user), }, self.request.event, ) messages.success(request, _("We sent you an e-mail containing further instructions.")) else: messages.success( request, _( "We are unable to send you a new password, as you did not enter an e-mail " "address at your registration." ), ) return redirect( "presale:event.forgot", organizer=self.request.event.organizer.slug, event=self.request.event.slug ) else: return self.get(request, *args, **kwargs)
def authentication_url(self, request): """ This method will be called to populate the URL for the authentication method's tab on the login page. """ redirect_uri = build_absolute_uri('plugins:pretix_oidc:oidc.response') client_id = config.get('pretix_oidc', 'oidc_client_id', fallback='pretix') base_authorize_url = config.get( 'pretix_oidc', 'oidc_authorize_url', fallback='https://sso.example.com/auth') oauth2_session = OAuth2Session(client_id, scope='openid email profile', redirect_uri=redirect_uri) authorization_url, state = oauth2_session.authorization_url( base_authorize_url) # Store state in session for later validation (see auth.py) request.session['OAUTH2_STATE'] = state request.session['OAUTH2_REDIRECT_URI'] = redirect_uri return authorization_url
def refresh_mollie_tokens(sender, **kwargs): seen = set() gs = GlobalSettingsObject() for es in Event_SettingsStore.objects.filter(key='payment_mollie_expires'): if time.time() - float(es.object.settings.payment_mollie_expires) < 600: rt = es.object.settings.payment_mollie_refresh_token if rt not in seen: try: resp = requests.post('https://api.mollie.com/oauth2/tokens', auth=( gs.settings.payment_mollie_connect_client_id, gs.settings.payment_mollie_connect_client_secret ), data={ 'grant_type': 'refresh_token', 'refresh_token': es.object.settings.payment_mollie_refresh_token, 'redirect_uri': build_absolute_uri('plugins:pretix_mollie:oauth.return') }) except: logger.exception('Unable to refresh mollie token') if float(es.object.settings.payment_mollie_expires) > time.time() and not \ es.object.settings.payment_mollie_api_key: es.object.settings.payment_mollie__enabled = False es.object.log_action('pretix_mollie.event.disabled') else: if resp.status_code == 200: data = resp.json() for ev in Event_SettingsStore.objects.filter(key='payment_mollie_refresh_token', value=rt): ev.object.settings.payment_mollie_access_token = data['access_token'] ev.object.settings.payment_mollie_refresh_token = data['refresh_token'] ev.object.settings.payment_mollie_expires = time.time() + data['expires_in'] seen.add(rt)
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data['user'] if user.email: mail( user, _('Password recovery'), 'pretixpresale/email/forgot.txt', { 'user': user, 'event': self.request.event, 'url': build_absolute_uri('presale:event.forgot.recover', kwargs={ 'event': self.request.event.slug, 'organizer': self.request.event.organizer.slug, }) + '?token=' + self.generate_token(user), }, self.request.event ) messages.success(request, _('We sent you an e-mail containing further instructions.')) else: messages.success(request, _('We are unable to send you a new password, as you did not enter an e-mail ' 'address at your registration.')) return redirect('presale:event.forgot', organizer=self.request.event.organizer.slug, event=self.request.event.slug) else: return self.get(request, *args, **kwargs)
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data["user"] mail( user.email, _("Password recovery"), "pretixpresale/email/forgot.txt", { "user": user, "event": self.request.event, "url": build_absolute_uri( "presale:event.forgot.recover", kwargs={"event": self.request.event.slug, "organizer": self.request.event.organizer.slug}, ) + "?id=%d&token=%s" % (user.id, default_token_generator.make_token(user)), }, self.request.event, locale=user.locale, ) messages.success(request, _("We sent you an e-mail containing further instructions.")) return redirect( "presale:event.forgot", organizer=self.request.event.organizer.slug, event=self.request.event.slug ) else: return self.get(request, *args, **kwargs)
def test_site_url_subpath(): settings.SITE_URL = 'https://example.com/presale' old_prefix = urls.get_script_prefix() urls.set_script_prefix('/presale/') assert build_absolute_uri( 'control:auth.login') == 'https://example.com/presale/control/login' urls.set_script_prefix(old_prefix)
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data['user'] if settings.HAS_REDIS: from django_redis import get_redis_connection rc = get_redis_connection("redis") if rc.exists('pretix_pwreset_%s' % (user.id)): user.log_action('pretix.control.auth.user.forgot_password.denied.repeated') messages.error(request, _('We already sent you an email in the last 24 hours.')) return redirect('control:auth.forgot') else: rc.setex('pretix_pwreset_%s' % (user.id), 3600 * 24, '1') mail( user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', { 'user': user, 'url': (build_absolute_uri('control:auth.forgot.recover') + '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user))) }, None, locale=user.locale ) user.log_action('pretix.control.auth.user.forgot_password.mail_sent') messages.success(request, _('We sent you an e-mail containing further instructions.')) return redirect('control:auth.forgot') else: return self.get(request, *args, **kwargs)
def perform_order(event: Event, payment_provider: BasePaymentProvider, positions: list, user: User=None, email: str=None, locale: str=None): dt = now() try: with event.lock(): check_positions(event, dt, positions) order = place_order(event, user, email if user is None else None, positions, dt, payment_provider, locale=locale) mail( order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri('presale:event.order', kwargs={ 'event': event.slug, 'organizer': event.organizer.slug, 'order': order.code, }) + '?order_secret=' + order.secret, 'payment': payment_provider.order_pending_mail_render(order) }, event, locale=order.locale ) return order except EventLock.LockTimeoutException: # Is raised when there are too many threads asking for event locks and we were # unable to get one raise OrderError(error_messages['busy'])
def build_notification(self, logentry: LogEntry): order = logentry.content_object order_url = build_absolute_uri( 'control:event.order', kwargs={ 'organizer': logentry.event.organizer.slug, 'event': logentry.event.slug, 'code': order.code } ) n = Notification( event=logentry.event, title=self._title.format(order=order, event=logentry.event), url=order_url ) n.add_attribute(_('Event'), order.event.name) n.add_attribute(_('Order code'), order.code) n.add_attribute(_('Order total'), money_filter(order.total, logentry.event.currency)) n.add_attribute(_('Pending amount'), money_filter(order.pending_sum, logentry.event.currency)) n.add_attribute(_('Order date'), date_format(order.datetime, 'SHORT_DATETIME_FORMAT')) n.add_attribute(_('Order status'), order.get_status_display()) n.add_attribute(_('Order positions'), str(order.positions.count())) n.add_action(_('View order details'), order_url) return n
def build_notification(self, logentry: LogEntry): order = logentry.content_object order_url = build_absolute_uri( 'control:event.order', kwargs={ 'organizer': logentry.event.organizer.slug, 'event': logentry.event.slug, 'code': order.code } ) n = Notification( event=logentry.event, title=self._title.format(order=order, event=logentry.event), url=order_url ) n.add_attribute(_('Event'), order.event.name) n.add_attribute(_('Order code'), order.code) n.add_attribute(_('Order total'), money_filter(order.total, logentry.event.currency)) n.add_attribute(_('Order date'), date_format(order.datetime, 'SHORT_DATETIME_FORMAT')) n.add_attribute(_('Order status'), order.get_status_display()) n.add_attribute(_('Order positions'), str(order.positions.count())) n.add_action(_('View order details'), order_url) return n
def perform_order(event, user, payment_provider, positions): error_messages = { 'busy': _('We were not able to process your request completely as the ' 'server was too busy. Please try again.'), } dt = now() quotas_locked = set() try: check_positions(event, dt, positions, quotas_locked) order = place_order(event, user, positions, dt, payment_provider) mail( user, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'user': user, 'order': order, 'event': event, 'url': build_absolute_uri('presale:event.order', kwargs={ 'event': event.slug, 'organizer': event.organizer.slug, 'order': order.code, }), 'payment': payment_provider.order_pending_mail_render(order) }, event ) return order except Quota.LockTimeoutException: # Is raised when there are too many threads asking for quota locks and we were # unaible to get one raise OrderError(error_messages['busy']) finally: # Release the locks. This is important ;) for quota in quotas_locked: quota.release()
def generate_order_url(self, code, secret): return build_absolute_uri('presale:event.order', kwargs={ 'event': self.request.event.slug, 'organizer': self.request.event.organizer.slug, 'order': code, 'secret': secret })
def build_notification(self, logentry: LogEntry): order = logentry.content_object order_url = build_absolute_uri( 'control:event.order', kwargs={ 'organizer': logentry.event.organizer.slug, 'event': logentry.event.slug, 'code': order.code } ) n = Notification( event=logentry.event, title=self._title.format(order=order, event=logentry.event), url=order_url ) n.add_attribute(_('Event'), order.event.name) if order.event.has_subevents: ses = [] for se in self.event.subevents.filter(id__in=order.positions.values_list('subevent', flat=True)): ses.append('{} ({})'.format(se.name, se.get_date_range_display())) n.add_attribute(pgettext_lazy('subevent', 'Dates'), '\n'.join(ses)) else: n.add_attribute(_('Event date'), order.event.get_date_range_display()) positions = list(order.positions.select_related('item', 'variation', 'subevent')) fees = list(order.fees.all()) n.add_attribute(_('Order code'), order.code) n.add_attribute(_('Net total'), money_filter(sum([p.net_price for p in positions] + [f.net_value for f in fees]), logentry.event.currency)) n.add_attribute(_('Order total'), money_filter(order.total, logentry.event.currency)) n.add_attribute(_('Pending amount'), money_filter(order.pending_sum, logentry.event.currency)) n.add_attribute(_('Order date'), date_format(order.datetime.astimezone(logentry.event.timezone), 'SHORT_DATETIME_FORMAT')) n.add_attribute(_('Order status'), order.get_status_display()) n.add_attribute(_('Order positions'), str(order.positions.count())) def sortkey(op): return op.item_id, op.variation_id, op.subevent_id def groupkey(op): return op.item, op.variation, op.subevent cart = [(k, list(v)) for k, v in groupby(sorted(positions, key=sortkey), key=groupkey)] items = [] for (item, variation, subevent), pos in cart: ele = [str(len(pos)) + 'x ' + str(item)] if variation: ele.append(str(variation.value)) if subevent: ele.append(str(subevent)) items.append(' – '.join(ele)) n.add_attribute(_('Purchased products'), '\n'.join(items)) n.add_action(_('View order details'), order_url) return n
def checkout_prepare(self, request, cart): self.init_api() items = [] for cp in cart['positions']: items.append({ "name": cp.item.name, "description": str(cp.variation) if cp.variation else "", "quantity": cp.count, "price": str(cp.price), "currency": request.event.currency }) if cart['payment_fee']: items.append({ "name": __('Payment method fee'), "description": "", "quantity": 1, "currency": request.event.currency, "price": str(cart['payment_fee']) }) payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri('plugins:paypal:return'), "cancel_url": build_absolute_uri('plugins:paypal:abort'), }, "transactions": [ { "item_list": { "items": items }, "amount": { "currency": request.event.currency, "total": str(cart['total']) }, "description": __('Event tickets for %s') % request.event.name } ] }) return self._create_payment(request, payment)
def send_password_reset(self): from pretix.base.services.mail import mail mail( self.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', { 'user': self, 'url': (build_absolute_uri('control:auth.forgot.recover') + '?id=%d&token=%s' % (self.id, default_token_generator.make_token(self))) }, None, locale=self.locale )
def mail(email: str, subject: str, template: str, context: dict=None, event: Event=None, locale: str=None): """ Sends out an email to a user. :param user: The user this should be sent to. :param subject: The e-mail subject. Should be localized. :param template: The filename of a template to be used. It will be rendered with the recipient's locale. Alternatively, you can pass a LazyI18nString and leave ``context`` empty :param context: The context for rendering the template. :param event: The event, used for determining the sender of the e-mail :return: ``False`` on obvious failures, like the user having to e-mail address, ``True`` otherwise. ``True`` does not necessarily mean that the email has been sent, just that it has been queued by the e-mail backend. """ _lng = translation.get_language() translation.activate(locale or settings.LANGUAGE_CODE) if isinstance(template, LazyI18nString): body = str(template) else: tpl = get_template(template) body = tpl.render(context) sender = event.settings.get('mail_from') if event else settings.MAIL_FROM subject = str(subject) prefix = event.settings.get('mail_prefix') if prefix: subject = "[%s] %s" % (prefix, subject) body += "\r\n\r\n----\r\n" body += _( "You are receiving this e-mail because you placed an order for %s." % event.name ) body += "\r\n" body += _( "You can view all of your orders at the following URL:" ) body += "\r\n" body += build_absolute_uri( 'presale:event.orders', kwargs={ 'event': event.slug, 'organizer': event.organizer.slug } ) body += "\r\n" try: return mail_send([email], subject, body, sender) finally: translation.activate(_lng)
def mark_order_paid(order, provider=None, info=None, date=None, manual=None, force=False): """ Marks an order as paid. This clones the order object, sets the payment provider, info and date and returns the cloned order object. :param provider: The payment provider that marked this as paid :type provider: str :param info: The information to store in order.payment_info :type info: str :param date: The date the payment was received (if you pass ``None``, the current time will be used). :type date: datetime :param force: Whether this payment should be marked as paid even if no remaining quota is available (default: ``False``). :type force: boolean :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ can_be_paid, quotas_locked = order._can_be_paid(keep_locked=True) if not force and can_be_paid is not True: raise Quota.QuotaExceededException(can_be_paid) order = order.clone() order.payment_provider = provider or order.payment_provider order.payment_info = info or order.payment_info order.payment_date = date or now() if manual is not None: order.payment_manual = manual order.status = Order.STATUS_PAID order.save() order_paid.send(order.event, order=order) if quotas_locked: for quota in quotas_locked: quota.release() from pretix.base.services.mail import mail mail( order.user, _('Payment received for your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_paid.txt', { 'user': order.user, 'order': order, 'event': order.event, 'url': build_absolute_uri('presale:event.order', kwargs={ 'event': order.event.slug, 'organizer': order.event.organizer.slug, 'order': order.code, }), 'downloads': order.event.settings.get('ticket_download', as_type=bool) }, order.event ) return order
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data['user'] mail( user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', { 'user': user, 'url': (build_absolute_uri('control:auth.forgot.recover') + '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user))) }, None, locale=user.locale ) messages.success(request, _('We sent you an e-mail containing further instructions.')) return redirect('control:auth.forgot') else: return self.get(request, *args, **kwargs)
def send_update_notification_email(): gs = GlobalSettingsObject() if not gs.settings.update_check_email: return mail( gs.settings.update_check_email, _('pretix update available'), LazyI18nString.from_gettext( gettext_noop( 'Hi!\n\nAn update is available for pretix or for one of the plugins you installed in your ' 'pretix installation. Please click on the following link for more information:\n\n {url} \n\n' 'You can always find information on the latest updates on the pretix.eu blog:\n\n' 'https://pretix.eu/about/en/blog/' '\n\nBest,\n\nyour pretix developers')), {'url': build_absolute_uri('control:global.update')}, )
def get_context_data(self, **kwargs): ctx = super().get_context_data() key = self.request.event.settings.get('pretixdroid_key') if not key or 'flush_key' in self.request.GET: key = get_random_string(length=32, allowed_chars=string.ascii_uppercase + string.ascii_lowercase + string.digits) self.request.event.settings.set('pretixdroid_key', key) ctx['qrdata'] = json.dumps({ 'version': API_VERSION, 'url': build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug })[:-7], # the slice removes the redeem/ part at the end 'key': key }) return ctx
def refresh_mollie_token(event, disable=True): # Rate limit rt = event.settings.payment_mollie_refresh_token if not rt: return False h = hashlib.sha1(rt.encode()).hexdigest() if cache.get('mollie_refresh_{}'.format(h)): return False cache.set('mollie_refresh_{}'.format(h), 'started', 30) gs = GlobalSettingsObject() try: resp = requests.post( 'https://api.mollie.com/oauth2/tokens', auth=(gs.settings.payment_mollie_connect_client_id, gs.settings.payment_mollie_connect_client_secret), data={ 'grant_type': 'refresh_token', 'refresh_token': event.settings.payment_mollie_refresh_token, 'redirect_uri': build_absolute_uri('plugins:pretix_mollie:oauth.return') }) except Exception as e: logger.exception('Unable to refresh mollie token') if float(event.settings.payment_mollie_expires) > time.time() and not \ event.settings.payment_mollie_api_key and disable: event.settings.payment_mollie__enabled = False event.log_action('pretix_mollie.event.disabled', {'reason': str(e)}) return False else: if resp.status_code == 200: data = resp.json() for ev in Event_SettingsStore.objects.filter( key='payment_mollie_refresh_token', value=rt): ev.object.settings.payment_mollie_access_token = data[ 'access_token'] ev.object.settings.payment_mollie_refresh_token = data[ 'refresh_token'] ev.object.settings.payment_mollie_expires = time.time( ) + data['expires_in'] return True return False
def send_security_notice(self, messages, email=None): from pretix.base.services.mail import mail, SendMailException try: with language(self.locale): msg = '- ' + '\n- '.join(str(m) for m in messages) mail(email or self.email, _('Account information changed'), 'pretixcontrol/email/security_notice.txt', { 'user': self, 'messages': msg, 'url': build_absolute_uri('control:user.settings') }, event=None, locale=self.locale) except SendMailException: pass # Already logged
def get_context_data(self, **kwargs): ctx = super().get_context_data() key = self.request.event.settings.get('pretixdroid_key') if not key or 'flush_key' in self.request.GET: key = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(32)) self.request.event.settings.set('pretixdroid_key', key) ctx['qrdata'] = json.dumps({ 'version': 1, 'url': build_absolute_uri('plugins:pretixdroid:api', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug }), 'key': key }) return ctx
def _send_invite(self, instance): try: mail( instance.invite_email, _('Account information changed'), 'pretixcontrol/email/invitation_organizer.txt', { 'user': self, 'organizer': self.request.organizer.name, 'url': build_absolute_uri('control:auth.invite', kwargs={'token': instance.invite_token}) }, event=None, locale=self.request.LANGUAGE_CODE) except SendMailException: pass # Already logged
def build_notification(self, logentry: LogEntry): control_url = build_absolute_uri( 'control:event.requiredactions', kwargs={ 'organizer': logentry.event.organizer.slug, 'event': logentry.event.slug, } ) n = Notification( event=logentry.event, title=_('Administrative action required'), detail=_('Something happened in your event that our system cannot handle automatically, e.g. an external ' 'refund. You need to resolve it manually or choose to ignore it, depending on the issue at hand.'), url=control_url ) n.add_action(_('View all unresolved problems'), control_url) return n
def _send_invite(self, instance): try: mail( instance.email, _('pretix account invitation'), 'pretixcontrol/email/invitation.txt', { 'user': self, 'organizer': self.request.organizer.name, 'team': instance.team.name, 'url': build_absolute_uri('control:auth.invite', kwargs={ 'token': instance.token }) }, event=None, locale=self.request.LANGUAGE_CODE ) except SendMailException: pass # Already logged
def _send_invite(self, instance): try: mail( instance.email, _('pretix account invitation'), 'pretixcontrol/email/invitation.txt', { 'user': self, 'organizer': self.context['organizer'].name, 'team': instance.team.name, 'url': build_absolute_uri('control:auth.invite', kwargs={ 'token': instance.token }) }, event=None, locale=get_language_without_region() # TODO: expose? ) except SendMailException: pass # Already logged
def build_notification(self, logentry: LogEntry): order = logentry.content_object order_url = build_absolute_uri('control:event.order', kwargs={ 'organizer': logentry.event.organizer.slug, 'event': logentry.event.slug, 'code': order.code }) n = Notification(event=logentry.event, title=self._title.format(order=order, event=logentry.event), url=order_url) n.add_attribute(_('Event'), order.event.name) if order.event.has_subevents: ses = [] for se in self.event.subevents.filter( id__in=order.positions.values_list('subevent', flat=True)): ses.append('{} ({})'.format(se.name, se.get_date_range_display())) n.add_attribute(pgettext_lazy('subevent', 'Dates'), '\n'.join(ses)) else: n.add_attribute(_('Event date'), order.event.get_date_range_display()) n.add_attribute(_('Order code'), order.code) n.add_attribute(_('Order total'), money_filter(order.total, logentry.event.currency)) n.add_attribute( _('Pending amount'), money_filter(order.pending_sum, logentry.event.currency)) n.add_attribute(_('Order date'), date_format(order.datetime, 'SHORT_DATETIME_FORMAT')) n.add_attribute(_('Order status'), order.get_status_display()) n.add_attribute(_('Order positions'), str(order.positions.count())) items = [] for it in self.event.items.filter( id__in=order.positions.values_list('item', flat=True)): items.append(str(it.name)) n.add_attribute(_('Purchased products'), '\n'.join(items)) n.add_action(_('View order details'), order_url) return n
def send_update_notification_email(): gs = GlobalSettingsObject() if not gs.settings.update_check_email: return mail( gs.settings.update_check_email, _('pretix update available'), LazyI18nString.from_gettext( ugettext_noop( 'Hi!\n\nAn update is available for pretix or for one of the plugins you installed in your ' 'pretix installation. Please click on the following link for more information:\n\n {url} \n\n' 'You can always find information on the latest updates on the pretix.eu blog:\n\n' 'https://pretix.eu/about/en/blog/' '\n\nBest,\n\nyour pretix developers' ) ), { 'url': build_absolute_uri('control:global.update') }, )
def post(self, request, *args, **kwargs): if self.form.is_valid(): user = self.form.cleaned_data['user'] mail(user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', { 'user': user, 'url': (build_absolute_uri('control:auth.forgot.recover') + '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user))) }, None, locale=user.locale) messages.success( request, _('We sent you an e-mail containing further instructions.')) return redirect('control:auth.forgot') else: return self.get(request, *args, **kwargs)
def send_security_notice(self, messages, email=None): from pretix.base.services.mail import mail, SendMailException try: with language(self.locale): msg = '- ' + '\n- '.join(str(m) for m in messages) mail( email or self.email, _('Account information changed'), 'pretixcontrol/email/security_notice.txt', { 'user': self, 'messages': msg, 'url': build_absolute_uri('control:user.settings') }, event=None, locale=self.locale ) except SendMailException: pass # Already logged
def _perform_order(event: Event, payment_provider: BasePaymentProvider, position_ids: list, email: str, locale: str): event = Event.objects.current.get(identity=event) responses = register_payment_providers.send(event) pprov = None for receiver, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list(CartPosition.objects.current.filter( identity__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) mail( order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri('presale:event.order', kwargs={ 'event': event.slug, 'organizer': event.organizer.slug, 'order': order.code, 'secret': order.secret }), 'payment': pprov.order_pending_mail_render(order) }, event, locale=order.locale ) return order.identity
def test_site_url_domain(): settings.SITE_URL = 'https://example.com' assert build_absolute_uri( 'control:auth.login') == 'https://example.com/control/login'
def settings_content_render(self, request): return "<div class='alert alert-info'>%s<br /><code>%s</code></div>" % ( _('Please configure a <a href="https://dashboard.stripe.com/account/webhooks">Stripe Webhook</a> to ' 'the following endpoint in order to automatically cancel orders when a charges are refunded externally.' ), build_absolute_uri('plugins:stripe:webhook'))
def settings_content_render(self, request): return "<div class='alert alert-info'>%s<br /><code>%s</code></div>" % ( _('Please configure a <a href="https://dashboard.stripe.com/account/webhooks">Stripe Webhook</a> to ' 'the following endpoint in order to automatically cancel orders when a charges are refunded externally.'), build_absolute_uri('plugins:stripe:webhook') )
def test_site_url_subpath(): settings.SITE_URL = 'https://example.com/presale' old_prefix = urlresolvers.get_script_prefix() urlresolvers.set_script_prefix('/presale/') assert build_absolute_uri('control:auth.login') == 'https://example.com/presale/control/login' urlresolvers.set_script_prefix(old_prefix)
def oauth_return(request, *args, **kwargs): if 'payment_mollie_oauth_event' not in request.session: messages.error(request, _('An error occurred during connecting with Mollie, please try again.')) return redirect(reverse('control:index')) event = get_object_or_404(Event, pk=request.session['payment_mollie_oauth_event']) if request.GET.get('state') != request.session['payment_mollie_oauth_token']: messages.error(request, _('An error occurred during connecting with Mollie, please try again.')) return redirect(reverse('control:event.settings.payment.provider', kwargs={ 'organizer': event.organizer.slug, 'event': event.slug, 'provider': 'mollie' })) gs = GlobalSettingsObject() try: resp = requests.post('https://api.mollie.com/oauth2/tokens', auth=( gs.settings.payment_mollie_connect_client_id, gs.settings.payment_mollie_connect_client_secret ), data={ 'grant_type': 'authorization_code', 'code': request.GET.get('code'), 'redirect_uri': build_absolute_uri('plugins:pretix_mollie:oauth.return'), }) resp.raise_for_status() data = resp.json() if 'error' not in data: orgaresp = requests.get('https://api.mollie.com/v2/organizations/me', headers={ 'Authorization': 'Bearer ' + data.get('access_token') }) orgaresp.raise_for_status() orgadata = orgaresp.json() profilesurl = 'https://api.mollie.com/v2/profiles' profiles = [] while profilesurl: profilesresp = requests.get(profilesurl, headers={ 'Authorization': 'Bearer ' + data.get('access_token') }) profilesresp.raise_for_status() d = profilesresp.json() profiles += d['_embedded']['profiles'] if d['_links']['next']: profilesurl = d['_links']['next']['href'] else: profilesurl = None except: logger.exception('Failed to obtain OAuth token') messages.error(request, _('An error occurred during connecting with Mollie, please try again.')) else: if 'error' in data: messages.error(request, _('Mollie returned an error: {}').format(data['error_description'])) elif not profiles: messages.error(request, _('Please create a website profile in your Mollie account and try again.')) elif not orgadata.get('id', '') or not orgadata.get('name', ''): messages.error(request, _('Please fill in your company details in your Mollie account and try again.')) else: messages.success(request, _('Your Mollie account is now connected to pretix. You can change the settings in ' 'detail below.')) event.settings.payment_mollie_access_token = data['access_token'] event.settings.payment_mollie_refresh_token = data['refresh_token'] event.settings.payment_mollie_expires = time.time() + data['expires_in'] event.settings.payment_mollie_connect_org_id = orgadata.get('id') event.settings.payment_mollie_connect_org_name = orgadata.get('name', '') event.settings.payment_mollie_connect_profiles = [ [ p.get('id'), p.get('name') + ' - ' + p.get('website', '') ] for p in profiles ] event.settings.payment_mollie_connect_profile = profiles[0].get('id') if request.session.get('payment_mollie_oauth_enable', False): event.settings.payment_mollie__enabled = True del request.session['payment_mollie_oauth_enable'] return redirect(reverse('control:event.settings.payment.provider', kwargs={ 'organizer': event.organizer.slug, 'event': event.slug, 'provider': 'mollie' }))
def test_site_url_domain(): settings.SITE_URL = 'https://example.com' assert build_absolute_uri('control:auth.login') == 'https://example.com/control/login'