Prepend ORCHESTRA_ to orchestra settigs
This commit is contained in:
parent
d165d7f03d
commit
4a6d29ebd7
29
TODO.md
29
TODO.md
|
@ -75,26 +75,19 @@
|
|||
|
||||
* Databases.User add reverse M2M databases widget (like mailbox.addresses)
|
||||
|
||||
* reconsider binding webapps to systemusers (pangea multiple users wordpress-ftp, moodle-pangea, etc)
|
||||
* Secondary user home in /home/secondaryuser and simlink to /home/main/webapps/app so it can have private storage?
|
||||
* Grant permissions to systemusers, the problem of creating a related permission model is out of sync with the server-side. evaluate tradeoff
|
||||
* Grant permissions to systemusers
|
||||
|
||||
* Make one dedicated CGI user for each account only for CGI execution (fpm/fcgid). Different from the files owner, and without W permissions, so attackers can not inject backdors and malware.
|
||||
* In most cases we can prevent the creation of files for the CGI users, preventing attackers to upload and executing PHPShells.
|
||||
* Make main systemuser able to write/read everything on its home, including stuff created by the CGI user and secondary users
|
||||
* Prevent users from accessing other users home while at the same time allow access Apache/fcgid/fpm and secondary users (x)
|
||||
|
||||
* resource min max allocation with validation
|
||||
|
||||
* mailman needs both aliases when address_name is provided (default messages and bounces and all)
|
||||
|
||||
* domain validation parse named-checzone output to assign errors to fields
|
||||
|
||||
* Directory Protection on webapp and use webapp path as base path (validate)
|
||||
|
||||
* validate systemuser.home on server-side
|
||||
|
||||
* webapp backend option compatibility check?
|
||||
* webapp backend option compatibility check? raise exception, missconfigured error
|
||||
|
||||
* admin systemuser home/directory, add default home and empty directory with has_shell on admin
|
||||
|
||||
|
@ -116,8 +109,6 @@
|
|||
|
||||
ln -s /proc/self/fd /dev/fd
|
||||
|
||||
* escape passwords and not allow ' on them !
|
||||
|
||||
|
||||
POST INSTALL
|
||||
------------
|
||||
|
@ -155,8 +146,6 @@ Php binaries should have this format: /usr/bin/php5.2-cgi
|
|||
|
||||
* tags = GenericRelation(TaggedItem, related_query_name='bookmarks')
|
||||
|
||||
# make home for all systemusers (/home/username) and fix monitors
|
||||
|
||||
* user provided crons
|
||||
|
||||
* ```<?php
|
||||
|
@ -167,15 +156,13 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
|||
|
||||
# WPMU blog traffic
|
||||
|
||||
* normurlpath '' return '/'
|
||||
|
||||
* more robust backend error handling, continue executing but exit code > 0 if failure: failing_cmd || exit_code=1 and don't forget to call super.commit()!!
|
||||
|
||||
* website directives uniquenes validation on serializers
|
||||
|
||||
+ is_Active custom filter with support for instance.account.is_Active annotate with F() needed (django 1.8)
|
||||
|
||||
* delete apache logs and php logs
|
||||
# delete apache logs and php logs
|
||||
|
||||
* document service help things: discount/refound/compensation effect and metric table
|
||||
* Document metric interpretation help_text
|
||||
|
@ -218,6 +205,7 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
|||
* write down insights
|
||||
|
||||
# use english on services defs and so on, an translate them on render time
|
||||
python3 manage.py dumpdata services.Service --indent 4 --natural
|
||||
|
||||
* websites directives get_location() and use it on last change view validation stage to compare with contents.location and also on the backend ?
|
||||
|
||||
|
@ -229,8 +217,6 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
|||
|
||||
# TDOO Base price: domini propi (all domains) + extra for other domains
|
||||
|
||||
# TODO prepend ORCHESTRA_ to orchestra/settings.py
|
||||
|
||||
|
||||
Translation
|
||||
-----------
|
||||
|
@ -260,16 +246,12 @@ celery max-tasks-per-child
|
|||
|
||||
* postupgradeorchestra send signals in order to hook custom stuff
|
||||
|
||||
# FIXME make base home for systemusers that ara homed into main account systemuser, and prevent shell users to have nested homes (if nnot implemented already)
|
||||
|
||||
* autoscale celery workers http://docs.celeryproject.org/en/latest/userguide/workers.html#autoscaling
|
||||
|
||||
* webapp has_website list filter
|
||||
|
||||
glic3rinu's django-fluent-dashboard
|
||||
* gevent is not ported to python3 :'(
|
||||
* uwsgi python3
|
||||
|
||||
|
||||
# FIXME account deletion generates an integrity error
|
||||
https://code.djangoproject.com/ticket/24576
|
||||
|
@ -289,11 +271,10 @@ https://code.djangoproject.com/ticket/24576
|
|||
|
||||
# FIXME model contact info and account info (email, name, etc) correctly/unredundant/dry
|
||||
|
||||
|
||||
* Use the new django.contrib.admin.RelatedOnlyFieldListFilter in ModelAdmin.list_filter to limit the list_filter choices to foreign objects which are attached to those from the ModelAdmin.
|
||||
+ Query Expressions, Conditional Expressions, and Database Functions¶
|
||||
* forms: You can now pass a callable that returns an iterable of choices when instantiating a ChoiceField.
|
||||
|
||||
|
||||
* migrate to DRF3.x
|
||||
|
||||
* move all tests on django-orchestra/tests
|
||||
|
|
|
@ -56,7 +56,7 @@ class LogApiMixin(object):
|
|||
class LinkHeaderRouter(DefaultRouter):
|
||||
def get_api_root_view(self):
|
||||
""" returns the root view, with all the linked collections """
|
||||
APIRoot = import_class(settings.API_ROOT_VIEW)
|
||||
APIRoot = import_class(settings.ORCHESTRA_API_ROOT_VIEW)
|
||||
APIRoot.router = self
|
||||
return APIRoot.as_view()
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ from ..core import services, accounts
|
|||
|
||||
|
||||
class APIRoot(views.APIView):
|
||||
names = ['SITE_NAME', 'SITE_VERBOSE_NAME']
|
||||
names = (
|
||||
'ORCHESTRA_SITE_NAME',
|
||||
'ORCHESTRA_SITE_VERBOSE_NAME'
|
||||
)
|
||||
|
||||
def get(self, request, format=None):
|
||||
root_url = reverse('api-root', request=request, format=format)
|
||||
|
|
|
@ -137,7 +137,7 @@ function install_requirements () {
|
|||
|
||||
PIP="django==1.8 \
|
||||
django-celery-email==1.0.4 \
|
||||
django-fluent-dashboard==0.4 \
|
||||
https://github.com/glic3rinu/django-fluent-dashboard/archive/master.zip \
|
||||
https://bitbucket.org/izi/django-admin-tools/get/a0abfffd76a0.zip \
|
||||
IPy==0.81 \
|
||||
django-extensions==1.5.2 \
|
||||
|
|
|
@ -68,5 +68,5 @@ LOCALE_PATHS = (
|
|||
# DEFAULT_FROM_EMAIL = 'orchestra@yourhost.eu'
|
||||
|
||||
|
||||
SITE_NAME = '{{ project_name }}'
|
||||
ORCHESTRA_SITE_NAME = '{{ project_name }}'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
ACCOUNTS_TYPES = getattr(settings, 'ACCOUNTS_TYPES', (
|
||||
|
@ -53,9 +53,9 @@ ACCOUNTS_CREATE_RELATED = getattr(settings, 'ACCOUNTS_CREATE_RELATED', (
|
|||
('domains.Domain',
|
||||
'name',
|
||||
{
|
||||
'name': '"%s.{}" % account.username.replace("_", "-")'.format(BASE_DOMAIN),
|
||||
'name': '"%s.{}" % account.username.replace("_", "-")'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
},
|
||||
_("Designates whether to creates a related subdomain <username>.{} or not.".format(BASE_DOMAIN)),
|
||||
_("Designates whether to creates a related subdomain <username>.{} or not.".format(ORCHESTRA_BASE_DOMAIN)),
|
||||
),
|
||||
))
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django_countries import data
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
BILLS_NUMBER_LENGTH = getattr(settings, 'BILLS_NUMBER_LENGTH',
|
||||
|
@ -60,12 +60,12 @@ BILLS_SELLER_PHONE = getattr(settings, 'BILLS_SELLER_PHONE',
|
|||
|
||||
|
||||
BILLS_SELLER_EMAIL = getattr(settings, 'BILLS_SELLER_EMAIL',
|
||||
'sales@{}'.format(BASE_DOMAIN)
|
||||
'sales@{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
BILLS_SELLER_WEBSITE = getattr(settings, 'BILLS_SELLER_WEBSITE',
|
||||
'www.{}'.format(BASE_DOMAIN)
|
||||
'www.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
from django.conf import settings
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
DOMAINS_DEFAULT_NAME_SERVER = getattr(settings, 'DOMAINS_DEFAULT_NAME_SERVER',
|
||||
'ns.{}'.format(BASE_DOMAIN)
|
||||
'ns.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
DOMAINS_DEFAULT_HOSTMASTER = getattr(settings, 'DOMAINS_DEFAULT_HOSTMASTER',
|
||||
'hostmaster@{}'.format(BASE_DOMAIN)
|
||||
'hostmaster@{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
@ -70,14 +70,14 @@ DOMAINS_DEFAULT_A = getattr(settings, 'DOMAINS_DEFAULT_A',
|
|||
|
||||
|
||||
DOMAINS_DEFAULT_MX = getattr(settings, 'DOMAINS_DEFAULT_MX', (
|
||||
'10 mail.{}.'.format(BASE_DOMAIN),
|
||||
'10 mail2.{}.'.format(BASE_DOMAIN),
|
||||
'10 mail.{}.'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
'10 mail2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
))
|
||||
|
||||
|
||||
DOMAINS_DEFAULT_NS = getattr(settings, 'DOMAINS_DEFAULT_NS', (
|
||||
'ns1.{}.'.format(BASE_DOMAIN),
|
||||
'ns2.{}.'.format(BASE_DOMAIN),
|
||||
'ns1.{}.'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
'ns2.{}.'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
))
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.conf import settings
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
LISTS_DOMAIN_MODEL = getattr(settings, 'LISTS_DOMAIN_MODEL',
|
||||
|
@ -9,12 +9,12 @@ LISTS_DOMAIN_MODEL = getattr(settings, 'LISTS_DOMAIN_MODEL',
|
|||
|
||||
|
||||
LISTS_DEFAULT_DOMAIN = getattr(settings, 'LIST_DEFAULT_DOMAIN',
|
||||
'lists.{}'.format(BASE_DOMAIN)
|
||||
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
LISTS_LIST_URL = getattr(settings, 'LISTS_LIST_URL',
|
||||
'https://lists.{}/mailman/listinfo/%(name)s'.format(BASE_DOMAIN)
|
||||
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import textwrap
|
|||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
MAILBOXES_DOMAIN_MODEL = getattr(settings, 'MAILBOXES_DOMAIN_MODEL',
|
||||
|
@ -48,7 +48,7 @@ MAILBOXES_VIRTUAL_ALIAS_DOMAINS_PATH = getattr(settings, 'MAILBOXES_VIRTUAL_ALIA
|
|||
|
||||
|
||||
MAILBOXES_VIRTUAL_MAILBOX_DEFAULT_DOMAIN = getattr(settings, 'MAILBOXES_VIRTUAL_MAILBOX_DEFAULT_DOMAIN',
|
||||
BASE_DOMAIN
|
||||
ORCHESTRA_BASE_DOMAIN
|
||||
)
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ MAILBOXES_MAILDIRSIZE_PATH = getattr(settings, 'MAILBOXES_MAILDIRSIZE_PATH',
|
|||
|
||||
|
||||
MAILBOXES_LOCAL_ADDRESS_DOMAIN = getattr(settings, 'MAILBOXES_LOCAL_ADDRESS_DOMAIN',
|
||||
BASE_DOMAIN
|
||||
ORCHESTRA_BASE_DOMAIN
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -11,8 +11,7 @@ from . import methods
|
|||
|
||||
|
||||
def replace(context, pattern, repl):
|
||||
if isinstance(context, str):
|
||||
return context.replace(patter, repl)
|
||||
""" applies replace to all context str values """
|
||||
for key, value in context.items():
|
||||
if isinstance(value, str):
|
||||
context[key] = value.replace(pattern, repl)
|
||||
|
@ -23,7 +22,7 @@ class ServiceMount(plugins.PluginMount):
|
|||
def __init__(cls, name, bases, attrs):
|
||||
# Make sure backends specify a model attribute
|
||||
if not (attrs.get('abstract', False) or name == 'ServiceBackend' or cls.model):
|
||||
raise AttributeError("'%s' does not have a defined model attribute." % cls)
|
||||
raise AttributeError("'%s' does not have a defined model attribute." % cls)
|
||||
super(ServiceMount, cls).__init__(name, bases, attrs)
|
||||
|
||||
|
||||
|
@ -36,15 +35,16 @@ class ServiceBackend(plugins.Plugin, metaclass=ServiceMount):
|
|||
the changes of all modified objects, reloading the daemon just once.
|
||||
"""
|
||||
model = None
|
||||
related_models = () # ((model, accessor__attribute),)
|
||||
related_models = () # ((model, accessor__attribute),)
|
||||
script_method = methods.SSH
|
||||
script_executable = '/bin/bash'
|
||||
function_method = methods.Python
|
||||
type = 'task' # 'sync'
|
||||
type = 'task' # 'sync'
|
||||
ignore_fields = []
|
||||
actions = []
|
||||
default_route_match = 'True'
|
||||
block = False # Force the backend manager to block in multiple backend executions and execute them synchronously
|
||||
# Force the backend manager to block in multiple backend executions executing them synchronously
|
||||
block = False
|
||||
|
||||
def __str__(self):
|
||||
return type(self).__name__
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models import Prefetch
|
||||
from django.utils import timezone
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
|
@ -17,7 +18,7 @@ from .models import Order, MetricStorage
|
|||
|
||||
class MetricStorageInline(admin.TabularInline):
|
||||
model = MetricStorage
|
||||
readonly_fields = ('value', 'updated_on')
|
||||
readonly_fields = ('value', 'created_on', 'updated_on')
|
||||
extra = 0
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
|
@ -33,10 +34,11 @@ class MetricStorageInline(admin.TabularInline):
|
|||
|
||||
def get_queryset(self, request):
|
||||
qs = super(MetricStorageInline, self).get_queryset(request)
|
||||
if self.parent_object and self.parent_object.pk:
|
||||
qs = qs.filter(order=self.parent_object.pk).order_by('-id')
|
||||
change_view = bool(self.parent_object and self.parent_object.pk)
|
||||
if change_view:
|
||||
qs = qs.order_by('-id')
|
||||
try:
|
||||
tenth_id = qs.values_list('id', flat=True)[10]
|
||||
tenth_id = qs.values_list('id', flat=True)[9]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
|
@ -59,7 +61,10 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
inlines = (MetricStorageInline,)
|
||||
add_inlines = ()
|
||||
search_fields = ('account__username', 'description')
|
||||
list_prefetch_related = ('metrics', 'content_object')
|
||||
list_prefetch_related = (
|
||||
'content_object',
|
||||
Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
|
||||
)
|
||||
list_select_related = ('account', 'service')
|
||||
|
||||
service_link = admin_link('service')
|
||||
|
|
|
@ -178,7 +178,7 @@ class Order(models.Model):
|
|||
metric = ', metric:{}'.format(metric)
|
||||
description = handler.get_order_description(instance)
|
||||
logger.info("UPDATED order id:{id}, description:{description}{metric}".format(
|
||||
id=self.id, description=description, metric=metric).encode('ascii', 'ignore')
|
||||
id=self.id, description=description, metric=metric).encode('ascii', 'replace')
|
||||
)
|
||||
if self.description != description:
|
||||
self.description = description
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.conf import settings
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
SAAS_ENABLED_SERVICES = getattr(settings, 'SAAS_ENABLED_SERVICES', (
|
||||
|
@ -21,7 +21,7 @@ SAAS_WORDPRESS_ADMIN_PASSWORD = getattr(settings, 'SAAS_WORDPRESSMU_ADMIN_PASSWO
|
|||
|
||||
|
||||
SAAS_WORDPRESS_BASE_URL = getattr(settings, 'SAAS_WORDPRESS_BASE_URL',
|
||||
'http://blogs.{}/'.format(BASE_DOMAIN)
|
||||
'http://blogs.{}/'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
@ -46,12 +46,12 @@ SAAS_PHPLIST_DB_NAME = getattr(settings, 'SAAS_PHPLIST_DB_NAME',
|
|||
|
||||
|
||||
SAAS_PHPLIST_BASE_DOMAIN = getattr(settings, 'SAAS_PHPLIST_BASE_DOMAIN',
|
||||
'lists.{}'.format(BASE_DOMAIN)
|
||||
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
SAAS_SEAFILE_DOMAIN = getattr(settings, 'SAAS_SEAFILE_DOMAIN',
|
||||
'seafile.{}'.format(BASE_DOMAIN)
|
||||
'seafile.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
@ -61,7 +61,7 @@ SAAS_SEAFILE_DEFAULT_QUOTA = getattr(settings, 'SAAS_SEAFILE_DEFAULT_QUOTA',
|
|||
|
||||
|
||||
SAAS_BSCW_DOMAIN = getattr(settings, 'SAAS_BSCW_DOMAIN',
|
||||
'bscw.{}'.format(BASE_DOMAIN)
|
||||
'bscw.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
||||
|
@ -80,6 +80,6 @@ SAAS_GITLAB_ROOT_PASSWORD = getattr(settings, 'SAAS_GITLAB_ROOT_PASSWORD',
|
|||
|
||||
|
||||
SAAS_GITLAB_DOMAIN = getattr(settings, 'SAAS_GITLAB_DOMAIN',
|
||||
'gitlab.{}'.format(BASE_DOMAIN)
|
||||
'gitlab.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
||||
|
|
|
@ -504,7 +504,7 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
|||
new_price += self.get_price(order, metric) * size
|
||||
new_metric += metric
|
||||
size = self.get_price_size(rini, bp)
|
||||
old_price = self.get_price(order, charged) * size
|
||||
old_price = self.get_price(account, charged) * size
|
||||
if new_price > old_price:
|
||||
metric = new_metric - charged
|
||||
price = new_price - old_price
|
||||
|
@ -520,7 +520,7 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
|||
if self.get_pricing_period() == self.NEVER:
|
||||
# Changes (Mailbox disk-like)
|
||||
for cini, cend, metric in order.get_metric(ini, bp, changes=True):
|
||||
price = self.get_price(order, metric)
|
||||
price = self.get_price(account, metric)
|
||||
lines.append(self.generate_line(order, price, cini, cend, metric=metric))
|
||||
elif self.get_pricing_period() == self.billing_period:
|
||||
# pricing_slots (Traffic-like)
|
||||
|
@ -528,7 +528,7 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
|||
raise NotImplementedError
|
||||
for cini, cend in self.get_pricing_slots(ini, bp):
|
||||
metric = order.get_metric(cini, cend)
|
||||
price = self.get_price(order, metric)
|
||||
price = self.get_price(account, metric)
|
||||
lines.append(self.generate_line(order, price, cini, cend, metric=metric))
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
@ -541,7 +541,7 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
|||
if self.get_pricing_period() == self.NEVER:
|
||||
# get metric (Job-like)
|
||||
metric = order.get_metric(date)
|
||||
price = self.get_price(order, metric)
|
||||
price = self.get_price(account, metric)
|
||||
lines.append(self.generate_line(order, price, date, metric=metric))
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -31,6 +31,12 @@ class UNIXUserBackend(ServiceController):
|
|||
chmod 750 %(home)s
|
||||
chown %(user)s:%(user)s %(home)s""") % context
|
||||
)
|
||||
if context['home'] != context['base_home']:
|
||||
self.append(textwrap.dedent("""
|
||||
mkdir -p %(base_home)s
|
||||
chmod 750 %(base_home)s
|
||||
chown %(user)s:%(user)s %(base_home)s""") % context
|
||||
)
|
||||
for member in settings.SYSTEMUSERS_DEFAULT_GROUP_MEMBERS:
|
||||
context['member'] = member
|
||||
self.append('usermod -a -G %(user)s %(member)s' % context)
|
||||
|
@ -45,19 +51,15 @@ class UNIXUserBackend(ServiceController):
|
|||
{ sleep 2 && killall -u %(user)s -s KILL; } &
|
||||
killall -u %(user)s || true
|
||||
userdel %(user)s || exit_code=1
|
||||
groupdel %(group)s || exit_code=1""") % context
|
||||
groupdel %(group)s || exit_code=1
|
||||
mv %(base_home)s %(base_home)s.deleted || exit_code=1
|
||||
""") % context
|
||||
)
|
||||
self.delete_home(context, user)
|
||||
|
||||
def grant_permission(self, user):
|
||||
context = self.get_context(user)
|
||||
# TODO setacl
|
||||
|
||||
def delete_home(self, context, user):
|
||||
if user.home.rstrip('/') == user.get_base_home().rstrip('/'):
|
||||
# TODO delete instead of this shit
|
||||
self.append("mv %(home)s %(home)s.deleted || exit_code=1" % context)
|
||||
|
||||
def get_groups(self, user):
|
||||
if user.is_main:
|
||||
return user.account.systemusers.exclude(username=user.username).values_list('username', flat=True)
|
||||
|
@ -71,7 +73,8 @@ class UNIXUserBackend(ServiceController):
|
|||
'password': user.password if user.active else '*%s' % user.password,
|
||||
'shell': user.shell,
|
||||
'mainuser': user.username if user.is_main else user.account.username,
|
||||
'home': user.get_home()
|
||||
'home': user.get_home(),
|
||||
'base_home': self.get_base_home(),
|
||||
}
|
||||
return replace(context, "'", '"')
|
||||
|
||||
|
@ -91,16 +94,12 @@ class UNIXUserDisk(ServiceMonitor):
|
|||
|
||||
def monitor(self, user):
|
||||
context = self.get_context(user)
|
||||
if user.is_main or os.path.normpath(user.home) == user.get_base_home():
|
||||
self.append("echo %(object_id)s $(monitor %(home)s)" % context)
|
||||
else:
|
||||
# Home is already included in other user home
|
||||
self.append("echo %(object_id)s 0" % context)
|
||||
self.append("echo %(object_id)s $(monitor %(base_home)s)" % context)
|
||||
|
||||
def get_context(self, user):
|
||||
context = {
|
||||
'object_id': user.pk,
|
||||
'home': user.home,
|
||||
'base_home': user.get_base_home(),
|
||||
}
|
||||
return replace(context, "'", '"')
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from orchestra.forms import UserCreationForm, UserChangeForm
|
|||
|
||||
from . import settings
|
||||
from .models import SystemUser
|
||||
from .validators import validate_home
|
||||
|
||||
|
||||
class SystemUserFormMixin(object):
|
||||
|
@ -63,7 +64,7 @@ class SystemUserFormMixin(object):
|
|||
if home and self.MOCK_USERNAME in home:
|
||||
username = self.cleaned_data.get('username', '')
|
||||
self.cleaned_data['home'] = home.replace(self.MOCK_USERNAME, username)
|
||||
self.instance.validate_home(self.cleaned_data, self.account)
|
||||
validate_home(self.instance, self.cleaned_data, self.account)
|
||||
|
||||
|
||||
class SystemUserCreationForm(SystemUserFormMixin, UserCreationForm):
|
||||
|
|
|
@ -92,29 +92,10 @@ class SystemUser(models.Model):
|
|||
raise ValidationError({
|
||||
'directory': directory_error,
|
||||
})
|
||||
|
||||
def validate_home(self, data, account):
|
||||
""" validates home based on account and data['shell'] """
|
||||
if not 'username' in data and not self.pk:
|
||||
# other validation will have been raised for required username
|
||||
return
|
||||
user = type(self)(
|
||||
username=data.get('username') or self.username,
|
||||
shell=data.get('shell') or self.shell,
|
||||
)
|
||||
if 'home' in data and data['home']:
|
||||
home = os.path.normpath(data['home'])
|
||||
user_home = user.get_base_home()
|
||||
account_home = account.main_systemuser.get_home()
|
||||
if user.has_shell:
|
||||
if home != user_home:
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
||||
elif home not in (user_home, account_home):
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
||||
if self.has_shell and self.home != self.get_base_home():
|
||||
raise ValidationError({
|
||||
'home': _("Shell users should use their own home."),
|
||||
})
|
||||
|
||||
def set_password(self, raw_password):
|
||||
self.password = make_password(raw_password)
|
||||
|
|
|
@ -8,6 +8,7 @@ from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
|||
from orchestra.core.validators import validate_password
|
||||
|
||||
from .models import SystemUser
|
||||
from .validators import validate_home
|
||||
|
||||
|
||||
class GroupSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSerializer):
|
||||
|
@ -38,7 +39,7 @@ class SystemUserSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
username=attrs.get('username') or self.object.username,
|
||||
shell=attrs.get('shell') or self.object.shell,
|
||||
)
|
||||
user.validate_home(attrs, self.account)
|
||||
validate_home(user, attrs, self.account)
|
||||
return attrs
|
||||
|
||||
def validate_password(self, attrs, source):
|
||||
|
|
27
orchestra/contrib/systemusers/validators.py
Normal file
27
orchestra/contrib/systemusers/validators.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def validate_home(user, data, account):
|
||||
""" validates home based on account and data['shell'] """
|
||||
if not 'username' in data and not user.pk:
|
||||
# other validation will have been raised for required username
|
||||
return
|
||||
user = type(user)(
|
||||
username=data.get('username') or user.username,
|
||||
shell=data.get('shell') or user.shell,
|
||||
)
|
||||
if 'home' in data and data['home']:
|
||||
home = os.path.normpath(data['home'])
|
||||
user_home = user.get_base_home()
|
||||
account_home = account.main_systemuser.get_home()
|
||||
if user.has_shell:
|
||||
if home != user_home:
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
||||
elif home not in (user_home, account_home):
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
|
@ -1,6 +1,6 @@
|
|||
from django.conf import settings
|
||||
|
||||
from orchestra.settings import BASE_DOMAIN
|
||||
from orchestra.settings import ORCHESTRA_BASE_DOMAIN
|
||||
|
||||
|
||||
WEBAPPS_BASE_ROOT = getattr(settings, 'WEBAPPS_BASE_ROOT',
|
||||
|
@ -169,5 +169,5 @@ WEBAPPS_ENABLED_OPTIONS = getattr(settings, 'WEBAPPS_ENABLED_OPTIONS', (
|
|||
|
||||
|
||||
WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST = getattr(settings, 'WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST',
|
||||
'mysql.{}'.format(BASE_DOMAIN)
|
||||
'mysql.{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ from orchestra import settings
|
|||
def site(request):
|
||||
""" Adds site-related context variables to the context """
|
||||
return {
|
||||
'SITE_NAME': settings.SITE_NAME,
|
||||
'SITE_VERBOSE_NAME': settings.SITE_VERBOSE_NAME
|
||||
'SITE_NAME': settings.ORCHESTRA_SITE_NAME,
|
||||
'SITE_VERBOSE_NAME': settings.ORCHESTRA_SITE_VERBOSE_NAME
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
|
||||
from orchestra.management.commands.startservices import ManageServiceCommand
|
||||
from orchestra.settings import RESTART_SERVICES
|
||||
from orchestra.settings import ORCHESTRA_RESTART_SERVICES
|
||||
|
||||
|
||||
class Command(ManageServiceCommand):
|
||||
services = RESTART_SERVICES
|
||||
services = ORCHESTRA_RESTART_SERVICES
|
||||
action = 'restart'
|
||||
option_list = BaseCommand.option_list
|
||||
help = 'Restart all related services. Usefull for reload configuration and files.'
|
||||
|
|
|
@ -2,7 +2,7 @@ from optparse import make_option
|
|||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from orchestra.settings import START_SERVICES
|
||||
from orchestra.settings import ORCHESTRA_START_SERVICES
|
||||
from orchestra.utils.sys import run, check_root
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ class ManageServiceCommand(BaseCommand):
|
|||
|
||||
|
||||
class Command(ManageServiceCommand):
|
||||
services = START_SERVICES
|
||||
services = ORCHESTRA_START_SERVICES
|
||||
action = 'start'
|
||||
option_list = BaseCommand.option_list
|
||||
help = 'Start all related services. Usefull for reload configuration and files.'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
|
||||
from orchestra.management.commands.startservices import ManageServiceCommand
|
||||
from orchestra.settings import STOP_SERVICES
|
||||
from orchestra.settings import ORCHESTRA_STOP_SERVICES
|
||||
|
||||
|
||||
class Command(ManageServiceCommand):
|
||||
services = STOP_SERVICES
|
||||
services = ORCHESTRA_STOP_SERVICES
|
||||
action = 'stop'
|
||||
option_list = BaseCommand.option_list
|
||||
help = 'Stop all related services. Usefull for reload configuration and files.'
|
||||
|
|
|
@ -4,27 +4,27 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
# Domain name used when it will not be possible to infere the domain from a request
|
||||
# For example in periodic tasks
|
||||
SITE_URL = getattr(settings, 'SITE_URL',
|
||||
ORCHESTRA_SITE_URL = getattr(settings, 'ORCHESTRA_SITE_URL',
|
||||
'http://localhost'
|
||||
)
|
||||
|
||||
SITE_NAME = getattr(settings, 'SITE_NAME',
|
||||
ORCHESTRA_SITE_NAME = getattr(settings, 'ORCHESTRA_SITE_NAME',
|
||||
'orchestra'
|
||||
)
|
||||
|
||||
|
||||
SITE_VERBOSE_NAME = getattr(settings, 'SITE_VERBOSE_NAME',
|
||||
_("%s Hosting Management" % SITE_NAME.capitalize())
|
||||
ORCHESTRA_SITE_VERBOSE_NAME = getattr(settings, 'ORCHESTRA_SITE_VERBOSE_NAME',
|
||||
_("%s Hosting Management" % ORCHESTRA_SITE_NAME.capitalize())
|
||||
)
|
||||
|
||||
|
||||
BASE_DOMAIN = getattr(settings, 'BASE_DOMAIN',
|
||||
ORCHESTRA_BASE_DOMAIN = getattr(settings, 'ORCHESTRA_BASE_DOMAIN',
|
||||
'orchestra.lan'
|
||||
)
|
||||
|
||||
# Service management commands
|
||||
|
||||
START_SERVICES = getattr(settings, 'START_SERVICES', [
|
||||
ORCHESTRA_START_SERVICES = getattr(settings, 'ORCHESTRA_START_SERVICES', [
|
||||
'postgresql',
|
||||
'celeryevcam',
|
||||
'celeryd',
|
||||
|
@ -33,13 +33,13 @@ START_SERVICES = getattr(settings, 'START_SERVICES', [
|
|||
])
|
||||
|
||||
|
||||
RESTART_SERVICES = getattr(settings, 'RESTART_SERVICES', [
|
||||
ORCHESTRA_RESTART_SERVICES = getattr(settings, 'ORCHESTRA_RESTART_SERVICES', [
|
||||
'celeryd',
|
||||
'celerybeat',
|
||||
'uwsgi'
|
||||
])
|
||||
|
||||
STOP_SERVICES = getattr(settings, 'STOP_SERVICES', [
|
||||
ORCHESTRA_STOP_SERVICES = getattr(settings, 'ORCHESTRA_STOP_SERVICES', [
|
||||
('uwsgi', 'nginx'),
|
||||
'celerybeat',
|
||||
'celeryd',
|
||||
|
@ -48,11 +48,11 @@ STOP_SERVICES = getattr(settings, 'STOP_SERVICES', [
|
|||
])
|
||||
|
||||
|
||||
API_ROOT_VIEW = getattr(settings, 'API_ROOT_VIEW',
|
||||
ORCHESTRA_API_ROOT_VIEW = getattr(settings, 'ORCHESTRA_API_ROOT_VIEW',
|
||||
'orchestra.api.root.APIRoot'
|
||||
)
|
||||
|
||||
|
||||
ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL = getattr(settings, 'ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL',
|
||||
'support@{}'.format(BASE_DOMAIN)
|
||||
'support@{}'.format(ORCHESTRA_BASE_DOMAIN)
|
||||
)
|
||||
|
|
|
@ -22,9 +22,9 @@ def send_email_template(template, context, to, email_from=None, html=None, attac
|
|||
|
||||
if not 'site' in context:
|
||||
from orchestra import settings
|
||||
url = urlparse.urlparse(settings.SITE_URL)
|
||||
url = urlparse.urlparse(settings.ORCHESTRA_SITE_URL)
|
||||
context['site'] = {
|
||||
'name': settings.SITE_NAME,
|
||||
'name': settings.ORCHESTRA_SITE_NAME,
|
||||
'scheme': url.scheme,
|
||||
'domain': url.netloc,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue