Moved apps to contrib
This commit is contained in:
parent
1ff4e05819
commit
10d2f7f247
14
TODO.md
14
TODO.md
|
@ -282,13 +282,10 @@ from django.utils import translation
|
||||||
translation.activate('ca')
|
translation.activate('ca')
|
||||||
ugettext("Description")
|
ugettext("Description")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* saas validate_creation generic approach, for all backends. standard output
|
* saas validate_creation generic approach, for all backends. standard output
|
||||||
|
|
||||||
* html code x: × for bill line verbose quantity
|
* html code x: × for bill line verbose quantity
|
||||||
|
|
||||||
|
|
||||||
* periodic task to cleanup backendlogs, monitor data and metricstorage
|
* periodic task to cleanup backendlogs, monitor data and metricstorage
|
||||||
* create orchestrate databases.Database pk=1 -n --dry-run | --noinput --action save (default)|delete --backend name (limit to this backend) --help
|
* create orchestrate databases.Database pk=1 -n --dry-run | --noinput --action save (default)|delete --backend name (limit to this backend) --help
|
||||||
|
|
||||||
|
@ -301,12 +298,10 @@ celery max-tasks-per-child
|
||||||
|
|
||||||
* make base home for systemusers that ara homed into main account systemuser, and prevent shell users to have nested homes (if nnot implemented already)
|
* 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
|
* autoscale celery workers http://docs.celeryproject.org/en/latest/userguide/workers.html#autoscaling
|
||||||
|
|
||||||
* webapp has_website list filter
|
* webapp has_website list filter
|
||||||
|
|
||||||
|
|
||||||
glic3rinu's django-fluent-dashboard
|
glic3rinu's django-fluent-dashboard
|
||||||
* gevent is not ported to python3 :'(
|
* gevent is not ported to python3 :'(
|
||||||
* uwsgi python3
|
* uwsgi python3
|
||||||
|
@ -322,13 +317,6 @@ https://code.djangoproject.com/ticket/24576
|
||||||
* read https://docs.djangoproject.com/en/dev/releases/1.8/ and fix deprecation warnings
|
* read https://docs.djangoproject.com/en/dev/releases/1.8/ and fix deprecation warnings
|
||||||
* remove admin object links , like contents webapps
|
* remove admin object links , like contents webapps
|
||||||
|
|
||||||
* SaaS and WebApp fieldsets, and helptexts !
|
* SaaS and WebApp types and services fieldsets, and helptexts !
|
||||||
|
|
||||||
* remove all six stuff "from django.utils.six.moves import input"
|
|
||||||
* replace make_option in management commands
|
* replace make_option in management commands
|
||||||
|
|
||||||
|
|
||||||
* rename apps to contrib find . -type f -name "*py"|xargs grep apps | grep -v 'orchestra\.apps\.'
|
|
||||||
|
|
||||||
* replace staticcheck by run(flake8 {orchestra,project} | grep -v "W293\|E501")
|
|
||||||
* rename utils.system to utils.sys
|
|
||||||
|
|
|
@ -41,10 +41,10 @@ def get_services():
|
||||||
|
|
||||||
def get_accounts():
|
def get_accounts():
|
||||||
childrens=[]
|
childrens=[]
|
||||||
if isinstalled('orchestra.apps.payments'):
|
if isinstalled('orchestra.contrib.payments'):
|
||||||
url = reverse('admin:payments_transactionprocess_changelist')
|
url = reverse('admin:payments_transactionprocess_changelist')
|
||||||
childrens.append(items.MenuItem(_("Transaction processes"), url))
|
childrens.append(items.MenuItem(_("Transaction processes"), url))
|
||||||
if isinstalled('orchestra.apps.issues'):
|
if isinstalled('orchestra.contrib.issues'):
|
||||||
url = reverse('admin:issues_ticket_changelist')
|
url = reverse('admin:issues_ticket_changelist')
|
||||||
childrens.append(items.MenuItem(_("Tickets"), url))
|
childrens.append(items.MenuItem(_("Tickets"), url))
|
||||||
for model, options in accounts.get().items():
|
for model, options in accounts.get().items():
|
||||||
|
@ -59,12 +59,12 @@ def get_accounts():
|
||||||
|
|
||||||
def get_administration_items():
|
def get_administration_items():
|
||||||
childrens = []
|
childrens = []
|
||||||
if isinstalled('orchestra.apps.services'):
|
if isinstalled('orchestra.contrib.services'):
|
||||||
url = reverse('admin:services_service_changelist')
|
url = reverse('admin:services_service_changelist')
|
||||||
childrens.append(items.MenuItem(_("Services"), url))
|
childrens.append(items.MenuItem(_("Services"), url))
|
||||||
url = reverse('admin:plans_plan_changelist')
|
url = reverse('admin:plans_plan_changelist')
|
||||||
childrens.append(items.MenuItem(_("Plans"), url))
|
childrens.append(items.MenuItem(_("Plans"), url))
|
||||||
if isinstalled('orchestra.apps.orchestration'):
|
if isinstalled('orchestra.contrib.orchestration'):
|
||||||
route = reverse('admin:orchestration_route_changelist')
|
route = reverse('admin:orchestration_route_changelist')
|
||||||
backendlog = reverse('admin:orchestration_backendlog_changelist')
|
backendlog = reverse('admin:orchestration_backendlog_changelist')
|
||||||
server = reverse('admin:orchestration_server_changelist')
|
server = reverse('admin:orchestration_server_changelist')
|
||||||
|
@ -73,7 +73,7 @@ def get_administration_items():
|
||||||
items.MenuItem(_("Backend logs"), backendlog),
|
items.MenuItem(_("Backend logs"), backendlog),
|
||||||
items.MenuItem(_("Servers"), server),
|
items.MenuItem(_("Servers"), server),
|
||||||
]))
|
]))
|
||||||
if isinstalled('orchestra.apps.resources'):
|
if isinstalled('orchestra.contrib.resources'):
|
||||||
resource = reverse('admin:resources_resource_changelist')
|
resource = reverse('admin:resources_resource_changelist')
|
||||||
data = reverse('admin:resources_resourcedata_changelist')
|
data = reverse('admin:resources_resourcedata_changelist')
|
||||||
monitor = reverse('admin:resources_monitordata_changelist')
|
monitor = reverse('admin:resources_monitordata_changelist')
|
||||||
|
@ -82,10 +82,10 @@ def get_administration_items():
|
||||||
items.MenuItem(_("Data"), data),
|
items.MenuItem(_("Data"), data),
|
||||||
items.MenuItem(_("Monitoring"), monitor),
|
items.MenuItem(_("Monitoring"), monitor),
|
||||||
]))
|
]))
|
||||||
if isinstalled('orchestra.apps.miscellaneous'):
|
if isinstalled('orchestra.contrib.miscellaneous'):
|
||||||
url = reverse('admin:miscellaneous_miscservice_changelist')
|
url = reverse('admin:miscellaneous_miscservice_changelist')
|
||||||
childrens.append(items.MenuItem(_("Miscellaneous"), url))
|
childrens.append(items.MenuItem(_("Miscellaneous"), url))
|
||||||
if isinstalled('orchestra.apps.issues'):
|
if isinstalled('orchestra.contrib.issues'):
|
||||||
url = reverse('admin:issues_queue_changelist')
|
url = reverse('admin:issues_queue_changelist')
|
||||||
childrens.append(items.MenuItem(_("Ticket queues"), url))
|
childrens.append(items.MenuItem(_("Ticket queues"), url))
|
||||||
if isinstalled('djcelery'):
|
if isinstalled('djcelery'):
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
from .backends import ServiceMonitor
|
|
||||||
|
|
||||||
|
|
||||||
default_app_config = 'orchestra.apps.resources.apps.ResourcesConfig'
|
|
|
@ -36,7 +36,7 @@ MEDIA_URL = '/media/'
|
||||||
ALLOWED_HOSTS = '*'
|
ALLOWED_HOSTS = '*'
|
||||||
|
|
||||||
# Set this to True to wrap each HTTP request in a transaction on this database.
|
# Set this to True to wrap each HTTP request in a transaction on this database.
|
||||||
# ATOMIC REQUESTS do not wrap middlewares (orchestra.apps.orchestration.middlewares.OperationsMiddleware)
|
# ATOMIC REQUESTS do not wrap middlewares (orchestra.contrib.orchestration.middlewares.OperationsMiddleware)
|
||||||
ATOMIC_REQUESTS = False
|
ATOMIC_REQUESTS = False
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'orchestra.core.caches.RequestCacheMiddleware',
|
'orchestra.core.caches.RequestCacheMiddleware',
|
||||||
# also handles transations, ATOMIC_REQUESTS does not wrap middlewares
|
# also handles transations, ATOMIC_REQUESTS does not wrap middlewares
|
||||||
'orchestra.apps.orchestration.middlewares.OperationsMiddleware',
|
'orchestra.contrib.orchestration.middlewares.OperationsMiddleware',
|
||||||
# Uncomment the next line for simple clickjacking protection:
|
# Uncomment the next line for simple clickjacking protection:
|
||||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
)
|
)
|
||||||
|
@ -69,25 +69,25 @@ TEMPLATE_CONTEXT_PROCESSORS =(
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
# django-orchestra apps
|
# django-orchestra apps
|
||||||
'orchestra',
|
'orchestra',
|
||||||
'orchestra.apps.accounts',
|
'orchestra.contrib.accounts',
|
||||||
'orchestra.apps.contacts',
|
'orchestra.contrib.contacts',
|
||||||
'orchestra.apps.orchestration',
|
'orchestra.contrib.orchestration',
|
||||||
'orchestra.apps.domains',
|
'orchestra.contrib.domains',
|
||||||
'orchestra.apps.systemusers',
|
'orchestra.contrib.systemusers',
|
||||||
'orchestra.apps.mailboxes',
|
'orchestra.contrib.mailboxes',
|
||||||
'orchestra.apps.lists',
|
'orchestra.contrib.lists',
|
||||||
'orchestra.apps.webapps',
|
'orchestra.contrib.webapps',
|
||||||
'orchestra.apps.websites',
|
'orchestra.contrib.websites',
|
||||||
'orchestra.apps.databases',
|
'orchestra.contrib.databases',
|
||||||
'orchestra.apps.vps',
|
'orchestra.contrib.vps',
|
||||||
'orchestra.apps.saas',
|
'orchestra.contrib.saas',
|
||||||
'orchestra.apps.issues',
|
'orchestra.contrib.issues',
|
||||||
'orchestra.apps.services',
|
'orchestra.contrib.services',
|
||||||
'orchestra.apps.plans',
|
'orchestra.contrib.plans',
|
||||||
'orchestra.apps.orders',
|
'orchestra.contrib.orders',
|
||||||
'orchestra.apps.miscellaneous',
|
'orchestra.contrib.miscellaneous',
|
||||||
'orchestra.apps.bills',
|
'orchestra.contrib.bills',
|
||||||
'orchestra.apps.payments',
|
'orchestra.contrib.payments',
|
||||||
|
|
||||||
# Third-party apps
|
# Third-party apps
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
|
@ -111,7 +111,7 @@ INSTALLED_APPS = (
|
||||||
'django.contrib.admin.apps.SimpleAdminConfig',
|
'django.contrib.admin.apps.SimpleAdminConfig',
|
||||||
|
|
||||||
# Last to load
|
# Last to load
|
||||||
'orchestra.apps.resources',
|
'orchestra.contrib.resources',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,29 +144,29 @@ FLUENT_DASHBOARD_APP_GROUPS = (
|
||||||
# Services group is generated by orchestra.admin.dashboard
|
# Services group is generated by orchestra.admin.dashboard
|
||||||
('Accounts', {
|
('Accounts', {
|
||||||
'models': (
|
'models': (
|
||||||
'orchestra.apps.accounts.models.Account',
|
'orchestra.contrib.accounts.models.Account',
|
||||||
'orchestra.apps.contacts.models.Contact',
|
'orchestra.contrib.contacts.models.Contact',
|
||||||
'orchestra.apps.orders.models.Order',
|
'orchestra.contrib.orders.models.Order',
|
||||||
'orchestra.apps.plans.models.ContractedPlan',
|
'orchestra.contrib.plans.models.ContractedPlan',
|
||||||
'orchestra.apps.bills.models.Bill',
|
'orchestra.contrib.bills.models.Bill',
|
||||||
# 'orchestra.apps.payments.models.PaymentSource',
|
# 'orchestra.contrib.payments.models.PaymentSource',
|
||||||
'orchestra.apps.payments.models.Transaction',
|
'orchestra.contrib.payments.models.Transaction',
|
||||||
# 'orchestra.apps.payments.models.TransactionProcess',
|
# 'orchestra.contrib.payments.models.TransactionProcess',
|
||||||
'orchestra.apps.issues.models.Ticket',
|
'orchestra.contrib.issues.models.Ticket',
|
||||||
),
|
),
|
||||||
'collapsible': True,
|
'collapsible': True,
|
||||||
}),
|
}),
|
||||||
('Administration', {
|
('Administration', {
|
||||||
'models': (
|
'models': (
|
||||||
'djcelery.models.TaskState',
|
'djcelery.models.TaskState',
|
||||||
'orchestra.apps.orchestration.models.Route',
|
'orchestra.contrib.orchestration.models.Route',
|
||||||
'orchestra.apps.orchestration.models.BackendLog',
|
'orchestra.contrib.orchestration.models.BackendLog',
|
||||||
'orchestra.apps.orchestration.models.Server',
|
'orchestra.contrib.orchestration.models.Server',
|
||||||
'orchestra.apps.resources.models.Resource',
|
'orchestra.contrib.resources.models.Resource',
|
||||||
'orchestra.apps.resources.models.ResourceData',
|
'orchestra.contrib.resources.models.ResourceData',
|
||||||
'orchestra.apps.services.models.Service',
|
'orchestra.contrib.services.models.Service',
|
||||||
'orchestra.apps.plans.models.Plan',
|
'orchestra.contrib.plans.models.Plan',
|
||||||
'orchestra.apps.miscellaneous.models.MiscService',
|
'orchestra.contrib.miscellaneous.models.MiscService',
|
||||||
),
|
),
|
||||||
'collapsible': True,
|
'collapsible': True,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import copy
|
import copy
|
||||||
import re
|
import re
|
||||||
|
from urllib.parse import parse_qsl
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import patterns, url
|
||||||
|
@ -8,7 +9,6 @@ from django.contrib.admin.util import unquote
|
||||||
from django.contrib.auth import admin as auth
|
from django.contrib.auth import admin as auth
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.six.moves.urllib.parse import parse_qsl
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||||
|
@ -80,11 +80,11 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
|
||||||
messages.warning(request, 'This account is disabled.')
|
messages.warning(request, 'This account is disabled.')
|
||||||
context = {
|
context = {
|
||||||
'services': sorted(
|
'services': sorted(
|
||||||
[ model._meta for model in services.get() if model is not Account ],
|
[model._meta for model in services.get() if model is not Account],
|
||||||
key=lambda i: i.verbose_name_plural.lower()
|
key=lambda i: i.verbose_name_plural.lower()
|
||||||
),
|
),
|
||||||
'accounts': sorted(
|
'accounts': sorted(
|
||||||
[ model._meta for model in accounts.get() if model is not Account ],
|
[model._meta for model in accounts.get() if model is not Account],
|
||||||
key=lambda i: i.verbose_name_plural.lower()
|
key=lambda i: i.verbose_name_plural.lower()
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -5,8 +5,8 @@ from django.db.models.loading import get_model
|
||||||
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.apps.orchestration.middlewares import OperationsMiddleware
|
from orchestra.contrib.orchestration.middlewares import OperationsMiddleware
|
||||||
from orchestra.apps.orchestration.models import BackendOperation as Operation
|
from orchestra.contrib.orchestration.models import BackendOperation as Operation
|
||||||
from orchestra.core import services, accounts
|
from orchestra.core import services, accounts
|
||||||
from orchestra.utils import send_email_template
|
from orchestra.utils import send_email_template
|
||||||
|
|
||||||
|
@ -16,26 +16,27 @@ from . import settings
|
||||||
class Account(auth.AbstractBaseUser):
|
class Account(auth.AbstractBaseUser):
|
||||||
# Username max_length determined by LINUX system user lentgh: 32
|
# Username max_length determined by LINUX system user lentgh: 32
|
||||||
username = models.CharField(_("username"), max_length=32, unique=True,
|
username = models.CharField(_("username"), max_length=32, unique=True,
|
||||||
help_text=_("Required. 64 characters or fewer. Letters, digits and ./-/_ only."),
|
help_text=_("Required. 64 characters or fewer. Letters, digits and ./-/_ only."),
|
||||||
validators=[validators.RegexValidator(r'^[\w.-]+$',
|
validators=[
|
||||||
_("Enter a valid username."), 'invalid')])
|
validators.RegexValidator(r'^[\w.-]+$', _("Enter a valid username."), 'invalid')
|
||||||
|
])
|
||||||
main_systemuser = models.ForeignKey(settings.ACCOUNTS_SYSTEMUSER_MODEL, null=True,
|
main_systemuser = models.ForeignKey(settings.ACCOUNTS_SYSTEMUSER_MODEL, null=True,
|
||||||
related_name='accounts_main', editable=False)
|
related_name='accounts_main', editable=False)
|
||||||
short_name = models.CharField(_("short name"), max_length=64, blank=True)
|
short_name = models.CharField(_("short name"), max_length=64, blank=True)
|
||||||
full_name = models.CharField(_("full name"), max_length=256)
|
full_name = models.CharField(_("full name"), max_length=256)
|
||||||
email = models.EmailField(_('email address'), help_text=_("Used for password recovery"))
|
email = models.EmailField(_('email address'), help_text=_("Used for password recovery"))
|
||||||
type = models.CharField(_("type"), choices=settings.ACCOUNTS_TYPES,
|
type = models.CharField(_("type"), choices=settings.ACCOUNTS_TYPES,
|
||||||
max_length=32, default=settings.ACCOUNTS_DEFAULT_TYPE)
|
max_length=32, default=settings.ACCOUNTS_DEFAULT_TYPE)
|
||||||
language = models.CharField(_("language"), max_length=2,
|
language = models.CharField(_("language"), max_length=2,
|
||||||
choices=settings.ACCOUNTS_LANGUAGES,
|
choices=settings.ACCOUNTS_LANGUAGES,
|
||||||
default=settings.ACCOUNTS_DEFAULT_LANGUAGE)
|
default=settings.ACCOUNTS_DEFAULT_LANGUAGE)
|
||||||
comments = models.TextField(_("comments"), max_length=256, blank=True)
|
comments = models.TextField(_("comments"), max_length=256, blank=True)
|
||||||
is_superuser = models.BooleanField(_("superuser status"), default=False,
|
is_superuser = models.BooleanField(_("superuser status"), default=False,
|
||||||
help_text=_("Designates that this user has all permissions without "
|
help_text=_("Designates that this user has all permissions without "
|
||||||
"explicitly assigning them."))
|
"explicitly assigning them."))
|
||||||
is_active = models.BooleanField(_("active"), default=True,
|
is_active = models.BooleanField(_("active"), default=True,
|
||||||
help_text=_("Designates whether this account should be treated as active. "
|
help_text=_("Designates whether this account should be treated as active. "
|
||||||
"Unselect this instead of deleting accounts."))
|
"Unselect this instead of deleting accounts."))
|
||||||
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
|
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
|
||||||
|
|
||||||
objects = auth.UserManager()
|
objects = auth.UserManager()
|
|
@ -10,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_date, insertattr
|
from orchestra.admin.utils import admin_date, insertattr
|
||||||
from orchestra.apps.accounts.admin import AccountAdminMixin, AccountAdmin
|
from orchestra.contrib.accounts.admin import AccountAdminMixin, AccountAdmin
|
||||||
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
||||||
|
|
||||||
from . import settings, actions
|
from . import settings, actions
|
|
@ -3,7 +3,7 @@ from rest_framework import viewsets
|
||||||
from rest_framework.decorators import detail_route
|
from rest_framework.decorators import detail_route
|
||||||
|
|
||||||
from orchestra.api import router
|
from orchestra.api import router
|
||||||
from orchestra.apps.accounts.api import AccountApiMixin
|
from orchestra.contrib.accounts.api import AccountApiMixin
|
||||||
from orchestra.utils.html import html_to_pdf
|
from orchestra.utils.html import html_to_pdf
|
||||||
|
|
||||||
from .models import Bill
|
from .models import Bill
|
|
@ -6,12 +6,10 @@ from orchestra.forms.widgets import ShowTextWidget
|
||||||
|
|
||||||
|
|
||||||
class SelectSourceForm(forms.ModelForm):
|
class SelectSourceForm(forms.ModelForm):
|
||||||
bill_link = forms.CharField(label=_("Number"), required=False,
|
bill_link = forms.CharField(label=_("Number"), required=False, widget=ShowTextWidget())
|
||||||
widget=ShowTextWidget())
|
|
||||||
account_link = forms.CharField(label=_("Account"), required=False)
|
account_link = forms.CharField(label=_("Account"), required=False)
|
||||||
display_total = forms.CharField(label=_("Total"), required=False)
|
display_total = forms.CharField(label=_("Total"), required=False)
|
||||||
display_type = forms.CharField(label=_("Type"), required=False,
|
display_type = forms.CharField(label=_("Type"), required=False, widget=ShowTextWidget())
|
||||||
widget=ShowTextWidget())
|
|
||||||
source = forms.ChoiceField(label=_("Source"), required=False)
|
source = forms.ChoiceField(label=_("Source"), required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
|
@ -8,8 +8,8 @@ from django.utils.encoding import force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.accounts.models import Account
|
from orchestra.contrib.accounts.models import Account
|
||||||
from orchestra.apps.contacts.models import Contact
|
from orchestra.contrib.contacts.models import Contact
|
||||||
from orchestra.core import accounts, validators
|
from orchestra.core import accounts, validators
|
||||||
from orchestra.utils.html import html_to_pdf
|
from orchestra.utils.html import html_to_pdf
|
||||||
|
|
||||||
|
@ -18,17 +18,17 @@ from . import settings
|
||||||
|
|
||||||
class BillContact(models.Model):
|
class BillContact(models.Model):
|
||||||
account = models.OneToOneField('accounts.Account', verbose_name=_("account"),
|
account = models.OneToOneField('accounts.Account', verbose_name=_("account"),
|
||||||
related_name='billcontact')
|
related_name='billcontact')
|
||||||
name = models.CharField(_("name"), max_length=256, blank=True,
|
name = models.CharField(_("name"), max_length=256, blank=True,
|
||||||
help_text=_("Account full name will be used when left blank."))
|
help_text=_("Account full name will be used when left blank."))
|
||||||
address = models.TextField(_("address"))
|
address = models.TextField(_("address"))
|
||||||
city = models.CharField(_("city"), max_length=128,
|
city = models.CharField(_("city"), max_length=128,
|
||||||
default=settings.BILLS_CONTACT_DEFAULT_CITY)
|
default=settings.BILLS_CONTACT_DEFAULT_CITY)
|
||||||
zipcode = models.CharField(_("zip code"), max_length=10,
|
zipcode = models.CharField(_("zip code"), max_length=10,
|
||||||
validators=[RegexValidator(r'^[0-9A-Z]{3,10}$', _("Enter a valid zipcode."))])
|
validators=[RegexValidator(r'^[0-9A-Z]{3,10}$', _("Enter a valid zipcode."))])
|
||||||
country = models.CharField(_("country"), max_length=20,
|
country = models.CharField(_("country"), max_length=20,
|
||||||
choices=settings.BILLS_CONTACT_COUNTRIES,
|
choices=settings.BILLS_CONTACT_COUNTRIES,
|
||||||
default=settings.BILLS_CONTACT_DEFAULT_COUNTRY)
|
default=settings.BILLS_CONTACT_DEFAULT_COUNTRY)
|
||||||
vat = models.CharField(_("VAT number"), max_length=64)
|
vat = models.CharField(_("VAT number"), max_length=64)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -81,7 +81,7 @@ class Bill(models.Model):
|
||||||
|
|
||||||
number = models.CharField(_("number"), max_length=16, unique=True, blank=True)
|
number = models.CharField(_("number"), max_length=16, unique=True, blank=True)
|
||||||
account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
|
account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
|
||||||
related_name='%(class)s')
|
related_name='%(class)s')
|
||||||
type = models.CharField(_("type"), max_length=16, choices=TYPES)
|
type = models.CharField(_("type"), max_length=16, choices=TYPES)
|
||||||
created_on = models.DateField(_("created on"), auto_now_add=True)
|
created_on = models.DateField(_("created on"), auto_now_add=True)
|
||||||
closed_on = models.DateField(_("closed on"), blank=True, null=True)
|
closed_on = models.DateField(_("closed on"), blank=True, null=True)
|
||||||
|
@ -279,7 +279,7 @@ class BillLine(models.Model):
|
||||||
# end = models.DateTimeField(null=True)
|
# end = models.DateTimeField(null=True)
|
||||||
|
|
||||||
order = models.ForeignKey(settings.BILLS_ORDER_MODEL, null=True, blank=True,
|
order = models.ForeignKey(settings.BILLS_ORDER_MODEL, null=True, blank=True,
|
||||||
help_text=_("Informative link back to the order"), on_delete=models.SET_NULL)
|
help_text=_("Informative link back to the order"), on_delete=models.SET_NULL)
|
||||||
order_billed_on = models.DateField(_("order billed"), null=True, blank=True)
|
order_billed_on = models.DateField(_("order billed"), null=True, blank=True)
|
||||||
order_billed_until = models.DateField(_("order billed until"), null=True, blank=True)
|
order_billed_until = models.DateField(_("order billed until"), null=True, blank=True)
|
||||||
created_on = models.DateField(_("created"), auto_now_add=True)
|
created_on = models.DateField(_("created"), auto_now_add=True)
|
|
@ -1,8 +1,8 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.api import router
|
from orchestra.api import router
|
||||||
from orchestra.apps.accounts.models import Account
|
from orchestra.contrib.accounts.models import Account
|
||||||
from orchestra.apps.accounts.serializers import AccountSerializerMixin
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||||||
|
|
||||||
from .models import Bill, BillLine, BillContact
|
from .models import Bill, BillLine, BillContact
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from orchestra.admin import AtLeastOneRequiredInlineFormSet, ExtendedModelAdmin
|
from orchestra.admin import AtLeastOneRequiredInlineFormSet, ExtendedModelAdmin
|
||||||
from orchestra.admin.actions import SendEmail
|
from orchestra.admin.actions import SendEmail
|
||||||
from orchestra.admin.utils import insertattr, change_url
|
from orchestra.admin.utils import insertattr, change_url
|
||||||
from orchestra.apps.accounts.admin import AccountAdmin, AccountAdminMixin
|
from orchestra.contrib.accounts.admin import AccountAdmin, AccountAdminMixin
|
||||||
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
||||||
|
|
||||||
from .filters import EmailUsageListFilter
|
from .filters import EmailUsageListFilter
|
|
@ -1,7 +1,7 @@
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
|
|
||||||
from orchestra.api import router
|
from orchestra.api import router
|
||||||
from orchestra.apps.accounts.api import AccountApiMixin
|
from orchestra.contrib.accounts.api import AccountApiMixin
|
||||||
|
|
||||||
from .models import Contact
|
from .models import Contact
|
||||||
from .serializers import ContactSerializer
|
from .serializers import ContactSerializer
|
|
@ -35,25 +35,27 @@ class Contact(models.Model):
|
||||||
objects = ContactQuerySet.as_manager()
|
objects = ContactQuerySet.as_manager()
|
||||||
|
|
||||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
||||||
related_name='contacts', null=True)
|
related_name='contacts', null=True)
|
||||||
short_name = models.CharField(_("short name"), max_length=128)
|
short_name = models.CharField(_("short name"), max_length=128)
|
||||||
full_name = models.CharField(_("full name"), max_length=256, blank=True)
|
full_name = models.CharField(_("full name"), max_length=256, blank=True)
|
||||||
email = models.EmailField()
|
email = models.EmailField()
|
||||||
email_usage = MultiSelectField(_("email usage"), max_length=256, blank=True,
|
email_usage = MultiSelectField(_("email usage"), max_length=256, blank=True,
|
||||||
choices=EMAIL_USAGES,
|
choices=EMAIL_USAGES,
|
||||||
default=settings.CONTACTS_DEFAULT_EMAIL_USAGES)
|
default=settings.CONTACTS_DEFAULT_EMAIL_USAGES)
|
||||||
phone = models.CharField(_("phone"), max_length=32, blank=True,
|
phone = models.CharField(_("phone"), max_length=32, blank=True,
|
||||||
validators=[validate_phone])
|
validators=[validate_phone])
|
||||||
phone2 = models.CharField(_("alternative phone"), max_length=32, blank=True,
|
phone2 = models.CharField(_("alternative phone"), max_length=32, blank=True,
|
||||||
validators=[validate_phone])
|
validators=[validate_phone])
|
||||||
address = models.TextField(_("address"), blank=True)
|
address = models.TextField(_("address"), blank=True)
|
||||||
city = models.CharField(_("city"), max_length=128, blank=True)
|
city = models.CharField(_("city"), max_length=128, blank=True)
|
||||||
zipcode = models.CharField(_("zip code"), max_length=10, blank=True,
|
zipcode = models.CharField(_("zip code"), max_length=10, blank=True,
|
||||||
validators=[RegexValidator(r'^[0-9,A-Z]{3,10}$',
|
validators=[
|
||||||
_("Enter a valid zipcode."), 'invalid')])
|
RegexValidator(r'^[0-9,A-Z]{3,10}$',
|
||||||
|
_("Enter a valid zipcode."), 'invalid')
|
||||||
|
])
|
||||||
country = models.CharField(_("country"), max_length=20, blank=True,
|
country = models.CharField(_("country"), max_length=20, blank=True,
|
||||||
choices=settings.CONTACTS_COUNTRIES,
|
choices=settings.CONTACTS_COUNTRIES,
|
||||||
default=settings.CONTACTS_DEFAULT_COUNTRY)
|
default=settings.CONTACTS_DEFAULT_COUNTRY)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.full_name or self.short_name
|
return self.full_name or self.short_name
|
|
@ -1,7 +1,7 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.api.serializers import MultiSelectField
|
from orchestra.api.serializers import MultiSelectField
|
||||||
from orchestra.apps.accounts.serializers import AccountSerializerMixin
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||||||
|
|
||||||
from .models import Contact
|
from .models import Contact
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||||
from orchestra.admin.utils import change_url
|
from orchestra.admin.utils import change_url
|
||||||
from orchestra.apps.accounts.admin import SelectAccountAdminMixin
|
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||||
|
|
||||||
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm
|
from .forms import DatabaseCreationForm, DatabaseUserChangeForm, DatabaseUserCreationForm
|
||||||
from .models import Database, DatabaseUser
|
from .models import Database, DatabaseUser
|
|
@ -1,7 +1,7 @@
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
|
|
||||||
from orchestra.api import router, SetPasswordApiMixin
|
from orchestra.api import router, SetPasswordApiMixin
|
||||||
from orchestra.apps.accounts.api import AccountApiMixin
|
from orchestra.contrib.accounts.api import AccountApiMixin
|
||||||
|
|
||||||
from .models import Database, DatabaseUser
|
from .models import Database, DatabaseUser
|
||||||
from .serializers import DatabaseSerializer, DatabaseUserSerializer
|
from .serializers import DatabaseSerializer, DatabaseUserSerializer
|
|
@ -2,8 +2,8 @@ import textwrap
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.orchestration import ServiceController
|
from orchestra.contrib.orchestration import ServiceController
|
||||||
from orchestra.apps.resources import ServiceMonitor
|
from orchestra.contrib.resources import ServiceMonitor
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.api.serializers import HyperlinkedModelSerializer
|
from orchestra.api.serializers import HyperlinkedModelSerializer
|
||||||
from orchestra.apps.accounts.serializers import AccountSerializerMixin
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||||||
from orchestra.core.validators import validate_password
|
from orchestra.core.validators import validate_password
|
||||||
|
|
||||||
from .models import Database, DatabaseUser
|
from .models import Database, DatabaseUser
|
|
@ -9,8 +9,8 @@ from django.core.urlresolvers import reverse
|
||||||
from selenium.webdriver.support.select import Select
|
from selenium.webdriver.support.select import Select
|
||||||
|
|
||||||
from orchestra.admin.utils import change_url
|
from orchestra.admin.utils import change_url
|
||||||
from orchestra.apps.orchestration.models import Server, Route
|
from orchestra.contrib.orchestration.models import Server, Route
|
||||||
from orchestra.utils.system import sshrun
|
from orchestra.utils.sys import sshrun
|
||||||
from orchestra.utils.tests import (BaseLiveServerTestCase, random_ascii, save_response_on_error,
|
from orchestra.utils.tests import (BaseLiveServerTestCase, random_ascii, save_response_on_error,
|
||||||
snapshot_on_error)
|
snapshot_on_error)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ from ...models import Database, DatabaseUser
|
||||||
class DatabaseTestMixin(object):
|
class DatabaseTestMixin(object):
|
||||||
MASTER_SERVER = os.environ.get('ORCHESTRA_SECOND_SERVER', 'localhost')
|
MASTER_SERVER = os.environ.get('ORCHESTRA_SECOND_SERVER', 'localhost')
|
||||||
DEPENDENCIES = (
|
DEPENDENCIES = (
|
||||||
'orchestra.apps.orchestration',
|
'orchestra.contrib.orchestration',
|
||||||
'orcgestra.apps.databases',
|
'orcgestra.apps.databases',
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_link, change_url
|
from orchestra.admin.utils import admin_link, change_url
|
||||||
from orchestra.apps.accounts.admin import AccountAdminMixin
|
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||||
from orchestra.utils import apps
|
from orchestra.utils import apps
|
||||||
|
|
||||||
from .actions import view_zone
|
from .actions import view_zone
|
||||||
|
@ -86,7 +86,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_is_top.admin_order_field = 'top'
|
display_is_top.admin_order_field = 'top'
|
||||||
|
|
||||||
def display_websites(self, domain):
|
def display_websites(self, domain):
|
||||||
if apps.isinstalled('orchestra.apps.websites'):
|
if apps.isinstalled('orchestra.contrib.websites'):
|
||||||
webs = domain.websites.all()
|
webs = domain.websites.all()
|
||||||
if webs:
|
if webs:
|
||||||
links = []
|
links = []
|
||||||
|
@ -111,7 +111,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
'structured_name': 'CONCAT({table}.name, domains_domain.name)'.format(table=table)
|
'structured_name': 'CONCAT({table}.name, domains_domain.name)'.format(table=table)
|
||||||
},
|
},
|
||||||
).order_by('structured_name')
|
).order_by('structured_name')
|
||||||
if apps.isinstalled('orchestra.apps.websites'):
|
if apps.isinstalled('orchestra.contrib.websites'):
|
||||||
qs = qs.prefetch_related('websites')
|
qs = qs.prefetch_related('websites')
|
||||||
return qs
|
return qs
|
||||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework.decorators import link
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from orchestra.api import router
|
from orchestra.api import router
|
||||||
from orchestra.apps.accounts.api import AccountApiMixin
|
from orchestra.contrib.accounts.api import AccountApiMixin
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
from .models import Domain
|
from .models import Domain
|
|
@ -3,8 +3,8 @@ import textwrap
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.orchestration import ServiceController
|
from orchestra.contrib.orchestration import ServiceController
|
||||||
from orchestra.apps.orchestration.models import BackendOperation as Operation
|
from orchestra.contrib.orchestration.models import BackendOperation as Operation
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class Bind9MasterDomainBackend(ServiceController):
|
||||||
|
|
||||||
def get_servers(self, domain, backend):
|
def get_servers(self, domain, backend):
|
||||||
""" Get related server IPs from registered backend routes """
|
""" Get related server IPs from registered backend routes """
|
||||||
from orchestra.apps.orchestration.manager import router
|
from orchestra.contrib.orchestration.manager import router
|
||||||
operation = Operation.create(backend, domain, Operation.SAVE)
|
operation = Operation.create(backend, domain, Operation.SAVE)
|
||||||
servers = []
|
servers = []
|
||||||
for server in router.get_servers(operation):
|
for server in router.get_servers(operation):
|
|
@ -9,7 +9,7 @@ from .models import Domain
|
||||||
|
|
||||||
class BatchDomainCreationAdminForm(forms.ModelForm):
|
class BatchDomainCreationAdminForm(forms.ModelForm):
|
||||||
name = forms.CharField(label=_("Names"), widget=forms.Textarea(attrs={'rows': 5, 'cols': 50}),
|
name = forms.CharField(label=_("Names"), widget=forms.Textarea(attrs={'rows': 5, 'cols': 50}),
|
||||||
help_text=_("Domain per line. All domains will share the same attributes."))
|
help_text=_("Domain per line. All domains will share the same attributes."))
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
self.extra_names = []
|
self.extra_names = []
|
|
@ -11,17 +11,17 @@ from . import settings, validators, utils
|
||||||
|
|
||||||
class Domain(models.Model):
|
class Domain(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=256, unique=True,
|
name = models.CharField(_("name"), max_length=256, unique=True,
|
||||||
help_text=_("Domain or subdomain name."),
|
help_text=_("Domain or subdomain name."),
|
||||||
validators=[
|
validators=[
|
||||||
validators.validate_domain_name,
|
validators.validate_domain_name,
|
||||||
validators.validate_allowed_domain
|
validators.validate_allowed_domain
|
||||||
])
|
])
|
||||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"), blank=True,
|
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"), blank=True,
|
||||||
related_name='domains', help_text=_("Automatically selected for subdomains."))
|
related_name='domains', help_text=_("Automatically selected for subdomains."))
|
||||||
top = models.ForeignKey('domains.Domain', null=True, related_name='subdomain_set',
|
top = models.ForeignKey('domains.Domain', null=True, related_name='subdomain_set',
|
||||||
editable=False)
|
editable=False)
|
||||||
serial = models.IntegerField(_("serial"), default=utils.generate_zone_serial,
|
serial = models.IntegerField(_("serial"), default=utils.generate_zone_serial,
|
||||||
help_text=_("Serial number"))
|
help_text=_("Serial number"))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -223,8 +223,8 @@ class Record(models.Model):
|
||||||
|
|
||||||
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records')
|
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records')
|
||||||
ttl = models.CharField(_("TTL"), max_length=8, blank=True,
|
ttl = models.CharField(_("TTL"), max_length=8, blank=True,
|
||||||
help_text=_("Record TTL, defaults to %s") % settings.DOMAINS_DEFAULT_TTL,
|
help_text=_("Record TTL, defaults to %s") % settings.DOMAINS_DEFAULT_TTL,
|
||||||
validators=[validators.validate_zone_interval])
|
validators=[validators.validate_zone_interval])
|
||||||
type = models.CharField(_("type"), max_length=32, choices=TYPE_CHOICES)
|
type = models.CharField(_("type"), max_length=32, choices=TYPE_CHOICES)
|
||||||
value = models.CharField(_("value"), max_length=256)
|
value = models.CharField(_("value"), max_length=256)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.api.serializers import HyperlinkedModelSerializer
|
from orchestra.api.serializers import HyperlinkedModelSerializer
|
||||||
from orchestra.apps.accounts.serializers import AccountSerializerMixin
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||||||
|
|
||||||
from .helpers import domain_for_validation
|
from .helpers import domain_for_validation
|
||||||
from .models import Domain, Record
|
from .models import Domain, Record
|
|
@ -88,4 +88,5 @@ DOMAINS_FORBIDDEN = getattr(settings, 'DOMAINS_FORBIDDEN',
|
||||||
# unzip -p /tmp/top-1m.csv.zip | head -n 5000 | sed "s/^.*,//" > forbidden_domains.list
|
# unzip -p /tmp/top-1m.csv.zip | head -n 5000 | sed "s/^.*,//" > forbidden_domains.list
|
||||||
|
|
||||||
# '%(site_dir)s/forbidden_domains.list')
|
# '%(site_dir)s/forbidden_domains.list')
|
||||||
'')
|
''
|
||||||
|
)
|
|
@ -7,9 +7,9 @@ from django.conf import settings as djsettings
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from selenium.webdriver.support.select import Select
|
from selenium.webdriver.support.select import Select
|
||||||
|
|
||||||
from orchestra.apps.orchestration.models import Server, Route
|
from orchestra.contrib.orchestration.models import Server, Route
|
||||||
from orchestra.utils.tests import BaseLiveServerTestCase, random_ascii, snapshot_on_error, save_response_on_error
|
from orchestra.utils.tests import BaseLiveServerTestCase, random_ascii, snapshot_on_error, save_response_on_error
|
||||||
from orchestra.utils.system import run
|
from orchestra.utils.sys import run
|
||||||
|
|
||||||
from ... import settings, utils, backends
|
from ... import settings, utils, backends
|
||||||
from ...models import Domain, Record
|
from ...models import Domain, Record
|
||||||
|
@ -305,7 +305,7 @@ class RESTDomainMixin(DomainTestMixin):
|
||||||
|
|
||||||
class Bind9BackendMixin(object):
|
class Bind9BackendMixin(object):
|
||||||
DEPENDENCIES = (
|
DEPENDENCIES = (
|
||||||
'orchestra.apps.orchestration',
|
'orchestra.contrib.orchestration',
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_route(self):
|
def add_route(self):
|
|
@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.core.validators import validate_hostname
|
from orchestra.core.validators import validate_hostname
|
||||||
from orchestra.utils import paths
|
from orchestra.utils import paths
|
||||||
from orchestra.utils.system import run
|
from orchestra.utils.sys import run
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
|
@ -11,7 +11,7 @@ from markdown import markdown
|
||||||
|
|
||||||
from orchestra.admin import ChangeListDefaultFilter, ExtendedModelAdmin#, ChangeViewActions
|
from orchestra.admin import ChangeListDefaultFilter, ExtendedModelAdmin#, ChangeViewActions
|
||||||
from orchestra.admin.utils import admin_link, admin_colored, wrap_admin_view, admin_date
|
from orchestra.admin.utils import admin_link, admin_colored, wrap_admin_view, admin_date
|
||||||
from orchestra.apps.contacts.models import Contact
|
from orchestra.contrib.contacts.models import Contact
|
||||||
|
|
||||||
from .actions import (reject_tickets, resolve_tickets, take_tickets, close_tickets,
|
from .actions import (reject_tickets, resolve_tickets, take_tickets, close_tickets,
|
||||||
mark_as_unread, mark_as_read, set_default_queue)
|
mark_as_unread, mark_as_read, set_default_queue)
|
|
@ -108,4 +108,4 @@ class TicketForm(forms.ModelForm):
|
||||||
|
|
||||||
class ChangeReasonForm(forms.Form):
|
class ChangeReasonForm(forms.Form):
|
||||||
reason = forms.CharField(widget=forms.Textarea(attrs={'cols': '100', 'rows': '10'}),
|
reason = forms.CharField(widget=forms.Textarea(attrs={'cols': '100', 'rows': '10'}),
|
||||||
required=False)
|
required=False)
|
|
@ -2,8 +2,8 @@ from django.conf import settings as djsettings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.contacts import settings as contacts_settings
|
from orchestra.contrib.contacts import settings as contacts_settings
|
||||||
from orchestra.apps.contacts.models import Contact
|
from orchestra.contrib.contacts.models import Contact
|
||||||
from orchestra.core.translations import ModelTranslation
|
from orchestra.core.translations import ModelTranslation
|
||||||
from orchestra.models.fields import MultiSelectField
|
from orchestra.models.fields import MultiSelectField
|
||||||
from orchestra.utils import send_email_template
|
from orchestra.utils import send_email_template
|
||||||
|
@ -16,9 +16,9 @@ class Queue(models.Model):
|
||||||
verbose_name = models.CharField(_("verbose_name"), max_length=128, blank=True)
|
verbose_name = models.CharField(_("verbose_name"), max_length=128, blank=True)
|
||||||
default = models.BooleanField(_("default"), default=False)
|
default = models.BooleanField(_("default"), default=False)
|
||||||
notify = MultiSelectField(_("notify"), max_length=256, blank=True,
|
notify = MultiSelectField(_("notify"), max_length=256, blank=True,
|
||||||
choices=Contact.EMAIL_USAGES,
|
choices=Contact.EMAIL_USAGES,
|
||||||
default=contacts_settings.CONTACTS_DEFAULT_EMAIL_USAGES,
|
default=contacts_settings.CONTACTS_DEFAULT_EMAIL_USAGES,
|
||||||
help_text=_("Contacts to notify by email"))
|
help_text=_("Contacts to notify by email"))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.verbose_name or self.name
|
return self.verbose_name or self.name
|
||||||
|
@ -59,15 +59,15 @@ class Ticket(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
creator = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("created by"),
|
creator = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("created by"),
|
||||||
related_name='tickets_created', null=True)
|
related_name='tickets_created', null=True)
|
||||||
creator_name = models.CharField(_("creator name"), max_length=256, blank=True)
|
creator_name = models.CharField(_("creator name"), max_length=256, blank=True)
|
||||||
owner = models.ForeignKey(djsettings.AUTH_USER_MODEL, null=True, blank=True,
|
owner = models.ForeignKey(djsettings.AUTH_USER_MODEL, null=True, blank=True,
|
||||||
related_name='tickets_owned', verbose_name=_("assigned to"))
|
related_name='tickets_owned', verbose_name=_("assigned to"))
|
||||||
queue = models.ForeignKey(Queue, related_name='tickets', null=True, blank=True)
|
queue = models.ForeignKey(Queue, related_name='tickets', null=True, blank=True)
|
||||||
subject = models.CharField(_("subject"), max_length=256)
|
subject = models.CharField(_("subject"), max_length=256)
|
||||||
description = models.TextField(_("description"))
|
description = models.TextField(_("description"))
|
||||||
priority = models.CharField(_("priority"), max_length=32, choices=PRIORITIES,
|
priority = models.CharField(_("priority"), max_length=32, choices=PRIORITIES,
|
||||||
default=MEDIUM)
|
default=MEDIUM)
|
||||||
state = models.CharField(_("state"), max_length=32, choices=STATES, default=NEW)
|
state = models.CharField(_("state"), max_length=32, choices=STATES, default=NEW)
|
||||||
created_at = models.DateTimeField(_("created"), auto_now_add=True)
|
created_at = models.DateTimeField(_("created"), auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(_("modified"), auto_now=True)
|
updated_at = models.DateTimeField(_("modified"), auto_now=True)
|
||||||
|
@ -154,9 +154,9 @@ class Ticket(models.Model):
|
||||||
|
|
||||||
class Message(models.Model):
|
class Message(models.Model):
|
||||||
ticket = models.ForeignKey('issues.Ticket', verbose_name=_("ticket"),
|
ticket = models.ForeignKey('issues.Ticket', verbose_name=_("ticket"),
|
||||||
related_name='messages')
|
related_name='messages')
|
||||||
author = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("author"),
|
author = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("author"),
|
||||||
related_name='ticket_messages')
|
related_name='ticket_messages')
|
||||||
author_name = models.CharField(_("author name"), max_length=256, blank=True)
|
author_name = models.CharField(_("author name"), max_length=256, blank=True)
|
||||||
content = models.TextField(_("content"))
|
content = models.TextField(_("content"))
|
||||||
created_on = models.DateTimeField(_("created on"), auto_now_add=True)
|
created_on = models.DateTimeField(_("created on"), auto_now_add=True)
|
||||||
|
@ -183,10 +183,9 @@ class Message(models.Model):
|
||||||
|
|
||||||
class TicketTracker(models.Model):
|
class TicketTracker(models.Model):
|
||||||
""" Keeps track of user read tickets """
|
""" Keeps track of user read tickets """
|
||||||
ticket = models.ForeignKey(Ticket, verbose_name=_("ticket"),
|
ticket = models.ForeignKey(Ticket, verbose_name=_("ticket"), related_name='trackers')
|
||||||
related_name='trackers')
|
|
||||||
user = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("user"),
|
user = models.ForeignKey(djsettings.AUTH_USER_MODEL, verbose_name=_("user"),
|
||||||
related_name='ticket_trackers')
|
related_name='ticket_trackers')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (
|
unique_together = (
|
Before Width: | Height: | Size: 204 B After Width: | Height: | Size: 204 B |
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||||
from orchestra.admin.utils import admin_link
|
from orchestra.admin.utils import admin_link
|
||||||
from orchestra.apps.accounts.admin import SelectAccountAdminMixin
|
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||||
|
|
||||||
from .forms import ListCreationForm, ListChangeForm
|
from .forms import ListCreationForm, ListChangeForm
|
||||||
from .models import List
|
from .models import List
|
|
@ -1,7 +1,7 @@
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
|
|
||||||
from orchestra.api import router, SetPasswordApiMixin
|
from orchestra.api import router, SetPasswordApiMixin
|
||||||
from orchestra.apps.accounts.api import AccountApiMixin
|
from orchestra.contrib.accounts.api import AccountApiMixin
|
||||||
|
|
||||||
from .models import List
|
from .models import List
|
||||||
from .serializers import ListSerializer
|
from .serializers import ListSerializer
|
|
@ -2,8 +2,8 @@ import textwrap
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.orchestration import ServiceController
|
from orchestra.contrib.orchestration import ServiceController
|
||||||
from orchestra.apps.resources import ServiceMonitor
|
from orchestra.contrib.resources import ServiceMonitor
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
from .models import List
|
from .models import List
|
|
@ -17,10 +17,10 @@ class CleanAddressMixin(object):
|
||||||
|
|
||||||
class ListCreationForm(CleanAddressMixin, forms.ModelForm):
|
class ListCreationForm(CleanAddressMixin, forms.ModelForm):
|
||||||
password1 = forms.CharField(label=_("Password"), validators=[validate_password],
|
password1 = forms.CharField(label=_("Password"), validators=[validate_password],
|
||||||
widget=forms.PasswordInput)
|
widget=forms.PasswordInput)
|
||||||
password2 = forms.CharField(label=_("Password confirmation"),
|
password2 = forms.CharField(label=_("Password confirmation"),
|
||||||
widget=forms.PasswordInput,
|
widget=forms.PasswordInput,
|
||||||
help_text=_("Enter the same password as above, for verification."))
|
help_text=_("Enter the same password as above, for verification."))
|
||||||
|
|
||||||
def clean_password2(self):
|
def clean_password2(self):
|
||||||
password1 = self.cleaned_data.get("password1")
|
password1 = self.cleaned_data.get("password1")
|
||||||
|
@ -33,7 +33,7 @@ class ListCreationForm(CleanAddressMixin, forms.ModelForm):
|
||||||
|
|
||||||
class ListChangeForm(CleanAddressMixin, forms.ModelForm):
|
class ListChangeForm(CleanAddressMixin, forms.ModelForm):
|
||||||
password = forms.CharField(label=_("Password"),
|
password = forms.CharField(label=_("Password"),
|
||||||
widget=ReadOnlyWidget('<strong>Unknown password</strong>'),
|
widget=ReadOnlyWidget('<strong>Unknown password</strong>'),
|
||||||
help_text=_("List passwords are not stored, so there is no way to see this "
|
help_text=_("List passwords are not stored, so there is no way to see this "
|
||||||
"list's password, but you can change the password using "
|
"list's password, but you can change the password using "
|
||||||
"<a href=\"password/\">this form</a>."))
|
"<a href=\"password/\">this form</a>."))
|
|
@ -12,15 +12,15 @@ from . import settings
|
||||||
|
|
||||||
class List(models.Model):
|
class List(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=128, unique=True, validators=[validate_name],
|
name = models.CharField(_("name"), max_length=128, unique=True, validators=[validate_name],
|
||||||
help_text=_("Default list address <name>@%s") % settings.LISTS_DEFAULT_DOMAIN)
|
help_text=_("Default list address <name>@%s") % settings.LISTS_DEFAULT_DOMAIN)
|
||||||
address_name = models.CharField(_("address name"), max_length=128,
|
address_name = models.CharField(_("address name"), max_length=128,
|
||||||
validators=[validate_name], blank=True)
|
validators=[validate_name], blank=True)
|
||||||
address_domain = models.ForeignKey(settings.LISTS_DOMAIN_MODEL,
|
address_domain = models.ForeignKey(settings.LISTS_DOMAIN_MODEL,
|
||||||
verbose_name=_("address domain"), blank=True, null=True)
|
verbose_name=_("address domain"), blank=True, null=True)
|
||||||
admin_email = models.EmailField(_("admin email"),
|
admin_email = models.EmailField(_("admin email"),
|
||||||
help_text=_("Administration email address"))
|
help_text=_("Administration email address"))
|
||||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
||||||
related_name='lists')
|
related_name='lists')
|
||||||
# TODO also admin
|
# TODO also admin
|
||||||
# TODO is_active = models.BooleanField(_("active"), default=True,
|
# TODO is_active = models.BooleanField(_("active"), default=True,
|
||||||
# help_text=_("Designates whether this account should be treated as active. "
|
# help_text=_("Designates whether this account should be treated as active. "
|
|
@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from orchestra.api.serializers import HyperlinkedModelSerializer
|
from orchestra.api.serializers import HyperlinkedModelSerializer
|
||||||
from orchestra.apps.accounts.serializers import AccountSerializerMixin
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||||||
from orchestra.core.validators import validate_password
|
from orchestra.core.validators import validate_password
|
||||||
|
|
||||||
from .models import List
|
from .models import List
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue