Compare commits

...
15 changed files with 44 additions and 36 deletions

No files matched your search

+21
View File
@@ -266,6 +266,22 @@ def _merge_csp(a, b):
class SecurityMiddleware(MiddlewareMixin):
SAFE_TYPES = (
# CSP policies are only used for:
# - HTML and SVG in top-level contexts
# - SVG or JS Workers delivered in embedded contexts
# See: https://www.w3.org/TR/CSP2/#which-policy-applies
# Therefore, we can save bandwidth on not including our (sometimes huge) policy
# on API responses or CSS. We do however include it with other types as a precaution
# (whitelist instead of blacklist) and we also do not whitelist JavaScript in
# we ever add service workers to not break the protection of this feature:
# https://www.w3.org/TR/CSP2/#sandboxing-and-workers
'application/json',
'text/css',
# We used to skip CSP for PDF since it was necessary for inline previews in Safari,
# but at the moment it does not seem to be an issue to just send it.
)
def process_response(self, request, resp):
if settings.DEBUG and resp.status_code >= 400:
# Don't use CSP on debug error page as it breaks of Django's fancy error
@@ -277,6 +293,11 @@ class SecurityMiddleware(MiddlewareMixin):
# https://github.com/pretix/pretix/issues/765
resp['P3P'] = 'CP=\"ALL DSP COR CUR ADM TAI OUR IND COM NAV INT\"'
if "Content-Type" in resp and resp["Content-Type"].split(";")[0] in self.SAFE_TYPES:
if 'Content-Security-Policy' in resp:
del resp['Content-Security-Policy']
return resp
if not getattr(resp, '_csp_ignore', False):
resp['Content-Security-Policy'] = _render_csp(self._build_csp(request, resp))
elif 'Content-Security-Policy' in resp:
@@ -560,11 +560,10 @@
</div>
</div>
</div>
<script type="text/plain" id="schema-url">{% static "schema/pdf-layout.schema.json" %}</script>
<script type="text/javascript" src="{% static "pdfjs/pdf.js" %}"></script>
<script type="text/javascript" src="{% static "ajv/ajv2020.bundle.min.js" %}"></script>
<script type="text/javascript" src="{% static "fabric/fabric.min.js" %}"></script>
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/editor.js" %}"></script>
<script type="text/javascript" src="{% static "schema/pdf-layout.validate.js" %}"></script>
<img src="{% static 'pretixpresale/pdf/powered_by_pretix_dark.png' %}" id="poweredby-dark" class="sr-only">
<img src="{% static 'pretixpresale/pdf/powered_by_pretix_white.png' %}" id="poweredby-white" class="sr-only">
{% for family, styles in fonts.items %}
+6 -1
View File
@@ -952,7 +952,12 @@ class MailSettingsRendererPreview(MailSettingsPreview):
context=context,
)
r = HttpResponse(v, content_type='text/html')
r._csp_ignore = True
r['Content-Security-Policy'] = (
# Plugin-provided email templates will contain inline styles or remote images
# but emails should not contain JS
"style-src 'unsafe-inline'; "
"img-src https: data:"
)
return r
else:
raise Http404(_('Unknown email renderer.'))
-1
View File
@@ -70,7 +70,6 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
if 'placeholders' in request.GET:
return self.get_placeholders_help(request)
resp = super().get(request, *args, **kwargs)
resp._csp_ignore = True
return resp
def get_placeholders_help(self, request):
-1
View File
@@ -162,7 +162,6 @@ class XHRView(View):
paypal_order = prov._create_paypal_order(request, None, cart_total)
r = JsonResponse(paypal_order.dict() if paypal_order else {})
r._csp_ignore = True
return r
-1
View File
@@ -48,7 +48,6 @@ def theme_css(request, **kwargs):
obj = getattr(request, "event", request.organizer)
css = get_theme_vars_css(obj, widget=False)
resp = HttpResponse(css, content_type="text/css")
resp._csp_ignore = True
resp["Access-Control-Allow-Origin"] = "*"
if "version" in request.GET:
resp["Expires"] = http_date(time.time() + 3600 * 24 * 30)
-4
View File
@@ -164,7 +164,6 @@ def widget_css(request, version, **kwargs):
css = f"/* v{version} */\n" + theme_css + widget_css
resp = FileResponse(css, content_type='text/css')
resp._csp_ignore = True
resp['Access-Control-Allow-Origin'] = '*'
return resp
@@ -246,7 +245,6 @@ def widget_js(request, version, lang, **kwargs):
cached_js = cache.get(cache_prefix)
if cached_js and not settings.DEBUG:
resp = HttpResponse(cached_js, content_type='text/javascript')
resp._csp_ignore = True
resp['Access-Control-Allow-Origin'] = '*'
return resp
@@ -278,7 +276,6 @@ def widget_js(request, version, lang, **kwargs):
gs.settings.set(checksum_key, checksum)
cache.set(cache_prefix, data, 3600 * 4)
resp = HttpResponse(data, content_type='text/javascript')
resp._csp_ignore = True
resp['Access-Control-Allow-Origin'] = '*'
return resp
@@ -414,7 +411,6 @@ class WidgetAPIProductList(EventListMixin, View):
self.post_process(data)
resp = JsonResponse(data)
resp['Access-Control-Allow-Origin'] = '*'
resp._csp_ignore = True
return resp
def get(self, request, *args, **kwargs):
-7
View File
@@ -1,7 +0,0 @@
!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).ajv2020=e()}(function(){return function a(o,s,n){function i(t,e){if(!s[t]){if(!o[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(c)return c(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}r=s[t]={exports:{}},o[t][0].call(r.exports,function(e){return i(o[t][1][e]||e)},r,r.exports,a,o,s,n)}return s[t].exports}for(var c="function"==typeof require&&require,e=0;e<n.length;e++)i(n[e]);return i}({1:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.regexpCode=r.getEsmExportName=r.getProperty=r.safeStringify=r.stringify=r.strConcat=r.addCodeArg=r.str=r._=r.nil=r._Code=r.Name=r.IDENTIFIER=r._CodeOrName=void 0;class a{}r._CodeOrName=a,r.IDENTIFIER=/^[a-z$_][a-z$_0-9]*$/i;class n extends a{constructor(e){if(super(),!r.IDENTIFIER.test(e))throw new Error("CodeGen: name must be a valid identifier");this.str=e}toString(){return this.str}emptyStr(){return!1}get names(){return{[this.str]:1}}}r.Name=n;class i extends a{constructor(e){super(),this._items="string"==typeof e?[e]:e}toString(){return this.str}emptyStr(){if(1<this._items.length)return!1;var e=this._items[0];return""===e||'""'===e}get str(){var e;return null!=(e=this._str)?e:this._str=this._items.reduce((e,t)=>""+e+t,"")}get names(){var e;return null!=(e=this._names)?e:this._names=this._items.reduce((e,t)=>(t instanceof n&&(e[t.str]=(e[t.str]||0)+1),e),{})}}function o(e,...t){const r=[e[0]];let a=0;for(;a<t.length;)l(r,t[a]),r.push(e[++a]);return new i(r)}r._Code=i,r.nil=new i(""),r._=o;const c=new i("+");function s(e,...t){const r=[d(e[0])];let a=0;for(;a<t.length;)r.push(c),l(r,t[a]),r.push(c,d(e[++a]));{var o=r;let e=1;for(;e<o.length-1;){if(o[e]===c){var s=function(e,t){return'""'===t?e:'""'===e?t:"string"!=typeof e?"string"!=typeof t||'"'!==t[0]||e instanceof n?void 0:'"'+e+t.slice(1):t instanceof n||'"'!==e[e.length-1]?void 0:"string"!=typeof t?""+e.slice(0,-1)+t+'"':'"'===t[0]?e.slice(0,-1)+t.slice(1):void 0}(o[e-1],o[e+1]);if(void 0!==s){o.splice(e-1,3,s);continue}o[e++]="+"}e++}}return new i(r)}function l(e,t){t instanceof i?e.push(...t._items):t instanceof n?e.push(t):e.push("number"==typeof(e=t)||"boolean"==typeof e||null===e?e:d(Array.isArray(e)?e.join(","):e))}function d(e){return JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}r.str=s,r.addCodeArg=l,r.strConcat=function(e,t){return t.emptyStr()?e:e.emptyStr()?t:s`${e}${t}`},r.stringify=function(e){return new i(d(e))},r.safeStringify=d,r.getProperty=function(e){return"string"==typeof e&&r.IDENTIFIER.test(e)?new i("."+e):o`[${e}]`},r.getEsmExportName=function(e){if("string"==typeof e&&r.IDENTIFIER.test(e))return new i(""+e);throw new Error(`CodeGen: invalid export name: ${e}, use explicit $id name mapping`)},r.regexpCode=function(e){return new i(e.toString())}},{}],2:[function(e,D,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.or=r.and=r.not=r.CodeGen=r.operators=r.varKinds=r.ValueScopeName=r.ValueScope=r.Scope=r.Name=r.regexpCode=r.stringify=r.getProperty=r.nil=r.strConcat=r.str=r._=void 0;const n=e("./code"),i=e("./scope");var t=e("./code"),a=(Object.defineProperty(r,"_",{enumerable:!0,get:function(){return t._}}),Object.defineProperty(r,"str",{enumerable:!0,get:function(){return t.str}}),Object.defineProperty(r,"strConcat",{enumerable:!0,get:function(){return t.strConcat}}),Object.defineProperty(r,"nil",{enumerable:!0,get:function(){return t.nil}}),Object.defineProperty(r,"getProperty",{enumerable:!0,get:function(){return t.getProperty}}),Object.defineProperty(r,"stringify",{enumerable:!0,get:function(){return t.stringify}}),Object.defineProperty(r,"regexpCode",{enumerable:!0,get:function(){return t.regexpCode}}),Object.defineProperty(r,"Name",{enumerable:!0,get:function(){return t.Name}}),e("./scope"));Object.defineProperty(r,"Scope",{enumerable:!0,get:function(){return a.Scope}}),Object.defineProperty(r,"ValueScope",{enumerable:!0,get:function(){return a.ValueScope}}),Object.defineProperty(r,"ValueScopeName",{enumerable:!0,get:function(){return a.ValueScopeName}}),Object.defineProperty(r,"varKinds",{enumerable:!0,get:function(){return a.varKinds}}),r.operators={GT:new n._Code(">"),GTE:new n._Code(">="),LT:new n._Code("<"),LTE:new n._Code("<="),EQ:new n._Code("==="),NEQ:new n._Code("!=="),NOT:new n._Code("!"),OR:new n._Code("||"),AND:new n._Code("&&"),ADD:new n._Code("+")};class o{optimizeNodes(){return this}optimizeNames(e,t){return this}}class s extends o{constructor(e,t,r){super(),this.varKind=e,this.name=t,this.rhs=r}render({es5:e,_n:t}){var e=e?i.varKinds.var:this.varKind,r=void 0===this.rhs?"":" = "+this.rhs;return`${e} ${this.name}${r};`+t}optimizeNames(e,t){if(e[this.name.str])return this.rhs&&(this.rhs=O(this.rhs,e,t)),Line truncated
|| (${a} == "string" && ${n} && ${n} == +${n})`).assign(i,(0,m._)`+${n}`);case"integer":return s.elseIf((0,m._)`${a} === "boolean" || ${n} === null
|| (${a} === "string" && ${n} && ${n} == +${n} && !(${n} % 1))`).assign(i,(0,m._)`+${n}`);case"boolean":return s.elseIf((0,m._)`${n} === "false" || ${n} === 0 || ${n} === null`).assign(i,!1).elseIf((0,m._)`${n} === "true" || ${n} === 1`).assign(i,!0);case"null":return s.elseIf((0,m._)`${n} === "" || ${n} === 0 || ${n} === false`),s.assign(i,null);case"array":s.elseIf((0,m._)`${a} === "string" || ${a} === "number"
|| ${a} === "boolean" || ${n} === null`).assign(i,(0,m._)`[${n}]`)}}(c);s.else(),h(o),s.endIf(),s.if((0,m._)`${i} !== undefined`,()=>{var e,t,r,a;s.assign(n,i),[{gen:e,parentData:t,parentDataProperty:r},a]=[o,i],e.if((0,m._)`${t} !== undefined`,()=>e.assign((0,m._)`${t}[${r}]`,a))})}else h(l)})),s};const p=new Set(["string","number","integer","boolean","null"]);function l(e,t,r,a=c.Correct){var o=a===c.Correct?m.operators.EQ:m.operators.NEQ;let s;switch(e){case"null":return(0,m._)`${t} ${o} null`;case"array":s=(0,m._)`Array.isArray(${t})`;break;case"object":s=(0,m._)`${t} && typeof ${t} == "object" && !Array.isArray(${t})`;break;case"integer":s=n((0,m._)`!(${t} % 1) && !isNaN(${t})`);break;case"number":s=n();break;default:return(0,m._)`typeof ${t} ${o} ${e}`}return a===c.Correct?s:(0,m.not)(s);function n(e=m.nil){return(0,m.and)((0,m._)`typeof ${t} == "number"`,e,r?(0,m._)`isFinite(${t})`:m.nil)}}function f(e,t,r,a){if(1===e.length)return l(e[0],t,r,a);let o;const s=(0,i.toHash)(e);s.array&&s.object?(e=(0,m._)`typeof ${t} != "object"`,o=s.null?e:(0,m._)`!${t} || ${e}`,delete s.null,delete s.array,delete s.object):o=m.nil,s.number&&delete s.integer;for(const n in s)o=(0,m.and)(o,l(n,t,r,a));return o}r.checkDataType=l,r.checkDataTypes=f;const d={message:({schema:e})=>"must be "+e,params:({schema:e,schemaValue:t})=>"string"==typeof e?(0,m._)`{type: ${e}}`:(0,m._)`{type: ${t}}`};function h(e){e=function(e){var{gen:t,data:r,schema:a}=e,o=(0,i.schemaRefOrVal)(e,a,"type");return{gen:t,keyword:"type",data:r,schema:a.type,schemaCode:o,schemaValue:o,parentSchema:a,params:{},it:e}}(e);(0,o.reportError)(e,d)}r.reportTypeError=h},{"../codegen":2,"../errors":4,"../rules":9,"../util":10,"./applicability":11}],14:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.assignDefaults=void 0;const i=e("../codegen"),c=e("../util");function s(e,t,r){const{gen:a,compositeRule:o,data:s,opts:n}=e;if(void 0!==r){t=(0,i._)`${s}${(0,i.getProperty)(t)}`;if(o)(0,c.checkStrictMode)(e,"default is ignored for: "+t);else{let e=(0,i._)`${t} === undefined`;"empty"===n.useDefaults&&(e=(0,i._)`${e} || ${t} === null || ${t} === ""`),a.if(e,(0,i._)`${t} = ${(0,i.stringify)(r)}`)}}}r.assignDefaults=function(r,e){const{properties:t,items:a}=r.schema;if("object"===e&&t)for(const o in t)s(r,o,t[o].default);else"array"===e&&Array.isArray(a)&&a.forEach((e,t)=>s(r,t,e.default))}},{"../codegen":2,"../util":10}],15:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.getData=r.KeywordCxt=r.validateFunctionCode=void 0;const l=e("./boolSchema"),a=e("./dataType"),E=e("./applicability"),P=e("./dataType"),s=e("./defaults"),o=e("./keyword"),n=e("./subschema"),S=e("../codegen"),j=e("../names"),d=e("../resolve"),N=e("../util"),i=e("../errors");function c({gen:r,validateName:e,schema:a,schemaEnv:t,opts:o},s){o.code.es5?r.func(e,(0,S._)`${j.default.data}, ${j.default.valCxt}`,t.$async,()=>{var e,t;r.code((0,S._)`"use strict"; ${u(a,o)}`),t=o,(e=r).if(j.default.valCxt,()=>{e.var(j.default.instancePath,(0,S._)`${j.default.valCxt}.${j.default.instancePath}`),e.var(j.default.parentData,(0,S._)`${j.default.valCxt}.${j.default.parentData}`),e.var(j.default.parentDataProperty,(0,S._)`${j.default.valCxt}.${j.default.parentDataProperty}`),e.var(j.default.rootData,(0,S._)`${j.default.valCxt}.${j.default.rootData}`),t.dynamicRef&&e.var(j.default.dynamicAnchors,(0,S._)`${j.default.valCxt}.${j.default.dynamicAnchors}`)},()=>{e.var(j.default.instancePath,(0,S._)`""`),e.var(j.default.parentData,(0,S._)`undefined`),e.var(j.default.parentDataProperty,(0,S._)`undefined`),e.var(j.default.rootData,j.default.data),t.dynamicRef&&e.var(j.default.dynamicAnchors,(0,S._)`{}`)}),r.code(s)}):r.func(e,(0,S._)`${j.default.data}, ${e=o,(0,S._)`{${j.default.instancePath}="", ${j.default.parentData}, ${j.default.parentDataProperty}, ${j.default.rootData}=${j.default.data}${e.dynamicRef?(0,S._)`, ${j.default.dynamicAnchors}={}`:S.nil}}={}`}`,t.$async,()=>r.code(u(a,o)).code(s))}function u(e,t){e="object"==typeof e&&e[t.schemaId];return e&&(t.code.source||t.code.process)?(0,S._)`/*# sourceURL=${e} */`:S.nil}function m(e,t){if(f(e)&&($(e),p(e))){var r=e,a=t;const{schema:n,gen:i,opts:c}=r;c.$comment&&n.$comment&&b(r);var o=r,s=o.schema[o.opts.schemaId],o=(s&&(o.baseId=(0,d.resolveUrl)(o.opts.uriResolver,o.baseId,s)),r);if(o.schema.$async&&!o.schemaEnv.$async)throw new Error("async schema in sync schema");s=i.const("_errs",j.default.errors);_(r,s),i.var(a,(0,S._)`${s} === ${j.default.errors}`)}else(0,l.boolOrEmptySchema)(e,t)}function p({schema:e,self:t}){if("boolean"==typeof e)return!e;for(const r in e)if(t.RULES.all[r])return 1}function f(e){return"boolean"!=typeof e.schema}function $(e){(0,N.checkUnknownRules)(e);{const{schema:t,errSchemaPath:r,opts:a,self:o}=e;return void(t.$ref&&a.ignoreKeywordsWithRef&&(0,N.schemaHasRulesButRef)(t,o.RULES)&&o.logger.warn(`$ref: keywords ignored in schema at path "${r}"`))}}function _(e,t){if(e. Line truncated
missingProperty: ${a},
depsCount: ${t},
deps: ${r}}`};e={keyword:"dependencies",type:"object",schemaType:"object",error:r.error,code(e){var[t,r]=function({schema:e}){var t={},r={};for(const a in e)if("__proto__"!==a){const o=Array.isArray(e[a])?t:r;o[a]=e[a]}return[t,r]}(e);a(e,t),o(e,r)}};function a(t,e=t.schema){const{gen:r,data:a,it:o}=t;if(0!==Object.keys(e).length){var s,n=r.let("missing");for(const i in e){const c=e[i];0!==c.length&&(s=(0,d.propertyInData)(r,a,i,o.opts.ownProperties),t.setParams({property:i,depsCount:c.length,deps:c.join(", ")}),o.allErrors?r.if(s,()=>{for(const e of c)(0,d.checkReportMissingProp)(t,e)}):(r.if((0,l._)`${s} && (${(0,d.checkMissingProp)(t,c,n)})`),(0,d.reportMissingProp)(t,n),r.else()))}}}function o(t,e=t.schema){const{gen:r,data:a,keyword:o,it:s}=t,n=r.name("valid");for(const i in e)(0,c.alwaysValidSchema)(s,e[i])||(r.if((0,d.propertyInData)(r,a,i,s.opts.ownProperties),()=>{var e=t.subschema({keyword:o,schemaProp:i},n);t.mergeValidEvaluated(e,n)},()=>r.var(n,!0)),t.ok(n))}r.validatePropertyDeps=a,r.validateSchemaDeps=o,r.default=e},{"../../compile/codegen":2,"../../compile/util":10,"../code":51}],39:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});const a=e("./dependencies");r.default={keyword:"dependentSchemas",type:"object",schemaType:"object",code:e=>(0,a.validateSchemaDeps)(e)}},{"./dependencies":38}],40:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});const d=e("../../compile/codegen"),u=e("../../compile/util");function m(e,t){t=e.schema[t];return void 0!==t&&!(0,u.alwaysValidSchema)(e,t)}r.default={keyword:"if",schemaType:["object","boolean"],trackErrors:!0,error:{message:({params:e})=>(0,d.str)`must match "${e.ifClause}" schema`,params:({params:e})=>(0,d._)`{failingKeyword: ${e.ifClause}}`},code(a){const{gen:o,parentSchema:e,it:t}=a;void 0===e.then&&void 0===e.else&&(0,u.checkStrictMode)(t,'"if" without "then" and "else" is ignored');var r,s=m(t,"then"),n=m(t,"else");if(s||n){const c=o.let("valid",!0),l=o.name("_valid");function i(t,r){return()=>{var e=a.subschema({keyword:t},l);o.assign(c,l),a.mergeValidEvaluated(e,c),r?o.assign(r,(0,d._)`${t}`):a.setParams({ifClause:t})}}r=a.subschema({keyword:"if",compositeRule:!0,createErrors:!1,allErrors:!1},l),a.mergeEvaluated(r),a.reset(),s&&n?(r=o.let("ifClause"),a.setParams({ifClause:r}),o.if(l,i("then",r),i("else",r))):s?o.if(l,i("then")):o.if((0,d.not)(l),i("else")),a.pass(c,()=>a.error(!0))}}}},{"../../compile/codegen":2,"../../compile/util":10}],41:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});const a=e("./additionalItems"),o=e("./prefixItems"),s=e("./items"),n=e("./items2020"),i=e("./contains"),c=e("./dependencies"),l=e("./propertyNames"),d=e("./additionalProperties"),u=e("./properties"),m=e("./patternProperties"),p=e("./not"),f=e("./anyOf"),h=e("./oneOf"),y=e("./allOf"),v=e("./if"),g=e("./thenElse");r.default=function(e=!1){const t=[p.default,f.default,h.default,y.default,v.default,g.default,l.default,d.default,c.default,u.default,m.default];return e?t.push(o.default,n.default):t.push(a.default,s.default),t.push(i.default),t}},{"./additionalItems":33,"./additionalProperties":34,"./allOf":35,"./anyOf":36,"./contains":37,"./dependencies":38,"./if":40,"./items":42,"./items2020":43,"./not":44,"./oneOf":45,"./patternProperties":46,"./prefixItems":47,"./properties":48,"./propertyNames":49,"./thenElse":50}],42:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.validateTuple=void 0;const f=e("../../compile/codegen"),h=e("../../compile/util"),a=e("../code");e={keyword:"items",type:"array",schemaType:["object","array","boolean"],before:"uniqueItems",code(e){const{schema:t,it:r}=e;if(Array.isArray(t))return o(e,"additionalItems",t);r.items=!0,(0,h.alwaysValidSchema)(r,t)||e.ok((0,a.validateArray)(e))}};function o(r,e,t=r.schema){const{gen:a,parentSchema:o,data:s,keyword:n,it:i}=r;var c=o,{opts:l,errSchemaPath:d}=i,u=t.length,c=u===c.minItems&&(u===c.maxItems||!1===c[e]);l.strictTuples&&!c&&(c=`"${n}" is ${u}-tuple, but minItems or maxItems/${e} are not specified or different at path "${d}"`,(0,h.checkStrictMode)(i,c,l.strictTuples)),i.opts.unevaluated&&t.length&&!0!==i.items&&(i.items=h.mergeEvaluated.items(a,t.length,i.items));const m=a.name("valid"),p=a.const("len",(0,f._)`${s}.length`);t.forEach((e,t)=>{(0,h.alwaysValidSchema)(i,e)||(a.if((0,f._)`${p} > ${t}`,()=>r.subschema({keyword:n,schemaProp:t,dataProp:t},m)),r.ok(m))})}r.validateTuple=o,r.default=e},{"../../compile/codegen":2,"../../compile/util":10,"../code":51}],43:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});const a=e("../../compile/codegen"),s=e("../../compile/util"),n=e("../code"),i=e("./additionalItems");r.default={keyword:"items",type:"array",schemaType:["object","boolean"],before:"uniqueItems",error:{message:({params:{len:e}})=>(0,a.str)`must NOT have more than ${e} items`,params:({params:{len:e}})=>(0,a._)`{limit: ${e}}`},code(e){const{s Line truncated
@@ -1,4 +1,7 @@
/*globals $, gettext, fabric, PDFJS*/
window.module = {} // Hack to load ajv-compiled schema without actual module loading
fabric.Poweredby = fabric.util.createClass(fabric.Image, {
type: 'poweredby',
@@ -219,7 +222,6 @@ var editor = {
uploaded_file_id: null,
_window_loaded: false,
_fabric_loaded: false,
schema: null,
_px2mm: function (v) {
return v / editor.pdf_scale / 72 * editor.pdf_page.userUnit * 25.4;
@@ -1320,14 +1322,11 @@ var editor = {
_source_save: function () {
try {
var Ajv = window.ajv2020
var ajv = new Ajv()
var validate = ajv.compile(editor.schema)
var data = JSON.parse($("#source-textarea").val())
var valid = validate(data)
var valid = validate30(data)
if (!valid) {
console.log(validate.errors)
console.log(validate30.errors)
alert("Invalid input syntax. If you're familiar with this, check out the developer console for a full " +
"error log. Otherwise, please contact support.")
} else {
@@ -1463,10 +1462,6 @@ var editor = {
editor._update_save_button();
});
$("#pdf-info-width, #pdf-info-height").bind('change input', editor._paper_size_warning);
$.getJSON($("#schema-url").text(), function (data) {
editor.schema = data;
})
}
};
@@ -1,5 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$comment": "If the schema is changed, regenerate pdf-layout.validate.js with $ ajv compile -s ./pretix/static/schema/pdf-layout.schema.json --spec=draft2020 -o ./pretix/static/schema/pdf-layout.validate.js",
"title": "Ticket Layout",
"description": "Dynamic elements for a PDF layout",
"type": "array",
@@ -0,0 +1 @@
"use strict";module.exports = validate30;module.exports.default = validate30;const schema42 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"If the schema is changed, regenerate pdf-layout.validate.js with $ ajv compile -s ./pretix/static/schema/pdf-layout.schema.json --spec=draft2020 -o ./pretix/static/schema/pdf-layout.validate.js","title":"Ticket Layout","description":"Dynamic elements for a PDF layout","type":"array","items":{"type":"object","description":"Layout object","oneOf":[{"required":["type","left","bottom","size"],"properties":{"type":{"type":"string","const":"barcodearea"},"page":{"description":"Page number this will be shown on, defaults to 1.","type":"number"},"left":{"description":"Position of the element on the x axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"bottom":{"description":"Position of the element on the y axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"content":{"description":"Name of a variable to use. The available values depend on event configuration and installed plugins. Defaults to 'secret'.","type":"string"},"text":{"description":"Custom text. Only used when 'content' is set to 'other'.","type":"string"},"text_i18n":{"description":"Custom text in multiple languages. Only used when 'content' is set to 'other_i18n'.","type":"object","patternProperties":{"[a-zA-Z-]+":{"type":"string"}},"additionalProperties":false},"size":{"description":"Size of the barcode in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"nowhitespace":{"description":"Whether a barcode should be rendered without margins. Only used for type 'barcodearea'.","type":"boolean"},"color":{"description":"QR color as a tuple of three integers in the 0-255 range and one float in the 0-1 range. The last value (alpha) is ignored by the current implementation but might be used in the future.","type":"array","items":{"type":"number","minimum":0,"maximum":255},"minItems":3,"maxItems":4}},"additionalProperties":false},{"required":["type","left","bottom","content","width","height"],"properties":{"type":{"type":"string","const":"imagearea"},"page":{"description":"Page number this will be shown on, defaults to 1.","type":"number"},"left":{"description":"Position of the element on the x axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"bottom":{"description":"Position of the element on the y axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"content":{"description":"Name of a variable to use. The available values depend on event configuration and installed plugins.","type":"string"},"width":{"description":"Width of the element in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"height":{"description":"Height of the element in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]}},"additionalProperties":false},{"required":["type","left","bottom","content","width","height","fontsize","fontfamily","bold","italic","align","verticalalign","color"],"properties":{"type":{"type":"string","const":"textcontainer"},"page":{"description":"Page number this will be shown on, defaults to 1.","type":"number"},"left":{"description":"Position of the element on the x axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"bottom":{"description":"Position of the element on the y axis in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"width":{"description":"Width of the element in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"height":{"description":"Width of the element in millimeters.","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"content":{"description":"Name of a variable to use. The available values depend on event configuration and installed plugins.","type":"string"},"text":{"description":"Custom text. Only used when 'content' is set to 'other'.","type":"string"},"text_i18n":{"description":"Custom text in multiple languages. Only used when 'content' is set to 'other_i18n'.","type":"object","patternProperties":{"[a-zA-Z-]+":{"type":"string"}},"additionalProperties":false},"locale":{"description":"Locale to render the text in.","type":["string","null"],"pattern":"[a-zA-Z-]*"},"fontsize":{"description":"Font size","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"lineheight":{"description":"Line height","oneOf":[{"type":"number"},{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$"}]},"fontfamily":{"description":"Font family. The available values depend on installed plugins.","type":"string"},"bold":{"description":"Use bold font variant.","type":"boolLine truncated
+2 -2
View File
@@ -258,7 +258,7 @@ def test_list_list(token_client, organizer, event, clist, item, subevent, django
res["id"] = clist.pk
res["limit_products"] = [item.pk]
with django_assert_num_queries(11):
with django_assert_num_queries(9):
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert [res] == resp.data['results']
@@ -437,7 +437,7 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
p3["addon_to"] = p1["id"]
# All items
with django_assert_num_queries(24):
with django_assert_num_queries(22):
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/?ordering=positionid'.format(
organizer.slug, event.slug, clist_all.pk
))
+4 -4
View File
@@ -1865,7 +1865,7 @@ def test_event_expand_seat_filter_and_querycount(token_client, organizer, event,
assert resp.status_code == 200
event.refresh_from_db()
with assert_num_queries(12):
with assert_num_queries(10):
resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'
'?expand=orderposition&expand=cartposition&expand=voucher&is_available=true'
.format(organizer.slug, event.slug))
@@ -1875,7 +1875,7 @@ def test_event_expand_seat_filter_and_querycount(token_client, organizer, event,
with scope(organizer=organizer):
v0 = event.vouchers.create(item=item, seat=event.seats.get(seat_guid='0-0'))
with assert_num_queries(14):
with assert_num_queries(12):
resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'
'?expand=orderposition&expand=cartposition&expand=voucher&is_available=false'
.format(organizer.slug, event.slug))
@@ -1883,7 +1883,7 @@ def test_event_expand_seat_filter_and_querycount(token_client, organizer, event,
assert len(resp.data['results']) == 1
assert resp.data['results'][0]['voucher']['id'] == v0.pk
with assert_num_queries(12):
with assert_num_queries(10):
resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'
'?expand=orderposition&expand=cartposition&expand=voucher&is_available=true'
.format(organizer.slug, event.slug))
@@ -1894,7 +1894,7 @@ def test_event_expand_seat_filter_and_querycount(token_client, organizer, event,
v1 = event.vouchers.create(item=item, seat=event.seats.get(seat_guid='0-1'))
v2 = event.vouchers.create(item=item, seat=event.seats.get(seat_guid='0-2'))
with assert_num_queries(16):
with assert_num_queries(14):
resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'
'?expand=orderposition&expand=cartposition&expand=voucher&is_available=false'
.format(organizer.slug, event.slug))
+1 -1
View File
@@ -425,7 +425,7 @@ def test_item_list(token_client, organizer, event, team, item):
@pytest.mark.django_db
def test_item_list_queries(token_client, organizer, event, team, item, item3):
with assert_num_queries(18):
with assert_num_queries(16):
resp = token_client.get('/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
+2 -2
View File
@@ -1166,10 +1166,10 @@ def test_orderposition_list(
'type': 'entry'
}]
if '/events/' in endpoint:
with django_assert_num_queries(18):
with django_assert_num_queries(16):
resp = token_client.get(endpoint + '?has_checkin=true')
else:
with django_assert_num_queries(17):
with django_assert_num_queries(15):
resp = token_client.get(endpoint + '?has_checkin=true')
assert [res] == resp.data['results']