mirror of
https://github.com/pretix/pretix.git
synced 2026-11-11 01:27:08 +00:00
switch to get_cleaned_setting everywhere
This commit is contained in:
1 parent
cd4da853da
commit
b3e40e9536
4 files changed
+95
-74
No files matched your search
@@ -11,7 +11,6 @@ import cryptography.hazmat.primitives.hashes
|
||||
import cryptography.hazmat.primitives.serialization.pkcs7
|
||||
import cryptography.x509
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.forms import ValidationError
|
||||
from django.utils.encoding import force_bytes
|
||||
@@ -180,18 +179,32 @@ class AppleWalletStyle(PassStyle):
|
||||
default="pretixplugins/wallet/icon.png",
|
||||
),
|
||||
ImageSettingsField(identifier="background", label=_("Background Image")),
|
||||
ColorSettingsField(identifier="bg_color", label=_("Background Color")),
|
||||
ColorSettingsField(
|
||||
identifier="bg_color",
|
||||
label=_("Background Color"),
|
||||
),
|
||||
ColorSettingsField(
|
||||
identifier="fg_color",
|
||||
label=_("Foreground Color"),
|
||||
help_text=_(
|
||||
"This color is ignored if a background image is set. Instead, the text will be displayed in white."
|
||||
),
|
||||
default=self.event.settings.primary_color,
|
||||
),
|
||||
ColorSettingsField(identifier="label_color", label=_("Label Color")),
|
||||
FloatSettingsField(identifier="lat", label=_("Latitude"), min=-90, max=90),
|
||||
FloatSettingsField(
|
||||
identifier="long", label=_("Longitude"), min=-180, max=180
|
||||
identifier="lat",
|
||||
label=_("Latitude"),
|
||||
min=-90,
|
||||
max=90,
|
||||
default=self.event.geo_lat,
|
||||
),
|
||||
FloatSettingsField(
|
||||
identifier="long",
|
||||
label=_("Longitude"),
|
||||
min=-180,
|
||||
max=180,
|
||||
default=self.event.geo_lon,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -235,17 +248,21 @@ class AppleWalletStyle(PassStyle):
|
||||
}
|
||||
|
||||
# TODO: Apples specs says this should be "specified as a CSS-style RGB triple, such as rgb(100, 10, 110).", but hex codes work as well
|
||||
if bg_color := self.layout["settings"].get("bg_color"):
|
||||
if bg_color := self.get_cleaned_setting("bg_color"):
|
||||
pass_json["backgroundColor"] = bg_color
|
||||
if self.file_settings.get("background"):
|
||||
if fg_color := self.get_cleaned_setting("fg_color"):
|
||||
pass_json["foregroundColor"] = fg_color
|
||||
if label_color := self.get_cleaned_setting("label_color"):
|
||||
pass_json["labelColor"] = label_color
|
||||
|
||||
if self.get_cleaned_setting("background"):
|
||||
# iOS ignores the set foregroundColor if a background is set and uses white instead.
|
||||
# Explicitly set white in this case so the pass looks the same on all platforms
|
||||
# https://developer.apple.com/forums/thread/809417
|
||||
pass_json["foregroundColor"] = "#ffffff"
|
||||
elif fg_color := self.layout["settings"].get("fg_color"):
|
||||
pass_json["foregroundColor"] = fg_color
|
||||
if label_color := self.layout["settings"].get("label_color"):
|
||||
pass_json["labelColor"] = label_color
|
||||
# macOS always shows transparency as black, iOS as backgroundColor.
|
||||
# Explicitly set black in this case so the pass looks the same on all platforms
|
||||
pass_json["backgroundColor"] = "#000000"
|
||||
|
||||
if "expirationDate" not in pass_json:
|
||||
if op.valid_until:
|
||||
@@ -280,15 +297,12 @@ class AppleWalletStyle(PassStyle):
|
||||
# TODO: also fill relevantDates from program times
|
||||
|
||||
if "locations" not in pass_json:
|
||||
if "lat" in self.layout["settings"] and "long" in self.layout["settings"]:
|
||||
if (lat := self.get_cleaned_setting("lat")) and (
|
||||
long := self.get_cleaned_setting("long")
|
||||
):
|
||||
pass_json["locations"] = {
|
||||
"latitude": float(self.layout["settings"]["lat"]),
|
||||
"longitude": float(self.layout["settings"]["long"]),
|
||||
}
|
||||
elif event.geo_lat and event.geo_lon:
|
||||
pass_json["locations"] = {
|
||||
"latitude": float(event.get_lat),
|
||||
"longitude": float(event.get_lon),
|
||||
"latitude": lat,
|
||||
"longitude": long,
|
||||
}
|
||||
|
||||
return pass_json
|
||||
@@ -308,31 +322,26 @@ class AppleWalletStyle(PassStyle):
|
||||
|
||||
pass_json = self.generate_pass_json(fields, op, strings)
|
||||
|
||||
if file := self.file_settings.get("logo"):
|
||||
if file := self.get_cleaned_setting("logo"):
|
||||
logo = convert_to_png(
|
||||
file, (480, 150)
|
||||
file.file, (480, 150)
|
||||
) # TODO: check max_size against apple HIG
|
||||
else:
|
||||
logo = open(finders.find("pretixplugins/wallet/logo.png"), "rb")
|
||||
|
||||
if file := self.file_settings.get("icon"):
|
||||
if file := self.get_cleaned_setting("icon"):
|
||||
icon = convert_to_png(
|
||||
file, max_size=(87, 87)
|
||||
file.file, max_size=(87, 87)
|
||||
) # TODO: check max_size against apple HIG
|
||||
else:
|
||||
icon = open(finders.find("pretixplugins/wallet/icon.png"), "rb")
|
||||
|
||||
pkpass.add_file("icon.png", icon.read())
|
||||
pkpass.add_file("logo.png", logo.read())
|
||||
|
||||
if file := self.file_settings.get("background"):
|
||||
if file := self.get_cleaned_setting("background"):
|
||||
background = convert_to_png(
|
||||
file, max_size=(540, 660)
|
||||
file.file, max_size=(540, 660)
|
||||
) # TODO: check max_size against apple HIG
|
||||
pkpass.add_file("background.png", background.read())
|
||||
|
||||
for lang, content in strings.generate().items():
|
||||
print(lang, content)
|
||||
pkpass.add_file(f"{lang}.lproj/pass.strings", content)
|
||||
pkpass.add_file("pass.json", json.dumps(pass_json))
|
||||
result = pkpass.finish()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import enum
|
||||
from functools import cached_property
|
||||
from typing import Any, Literal, TypedDict
|
||||
from typing import Any, BinaryIO, Literal, TypedDict
|
||||
from django.contrib.staticfiles import finders
|
||||
|
||||
import jsonschema
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -456,6 +457,15 @@ class BooleanSettingsField(SettingsField):
|
||||
return {"type": "boolean"}
|
||||
|
||||
|
||||
class SettingsFile:
|
||||
url: str
|
||||
file: BinaryIO
|
||||
|
||||
def __init__(self, url, file):
|
||||
self.url = url
|
||||
self.file = file
|
||||
|
||||
|
||||
class PassStyle:
|
||||
identifier: str # unique within platform
|
||||
name: str
|
||||
@@ -491,7 +501,7 @@ class PassStyle:
|
||||
def preview_data(self) -> dict:
|
||||
return {}
|
||||
|
||||
def get_cleaned_setting(self, setting_identifier: str):
|
||||
def get_cleaned_setting(self, setting_identifier: str) -> SettingsFile | str | float | bool | None:
|
||||
if not self.layout:
|
||||
raise ValueError("`layout` needs to be set")
|
||||
|
||||
@@ -502,15 +512,19 @@ class PassStyle:
|
||||
|
||||
if isinstance(setting, ImageSettingsField):
|
||||
if setting.identifier in self.file_settings:
|
||||
return self.file_settings[setting.identifier].url
|
||||
return SettingsFile(self.file_settings[setting.identifier].url, self.file_settings[setting.identifier])
|
||||
elif isinstance(setting._default, File):
|
||||
return SettingsFile(setting._default.url, setting._default)
|
||||
elif isinstance(setting._default, str):
|
||||
return SettingsFile(static(setting._default), File(None, finders.find(setting._default)))
|
||||
else:
|
||||
if val := self.layout.get("settings", {}).get(
|
||||
setting.identifier, setting.default
|
||||
):
|
||||
return val
|
||||
|
||||
if setting.default:
|
||||
return setting.default
|
||||
if setting.default:
|
||||
return setting.default
|
||||
|
||||
def asdict(self):
|
||||
context = LayoutContext(
|
||||
|
||||
@@ -136,11 +136,13 @@ class GoogleWalletEventTicketStyle(PassStyle):
|
||||
self.put_item_cached(Resource.EVENT_TICKET_CLASS, class_object)
|
||||
self.put_item_cached(Resource.EVENT_TICKET_OBJECT, ticket_object)
|
||||
|
||||
generated_jwt = ButtonJWT(
|
||||
origins=[settings.SITE_URL],
|
||||
issuer=self.comms.client_email,
|
||||
payload={"eventTicketObjects": [ticket_object]},
|
||||
).sign(self.comms)
|
||||
generated_jwt = self.comms.sign_jwt(
|
||||
ButtonJWT(
|
||||
origins=[settings.SITE_URL],
|
||||
issuer=self.comms.client_email,
|
||||
payload={"eventTicketObjects": [ticket_object]},
|
||||
).serialize()
|
||||
)
|
||||
|
||||
return (
|
||||
"googlepaypass",
|
||||
@@ -167,9 +169,9 @@ class GoogleWalletEventTicketStyle(PassStyle):
|
||||
label=_("Background Color"),
|
||||
default=self.event.settings.primary_color,
|
||||
),
|
||||
FloatSettingsField(identifier="lat", label=_("Latitude"), min=-90, max=90),
|
||||
FloatSettingsField(identifier="lat", label=_("Latitude"), min=-90, max=90, default=self.event.geo_lat),
|
||||
FloatSettingsField(
|
||||
identifier="long", label=_("Longitude"), min=-180, max=180
|
||||
identifier="long", label=_("Longitude"), min=-180, max=180, default=self.event.geo_lon
|
||||
),
|
||||
BooleanSettingsField(
|
||||
identifier="shimmer", label=_("Add shimmer animation around barcode")
|
||||
@@ -244,20 +246,17 @@ class GoogleWalletEventTicketStyle(PassStyle):
|
||||
# long := self.get_cleaned_setting("long")
|
||||
# ):
|
||||
# output_class.locations(lat, long)
|
||||
# elif self.event.geo_lat and self.event.geo_lon:
|
||||
# output_class.locations(self.event.geo_lat, self.event.geo_lon)
|
||||
|
||||
output_class.country_code(self.event.settings.locale)
|
||||
|
||||
if hero := self.get_cleaned_setting("hero"):
|
||||
output_class.hero_image(
|
||||
urljoin(eventreverse_absolute(self.event, "presale:event.index"), hero),
|
||||
urljoin(eventreverse_absolute(self.event, "presale:event.index"), hero.url),
|
||||
self.event.name,
|
||||
)
|
||||
|
||||
if logo := self.get_cleaned_setting("logo"):
|
||||
output_class.logo(
|
||||
urljoin(eventreverse_absolute(self.event, "presale:event.index"), logo),
|
||||
urljoin(eventreverse_absolute(self.event, "presale:event.index"), logo.url),
|
||||
self.event.name,
|
||||
)
|
||||
|
||||
|
||||
@@ -356,6 +356,33 @@ class EventTicketObject(GoogleWalletObjectMixin):
|
||||
)
|
||||
|
||||
|
||||
class ButtonJWT(dict):
|
||||
def __init__(
|
||||
self,
|
||||
issuer,
|
||||
origins,
|
||||
payload: dict[str, list[GoogleWalletObjectMixin]],
|
||||
precreated=True,
|
||||
):
|
||||
serialized_payload = {}
|
||||
for k, v in payload.items():
|
||||
serialized_payload[k] = [x.serialize(mini=precreated) for x in v]
|
||||
|
||||
self.payload = serialized_payload
|
||||
self.issuer = issuer
|
||||
self.origins = origins
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
"iss": self.issuer,
|
||||
"aud": "google",
|
||||
"typ": "savetowallet",
|
||||
"iat": int(time.time()),
|
||||
"payload": self.payload,
|
||||
"origins": self.origins,
|
||||
}
|
||||
|
||||
|
||||
class Comms:
|
||||
def __init__(self, service_account_info: dict):
|
||||
credentials = service_account.Credentials.from_service_account_info(
|
||||
@@ -403,31 +430,3 @@ class Comms:
|
||||
return False
|
||||
|
||||
return encoded.decode("utf-8")
|
||||
|
||||
|
||||
class ButtonJWT(dict):
|
||||
def __init__(
|
||||
self,
|
||||
issuer,
|
||||
origins,
|
||||
payload: dict[str, list[GoogleWalletObjectMixin]],
|
||||
precreated=True,
|
||||
):
|
||||
serialized_payload = {}
|
||||
for k, v in payload.items():
|
||||
serialized_payload[k] = [x.serialize(mini=precreated) for x in v]
|
||||
|
||||
self.payload = serialized_payload
|
||||
self.issuer = issuer
|
||||
self.origins = origins
|
||||
|
||||
def sign(self, comms):
|
||||
payload = {
|
||||
"iss": self.issuer,
|
||||
"aud": "google",
|
||||
"typ": "savetowallet",
|
||||
"iat": int(time.time()),
|
||||
"payload": self.payload,
|
||||
"origins": self.origins,
|
||||
}
|
||||
return comms.sign_jwt(payload)
|
||||
Reference in new issue
Block a user