^
This commit is contained in:
parent
715491017a
commit
470c808d52
4 changed files with 791 additions and 72 deletions
117
deploy-saleor.sh
117
deploy-saleor.sh
|
@ -258,18 +258,18 @@ done
|
|||
echo -n "Enter a custom Static Files URI (optional):"
|
||||
read STATIC_URL
|
||||
# Get the Admin's email address
|
||||
while [ "$EMAIL" = "" ]
|
||||
while [ "$ADMIN_EMAIL" = "" ]
|
||||
do
|
||||
echo ""
|
||||
echo -n "Enter the Dashboard admin's email:"
|
||||
read EMAIL
|
||||
read ADMIN_EMAIL
|
||||
done
|
||||
# Get the Admin's desired password
|
||||
while [ "$PASSW" = "" ]
|
||||
while [ "$ADMIN_PASS" = "" ]
|
||||
do
|
||||
echo ""
|
||||
echo -n "Enter the Dashboard admin's desired password:"
|
||||
read -s PASSW
|
||||
read -s ADMIN_PASS
|
||||
done
|
||||
#########################################################################################
|
||||
|
||||
|
@ -376,24 +376,28 @@ echo ""
|
|||
# Replace any parameter slugs in the template files with real paramaters & write them to
|
||||
# the production files
|
||||
#########################################################################################
|
||||
# Replace the settings.py with the production version
|
||||
if [ -f "$HD/saleor/saleor/settings.py" ]; then
|
||||
sudo rm $HD/saleor/saleor/settings.py
|
||||
fi
|
||||
sudo cp $HD/Deploy_Saleor/resources/saleor/settings.py $HD/saleor/saleor/
|
||||
# Replace the populatedb.py file with the production version
|
||||
if [ -f "$HD/saleor/saleor/core/management/commands/populatedb.py" ]; then
|
||||
sudo rm $HD/saleor/saleor/core/management/commands/populatedb.py
|
||||
fi
|
||||
sudo cp $HD/Deploy_Saleor/resources/saleor/populatedb.py $HD/saleor/saleor/core/management/commands/
|
||||
# Replace the test_core.py file with the production version
|
||||
if [ -f "$HD/saleor/saleor/core/tests/test_core.py" ]; then
|
||||
sudo rm $HD/saleor/saleor/core/tests/test_core.py
|
||||
fi
|
||||
sudo cp $HD/Deploy_Saleor/resources/saleor/test_core.py $HD/saleor/saleor/core/tests/
|
||||
wait
|
||||
# Does an old saleor.service file exist?
|
||||
if [ -f "/etc/systemd/system/saleor.service" ]; then
|
||||
# Remove the old service file
|
||||
sudo rm /etc/systemd/system/saleor.service
|
||||
fi
|
||||
READ_ENV='
|
||||
try:
|
||||
from decouple import RepositoryEnv
|
||||
file_path = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
#print("{}/.env".format(file_path))
|
||||
for k,v in RepositoryEnv("{}/.env".format(file_path)).data.items():
|
||||
print(k, v)
|
||||
os.environ[k] = v
|
||||
except Exception as e:
|
||||
#print(e)
|
||||
pass
|
||||
|
||||
def get_list(text):'
|
||||
###### This following section is for future use and will be modified to allow an alternative repo clone ######
|
||||
# Was the -v (version) option used or Mirumee repo specified?
|
||||
if [ "vOPT" = "true" ] || [ "$REPO" = "mirumee" ]; then
|
||||
# Create the new service file
|
||||
|
@ -411,16 +415,6 @@ if [ "vOPT" = "true" ] || [ "$REPO" = "mirumee" ]; then
|
|||
s/{host}/$HOST/g
|
||||
s/{apiport}/$API_PORT/" $HD/Deploy_Saleor/resources/saleor/server_block > /etc/nginx/sites-available/saleor
|
||||
wait
|
||||
# Replace demo credentials with production credentials in /saleor/saleor/core/management/commands/populatedb.py
|
||||
sudo sed -i 's/{"email": "admin@example.com", "password": "admin"}/{"email": "'$EMAIL'", "password": "'$PASSW'"}/' $HD/saleor/saleor/core/management/commands/populatedb.py
|
||||
wait
|
||||
# Replace demo credentials with production credentials in /saleor/saleor/core/tests/test_core.py
|
||||
sudo sed -i 's/{"email": "admin@example.com", "password": "admin"}/{"email": "'$EMAIL'", "password": "'$PASSW'"}/' $HD/saleor/saleor/core/tests/test_core.py
|
||||
wait
|
||||
# Replace the insecure demo secret key assignemnt with a more secure file reference in /saleor/saleor/settings.py
|
||||
sudo sed -i 's|SECRET_KEY = os.environ.get("SECRET_KEY")|with open("/etc/saleor/api_sk") as f: SECRET_KEY = f.read().strip()|
|
||||
s|def get_list(text):|'$READ_ENV'|' $HD/saleor/saleor/settings.py
|
||||
wait
|
||||
else
|
||||
# Create the new service file
|
||||
sudo sed "s/{un}/$UN/
|
||||
|
@ -437,42 +431,6 @@ else
|
|||
s/{host}/$HOST/g
|
||||
s/{apiport}/$API_PORT/" $HD/Deploy_Saleor/resources/saleor/server_block > /etc/nginx/sites-available/saleor
|
||||
wait
|
||||
# Replace demo credentials with production credentials in /saleor/saleor/core/management/commands/populatedb.py
|
||||
sudo sed -i "s/{\"email\": \"admin@example.com\", \"password\": \"admin\"}/{\"email\": \"$EMAIL\", \"password\": \"$PASSW\"}/" $HD/saleor/saleor/core/management/commands/populatedb.py
|
||||
wait
|
||||
# Replace demo credentials with production credentials in /saleor/saleor/core/tests/test_core.py
|
||||
sudo sed -i "s/{\"email\": \"admin@example.com\", \"password\": \"admin\"}/{\"email\": \"$EMAIL\", \"password\": \"$PASSW\"}/" $HD/saleor/saleor/core/tests/test_core.py
|
||||
wait
|
||||
# Replace the insecure demo secret key assignemnt with a more secure file reference in /saleor/saleor/settings.py
|
||||
sudo sed -i "s|SECRET_KEY = os.environ.get(\"SECRET_KEY\")|with open('/etc/saleor/api_sk') as f: SECRET_KEY = f.read().strip()|
|
||||
s|def get_list(text):|$READ_ENV|" $HD/saleor/saleor/settings.py
|
||||
wait
|
||||
|
||||
###### For possible later use ######
|
||||
# Create the new service file
|
||||
#sudo sed "s/{un}/$UN/
|
||||
# s|{hd}|$HD|" $HD/saleor/resources/saleor/template.service > /etc/systemd/system/saleor.service
|
||||
#wait
|
||||
# Does an old server block exist?
|
||||
#if [ -f "/etc/nginx/sites-available/saleor" ]; then
|
||||
# # Remove the old service file
|
||||
# sudo rm /etc/nginx/sites-available/saleor
|
||||
#fi
|
||||
# Create the new server block
|
||||
#sudo sed "s|{hd}|$HD|
|
||||
# s/{api_host}/$API_HOST/
|
||||
# s/{host}/$HOST/g
|
||||
# s/{apiport}/$API_PORT/" $HD/saleor/resources/saleor/server_block > /etc/nginx/sites-available/saleor
|
||||
#wait
|
||||
# Set the production credentials in /saleor/saleor/core/management/commands/populatedb.py
|
||||
#sudo sed -i "s/{email}/$EMAIL/
|
||||
# s/{passw}/$PASSW/" $HD/saleor/saleor/core/management/commands/populatedb.py
|
||||
#wait
|
||||
# Set the production credentials in /saleor/saleor/core/tests/test_core.py
|
||||
#sudo sed -i "s/{email}/$EMAIL/
|
||||
# s/{passw}/$PASSW/" $HD/saleor/saleor/core/tests/test_core.py
|
||||
#wait
|
||||
###### For possible later use ######
|
||||
fi
|
||||
#########################################################################################
|
||||
|
||||
|
@ -503,6 +461,7 @@ sudo sed "s|{dburl}|$DB_URL|
|
|||
s/{ahosts}/$A_HOSTS/
|
||||
s|{static}|$STATIC_URL|
|
||||
s|{media}|$MEDIA_URL|
|
||||
s/{adminemail}/$ADMIN_EMAIL/
|
||||
s/{gqlorigins}/$QL_ORIGINS/" $HD/Deploy_Saleor/resources/saleor/template.env > $HD/saleor/.env
|
||||
wait
|
||||
#########################################################################################
|
||||
|
@ -561,18 +520,29 @@ wait
|
|||
# Install the project requirements
|
||||
pip3 install -r requirements.txt
|
||||
wait
|
||||
# Install the decoupler for .env file
|
||||
pip3 install python3-decouple
|
||||
wait
|
||||
# Set any secret Environment Variables
|
||||
export ADMIN_PASS="$ADMIN_PASS"
|
||||
# Install the project
|
||||
npm install
|
||||
wait
|
||||
# Run an audit to fix any vulnerabilities
|
||||
npm audit fix
|
||||
wait
|
||||
# Establish the database
|
||||
python3 manage.py migrate
|
||||
python3 manage.py migrate --createsuperuser
|
||||
wait
|
||||
# Collect the static elemants
|
||||
python3 manage.py collectstatic
|
||||
wait
|
||||
# Build the schema
|
||||
npm run build-schema
|
||||
wait
|
||||
# Build the emails
|
||||
npm run build-emails
|
||||
wait
|
||||
# Exit the virtual environment here? _#_
|
||||
deactivate
|
||||
#########################################################################################
|
||||
|
@ -580,17 +550,13 @@ deactivate
|
|||
|
||||
|
||||
#########################################################################################
|
||||
# Create the Saleor service
|
||||
# Enable the Saleor service
|
||||
#########################################################################################
|
||||
# Touch
|
||||
sudo touch /etc/init.d/saleor
|
||||
# Allow execute
|
||||
sudo chmod +x /etc/init.d/saleor
|
||||
# Update with defaults
|
||||
sudo update-rc.d saleor defaults
|
||||
sudo systemctl enable saleor.service
|
||||
#########################################################################################
|
||||
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
systemctl start emperor.uwsgi.service
|
||||
|
||||
#########################################################################################
|
||||
echo "Enabling server block and Restarting nginx..."
|
||||
|
@ -607,3 +573,10 @@ echo ""
|
|||
echo "Finished creating production deployment packages for Saleor API & GraphQL"
|
||||
echo ""
|
||||
#########################################################################################
|
||||
|
||||
|
||||
#########################################################################################
|
||||
# Call the dashboard deployment script
|
||||
#########################################################################################
|
||||
source ./deploy-dashboard.sh
|
||||
#########################################################################################
|
142
resources/saleor/populatedb.py
Normal file
142
resources/saleor/populatedb.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
from io import StringIO
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import connection
|
||||
|
||||
from ....account.utils import create_superuser
|
||||
from ...utils.random_data import (
|
||||
add_address_to_admin,
|
||||
create_channels,
|
||||
create_gift_card,
|
||||
create_menus,
|
||||
create_orders,
|
||||
create_page_type,
|
||||
create_pages,
|
||||
create_permission_groups,
|
||||
create_product_sales,
|
||||
create_products_by_schema,
|
||||
create_shipping_zones,
|
||||
create_staffs,
|
||||
create_users,
|
||||
create_vouchers,
|
||||
create_warehouses,
|
||||
)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Populate database with test objects"
|
||||
placeholders_dir = "saleor/static/placeholders/"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"--createsuperuser",
|
||||
action="store_true",
|
||||
dest="createsuperuser",
|
||||
default=False,
|
||||
help="Create admin account",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sampledata",
|
||||
action="store_true",
|
||||
dest="sampledata",
|
||||
default=False,
|
||||
help="Create sample products, etc..",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--withoutimages",
|
||||
action="store_true",
|
||||
dest="withoutimages",
|
||||
default=False,
|
||||
help="Don't create product images",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--skipsequencereset",
|
||||
action="store_true",
|
||||
dest="skipsequencereset",
|
||||
default=False,
|
||||
help="Don't reset SQL sequences that are out of sync.",
|
||||
)
|
||||
|
||||
def make_database_faster(self):
|
||||
"""Sacrifice some of the safeguards of sqlite3 for speed.
|
||||
|
||||
Users are not likely to run this command in a production environment.
|
||||
They are even less likely to run it in production while using sqlite3.
|
||||
"""
|
||||
if "sqlite3" in connection.settings_dict["ENGINE"]:
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("PRAGMA temp_store = MEMORY;")
|
||||
cursor.execute("PRAGMA synchronous = OFF;")
|
||||
|
||||
def sequence_reset(self):
|
||||
"""Run a SQL sequence reset on all saleor.* apps.
|
||||
|
||||
When a value is manually assigned to an auto-incrementing field
|
||||
it doesn't update the field's sequence, which might cause a conflict
|
||||
later on.
|
||||
"""
|
||||
commands = StringIO()
|
||||
for app in apps.get_app_configs():
|
||||
if "saleor" in app.name:
|
||||
call_command(
|
||||
"sqlsequencereset", app.label, stdout=commands, no_color=True
|
||||
)
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(commands.getvalue())
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# set only our custom plugin to not call external API when preparing
|
||||
# example database
|
||||
settings.PLUGINS = [
|
||||
"saleor.payment.gateways.dummy.plugin.DummyGatewayPlugin",
|
||||
"saleor.payment.gateways.dummy_credit_card.plugin."
|
||||
"DummyCreditCardGatewayPlugin",
|
||||
]
|
||||
|
||||
ADMIN_EMAIL = os.environ.get("ADMIN_EMAIL")
|
||||
ADMIN_PASS = os.environ.get("ADMIN_PASS")
|
||||
|
||||
if options["createsuperuser"]:
|
||||
credentials = {"email": ADMIN_EMAIL, "password": ADMIN_PASS}
|
||||
msg = create_superuser(credentials)
|
||||
self.stdout.write(msg)
|
||||
add_address_to_admin(credentials["email"])
|
||||
|
||||
if options["sampledata"]:
|
||||
self.make_database_faster()
|
||||
create_images = not options["withoutimages"]
|
||||
for msg in create_channels():
|
||||
self.stdout.write(msg)
|
||||
for msg in create_shipping_zones():
|
||||
self.stdout.write(msg)
|
||||
create_warehouses()
|
||||
self.stdout.write("Created warehouses")
|
||||
for msg in create_page_type():
|
||||
self.stdout.write(msg)
|
||||
for msg in create_pages():
|
||||
self.stdout.write(msg)
|
||||
create_products_by_schema(self.placeholders_dir, create_images)
|
||||
self.stdout.write("Created products")
|
||||
for msg in create_product_sales(5):
|
||||
self.stdout.write(msg)
|
||||
for msg in create_vouchers():
|
||||
self.stdout.write(msg)
|
||||
for msg in create_gift_card():
|
||||
self.stdout.write(msg)
|
||||
for msg in create_users(20):
|
||||
self.stdout.write(msg)
|
||||
for msg in create_orders(20):
|
||||
self.stdout.write(msg)
|
||||
for msg in create_menus():
|
||||
self.stdout.write(msg)
|
||||
|
||||
if not options["skipsequencereset"]:
|
||||
self.sequence_reset()
|
||||
|
||||
for msg in create_permission_groups():
|
||||
self.stdout.write(msg)
|
||||
for msg in create_staffs():
|
||||
self.stdout.write(msg)
|
603
resources/saleor/settings.py
Normal file
603
resources/saleor/settings.py
Normal file
|
@ -0,0 +1,603 @@
|
|||
import ast
|
||||
import os.path
|
||||
import warnings
|
||||
from datetime import timedelta
|
||||
|
||||
import dj_database_url
|
||||
import dj_email_url
|
||||
import django_cache_url
|
||||
import jaeger_client
|
||||
import jaeger_client.config
|
||||
import pkg_resources
|
||||
import sentry_sdk
|
||||
import sentry_sdk.utils
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.management.utils import get_random_secret_key
|
||||
from pytimeparse import parse
|
||||
from sentry_sdk.integrations.celery import CeleryIntegration
|
||||
from sentry_sdk.integrations.django import DjangoIntegration
|
||||
|
||||
|
||||
try:
|
||||
from decouple import RepositoryEnv
|
||||
file_path = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
#print("{}/.env".format(file_path))
|
||||
for k,v in RepositoryEnv("{}/.env".format(file_path)).data.items():
|
||||
print(k, v)
|
||||
os.environ[k] = v
|
||||
except Exception as e:
|
||||
#print(e)
|
||||
pass
|
||||
|
||||
|
||||
def get_list(text):
|
||||
return [item.strip() for item in text.split(",")]
|
||||
|
||||
|
||||
def get_bool_from_env(name, default_value):
|
||||
if name in os.environ:
|
||||
value = os.environ[name]
|
||||
try:
|
||||
return ast.literal_eval(value)
|
||||
except ValueError as e:
|
||||
raise ValueError("{} is an invalid value for {}".format(value, name)) from e
|
||||
return default_value
|
||||
|
||||
|
||||
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
PROJECT_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
ROOT_URLCONF = "saleor.urls"
|
||||
|
||||
WSGI_APPLICATION = "saleor.wsgi.application"
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@example.com'),
|
||||
)
|
||||
MANAGERS = ADMINS
|
||||
|
||||
_DEFAULT_CLIENT_HOSTS = "localhost,127.0.0.1"
|
||||
|
||||
ALLOWED_CLIENT_HOSTS = os.environ.get("ALLOWED_CLIENT_HOSTS")
|
||||
if not ALLOWED_CLIENT_HOSTS:
|
||||
if DEBUG:
|
||||
ALLOWED_CLIENT_HOSTS = _DEFAULT_CLIENT_HOSTS
|
||||
else:
|
||||
raise ImproperlyConfigured(
|
||||
"ALLOWED_CLIENT_HOSTS environment variable must be set when DEBUG=False."
|
||||
)
|
||||
|
||||
ALLOWED_CLIENT_HOSTS = get_list(ALLOWED_CLIENT_HOSTS)
|
||||
|
||||
INTERNAL_IPS = get_list(os.environ.get("INTERNAL_IPS", "127.0.0.1"))
|
||||
|
||||
DATABASES = {
|
||||
"default": dj_database_url.config(
|
||||
default="postgres://saleor:saleor@localhost:5432/saleor", conn_max_age=600
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
TIME_ZONE = "UTC"
|
||||
LANGUAGE_CODE = "en"
|
||||
LANGUAGES = [
|
||||
("ar", "Arabic"),
|
||||
("az", "Azerbaijani"),
|
||||
("bg", "Bulgarian"),
|
||||
("bn", "Bengali"),
|
||||
("ca", "Catalan"),
|
||||
("cs", "Czech"),
|
||||
("da", "Danish"),
|
||||
("de", "German"),
|
||||
("el", "Greek"),
|
||||
("en", "English"),
|
||||
("es", "Spanish"),
|
||||
("es-co", "Colombian Spanish"),
|
||||
("et", "Estonian"),
|
||||
("fa", "Persian"),
|
||||
("fi", "Finnish"),
|
||||
("fr", "French"),
|
||||
("hi", "Hindi"),
|
||||
("hu", "Hungarian"),
|
||||
("hy", "Armenian"),
|
||||
("id", "Indonesian"),
|
||||
("is", "Icelandic"),
|
||||
("it", "Italian"),
|
||||
("ja", "Japanese"),
|
||||
("ka", "Georgian"),
|
||||
("km", "Khmer"),
|
||||
("ko", "Korean"),
|
||||
("lt", "Lithuanian"),
|
||||
("mn", "Mongolian"),
|
||||
("my", "Burmese"),
|
||||
("nb", "Norwegian"),
|
||||
("nl", "Dutch"),
|
||||
("pl", "Polish"),
|
||||
("pt", "Portuguese"),
|
||||
("pt-br", "Brazilian Portuguese"),
|
||||
("ro", "Romanian"),
|
||||
("ru", "Russian"),
|
||||
("sk", "Slovak"),
|
||||
("sl", "Slovenian"),
|
||||
("sq", "Albanian"),
|
||||
("sr", "Serbian"),
|
||||
("sv", "Swedish"),
|
||||
("sw", "Swahili"),
|
||||
("ta", "Tamil"),
|
||||
("th", "Thai"),
|
||||
("tr", "Turkish"),
|
||||
("uk", "Ukrainian"),
|
||||
("vi", "Vietnamese"),
|
||||
("zh-hans", "Simplified Chinese"),
|
||||
("zh-hant", "Traditional Chinese"),
|
||||
]
|
||||
LOCALE_PATHS = [os.path.join(PROJECT_ROOT, "locale")]
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
|
||||
|
||||
EMAIL_URL = os.environ.get("EMAIL_URL")
|
||||
SENDGRID_USERNAME = os.environ.get("SENDGRID_USERNAME")
|
||||
SENDGRID_PASSWORD = os.environ.get("SENDGRID_PASSWORD")
|
||||
if not EMAIL_URL and SENDGRID_USERNAME and SENDGRID_PASSWORD:
|
||||
EMAIL_URL = "smtp://%s:%s@smtp.sendgrid.net:587/?tls=True" % (
|
||||
SENDGRID_USERNAME,
|
||||
SENDGRID_PASSWORD,
|
||||
)
|
||||
email_config = dj_email_url.parse(
|
||||
EMAIL_URL or "console://demo@example.com:console@example/"
|
||||
)
|
||||
|
||||
EMAIL_FILE_PATH = email_config["EMAIL_FILE_PATH"]
|
||||
EMAIL_HOST_USER = email_config["EMAIL_HOST_USER"]
|
||||
EMAIL_HOST_PASSWORD = email_config["EMAIL_HOST_PASSWORD"]
|
||||
EMAIL_HOST = email_config["EMAIL_HOST"]
|
||||
EMAIL_PORT = email_config["EMAIL_PORT"]
|
||||
EMAIL_BACKEND = email_config["EMAIL_BACKEND"]
|
||||
EMAIL_USE_TLS = email_config["EMAIL_USE_TLS"]
|
||||
EMAIL_USE_SSL = email_config["EMAIL_USE_SSL"]
|
||||
|
||||
# If enabled, make sure you have set proper storefront address in ALLOWED_CLIENT_HOSTS.
|
||||
ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL = get_bool_from_env(
|
||||
"ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL", True
|
||||
)
|
||||
|
||||
ENABLE_SSL = get_bool_from_env("ENABLE_SSL", False)
|
||||
|
||||
if ENABLE_SSL:
|
||||
SECURE_SSL_REDIRECT = not DEBUG
|
||||
|
||||
DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", EMAIL_HOST_USER)
|
||||
|
||||
MEDIA_ROOT = os.path.join(PROJECT_ROOT, "media")
|
||||
MEDIA_URL = os.environ.get("MEDIA_URL", "/media/")
|
||||
|
||||
STATIC_ROOT = os.path.join(PROJECT_ROOT, "static")
|
||||
STATIC_URL = os.environ.get("STATIC_URL", "/static/")
|
||||
STATICFILES_DIRS = [
|
||||
("images", os.path.join(PROJECT_ROOT, "saleor", "static", "images"))
|
||||
]
|
||||
STATICFILES_FINDERS = [
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
]
|
||||
|
||||
context_processors = [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.media",
|
||||
"django.template.context_processors.static",
|
||||
"saleor.site.context_processors.site",
|
||||
]
|
||||
|
||||
loaders = [
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
]
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [os.path.join(PROJECT_ROOT, "templates")],
|
||||
"OPTIONS": {
|
||||
"debug": DEBUG,
|
||||
"context_processors": context_processors,
|
||||
"loaders": loaders,
|
||||
"string_if_invalid": '<< MISSING VARIABLE "%s" >>' if DEBUG else "",
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
# Read secret key from a file
|
||||
with open('/etc/saleor/api_sk') as f:
|
||||
SECRET_KEY = f.read().strip()
|
||||
|
||||
if not SECRET_KEY and DEBUG:
|
||||
warnings.warn("SECRET_KEY not configured, using a random temporary key.")
|
||||
SECRET_KEY = get_random_secret_key()
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"saleor.core.middleware.request_time",
|
||||
"saleor.core.middleware.discounts",
|
||||
"saleor.core.middleware.google_analytics",
|
||||
"saleor.core.middleware.country",
|
||||
"saleor.core.middleware.currency",
|
||||
"saleor.core.middleware.site",
|
||||
"saleor.core.middleware.plugins",
|
||||
"saleor.core.middleware.jwt_refresh_token_middleware",
|
||||
]
|
||||
|
||||
INSTALLED_APPS = [
|
||||
# External apps that need to go before django's
|
||||
"storages",
|
||||
# Django modules
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sites",
|
||||
"django.contrib.staticfiles",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.postgres",
|
||||
# Local apps
|
||||
"saleor.plugins",
|
||||
"saleor.account",
|
||||
"saleor.discount",
|
||||
"saleor.giftcard",
|
||||
"saleor.product",
|
||||
"saleor.attribute",
|
||||
"saleor.channel",
|
||||
"saleor.checkout",
|
||||
"saleor.core",
|
||||
"saleor.csv",
|
||||
"saleor.graphql",
|
||||
"saleor.menu",
|
||||
"saleor.order",
|
||||
"saleor.invoice",
|
||||
"saleor.seo",
|
||||
"saleor.shipping",
|
||||
"saleor.search",
|
||||
"saleor.site",
|
||||
"saleor.page",
|
||||
"saleor.payment",
|
||||
"saleor.warehouse",
|
||||
"saleor.webhook",
|
||||
"saleor.wishlist",
|
||||
"saleor.app",
|
||||
# External apps
|
||||
"versatileimagefield",
|
||||
"django_measurement",
|
||||
"django_prices",
|
||||
"django_prices_openexchangerates",
|
||||
"django_prices_vatlayer",
|
||||
"graphene_django",
|
||||
"mptt",
|
||||
"django_countries",
|
||||
"django_filters",
|
||||
"phonenumber_field",
|
||||
]
|
||||
|
||||
|
||||
ENABLE_DEBUG_TOOLBAR = get_bool_from_env("ENABLE_DEBUG_TOOLBAR", False)
|
||||
if ENABLE_DEBUG_TOOLBAR:
|
||||
# Ensure the graphiql debug toolbar is actually installed before adding it
|
||||
try:
|
||||
__import__("graphiql_debug_toolbar")
|
||||
except ImportError as exc:
|
||||
msg = (
|
||||
f"{exc} -- Install the missing dependencies by "
|
||||
f"running `pip install -r requirements_dev.txt`"
|
||||
)
|
||||
warnings.warn(msg)
|
||||
else:
|
||||
INSTALLED_APPS += ["django.forms", "debug_toolbar", "graphiql_debug_toolbar"]
|
||||
MIDDLEWARE.append("saleor.graphql.middleware.DebugToolbarMiddleware")
|
||||
|
||||
DEBUG_TOOLBAR_PANELS = [
|
||||
"ddt_request_history.panels.request_history.RequestHistoryPanel",
|
||||
"debug_toolbar.panels.timer.TimerPanel",
|
||||
"debug_toolbar.panels.headers.HeadersPanel",
|
||||
"debug_toolbar.panels.request.RequestPanel",
|
||||
"debug_toolbar.panels.sql.SQLPanel",
|
||||
"debug_toolbar.panels.profiling.ProfilingPanel",
|
||||
]
|
||||
DEBUG_TOOLBAR_CONFIG = {"RESULTS_CACHE_SIZE": 100}
|
||||
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"root": {"level": "INFO", "handlers": ["default"]},
|
||||
"formatters": {
|
||||
"django.server": {
|
||||
"()": "django.utils.log.ServerFormatter",
|
||||
"format": "[{server_time}] {message}",
|
||||
"style": "{",
|
||||
},
|
||||
"json": {
|
||||
"()": "saleor.core.logging.JsonFormatter",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%SZ",
|
||||
"format": (
|
||||
"%(asctime)s %(levelname)s %(lineno)s %(message)s %(name)s "
|
||||
+ "%(pathname)s %(process)d %(threadName)s"
|
||||
),
|
||||
},
|
||||
"verbose": {
|
||||
"format": (
|
||||
"%(levelname)s %(name)s %(message)s [PID:%(process)d:%(threadName)s]"
|
||||
)
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"default": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose" if DEBUG else "json",
|
||||
},
|
||||
"django.server": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "django.server" if DEBUG else "json",
|
||||
},
|
||||
},
|
||||
"loggers": {
|
||||
"django": {"level": "INFO", "propagate": True},
|
||||
"django.server": {
|
||||
"handlers": ["django.server"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
"saleor": {"level": "DEBUG", "propagate": True},
|
||||
"saleor.graphql.errors.handled": {
|
||||
"handlers": ["default"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
"graphql.execution.utils": {"propagate": False},
|
||||
},
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = "account.User"
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
"OPTIONS": {"min_length": 8},
|
||||
}
|
||||
]
|
||||
|
||||
DEFAULT_COUNTRY = os.environ.get("DEFAULT_COUNTRY", "US")
|
||||
DEFAULT_CURRENCY = os.environ.get("DEFAULT_CURRENCY", "USD")
|
||||
DEFAULT_DECIMAL_PLACES = 3
|
||||
DEFAULT_MAX_DIGITS = 12
|
||||
DEFAULT_CURRENCY_CODE_LENGTH = 3
|
||||
|
||||
# The default max length for the display name of the
|
||||
# sender email address.
|
||||
# Following the recommendation of https://tools.ietf.org/html/rfc5322#section-2.1.1
|
||||
DEFAULT_MAX_EMAIL_DISPLAY_NAME_LENGTH = 78
|
||||
|
||||
COUNTRIES_OVERRIDE = {"EU": "European Union"}
|
||||
|
||||
OPENEXCHANGERATES_API_KEY = os.environ.get("OPENEXCHANGERATES_API_KEY")
|
||||
|
||||
GOOGLE_ANALYTICS_TRACKING_ID = os.environ.get("GOOGLE_ANALYTICS_TRACKING_ID")
|
||||
|
||||
|
||||
def get_host():
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
return Site.objects.get_current().domain
|
||||
|
||||
|
||||
PAYMENT_HOST = get_host
|
||||
|
||||
PAYMENT_MODEL = "order.Payment"
|
||||
|
||||
MAX_CHECKOUT_LINE_QUANTITY = int(os.environ.get("MAX_CHECKOUT_LINE_QUANTITY", 50))
|
||||
|
||||
TEST_RUNNER = "saleor.tests.runner.PytestTestRunner"
|
||||
|
||||
|
||||
PLAYGROUND_ENABLED = get_bool_from_env("PLAYGROUND_ENABLED", True)
|
||||
|
||||
ALLOWED_HOSTS = get_list(os.environ.get("ALLOWED_HOSTS", "localhost,127.0.0.1"))
|
||||
ALLOWED_GRAPHQL_ORIGINS = get_list(os.environ.get("ALLOWED_GRAPHQL_ORIGINS", "*"))
|
||||
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
|
||||
# Amazon S3 configuration
|
||||
# See https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html
|
||||
AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID")
|
||||
AWS_LOCATION = os.environ.get("AWS_LOCATION", "")
|
||||
AWS_MEDIA_BUCKET_NAME = os.environ.get("AWS_MEDIA_BUCKET_NAME")
|
||||
AWS_MEDIA_CUSTOM_DOMAIN = os.environ.get("AWS_MEDIA_CUSTOM_DOMAIN")
|
||||
AWS_QUERYSTRING_AUTH = get_bool_from_env("AWS_QUERYSTRING_AUTH", False)
|
||||
AWS_QUERYSTRING_EXPIRE = get_bool_from_env("AWS_QUERYSTRING_EXPIRE", 3600)
|
||||
AWS_S3_CUSTOM_DOMAIN = os.environ.get("AWS_STATIC_CUSTOM_DOMAIN")
|
||||
AWS_S3_ENDPOINT_URL = os.environ.get("AWS_S3_ENDPOINT_URL", None)
|
||||
AWS_S3_REGION_NAME = os.environ.get("AWS_S3_REGION_NAME", None)
|
||||
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY")
|
||||
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME")
|
||||
AWS_DEFAULT_ACL = os.environ.get("AWS_DEFAULT_ACL", None)
|
||||
|
||||
# Google Cloud Storage configuration
|
||||
GS_PROJECT_ID = os.environ.get("GS_PROJECT_ID")
|
||||
GS_STORAGE_BUCKET_NAME = os.environ.get("GS_STORAGE_BUCKET_NAME")
|
||||
GS_MEDIA_BUCKET_NAME = os.environ.get("GS_MEDIA_BUCKET_NAME")
|
||||
GS_AUTO_CREATE_BUCKET = get_bool_from_env("GS_AUTO_CREATE_BUCKET", False)
|
||||
GS_QUERYSTRING_AUTH = get_bool_from_env("GS_QUERYSTRING_AUTH", False)
|
||||
GS_DEFAULT_ACL = os.environ.get("GS_DEFAULT_ACL", None)
|
||||
GS_MEDIA_CUSTOM_ENDPOINT = os.environ.get("GS_MEDIA_CUSTOM_ENDPOINT", None)
|
||||
GS_EXPIRATION = os.environ.get("GS_EXPIRATION", None)
|
||||
|
||||
# If GOOGLE_APPLICATION_CREDENTIALS is set there is no need to load OAuth token
|
||||
# See https://django-storages.readthedocs.io/en/latest/backends/gcloud.html
|
||||
if "GOOGLE_APPLICATION_CREDENTIALS" not in os.environ:
|
||||
GS_CREDENTIALS = os.environ.get("GS_CREDENTIALS")
|
||||
|
||||
if AWS_STORAGE_BUCKET_NAME:
|
||||
STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
|
||||
elif GS_STORAGE_BUCKET_NAME:
|
||||
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
|
||||
|
||||
if AWS_MEDIA_BUCKET_NAME:
|
||||
DEFAULT_FILE_STORAGE = "saleor.core.storages.S3MediaStorage"
|
||||
THUMBNAIL_DEFAULT_STORAGE = DEFAULT_FILE_STORAGE
|
||||
elif GS_MEDIA_BUCKET_NAME:
|
||||
DEFAULT_FILE_STORAGE = "saleor.core.storages.GCSMediaStorage"
|
||||
THUMBNAIL_DEFAULT_STORAGE = DEFAULT_FILE_STORAGE
|
||||
|
||||
VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
|
||||
"products": [
|
||||
("product_gallery", "thumbnail__540x540"),
|
||||
("product_gallery_2x", "thumbnail__1080x1080"),
|
||||
("product_small", "thumbnail__60x60"),
|
||||
("product_small_2x", "thumbnail__120x120"),
|
||||
("product_list", "thumbnail__255x255"),
|
||||
("product_list_2x", "thumbnail__510x510"),
|
||||
],
|
||||
"background_images": [("header_image", "thumbnail__1080x440")],
|
||||
"user_avatars": [("default", "thumbnail__445x445")],
|
||||
}
|
||||
|
||||
VERSATILEIMAGEFIELD_SETTINGS = {
|
||||
# Images should be pre-generated on Production environment
|
||||
"create_images_on_demand": get_bool_from_env("CREATE_IMAGES_ON_DEMAND", DEBUG)
|
||||
}
|
||||
|
||||
PLACEHOLDER_IMAGES = {
|
||||
60: "images/placeholder60x60.png",
|
||||
120: "images/placeholder120x120.png",
|
||||
255: "images/placeholder255x255.png",
|
||||
540: "images/placeholder540x540.png",
|
||||
1080: "images/placeholder1080x1080.png",
|
||||
}
|
||||
|
||||
DEFAULT_PLACEHOLDER = "images/placeholder255x255.png"
|
||||
|
||||
SEARCH_BACKEND = "saleor.search.backends.postgresql"
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
"saleor.core.auth_backend.JSONWebTokenBackend",
|
||||
]
|
||||
|
||||
# CELERY SETTINGS
|
||||
CELERY_TIMEZONE = TIME_ZONE
|
||||
CELERY_BROKER_URL = (
|
||||
os.environ.get("CELERY_BROKER_URL", os.environ.get("CLOUDAMQP_URL")) or ""
|
||||
)
|
||||
CELERY_TASK_ALWAYS_EAGER = not CELERY_BROKER_URL
|
||||
CELERY_ACCEPT_CONTENT = ["json"]
|
||||
CELERY_TASK_SERIALIZER = "json"
|
||||
CELERY_RESULT_SERIALIZER = "json"
|
||||
CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND", None)
|
||||
|
||||
# Change this value if your application is running behind a proxy,
|
||||
# e.g. HTTP_CF_Connecting_IP for Cloudflare or X_FORWARDED_FOR
|
||||
REAL_IP_ENVIRON = os.environ.get("REAL_IP_ENVIRON", "REMOTE_ADDR")
|
||||
|
||||
# Slugs for menus precreated in Django migrations
|
||||
DEFAULT_MENUS = {"top_menu_name": "navbar", "bottom_menu_name": "footer"}
|
||||
|
||||
# Slug for channel precreated in Django migrations
|
||||
DEFAULT_CHANNEL_SLUG = os.environ.get("DEFAULT_CHANNEL_SLUG", "default-channel")
|
||||
|
||||
|
||||
# Sentry
|
||||
sentry_sdk.utils.MAX_STRING_LENGTH = 4096
|
||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||
if SENTRY_DSN:
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN, integrations=[CeleryIntegration(), DjangoIntegration()]
|
||||
)
|
||||
|
||||
GRAPHENE = {
|
||||
"RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST": True,
|
||||
"RELAY_CONNECTION_MAX_LIMIT": 100,
|
||||
"MIDDLEWARE": [
|
||||
"saleor.graphql.middleware.OpentracingGrapheneMiddleware",
|
||||
"saleor.graphql.middleware.JWTMiddleware",
|
||||
"saleor.graphql.middleware.app_middleware",
|
||||
],
|
||||
}
|
||||
|
||||
PLUGINS_MANAGER = "saleor.plugins.manager.PluginsManager"
|
||||
|
||||
PLUGINS = [
|
||||
"saleor.plugins.avatax.plugin.AvataxPlugin",
|
||||
"saleor.plugins.vatlayer.plugin.VatlayerPlugin",
|
||||
"saleor.plugins.webhook.plugin.WebhookPlugin",
|
||||
"saleor.payment.gateways.dummy.plugin.DummyGatewayPlugin",
|
||||
"saleor.payment.gateways.dummy_credit_card.plugin.DummyCreditCardGatewayPlugin",
|
||||
"saleor.payment.gateways.stripe.plugin.StripeGatewayPlugin",
|
||||
"saleor.payment.gateways.braintree.plugin.BraintreeGatewayPlugin",
|
||||
"saleor.payment.gateways.razorpay.plugin.RazorpayGatewayPlugin",
|
||||
"saleor.payment.gateways.adyen.plugin.AdyenGatewayPlugin",
|
||||
"saleor.payment.gateways.authorize_net.plugin.AuthorizeNetGatewayPlugin",
|
||||
"saleor.plugins.invoicing.plugin.InvoicingPlugin",
|
||||
]
|
||||
|
||||
# Plugin discovery
|
||||
installed_plugins = pkg_resources.iter_entry_points("saleor.plugins")
|
||||
for entry_point in installed_plugins:
|
||||
plugin_path = "{}.{}".format(entry_point.module_name, entry_point.attrs[0])
|
||||
if plugin_path not in PLUGINS:
|
||||
if entry_point.name not in INSTALLED_APPS:
|
||||
INSTALLED_APPS.append(entry_point.name)
|
||||
PLUGINS.append(plugin_path)
|
||||
|
||||
if (
|
||||
not DEBUG
|
||||
and ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL
|
||||
and ALLOWED_CLIENT_HOSTS == get_list(_DEFAULT_CLIENT_HOSTS)
|
||||
):
|
||||
raise ImproperlyConfigured(
|
||||
"Make sure you've added storefront address to ALLOWED_CLIENT_HOSTS "
|
||||
"if ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL is enabled."
|
||||
)
|
||||
|
||||
# Initialize a simple and basic Jaeger Tracing integration
|
||||
# for open-tracing if enabled.
|
||||
#
|
||||
# Refer to our guide on https://docs.saleor.io/docs/next/guides/opentracing-jaeger/.
|
||||
#
|
||||
# If running locally, set:
|
||||
# JAEGER_AGENT_HOST=localhost
|
||||
if "JAEGER_AGENT_HOST" in os.environ:
|
||||
jaeger_client.Config(
|
||||
config={
|
||||
"sampler": {"type": "const", "param": 1},
|
||||
"local_agent": {
|
||||
"reporting_port": os.environ.get(
|
||||
"JAEGER_AGENT_PORT", jaeger_client.config.DEFAULT_REPORTING_PORT
|
||||
),
|
||||
"reporting_host": os.environ.get("JAEGER_AGENT_HOST"),
|
||||
},
|
||||
"logging": get_bool_from_env("JAEGER_LOGGING", False),
|
||||
},
|
||||
service_name="saleor",
|
||||
validate=True,
|
||||
).initialize_tracer()
|
||||
|
||||
|
||||
# Some cloud providers (Heroku) export REDIS_URL variable instead of CACHE_URL
|
||||
REDIS_URL = os.environ.get("REDIS_URL")
|
||||
if REDIS_URL:
|
||||
CACHE_URL = os.environ.setdefault("CACHE_URL", REDIS_URL)
|
||||
CACHES = {"default": django_cache_url.config()}
|
||||
|
||||
# Default False because storefront and dashboard don't support expiration of token
|
||||
JWT_EXPIRE = get_bool_from_env("JWT_EXPIRE", False)
|
||||
JWT_TTL_ACCESS = timedelta(seconds=parse(os.environ.get("JWT_TTL_ACCESS", "5 minutes")))
|
||||
JWT_TTL_APP_ACCESS = timedelta(
|
||||
seconds=parse(os.environ.get("JWT_TTL_APP_ACCESS", "5 minutes"))
|
||||
)
|
||||
JWT_TTL_REFRESH = timedelta(seconds=parse(os.environ.get("JWT_TTL_REFRESH", "30 days")))
|
||||
|
||||
|
||||
JWT_TTL_REQUEST_EMAIL_CHANGE = timedelta(
|
||||
seconds=parse(os.environ.get("JWT_TTL_REQUEST_EMAIL_CHANGE", "1 hour")),
|
||||
)
|
|
@ -22,5 +22,6 @@ MEDIA_URL="{media}"
|
|||
|
||||
#OPENEXCHANGERATES_API_KEY="{openxkey}"
|
||||
#GOOGLE_ANALYTICS_TRACKING_ID="{gatid}"
|
||||
ADMIN_EMAIL="{adminemail}"
|
||||
|
||||
DEBUG=False
|
Loading…
Reference in a new issue