class UnsafeJSEvalMixin(object): @method_decorator( csp_update( # jquery.datetimepicker.min.js requires javascript eval SCRIPT_SRC=("'unsafe-eval'", ), )) def dispatch(self, *args, **kwargs): return super(UnsafeJSEvalMixin, self).dispatch(*args, **kwargs)
def get_urls(self): return [ path( "dashboard/", self.site.admin_view( # Argh, it's really unfortunate that we have to break CSP # in order to use Vega, which apparently uses eval(). :( # # But, since our datasets never contain arbitrary string data # entered by untrusted users, this *should* be ok. csp_update(SCRIPT_SRC="'unsafe-eval'") (self.dashboard_view)), name="dashboard"), ]
def embeddable_in_frontapp(view): embeddable_view = csp_update(FRAME_ANCESTORS=[ "https://*.frontapp.com", "https://*.frontapplication.com", ])(view) @functools.wraps(view) def wrapped_view(request, *args, **kwargs): v = view if does_url_have_auth_secret(request.get_full_path(), settings.FRONTAPP_PLUGIN_AUTH_SECRET): v = embeddable_view return v(request, *args, **kwargs) return wrapped_view
def csp_fixes(view): CSP_REPLACEMENTS = { 'SCRIPT_SRC': ( "'self'", "'unsafe-inline'", ), } CSP_ADDITIONS = { 'STYLE_SRC': ( # float: left "'sha256-e+Z0n8P0IwqIce2RMye3/p5TaNb2k/QdJT4urKCsrwk='", # clear: both "'sha256-matwEc6givhWX0+jiSfM1+E5UMk8/UGLdl902bjFBmY='", ), } view = csp_replace(**CSP_REPLACEMENTS)(view) view = csp_update(**CSP_ADDITIONS)(view) return view
app_description, AppReleasesView, AppUploadView, AppRatingApi, \ AppRegisterView from nextcloudappstore.scaffolding.views import AppScaffoldingView admin.site.login = login_required(admin.site.login) urlpatterns = [ url(r'^$', CategoryAppListView.as_view(), {'id': None}, name='home'), url(r"^featured$", CategoryAppListView.as_view(), { 'id': None, 'is_featured_category': True }, name='featured'), url(r"^signup/$", csp_update(**settings.CSP_SIGNUP)(signup), name="account_signup"), url(r"^social/signup/$", csp_update(**settings.CSP_SIGNUP)(social_signup), name="socialaccount_signup"), url(r'^', include('allauth.urls')), url(r'^categories/(?P<id>[\w]*)/?$', CategoryAppListView.as_view(), name='category-app-list'), url(r'^developer/apps/generate/?$', AppScaffoldingView.as_view(), name='app-scaffold'), url(r'^developer/apps/releases/new/?$', AppUploadView.as_view(), name='app-upload'), url(r'^developer/apps/new/?$',
class CreateReportChoiceEntryPoint(TemplateView): template_name = 'newreportchoice.html' def get_context_data(self, **kwargs): context = super(CreateReportChoiceEntryPoint, self).get_context_data(**kwargs) context['type'] = { 'report': ContentType.objects.get_for_model(Report).id, 'onlinereport': ContentType.objects.get_for_model(OnlineReport).id } context['authenticated'] = self.request.user.is_authenticated return context @method_decorator(csp_update(STYLE_SRC=("'unsafe-inline'", )), name='dispatch') class CreateReportView(FormView): """ Creates a new report and returns the new report's ID """ form_class = NewReportForm template_name = "newreport.html" def get_context_data(self, **kwargs): context = super(CreateReportView, self).get_context_data(**kwargs) context['type'] = { 'report': ContentType.objects.get_for_model(Report).id, 'onlinereport': ContentType.objects.get_for_model(OnlineReport).id } context['this_type'] = "report" context['mode'] = 'new'
'end': current_date + timedelta(days=1), 'first_start': min([t.start for t in talks if t.start and t.start.astimezone(tz).date() == current_date.date()] or [0]), 'last_end': max([t.end for t in talks if t.start and t.start.astimezone(tz).date() == current_date.date()] or [0]), 'rooms': [{ 'name': room.name, 'talks': [talk for talk in talks if talk.start and talk.start.astimezone(tz).date() == current_date.date() and talk.room_id == room.pk], } for room in rooms], } for index, current_date in enumerate([ event.datetime_from + timedelta(days=i) for i in range((event.date_to - event.date_from).days + 1) ]) ] return ctx @method_decorator(csp_update(STYLE_SRC="'self' 'unsafe-inline'"), name='dispatch') class ScheduleView(PermissionRequired, ScheduleDataView): template_name = 'agenda/schedule.html' permission_required = 'agenda.view_schedule' def get_permission_object(self): return self.request.event def get_object(self): if self.version == 'wip' and self.request.user.has_perm('orga.view_schedule', self.request.event): return self.request.event.wip_schedule return super().get_object() def get_context_data(self, *args, **kwargs): ctx = super().get_context_data(*args, **kwargs) tz = pytz.timezone(self.request.event.timezone)
_('Yay, your changes have been saved and the connection attempt to ' 'your SMTP server was successful.')) else: messages.success( self.request, _('We\'ve been able to contact the SMTP server you configured. ' 'Remember to check the "use custom SMTP server" checkbox, ' 'otherwise your SMTP server will not be used.')) else: messages.success(self.request, _('Yay! We saved your changes.')) ret = super().form_valid(form) return ret @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-inline'"), name='get') class EventTeam(EventSettingsPermission, TemplateView): template_name = 'orga/settings/team.html' @cached_property def formset(self): formset_class = forms.inlineformset_factory( Event, EventPermission, can_delete=True, extra=0, fields=[ 'is_orga', 'is_reviewer', 'review_override_count', 'invitation_email',
from django.conf.urls import url from djangae.utils import djangae_webapp from django.views.decorators.csrf import csrf_exempt # The Mapreduce status UI uses inline JS, which will fail If we have django-csp # installed and are not allowing 'unsafe-inline' as a SCRIPT_SRC. try: from csp.decorators import csp_update exempt_from_unsafe_inline = csp_update(SCRIPT_SRC=("'unsafe-inline'",)) except ImportError: exempt_from_unsafe_inline = lambda func: func try: from mapreduce.main import create_handlers_map wrapped_urls = [ url( url_re.replace('.*/', '^', 1), exempt_from_unsafe_inline(csrf_exempt(djangae_webapp(func))) ) for url_re, func in create_handlers_map() ] except ImportError as e: wrapped_urls = [] urlpatterns = wrapped_urls
elif self.request.GET["role"] == "false": qs = qs.exclude( user__submissions__in=self.request.event.submissions.filter( state__in=[ SubmissionStates.ACCEPTED, SubmissionStates.CONFIRMED, ] ) ) qs = qs.order_by("id").distinct() qs = self.sort_queryset(qs) return qs @method_decorator(csp_update(IMG_SRC="https://www.gravatar.com"), name="dispatch") class SpeakerDetail(PermissionRequired, ActionFromUrl, CreateOrUpdateView): template_name = "orga/speaker/form.html" form_class = SpeakerProfileForm model = User permission_required = "orga.view_speaker" write_permission_required = "orga.change_speaker" def get_object(self): return get_object_or_404( User.objects.filter( submissions__in=Submission.all_objects.filter(event=self.request.event) ) .order_by("id") .distinct(), pk=self.kwargs["pk"],
def next(self, request, event): from payments.models import CheckoutPayment order = get_order(request, event) payment = CheckoutPayment.from_order(order) payment.save() result = payment.perform_create_payment_request(request) return redirect(result["href"]) # Confirm view needs to be able to redirect to Checkout payment wall, so this needs to be included in CSP. tickets_confirm_phase = ConfirmPhase() tickets_confirm_view = csp_update(FORM_ACTION=CHECKOUT_PAYMENT_WALL_ORIGIN)( decorate(tickets_confirm_phase)) class ThanksPhase(Phase): name = "tickets_thanks_view" friendly_name = _("Thank you!") template = "tickets_thanks_phase.pug" prev_phase = None next_phase = "tickets_welcome_view" can_cancel = False def available(self, request, event): order = get_order(request, event) return order.is_confirmed and order.is_paid def vars(self, request, event, form):
from django.contrib import admin from django.contrib.flatpages import admin as flatpage_admin, forms as flatpage_forms from django.contrib.flatpages.models import FlatPage from django.utils import html from django.utils.decorators import method_decorator from django.utils.text import Truncator from .models import HierarchicalFlatPage # The CKEditorWidget requires inline css and javascript, which violate the # site-wide CSP. This decorator loosens the CSP on the admin pages that load # the editor widget. _CSP_UPDATE_DECORATOR = csp_update( SCRIPT_SRC=("'unsafe-inline'", 'www.webspellchecker.net/spellcheck31/'), STYLE_SRC="'unsafe-inline'", IMG_SRC='data:', # used by the iframe tools FRAME_SRC=( # used by ckeditor spell checker 'https://svc.webspellchecker.net/spellcheck/lf/23/banner/banner.html', 'www.webspellchecker.net/spellcheck/script/ssrv.cgi'), ) class ParentPageListFilter(admin.SimpleListFilter): title = "parent page" parameter_name = 'parent' def lookups(self, request, model_admin): pages = HierarchicalFlatPage.objects.children_for_url('/', depth=3) return [(p.url, p.url) for p in pages] def queryset(self, request, queryset):
Command as ExportScheduleHtml, ) from pretalx.agenda.tasks import export_schedule_html from pretalx.api.serializers.room import AvailabilitySerializer from pretalx.common.mixins.views import ( ActionFromUrl, EventPermissionRequired, PermissionRequired, ) from pretalx.common.signals import register_data_exporters from pretalx.common.views import CreateOrUpdateView from pretalx.orga.forms.schedule import ScheduleImportForm, ScheduleReleaseForm from pretalx.schedule.forms import QuickScheduleForm, RoomForm from pretalx.schedule.models import Availability, Room from pretalx.schedule.utils import guess_schedule_version @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-eval'"), name='dispatch') class ScheduleView(EventPermissionRequired, TemplateView): template_name = 'orga/schedule/index.html' permission_required = 'orga.view_schedule' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) version = self.request.GET.get('version') context['schedule_version'] = version context['active_schedule'] = ( self.request.event.schedules.filter(version=version).first() if version else self.request.event.wip_schedule ) return context
room.name, 'talks': [ talk for talk in talks.filter( start__gte=day_start(current_date), start__lte=day_end(current_date), room=room).order_by('start') ], } for room in event.rooms.all()], } for index, current_date in enumerate([ event.datetime_from + timedelta(days=i) for i in range((event.date_to - event.date_from).days + 1) ])] return ctx @method_decorator(csp_update(STYLE_SRC="'self' 'unsafe-inline'"), name='dispatch') class ScheduleView(ScheduleDataView): template_name = 'agenda/schedule.html' def get_object(self): obj = super().get_object() if not obj and self.request.is_orga: return self.request.event.wip_schedule return obj def get_context_data(self, *args, **kwargs): ctx = super().get_context_data(*args, **kwargs) tz = pytz.timezone(self.request.event.timezone) if 'data' in ctx: for date in ctx['data']:
form.instance.log_action( "pretalx_pages.page.added", data=dict(form.cleaned_data), person=self.request.user, orga=True, ) return ret def form_invalid(self, form): messages.error( self.request, _("We could not save your changes. See below for details.") ) return super().form_invalid(form) @method_decorator(csp_update(IMG_SRC="*"), name="dispatch") class ShowPageView(TemplateView): template_name = "pretalx_pages/show.html" def get_page(self): try: return Page.objects.get( event=self.request.event, slug__iexact=self.kwargs["slug"] ) except Page.DoesNotExist: raise Http404(_("The requested page does not exist.")) def get_context_data(self, **kwargs): ctx = super().get_context_data() page = self.get_page() ctx["page_title"] = page.title
else: raise Http404() @require_safe @etag(lambda r: getattr(settings, "DONATE_BITCOIN_ADDRESS", "")) @cache_page(60 * 60) # NOTE: if only etag is set, Django doesn't include cache headers def bitcoin_qrcode(request): """Return a QR Code for donating via Bitcoin.""" address = getattr(settings, "DONATE_BITCOIN_ADDRESS", None) if address: raw = make_qr_code( bitcoin_donation_url(get_current_site(request).name, address) ) return HttpResponse(raw.getvalue(), content_type="image/svg+xml") else: raise Http404 @method_decorator( csp_update( # https://github.com/praekelt/django-recaptcha/issues/101 # https://developers.google.com/recaptcha/docs/faq#im-using-content-security-policy-csp-on-my-website.-how-can-i-configure-it-to-work-with-recaptcha SCRIPT_SRC="'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/", FRAME_SRC="'self' https://www.google.com/recaptcha/", ), name="dispatch", ) class CaptchaSignupView(SignupView): pass
.. deprecated:: 0.8.2 Removed in favor of :func:`~api.v2.views.rapidoc`. """ return HttpResponse('Use /api/v2/docs/ instead', status=410) def _rapidoc(request: HttpRequest) -> HttpResponse: """ View that serves the RapiDoc_ documentation of the site. :param request: The original request. :return: A response with the rendered ``rapidoc.html`` template. .. _RapiDoc: https://mrin9.github.io/RapiDoc/ """ return render(request, 'rapidoc.html', { 'schema': reverse('api:v2:schema'), }) if find_spec('csp'): # pragma: no cover from csp.decorators import csp_update rapidoc = csp_update(style_src="'unsafe-inline'")(_rapidoc) else: rapidoc = _rapidoc rapidoc.__doc__ = _rapidoc.__doc__ __all__ = ['openapi', 'redoc_redirect', 'swagger_redirect', 'rapidoc']
from django.conf.urls import url from djangae.utils import djangae_webapp from django.views.decorators.csrf import csrf_exempt # The Mapreduce status UI uses inline JS, which will fail If we have django-csp # installed and are not allowing 'unsafe-inline' as a SCRIPT_SRC. try: from csp.decorators import csp_update exempt_from_unsafe_inline = csp_update(SCRIPT_SRC=("'unsafe-inline'", )) except ImportError: exempt_from_unsafe_inline = lambda func: func try: from mapreduce.main import create_handlers_map wrapped_urls = [ url(url_re.replace('.*/', '^', 1), exempt_from_unsafe_inline(csrf_exempt(djangae_webapp(func)))) for url_re, func in create_handlers_map() ] except ImportError as e: wrapped_urls = [] urlpatterns = wrapped_urls
"""The URLconf of the config app.""" from importlib.util import find_spec from django.conf import settings from django.contrib.flatpages.views import flatpage from django.urls import include, path info_page = flatpage if find_spec('csp'): # pragma: no cover from csp.decorators import csp_update info_page = csp_update(style_src="'unsafe-inline'", img_src="https:")(flatpage) #: The URL patterns of the config app. urlpatterns = [ path('info/', info_page, {'url': '/info/'}, name='info'), path('privacy/', info_page, {'url': '/privacy/'}, name='privacy'), ] if settings.DEBUG: # pragma: no cover from django.conf.urls.static import static urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) if find_spec('debug_toolbar'): from debug_toolbar import urls as djdt_urls urlpatterns.append(path('__debug__/', include(djdt_urls))) __all__ = ['urlpatterns']
FormView, ListView, TemplateView, UpdateView, View, ) from pretalx.cfp.forms.submissions import SubmissionInvitationForm from pretalx.cfp.views.event import LoggedInEventPageMixin from pretalx.common.phrases import phrases from pretalx.person.forms import LoginInfoForm, SpeakerProfileForm from pretalx.submission.forms import InfoForm, QuestionsForm, ResourceForm from pretalx.submission.models import Resource, Submission, SubmissionStates @method_decorator(csp_update(IMG_SRC="https://www.gravatar.com", SCRIPT_SRC="'self' 'unsafe-inline'"), name='dispatch') class ProfileView(LoggedInEventPageMixin, TemplateView): template_name = 'cfp/event/user_profile.html' @cached_property def login_form(self): return LoginInfoForm( user=self.request.user, data=(self.request.POST if self.request.method == 'POST' and self.request.POST.get('form') == 'login' else None)) @cached_property def profile_form(self): if self.request.method == 'POST' and self.request.POST.get( 'form') == 'profile':
from csp.decorators import csp_update from django.conf import settings from django.conf.urls import url, include from django.conf.urls.i18n import i18n_patterns from django.contrib import admin from django.views.decorators.http import etag from nextcloudappstore.core.caching import app_rating_etag from nextcloudappstore.core.feeds import AppReleaseAtomFeed, AppReleaseRssFeed from nextcloudappstore.core.views import CategoryAppListView, AppDetailView, \ app_description, AppReleasesView, AppUploadView, LegalNoticeView, \ AppRatingApi, AppRegisterView, AppScaffoldingView urlpatterns = [ url(r'^$', CategoryAppListView.as_view(), {'id': None}, name='home'), url(r"^signup/$", csp_update(**settings.CSP_SIGNUP)(signup), name="account_signup"), url(r"^social/signup/$", csp_update(**settings.CSP_SIGNUP)(social_signup), name="socialaccount_signup"), url(r'^', include('allauth.urls')), url(r'^legal/?$', LegalNoticeView.as_view(), name='legal-notice'), url(r'^categories/(?P<id>[\w]*)/?$', CategoryAppListView.as_view(), name='category-app-list'), url(r'^developer/apps/generate/?$', AppScaffoldingView.as_view(), name='app-scaffold'), url(r'^developer/apps/releases/new/?$', AppUploadView.as_view(), name='app-upload'), url(r'^developer/apps/new/?$', AppRegisterView.as_view(), name='app-register'), url(r'^apps/(?P<id>[\w_]+)/?$', AppDetailView.as_view(), name='app-detail'),
from django.views.generic import FormView, TemplateView, View from i18nfield.utils import I18nJSONEncoder from pretalx.agenda.management.commands.export_schedule_html import ( Command as ExportScheduleHtml, ) from pretalx.agenda.tasks import export_schedule_html from pretalx.common.mixins.views import ActionFromUrl, PermissionRequired from pretalx.common.signals import register_data_exporters from pretalx.common.views import CreateOrUpdateView from pretalx.orga.forms.schedule import ScheduleImportForm, ScheduleReleaseForm from pretalx.orga.views.event import EventSettingsPermission from pretalx.schedule.forms import RoomForm from pretalx.schedule.models import Availability, Room @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-eval'"), name='dispatch') class ScheduleView(PermissionRequired, TemplateView): template_name = 'orga/schedule/index.html' permission_required = 'orga.view_schedule' def get_permission_object(self): return self.request.event def get_context_data(self, event): context = super().get_context_data() version = self.request.GET.get('version') context['schedule_version'] = version context['active_schedule'] = self.request.event.schedules.filter( version=version).first( ) if version else self.request.event.wip_schedule
else: raise Http404() @require_safe @etag(lambda r: getattr(settings, "DONATE_BITCOIN_ADDRESS", "")) @cache_page( 60 * 60) # NOTE: if only etag is set, Django doesn't include cache headers def bitcoin_qrcode(request): """Return a QR Code for donating via Bitcoin.""" address = getattr(settings, "DONATE_BITCOIN_ADDRESS", None) if address: raw = make_qr_code( bitcoin_donation_url(get_current_site(request).name, address)) return HttpResponse(raw.getvalue(), content_type="image/svg+xml") else: raise Http404 @method_decorator( csp_update( # https://github.com/praekelt/django-recaptcha/issues/101 SCRIPT_SRC_ELEM= "'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/", FRAME_SRC="'self' https://www.google.com/recaptcha/", ), name="dispatch", ) class CaptchaSignupView(SignupView): pass
qs = qs.filter(user__submissions__state__in=[ SubmissionStates.ACCEPTED, SubmissionStates.CONFIRMED, ]) elif self.request.GET['role'] == 'false': qs = qs.exclude(user__submissions__state__in=[ SubmissionStates.ACCEPTED, SubmissionStates.CONFIRMED, ]) qs = qs.order_by('id').distinct() qs = self.sort_queryset(qs) return qs @method_decorator(csp_update(IMG_SRC="https://www.gravatar.com"), name='dispatch') class SpeakerDetail(PermissionRequired, ActionFromUrl, CreateOrUpdateView): template_name = 'orga/speaker/form.html' form_class = SpeakerProfileForm model = User permission_required = 'orga.view_speaker' write_permission_required = 'orga.change_speaker' def get_object(self): return get_object_or_404( User.objects.filter( Q(submissions__in=self.request.event.submissions.all()) | Q(submissions__in=self.request.event.submissions( manager='deleted_objects').all())).order_by( 'id').distinct(),
return qs class DefaultPagination(LimitOffsetPagination): default_limit = 50 max_limit = 100 @method_decorator( csp_update( IMG_SRC=( "maps.googleapis.com", # Google Maps "maps.gstatic.com", # Google Maps "cbks0.googleapis.com", "khms0.googleapis.com", "khms1.googleapis.com", "lh3.ggpht.com", "geo0.ggpht.com", # Google Street View "geo1.ggpht.com", # Google Street View "geo2.ggpht.com", # Google Street View "geo3.ggpht.com", # Google Street View ), SCRIPT_SRC=("maps.googleapis.com", "maps.gstatic.com")), name='dispatch') class CallsignDetailView(DetailView): queryset = Callsign.objects\ .select_related("prefix") \ .select_related("prefix__dxcc") \ .select_related("owner")\ .select_related("country") \ .select_related("country__telecommunicationagency") \ .select_related("clubloguser") \