7c77001d5e
Create Venueless login token as part of checkin to allow attendee to join an online event from the dashboard.
579 lines
17 KiB
Python
579 lines
17 KiB
Python
from decimal import Decimal
|
|
import os
|
|
import sys
|
|
|
|
import django
|
|
import dj_database_url
|
|
import saml2
|
|
import saml2.saml
|
|
|
|
from datetime import date, datetime, timedelta
|
|
import pytz
|
|
|
|
from dataclasses import dataclass
|
|
|
|
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
|
|
PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
DJANGO_ROOT = os.path.abspath(os.path.dirname(django.__file__))
|
|
BASE_DIR = PACKAGE_ROOT
|
|
sys.path.append(os.path.join(PROJECT_ROOT, 'vendor'))
|
|
|
|
|
|
### USER SETTINGS
|
|
DEV_MODE = os.environ.get("SYMPOSION_DEV_MODE", None)
|
|
DEBUG = os.environ.get('SYMPOSION_APP_DEBUG', '0')
|
|
if isinstance(DEBUG, str):
|
|
try:
|
|
i = int(DEBUG)
|
|
if not i in [0, 1]:
|
|
raise ValueError("not 0 or 1")
|
|
DEBUG = bool(i)
|
|
except ValueError:
|
|
sys.exit('DEBUG env var must be set to string value of a 0 or 1')
|
|
else:
|
|
sys.exit('DEBUG env var is in unexpected format. Should be a string'
|
|
'containing either a 0 or a 1 - Got type %s' % type(DEBUG))
|
|
|
|
DATABASES = {}
|
|
DATABASES['default'] = dj_database_url.config(conn_max_age=600)
|
|
if DATABASES['default']['ENGINE'] == 'django.db.backends.mysql':
|
|
DATABASES['default']['OPTIONS'] = {'charset': 'utf8mb4'}
|
|
|
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
|
EMAIL_HOST = os.environ.get('EMAIL_HOST', None)
|
|
EMAIL_PORT = os.environ.get('EMAIL_PORT', 25)
|
|
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', None)
|
|
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', None)
|
|
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
|
|
EMAIL_USE_SSL = False
|
|
EMAIL_USE_TLS = False
|
|
_EMAIL_SSL_FLAVOR=os.environ.get('EMAIL_SSL_FLAVOR', None)
|
|
if _EMAIL_SSL_FLAVOR == "TLS":
|
|
EMAIL_USE_TLS = True
|
|
elif _EMAIL_SSL_FLAVOR == "SSL":
|
|
EMAIL_USE_SSL = True
|
|
|
|
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', None)
|
|
|
|
PINAX_STRIPE_PUBLIC_KEY = os.environ.get('STRIPE_PUBLIC_KEY', None)
|
|
PINAX_STRIPE_SECRET_KEY = os.environ.get('STRIPE_SECRET_KEY', None)
|
|
PINAX_STRIPE_SEND_EMAIL_RECEIPTS = False
|
|
|
|
ANALYTICS_KEY = os.environ.get('ANALYTICS_KEY', None)
|
|
|
|
saml2_entityid = os.environ.get('SAML2_ENTITYID', None)
|
|
saml2_sp_name = os.environ.get('SAML2_SP_NAME', None)
|
|
saml2_sp_assertion_service = os.environ.get('SAML2_SP_ASSERTION_SERVICE', None)
|
|
saml2_sp_slo_rdir = os.environ.get('SAML2_SP_SLO_RDIR', None)
|
|
saml2_sp_slo_post = os.environ.get('SAML2_SP_SLO_POST', None)
|
|
|
|
saml2_idp_metadata = {
|
|
'local': [os.environ.get('SAML2_IDP_METADATA_FILE', None)],
|
|
}
|
|
saml2_signing_key = os.environ.get('SAML2_SIGNING_KEY', None)
|
|
saml2_signing_crt = os.environ.get('SAML2_SIGNING_CRT', None)
|
|
saml2_encr_key = os.environ.get('SAML2_ENCRYPTION_KEY', None)
|
|
saml2_encr_crt = os.environ.get('SAML2_ENCRYPTION_CRT', None)
|
|
saml2_contact = {
|
|
'given_name': os.environ.get("META_GIVEN_NAME", 'Bastard'),
|
|
'sur_name': os.environ.get('META_FAM_NAME', 'Operator'),
|
|
'company': os.environ.get('META_COMPANY', 'Corp1'),
|
|
'email_address': os.environ.get('META_EMAIL', 'op@example.com'),
|
|
'contact_type': 'technical'},
|
|
|
|
fail = False
|
|
|
|
BADGER_DEFAULT_SVG = 'registrasion/badge.svg'
|
|
BADGER_DEFAULT_FORM = "registrasion/badge_form.html"
|
|
|
|
if SECRET_KEY is None:
|
|
print("FAILURE: You need to supply a DJANGO_SECRET_KEY "
|
|
"environment variable")
|
|
fail = True
|
|
|
|
if PINAX_STRIPE_PUBLIC_KEY is None:
|
|
print("FAILURE: You need to supply a STRIPE_PUBLIC_KEY "
|
|
"environment variable")
|
|
fail = True
|
|
|
|
if PINAX_STRIPE_SECRET_KEY is None:
|
|
print("FAILURE: You need to supply a STRIPE_SECRET_KEY "
|
|
"environment variable")
|
|
fail = True
|
|
|
|
if fail:
|
|
sys.exit('FAILURE: Missing environment variables.')
|
|
|
|
### Standard settings
|
|
|
|
ADMIN_USERNAMES = []
|
|
|
|
if DEV_MODE and DEV_MODE == "LAPTOP":
|
|
CACHES = {
|
|
'default': {
|
|
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
|
}
|
|
}
|
|
else:
|
|
CACHES = {
|
|
'default': {
|
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
|
'LOCATION': 'unique-snowflake',
|
|
}
|
|
}
|
|
|
|
|
|
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '*']
|
|
|
|
TIME_ZONE = "Australia/Melbourne"
|
|
DATE_FORMAT = "j F Y"
|
|
LANGUAGE_CODE = "en-au"
|
|
|
|
SITE_ID = int(os.environ.get("SITE_ID", 1))
|
|
USE_I18N = True
|
|
USE_L10N = True
|
|
USE_TZ = True
|
|
|
|
MEDIA_ROOT = os.environ.get("MEDIA_ROOT", os.path.join(PACKAGE_ROOT, "site_media", "media"))
|
|
MEDIA_URL = "/site_media/media/"
|
|
|
|
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static', 'build')
|
|
STATIC_URL = '/static/build/'
|
|
|
|
STATICFILES_DIRS = [
|
|
os.path.join(PROJECT_ROOT, 'static', 'src'),
|
|
]
|
|
|
|
STATICFILES_FINDERS = [
|
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
|
"sass_processor.finders.CssFinder",
|
|
]
|
|
|
|
TEMPLATES = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"DIRS": [
|
|
os.path.join(PACKAGE_ROOT, "templates"),
|
|
os.path.join(DJANGO_ROOT, 'forms/templates')
|
|
],
|
|
"APP_DIRS": True,
|
|
"OPTIONS": {
|
|
"debug": DEBUG,
|
|
"context_processors": [
|
|
"django.contrib.auth.context_processors.auth",
|
|
"django.template.context_processors.debug",
|
|
"django.template.context_processors.i18n",
|
|
"django.template.context_processors.media",
|
|
"django.template.context_processors.static",
|
|
"django.template.context_processors.tz",
|
|
"django.template.context_processors.request",
|
|
"django.contrib.messages.context_processors.messages",
|
|
"pinax_theme_bootstrap.context_processors.theme",
|
|
"symposion.reviews.context_processors.reviews",
|
|
"django_settings_export.settings_export",
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
MIDDLEWARE = [
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
"django.middleware.common.CommonMiddleware",
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
"djangosaml2.middleware.SamlSessionMiddleware",
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
|
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
|
"reversion.middleware.RevisionMiddleware",
|
|
"waffle.middleware.WaffleMiddleware",
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
"django.contrib.flatpages.middleware.FlatpageFallbackMiddleware",
|
|
'pinaxcon.monkey_patch.MonkeyPatchMiddleware',
|
|
]
|
|
|
|
if DEV_MODE and DEV_MODE == "LAPTOP":
|
|
ROOT_URLCONF = "pinaxcon.devmode_urls"
|
|
else:
|
|
ROOT_URLCONF = "pinaxcon.urls"
|
|
|
|
# Python dotted path to the WSGI application used by Django's runserver.
|
|
WSGI_APPLICATION = "pinaxcon.wsgi.application"
|
|
|
|
INSTALLED_APPS = [
|
|
"whitenoise.runserver_nostatic",
|
|
"django.contrib.admin",
|
|
"django.contrib.auth",
|
|
"django.contrib.contenttypes",
|
|
"django.contrib.flatpages",
|
|
"django.contrib.messages",
|
|
"django.contrib.sessions",
|
|
"django.contrib.sites",
|
|
"django.contrib.staticfiles",
|
|
"django.contrib.humanize",
|
|
"debug_toolbar",
|
|
|
|
'djangosaml2',
|
|
|
|
# theme
|
|
"bootstrapform",
|
|
"pinax_theme_bootstrap",
|
|
"sass_processor",
|
|
"capture_tag",
|
|
|
|
# external
|
|
"easy_thumbnails",
|
|
"taggit",
|
|
"reversion",
|
|
"sitetree",
|
|
"django_jsonfield_backport",
|
|
"pinax.eventlog",
|
|
|
|
# symposion
|
|
"symposion",
|
|
"symposion.conference",
|
|
"symposion.proposals",
|
|
"symposion.reviews",
|
|
"symposion.schedule",
|
|
"symposion.speakers",
|
|
"symposion.teams",
|
|
|
|
# Registrasion
|
|
"registrasion",
|
|
|
|
# Registrasion-stripe
|
|
"pinax.stripe",
|
|
"django_countries",
|
|
"registripe",
|
|
|
|
#registrasion-desk
|
|
"regidesk",
|
|
|
|
# admin - required by registrasion ??
|
|
"nested_admin",
|
|
|
|
# project
|
|
"pinaxcon",
|
|
"pinaxcon.proposals",
|
|
"pinaxcon.registrasion",
|
|
"pinaxcon.raffle",
|
|
"jquery",
|
|
"djangoformsetjs",
|
|
|
|
# testing and rollout
|
|
"django_nose",
|
|
"waffle",
|
|
|
|
"crispy_forms",
|
|
]
|
|
|
|
CRISPY_TEMPLATE_PACK = "bootstrap4"
|
|
|
|
DEBUG_TOOLBAR_PANELS = [
|
|
'debug_toolbar.panels.versions.VersionsPanel',
|
|
'debug_toolbar.panels.timer.TimerPanel',
|
|
'debug_toolbar.panels.settings.SettingsPanel',
|
|
'debug_toolbar.panels.headers.HeadersPanel',
|
|
'debug_toolbar.panels.request.RequestPanel',
|
|
'debug_toolbar.panels.sql.SQLPanel',
|
|
'debug_toolbar.panels.staticfiles.StaticFilesPanel',
|
|
'debug_toolbar.panels.cache.CachePanel',
|
|
'debug_toolbar.panels.signals.SignalsPanel',
|
|
'debug_toolbar.panels.logging.LoggingPanel',
|
|
'debug_toolbar.panels.templates.TemplatesPanel',
|
|
'debug_toolbar.panels.redirects.RedirectsPanel',
|
|
]
|
|
|
|
DEBUG_TOOLBAR_CONFIG = {
|
|
'INTERCEPT_REDIRECTS': False,
|
|
}
|
|
|
|
INTERNAL_IPS = [
|
|
'127.0.0.1',
|
|
]
|
|
|
|
from debug_toolbar.panels.logging import collector
|
|
LOGGING = {
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'formatters': {
|
|
'verbose': {
|
|
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
|
},
|
|
'simple': {
|
|
'format': '%(asctime)s %(levelname)s $(module)s %(message)s'
|
|
},
|
|
},
|
|
'filters': {
|
|
'require_debug_false': {
|
|
'()': 'django.utils.log.RequireDebugFalse'
|
|
}
|
|
},
|
|
'handlers': {
|
|
'console': {
|
|
'level': 'DEBUG',
|
|
'class': 'logging.StreamHandler',
|
|
'formatter': 'simple'
|
|
},
|
|
'mail_admins': {
|
|
'level': 'ERROR',
|
|
'filters': ['require_debug_false'],
|
|
'class': 'django.utils.log.AdminEmailHandler',
|
|
'include_html': True,
|
|
},
|
|
'djdt_log': {
|
|
'level': 'DEBUG',
|
|
'class': 'debug_toolbar.panels.logging.ThreadTrackingHandler',
|
|
'collector': collector,
|
|
},
|
|
},
|
|
'loggers': {
|
|
'django.request': {
|
|
'handlers': ['mail_admins'],
|
|
'level': 'DEBUG',
|
|
'propagate': True,
|
|
},
|
|
'symposion.request': {
|
|
'handlers': ['mail_admins'],
|
|
'level': 'DEBUG',
|
|
'propagate': True,
|
|
},
|
|
},
|
|
'root': {
|
|
'handlers': ['console', 'djdt_log'],
|
|
'level': 'DEBUG'
|
|
},
|
|
}
|
|
FIXTURE_DIRS = [
|
|
os.path.join(PROJECT_ROOT, "fixtures"),
|
|
]
|
|
|
|
AUTHENTICATION_BACKENDS = [
|
|
'symposion.teams.backends.TeamPermissionsBackend',
|
|
'django.contrib.auth.backends.ModelBackend',
|
|
'djangosaml2.backends.Saml2Backend',
|
|
]
|
|
|
|
LOGIN_URL = '/saml2/login/'
|
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
|
|
|
CONFERENCE_ID = 1
|
|
PROPOSAL_FORMS = {
|
|
"talk": "pinaxcon.proposals.forms.TalkProposalForm",
|
|
"tutorial": "pinaxcon.proposals.forms.TutorialProposalForm",
|
|
"miniconf": "pinaxcon.proposals.forms.MiniconfProposalForm",
|
|
### LCA2021 Miniconfs
|
|
"glam-miniconf": "pinaxcon.proposals.forms.GlamProposalForm",
|
|
"kernel-miniconf": "pinaxcon.proposals.forms.KernelProposalForm",
|
|
"open-hardware-miniconf": "pinaxcon.proposals.forms.OpenHardwareProposalForm",
|
|
"sysadmin-miniconf": "pinaxcon.proposals.forms.SysAdminProposalForm",
|
|
}
|
|
MAIN_CONFERENCE_PROPOSAL_KINDS = ("Talk", "Miniconf")
|
|
|
|
# Registrasion bits:
|
|
ATTENDEE_PROFILE_MODEL = "pinaxcon.registrasion.models.AttendeeProfile"
|
|
ATTENDEE_PROFILE_FORM = "pinaxcon.registrasion.forms.ProfileForm"
|
|
INVOICE_CURRENCY = "AUD"
|
|
GST_RATE = Decimal('0.1')
|
|
TICKET_PRODUCT_CATEGORY = 1
|
|
TERMS_PRODUCT_CATEGORY = 2
|
|
ATTENDEE_PROFILE_FORM = "pinaxcon.registrasion.forms.ProfileForm"
|
|
|
|
#REGIDESK
|
|
REGIDESK_BOARDING_GROUP = "Ready For Boarding"
|
|
|
|
# CSRF custom error screen
|
|
CSRF_FAILURE_VIEW = "pinaxcon.csrf_view.csrf_failure"
|
|
|
|
# Use nose to run all tests
|
|
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
|
|
|
|
# Tell nose to measure coverage on the 'foo' and 'bar' apps
|
|
NOSE_ARGS = [
|
|
'--with-coverage',
|
|
'--cover-package=registrasion.controllers,registrasion.models',
|
|
]
|
|
|
|
SASS_PROCESSOR_INCLUDE_DIRS = [
|
|
os.path.join(PROJECT_ROOT, 'static/src/bootstrap/scss'),
|
|
os.path.join(PROJECT_ROOT, 'static/src/scss'),
|
|
]
|
|
|
|
xmlsec_binary = '/usr/bin/xmlsec1'
|
|
if not os.path.isfile(xmlsec_binary):
|
|
sys.exit('ERROR: xmlsec1 binary missing, EXITING')
|
|
|
|
SAML_ATTRIBUTE_MAPPING = {
|
|
'uid': ('username', ),
|
|
'mail': ('email', ),
|
|
'givenName': ('first_name', ),
|
|
'sn': ('last_name', ),
|
|
}
|
|
SAML_CONFIG = {
|
|
'xmlsec_binary': xmlsec_binary,
|
|
'entityid': saml2_entityid,
|
|
'attribute_map_dir': os.path.join(PACKAGE_ROOT, 'saml2/attribute-maps'),
|
|
'service': {
|
|
'sp': {
|
|
'name': saml2_sp_name,
|
|
'endpoints': {
|
|
'assertion_consumer_service': [
|
|
saml2_sp_assertion_service,
|
|
],
|
|
'single_logout_service': [
|
|
(saml2_sp_slo_rdir, saml2.BINDING_HTTP_REDIRECT),
|
|
(saml2_sp_slo_post, saml2.BINDING_HTTP_POST),
|
|
],
|
|
},
|
|
'logout_requests_signed': True,
|
|
'required_attributes': ['uid', 'mail', 'givenName', 'sn'],
|
|
},
|
|
},
|
|
'metadata': saml2_idp_metadata,
|
|
'debug': 0,
|
|
'key_file': saml2_signing_key,
|
|
'cert_file': saml2_signing_crt,
|
|
'encryption_keypairs': [{
|
|
'key_file': saml2_encr_key,
|
|
'cert_file': saml2_encr_crt,
|
|
}],
|
|
'contact_person': saml2_contact,
|
|
'valid_for': 10,
|
|
}
|
|
|
|
if 'SAML_CONFIG_LOADER' in os.environ:
|
|
SAML_CONFIG_LOADER = os.environ.get('SAML_CONFIG_LOADER')
|
|
|
|
DEFAULT_FILE_STORAGE = os.environ.get('DEFAULT_FILE_STORAGE', 'gapc_storage.storage.GoogleCloudStorage')
|
|
GAPC_STORAGE = {
|
|
'num_retries': 2,
|
|
}
|
|
|
|
SETTINGS_EXPORT = [
|
|
'DEBUG',
|
|
'ANALYTICS_KEY',
|
|
]
|
|
|
|
if DEV_MODE and DEV_MODE == "LAPTOP":
|
|
print("ENABLING LAPTOP MODE")
|
|
from .devmode_settings import *
|
|
|
|
|
|
class Category(object):
|
|
tickets = []
|
|
|
|
@classmethod
|
|
def order(cls, ticket) -> int:
|
|
return (cls.tickets.index(ticket) + 1) * 10
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Ticket:
|
|
name: str
|
|
regular_price: Decimal
|
|
earlybird_price: Decimal
|
|
|
|
def earlybird_discount(self):
|
|
return self.regular_price - self.earlybird_price
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DinnerTicket:
|
|
name: str
|
|
price: Decimal
|
|
description: str
|
|
reservation: timedelta
|
|
cat: Category
|
|
|
|
def order(self):
|
|
return self.cat.order(self)
|
|
|
|
|
|
class PenguinDinnerTicket(DinnerTicket):
|
|
pass
|
|
|
|
|
|
class SpeakersDinnerTicket(DinnerTicket):
|
|
pass
|
|
|
|
|
|
class SpeakersDinnerCat(Category):
|
|
@classmethod
|
|
def create(cls, name: str, price: Decimal, description: str, reservation: timedelta) -> SpeakersDinnerTicket:
|
|
t = SpeakersDinnerTicket(name, price, description, reservation, cls)
|
|
cls.tickets.append(t)
|
|
return t
|
|
|
|
|
|
class PenguinDinnerCat(Category):
|
|
@classmethod
|
|
def create(cls, name: str, price: Decimal, description: str, reservation: timedelta) -> PenguinDinnerTicket:
|
|
t = PenguinDinnerTicket(name, price, description, reservation, cls)
|
|
cls.tickets.append(t)
|
|
return t
|
|
|
|
|
|
_TZINFO = pytz.timezone(TIME_ZONE)
|
|
LCA_START = datetime(2021, 1, 23, tzinfo=_TZINFO)
|
|
LCA_END = datetime(2021, 1, 25, tzinfo=_TZINFO)
|
|
EARLY_BIRD_DEADLINE = datetime(2020, 12, 1, tzinfo=_TZINFO)
|
|
PENGUIN_DINNER_TICKET_DATE = date(2021, 1, 23)
|
|
SPEAKER_DINNER_TICKET_DATE = date(2021, 1, 25)
|
|
PDNS_TICKET_DATE = date(2021, 1, 24)
|
|
|
|
TSHIRT_PRICE = Decimal("25.00")
|
|
|
|
CONTRIBUTOR = Ticket("Contributor", Decimal("300.00"), Decimal("250.00"))
|
|
PROFESSIONAL = Ticket("Professional", Decimal("125.00"), Decimal("100.00"))
|
|
HOBBYIST = Ticket("Hobbyist", Decimal("70.00"), None)
|
|
STUDENT = Ticket("Student", Decimal("30.00"), None)
|
|
MINICONF_ONLY = Ticket("Miniconf Only", Decimal("25.00"), None)
|
|
|
|
MEDIA = Ticket("Media", Decimal("0.0"), None)
|
|
SPEAKER = Ticket("Speaker", Decimal("0.0"), None)
|
|
SPONSOR = Ticket("Sponsor", Decimal("0.0"), None)
|
|
|
|
CONFERENCE_ORG = Ticket("Conference Organiser", Decimal("0.0"), None)
|
|
CONFERENCE_VOL = Ticket("Conference Volunteer", Decimal("0.0"), None)
|
|
|
|
PENGUIN_DINNER = PenguinDinnerCat
|
|
PENGUIN_DINNER_ADULT = PenguinDinnerCat.create(
|
|
"Adult", Decimal("95.00"),
|
|
"Includes an adult's meal and full beverage service.",
|
|
timedelta(hours=1))
|
|
PENGUIN_DINNER_CHILD = PenguinDinnerCat.create(
|
|
"Child", Decimal("50.00"),
|
|
"Children 14 and under. "
|
|
"Includes a child's meal and soft drink service.",
|
|
timedelta(hours=1))
|
|
PENGUIN_DINNER_INFANT = PenguinDinnerCat.create(
|
|
"Infant", Decimal("0.0"),
|
|
"Includes no food or beverage service.",
|
|
timedelta(hours=1))
|
|
|
|
SPEAKERS_DINNER = SpeakersDinnerCat
|
|
|
|
SPEAKERS_DINNER_ADULT = SpeakersDinnerCat.create(
|
|
"Adult", Decimal("100.00"),
|
|
"Includes an adult's meal and full beverage service.",
|
|
timedelta(hours=1))
|
|
|
|
# SPEAKERS_DINNER_CHILD = SpeakersDinnerCat.create(
|
|
# "Child", Decimal("60.00"),
|
|
# "Children 14 and under. "
|
|
# "Includes a child's meal and soft drink service.",
|
|
# timedelta(hours=1))
|
|
|
|
# SPEAKERS_DINNER_INFANT = SpeakersDinnerCat.create(
|
|
# "Infant", Decimal("00.00"),
|
|
# "Infant must be seated in an adult's lap. "
|
|
# "No food or beverage service.",
|
|
# timedelta(hours=1))
|
|
|
|
|
|
# Venueless integration
|
|
VENUELESS_URL = os.environ.get('VENUELESS_URL', None)
|
|
VENUELESS_AUDIENCE = os.environ.get('VENUELESS_AUDIENCE', "venueless")
|
|
VENUELESS_TOKEN_ISSUER = os.environ.get('VENUELESS_TOKEN_ISSUER', "any")
|
|
VENUELESS_SECRET = os.environ.get('VENUELESS_SECRET', SECRET_KEY)
|