Improvemnts on installation
This commit is contained in:
parent
3207f7de8b
commit
f13ced72e3
2
TODO.md
2
TODO.md
|
@ -391,4 +391,6 @@ TODO mount the filesystem with "nosuid" option
|
||||||
# wkhtmltopdf -> reportlab
|
# wkhtmltopdf -> reportlab
|
||||||
|
|
||||||
|
|
||||||
|
# MAKE DEPENDENCIES OPTIONAL, check on deploy and warn that functionallity will not be available
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -126,13 +126,17 @@ function install_requirements () {
|
||||||
python3-pip \
|
python3-pip \
|
||||||
python3-dev \
|
python3-dev \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
|
bind9utils \
|
||||||
libxslt1-dev \
|
libxslt1-dev \
|
||||||
wkhtmltopdf \
|
wkhtmltopdf \
|
||||||
xvfb \
|
xvfb \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
gettext"
|
gettext"
|
||||||
|
|
||||||
PIP=$(wget https://raw.githubusercontent.com/glic3rinu/django-orchestra/master/requirements.txt -q -O - | tr '\n' ' ')
|
PIP="$(wget https://raw.githubusercontent.com/glic3rinu/django-orchestra/master/requirements.txt -q -O - | tr '\n' ' ') \
|
||||||
|
https://github.com/glic3rinu/passlib/archive/master.zip \
|
||||||
|
cracklib \
|
||||||
|
lxml==3.3.5"
|
||||||
|
|
||||||
if $testing; then
|
if $testing; then
|
||||||
APT="${APT} \
|
APT="${APT} \
|
||||||
|
|
|
@ -66,6 +66,7 @@ INSTALLED_APPS = [
|
||||||
'passlib.ext.django',
|
'passlib.ext.django',
|
||||||
'django_countries',
|
'django_countries',
|
||||||
# 'django_mailer',
|
# 'django_mailer',
|
||||||
|
# 'debug_toolbar',
|
||||||
|
|
||||||
# Django.contrib
|
# Django.contrib
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.apps import AppConfig
|
||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from .management import create_initial_superuser
|
from orchestra.core import services, accounts
|
||||||
|
|
||||||
|
|
||||||
class AccountConfig(AppConfig):
|
class AccountConfig(AppConfig):
|
||||||
|
@ -10,5 +10,9 @@ class AccountConfig(AppConfig):
|
||||||
verbose_name = _("Accounts")
|
verbose_name = _("Accounts")
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from .management import create_initial_superuser
|
||||||
|
from .models import Account
|
||||||
|
services.register(Account, menu=False)
|
||||||
|
accounts.register(Account)
|
||||||
post_migrate.connect(create_initial_superuser,
|
post_migrate.connect(create_initial_superuser,
|
||||||
dispatch_uid="orchestra.contrib.accounts.management.createsuperuser")
|
dispatch_uid="orchestra.contrib.accounts.management.createsuperuser")
|
||||||
|
|
|
@ -2,7 +2,9 @@ import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.exceptions import FieldError
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
def create_initial_superuser(**kwargs):
|
def create_initial_superuser(**kwargs):
|
||||||
|
@ -15,5 +17,11 @@ def create_initial_superuser(**kwargs):
|
||||||
|
|
||||||
""")
|
""")
|
||||||
)
|
)
|
||||||
|
from ..models import Account
|
||||||
|
try:
|
||||||
|
Account.systemusers.related.model.objects.filter(account_id=1).exists()
|
||||||
|
except FieldError:
|
||||||
|
# avoid creating a systemuser when systemuser table is not ready
|
||||||
|
Account.save = models.Model.save
|
||||||
manager = sys.argv[0]
|
manager = sys.argv[0]
|
||||||
execute_from_command_line(argv=[manager, 'createsuperuser'])
|
execute_from_command_line(argv=[manager, 'createsuperuser'])
|
||||||
|
|
|
@ -7,7 +7,6 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.contrib.orchestration.middlewares import OperationsMiddleware
|
from orchestra.contrib.orchestration.middlewares import OperationsMiddleware
|
||||||
from orchestra.contrib.orchestration import Operation
|
from orchestra.contrib.orchestration import Operation
|
||||||
from orchestra.core import services, accounts
|
|
||||||
from orchestra.utils import send_email_template
|
from orchestra.utils import send_email_template
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
@ -156,7 +155,3 @@ class Account(auth.AbstractBaseUser):
|
||||||
continue
|
continue
|
||||||
related.append(rel)
|
related.append(rel)
|
||||||
return related
|
return related
|
||||||
|
|
||||||
|
|
||||||
services.register(Account, menu=False)
|
|
||||||
accounts.register(Account)
|
|
||||||
|
|
Binary file not shown.
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -11,6 +12,9 @@ from orchestra.utils.sys import run
|
||||||
from .. import domains
|
from .. import domains
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def validate_allowed_domain(value):
|
def validate_allowed_domain(value):
|
||||||
context = {
|
context = {
|
||||||
'site_dir': paths.get_site_dir()
|
'site_dir': paths.get_site_dir()
|
||||||
|
@ -114,9 +118,11 @@ def validate_zone(zone):
|
||||||
with open(zone_path, 'wb') as f:
|
with open(zone_path, 'wb') as f:
|
||||||
f.write(zone.encode('ascii'))
|
f.write(zone.encode('ascii'))
|
||||||
# Don't use /dev/stdin becuase the 'argument list is too long' error
|
# Don't use /dev/stdin becuase the 'argument list is too long' error
|
||||||
check = run(' '.join([checkzone, zone_name, zone_path]), error_codes=[0,1], display=False)
|
check = run(' '.join([checkzone, zone_name, zone_path]), error_codes=[0,1,127], display=False)
|
||||||
finally:
|
finally:
|
||||||
os.unlink(zone_path)
|
os.unlink(zone_path)
|
||||||
if check.return_code == 1:
|
if check.return_code == 127:
|
||||||
|
logger.error("Cannot validate domain zone: %s not installed." % checkzone)
|
||||||
|
elif check.return_code == 1:
|
||||||
errors = re.compile(r'zone.*: (.*)').findall(check.stdout)[:-1]
|
errors = re.compile(r'zone.*: (.*)').findall(check.stdout)[:-1]
|
||||||
raise ValidationError(', '.join(errors))
|
raise ValidationError(', '.join(errors))
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'orchestra.contrib.orders.apps.OrdersConfig'
|
|
@ -0,0 +1,15 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
from orchestra.core import accounts
|
||||||
|
from orchestra.utils import database_ready
|
||||||
|
|
||||||
|
|
||||||
|
class OrdersConfig(AppConfig):
|
||||||
|
name = 'orchestra.contrib.orders'
|
||||||
|
verbose_name = 'Orders'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from .models import Order
|
||||||
|
accounts.register(Order)
|
||||||
|
if database_ready():
|
||||||
|
from . import signals
|
|
@ -5,18 +5,16 @@ import logging
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.db.models.signals import post_delete, post_save, pre_delete
|
|
||||||
from django.dispatch import receiver
|
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.core import accounts, services
|
from orchestra.core import services
|
||||||
from orchestra.models import queryset
|
from orchestra.models import queryset
|
||||||
from orchestra.utils.python import import_class
|
from orchestra.utils.python import import_class
|
||||||
|
|
||||||
from . import helpers, settings
|
from . import settings
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -273,38 +271,3 @@ class MetricStorage(models.Model):
|
||||||
else:
|
else:
|
||||||
last.updated_on = now
|
last.updated_on = now
|
||||||
last.save(update_fields=['updated_on'])
|
last.save(update_fields=['updated_on'])
|
||||||
|
|
||||||
|
|
||||||
accounts.register(Order)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO perhas use cache = caches.get_request_cache() to cache an account delete and don't processes get_related_objects() if the case
|
|
||||||
# FIXME https://code.djangoproject.com/ticket/24576
|
|
||||||
# TODO build a cache hash table {model: related, model: None}
|
|
||||||
@receiver(post_delete, dispatch_uid="orders.cancel_orders")
|
|
||||||
def cancel_orders(sender, **kwargs):
|
|
||||||
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
|
||||||
instance = kwargs['instance']
|
|
||||||
# Account delete will delete all related orders, no need to maintain order consistency
|
|
||||||
if isinstance(instance, Order.account.field.rel.to):
|
|
||||||
return
|
|
||||||
if type(instance) in services:
|
|
||||||
for order in Order.objects.by_object(instance).active():
|
|
||||||
order.cancel()
|
|
||||||
elif not hasattr(instance, 'account'):
|
|
||||||
# FIXME Indeterminate behaviour
|
|
||||||
related = helpers.get_related_object(instance)
|
|
||||||
if related and related != instance:
|
|
||||||
type(related).objects.get(pk=related.pk)
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, dispatch_uid="orders.update_orders")
|
|
||||||
def update_orders(sender, **kwargs):
|
|
||||||
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
|
||||||
instance = kwargs['instance']
|
|
||||||
if type(instance) in services:
|
|
||||||
Order.update_orders(instance)
|
|
||||||
elif not hasattr(instance, 'account'):
|
|
||||||
related = helpers.get_related_object(instance)
|
|
||||||
if related and related != instance:
|
|
||||||
Order.update_orders(related)
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
from django.db.models.signals import post_delete, post_save, pre_delete
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from orchestra.core import services
|
||||||
|
|
||||||
|
from . import helpers, settings
|
||||||
|
from .models import Order
|
||||||
|
|
||||||
|
|
||||||
|
# TODO perhas use cache = caches.get_request_cache() to cache an account delete and don't processes get_related_objects() if the case
|
||||||
|
# FIXME https://code.djangoproject.com/ticket/24576
|
||||||
|
# TODO build a cache hash table {model: related, model: None}
|
||||||
|
@receiver(post_delete, dispatch_uid="orders.cancel_orders")
|
||||||
|
def cancel_orders(sender, **kwargs):
|
||||||
|
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
||||||
|
instance = kwargs['instance']
|
||||||
|
# Account delete will delete all related orders, no need to maintain order consistency
|
||||||
|
if isinstance(instance, Order.account.field.rel.to):
|
||||||
|
return
|
||||||
|
if type(instance) in services:
|
||||||
|
for order in Order.objects.by_object(instance).active():
|
||||||
|
order.cancel()
|
||||||
|
elif not hasattr(instance, 'account'):
|
||||||
|
# FIXME Indeterminate behaviour
|
||||||
|
related = helpers.get_related_object(instance)
|
||||||
|
if related and related != instance:
|
||||||
|
type(related).objects.get(pk=related.pk)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, dispatch_uid="orders.update_orders")
|
||||||
|
def update_orders(sender, **kwargs):
|
||||||
|
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
||||||
|
instance = kwargs['instance']
|
||||||
|
if type(instance) in services:
|
||||||
|
Order.update_orders(instance)
|
||||||
|
elif not hasattr(instance, 'account'):
|
||||||
|
related = helpers.get_related_object(instance)
|
||||||
|
if related and related != instance:
|
||||||
|
Order.update_orders(related)
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
from dateutil import relativedelta
|
from dateutil import relativedelta
|
||||||
|
|
||||||
from orchestra import plugins
|
from orchestra import plugins
|
||||||
|
@ -7,6 +8,9 @@ from orchestra.utils.python import import_class
|
||||||
from .. import settings
|
from .. import settings
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PaymentMethod(plugins.Plugin):
|
class PaymentMethod(plugins.Plugin):
|
||||||
label_field = 'label'
|
label_field = 'label'
|
||||||
number_field = 'number'
|
number_field = 'number'
|
||||||
|
@ -19,7 +23,10 @@ class PaymentMethod(plugins.Plugin):
|
||||||
def get_plugins(cls):
|
def get_plugins(cls):
|
||||||
plugins = []
|
plugins = []
|
||||||
for cls in settings.PAYMENTS_ENABLED_METHODS:
|
for cls in settings.PAYMENTS_ENABLED_METHODS:
|
||||||
plugins.append(import_class(cls))
|
try:
|
||||||
|
plugins.append(import_class(cls))
|
||||||
|
except ImportError as exc:
|
||||||
|
logger.error(str(exc))
|
||||||
return plugins
|
return plugins
|
||||||
|
|
||||||
def get_label(self):
|
def get_label(self):
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django import db
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
from orchestra.utils import database_ready
|
from orchestra.utils import database_ready
|
||||||
|
@ -10,7 +11,11 @@ class ResourcesConfig(AppConfig):
|
||||||
def ready(self):
|
def ready(self):
|
||||||
if database_ready():
|
if database_ready():
|
||||||
from .models import create_resource_relation
|
from .models import create_resource_relation
|
||||||
create_resource_relation()
|
try:
|
||||||
|
create_resource_relation()
|
||||||
|
except db.utils.OperationalError:
|
||||||
|
# Not ready afterall
|
||||||
|
pass
|
||||||
|
|
||||||
def reload_relations(self):
|
def reload_relations(self):
|
||||||
from .admin import insert_resource_inlines
|
from .admin import insert_resource_inlines
|
||||||
|
|
|
@ -1,6 +1,28 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
from django.db.models.signals import post_migrate
|
||||||
|
|
||||||
|
from orchestra.core import services
|
||||||
|
|
||||||
|
|
||||||
class SystemUsersConfig(AppConfig):
|
class SystemUsersConfig(AppConfig):
|
||||||
name = 'orchestra.contrib.systemusers'
|
name = 'orchestra.contrib.systemusers'
|
||||||
verbose_name = "System users"
|
verbose_name = "System users"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from .models import SystemUser
|
||||||
|
services.register(SystemUser)
|
||||||
|
if 'migrate' in sys.argv and 'accounts' not in sys.argv:
|
||||||
|
post_migrate.connect(self.create_initial_systemuser,
|
||||||
|
dispatch_uid="orchestra.contrib.systemusers.apps.create_initial_systemuser")
|
||||||
|
|
||||||
|
def create_initial_systemuser(self, **kwargs):
|
||||||
|
from .models import SystemUser
|
||||||
|
Account = SystemUser.account.field.related.model
|
||||||
|
for account in Account.objects.filter(is_superuser=True, main_systemuser_id__isnull=True):
|
||||||
|
systemuser = SystemUser.objects.create(username=account.username,
|
||||||
|
password=account.password, account=account)
|
||||||
|
account.main_systemuser = systemuser
|
||||||
|
account.save()
|
||||||
|
sys.stdout.write("Created initial systemuser %s.\n" % systemuser.username)
|
||||||
|
|
|
@ -108,6 +108,3 @@ class SystemUser(models.Model):
|
||||||
|
|
||||||
def get_home(self):
|
def get_home(self):
|
||||||
return os.path.normpath(os.path.join(self.home, self.directory))
|
return os.path.normpath(os.path.join(self.home, self.directory))
|
||||||
|
|
||||||
|
|
||||||
services.register(SystemUser)
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
try:
|
|
||||||
import crack
|
|
||||||
except:
|
|
||||||
import cracklib as crack
|
|
||||||
import phonenumbers
|
import phonenumbers
|
||||||
|
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -14,6 +10,9 @@ from IPy import IP
|
||||||
from ..utils.python import import_class
|
from ..utils.python import import_class
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def all_valid(*args):
|
def all_valid(*args):
|
||||||
""" helper function to merge multiple validators at once """
|
""" helper function to merge multiple validators at once """
|
||||||
if len(args) == 1:
|
if len(args) == 1:
|
||||||
|
@ -103,6 +102,14 @@ def validate_username(value):
|
||||||
|
|
||||||
|
|
||||||
def validate_password(value):
|
def validate_password(value):
|
||||||
|
try:
|
||||||
|
import crack
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
import cracklib as crack
|
||||||
|
except:
|
||||||
|
logger.error("Can not validate password. Cracklib bindings are not installed.")
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
crack.VeryFascistCheck(value)
|
crack.VeryFascistCheck(value)
|
||||||
except ValueError as message:
|
except ValueError as message:
|
||||||
|
|
|
@ -3,11 +3,13 @@ from django.conf import settings
|
||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import patterns, include, url
|
||||||
|
|
||||||
from . import api
|
from . import api
|
||||||
|
from .utils.apps import isinstalled
|
||||||
|
|
||||||
|
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
api.autodiscover()
|
api.autodiscover()
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
# Admin
|
# Admin
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
@ -27,7 +29,7 @@ urlpatterns = patterns('',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
if isinstalled('debug_toolbar'):
|
||||||
import debug_toolbar
|
import debug_toolbar
|
||||||
urlpatterns += patterns('',
|
urlpatterns += patterns('',
|
||||||
url(r'^__debug__/', include(debug_toolbar.urls)),
|
url(r'^__debug__/', include(debug_toolbar.urls)),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
cracklib
|
|
||||||
django==1.8.1
|
django==1.8.1
|
||||||
django-celery-email==1.0.4
|
django-celery-email==1.0.4
|
||||||
django-fluent-dashboard==0.5
|
django-fluent-dashboard==0.5
|
||||||
|
@ -16,9 +15,7 @@ paramiko==1.15.1
|
||||||
ecdsa==0.11
|
ecdsa==0.11
|
||||||
Pygments==1.6
|
Pygments==1.6
|
||||||
django-filter==0.7
|
django-filter==0.7
|
||||||
https://github.com/glic3rinu/passlib/archive/master.zip
|
|
||||||
jsonfield==0.9.22
|
jsonfield==0.9.22
|
||||||
lxml==3.3.5
|
|
||||||
python-dateutil==2.2
|
python-dateutil==2.2
|
||||||
django-iban==0.3.0
|
django-iban==0.3.0
|
||||||
requests
|
requests
|
||||||
|
|
Loading…
Reference in New Issue