mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
Merge branch '1.4.x'
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
from .app_settings import load_admin_settings
|
||||
|
||||
|
||||
class AdminConfig(AppConfig):
|
||||
|
||||
@@ -11,4 +13,6 @@ class AdminConfig(AppConfig):
|
||||
verbose_name = "Modoboa admin console"
|
||||
|
||||
def ready(self):
|
||||
load_admin_settings()
|
||||
|
||||
from . import handlers
|
||||
|
||||
@@ -49,16 +49,6 @@ def extra_permissions(rolename):
|
||||
return PERMISSIONS.get(rolename, [])
|
||||
|
||||
|
||||
@events.observe("ExtraUprefsRoutes")
|
||||
def extra_routes():
|
||||
from django.conf.urls import url
|
||||
return [
|
||||
url(r'^user/forward/',
|
||||
'modoboa.admin.views.user.forward',
|
||||
name="user_forward"),
|
||||
]
|
||||
|
||||
|
||||
@events.observe("AdminMenuDisplay")
|
||||
def admin_menu(target, user):
|
||||
if target != "top_menu":
|
||||
|
||||
@@ -4,7 +4,6 @@ from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from ...models import Domain
|
||||
|
||||
@@ -20,8 +19,6 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar'])
|
||||
for dom in Domain.objects.all():
|
||||
dom.to_csv(csvwriter)
|
||||
|
||||
@@ -4,7 +4,6 @@ from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.models import User
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from ...models import Alias
|
||||
@@ -21,11 +20,10 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar'])
|
||||
for u in User.objects.all():
|
||||
u.to_csv(csvwriter)
|
||||
|
||||
for a in Alias.objects.prefetch_related('mboxes', 'aliases'):
|
||||
for a in Alias.objects.prefetch_related('aliasrecipient_set'):
|
||||
a.to_csv(csvwriter)
|
||||
|
||||
@@ -2,8 +2,6 @@ from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
|
||||
from ._import import import_csv
|
||||
@@ -25,7 +23,5 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
for filename in args:
|
||||
import_csv(filename, kwargs)
|
||||
|
||||
@@ -2,7 +2,6 @@ from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
|
||||
from ._import import import_csv
|
||||
@@ -12,23 +11,20 @@ class Command(BaseCommand):
|
||||
args = 'csvfile'
|
||||
help = 'Import identities from a csv file'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
'--sepchar', action='store_true', dest='sepchar', default=';'
|
||||
),
|
||||
make_option(
|
||||
'--continue-if-exists', action='store_true',
|
||||
dest='continue_if_exists', default=True
|
||||
),
|
||||
make_option(
|
||||
'--crypt-password', action='store_true', dest='crypt_password',
|
||||
default=False
|
||||
)
|
||||
)
|
||||
def add_arguments(self, parser):
|
||||
"""Add extra arguments to command."""
|
||||
parser.add_argument(
|
||||
"--sepchar", type=str, default=";",
|
||||
help="Separator used in file.")
|
||||
parser.add_argument(
|
||||
"--continue-if-exists", action="store_true",
|
||||
dest='continue_if_exists', default=True,
|
||||
help="Continue even if an entry already exists.")
|
||||
parser.add_argument(
|
||||
"--crypt-password", action="store_true", dest="crypt_password",
|
||||
default=False, help="Encrypt provided passwords.")
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
def handle(self, *args, **options):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
for filename in args:
|
||||
import_csv(filename, kwargs)
|
||||
import_csv(filename, options)
|
||||
|
||||
@@ -262,16 +262,18 @@ class Mailbox(AdminObject):
|
||||
from modoboa.lib.permissions import grant_access_to_object
|
||||
super(Mailbox, self).post_create(creator)
|
||||
conditions = (
|
||||
creator.is_superuser,
|
||||
creator.has_perm("admin.add_mailbox"),
|
||||
not self.user.has_perm("admin.add_domain")
|
||||
)
|
||||
if all(conditions):
|
||||
# A super user is creating a new mailbox. Give
|
||||
# An admin is creating a new mailbox. Give
|
||||
# access to that mailbox (and the associated
|
||||
# account) to the appropriate domain admins,
|
||||
# except if the new account has a more important
|
||||
# role (SuperAdmin, Reseller)
|
||||
for admin in self.domain.admins:
|
||||
if admin == creator:
|
||||
continue
|
||||
grant_access_to_object(admin, self)
|
||||
grant_access_to_object(admin, self.user)
|
||||
|
||||
|
||||
@@ -132,7 +132,15 @@ class PermissionsTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create test data."""
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.limits.models import LimitTemplates
|
||||
|
||||
super(PermissionsTestCase, cls).setUpTestData()
|
||||
for tpl in LimitTemplates().templates:
|
||||
parameters.save_admin(
|
||||
"DEFLT_{0}".format(tpl[0].upper()), 2,
|
||||
app="limits"
|
||||
)
|
||||
factories.populate_database()
|
||||
cls.user = User.objects.get(username='user@test.com')
|
||||
cls.values = dict(
|
||||
@@ -263,3 +271,27 @@ class PermissionsTestCase(ModoTestCase):
|
||||
reverse("admin:account_add"),
|
||||
values, status=400
|
||||
)
|
||||
|
||||
def test_domadmins_permissions(self):
|
||||
"""
|
||||
Check that two domain admins in the same domains see the same
|
||||
content.
|
||||
"""
|
||||
dom = models.Domain.objects.get(name="test.com")
|
||||
mb = factories.MailboxFactory(
|
||||
domain=dom, address="admin2",
|
||||
user__username="admin2@test.com", user__groups=('DomainAdmins', ),
|
||||
user__password="{PLAIN}toto")
|
||||
dom.add_admin(mb.user)
|
||||
self.client.logout()
|
||||
self.assertTrue(
|
||||
self.client.login(username="admin@test.com", password="toto"))
|
||||
values = {
|
||||
"username": "new@test.com", "password1": "Toto1234",
|
||||
"password2": "Toto1234", "role": "SimpleUsers", "quota_act": True,
|
||||
"is_active": True, "email": "new@test.com", "stepid": "step2"
|
||||
}
|
||||
self.ajax_post(reverse("admin:account_add"), values)
|
||||
|
||||
new_mb = models.Mailbox.objects.get(user__username="new@test.com")
|
||||
self.assertTrue(mb.user.can_access(new_mb))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
from modoboa.lib import parameters
|
||||
@@ -16,11 +15,6 @@ class PasswordSchemesTestCase(ModoTestCase):
|
||||
super(PasswordSchemesTestCase, cls).setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def setUp(self):
|
||||
"""Test initialization."""
|
||||
super(PasswordSchemesTestCase, self).setUp()
|
||||
load_core_settings()
|
||||
|
||||
def _create_account(self):
|
||||
values = dict(
|
||||
username="tester@test.com", first_name="Tester", last_name="Toto",
|
||||
|
||||
@@ -1,65 +1,15 @@
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.lib import parameters, events
|
||||
from modoboa.lib import events
|
||||
|
||||
BASE_EVENTS = [
|
||||
"CanCreate",
|
||||
|
||||
"AccountCreated",
|
||||
"AccountAutoCreated",
|
||||
"AccountModified",
|
||||
"AccountDeleted",
|
||||
"AccountExported",
|
||||
"AccountImported",
|
||||
"PasswordUpdated",
|
||||
"ExtraAccountActions",
|
||||
"RoleChanged",
|
||||
"GetExtraRoles",
|
||||
"GetExtraRolePermissions",
|
||||
"PasswordChange",
|
||||
"UserCanSetRole",
|
||||
|
||||
"InitialDataLoaded",
|
||||
|
||||
"UserMenuDisplay",
|
||||
"AdminMenuDisplay",
|
||||
"GetStaticContent",
|
||||
|
||||
"UserLogin",
|
||||
"UserLogout",
|
||||
|
||||
"GetAnnouncement",
|
||||
|
||||
"TopNotifications",
|
||||
"ExtraAdminContent",
|
||||
|
||||
"ExtraUprefsRoutes",
|
||||
"ExtraUprefsJS",
|
||||
|
||||
"GetExtraParameters",
|
||||
"ExtraFormFields",
|
||||
"SaveExtraFormFields",
|
||||
]
|
||||
|
||||
PERMISSIONS = {
|
||||
"SimpleUsers": []
|
||||
}
|
||||
|
||||
|
||||
def load_core_settings():
|
||||
"""Load core settings.
|
||||
|
||||
This function must be manually called (see :file:`urls.py`) in
|
||||
order to load base settings.
|
||||
"""
|
||||
from modoboa.core.app_settings import GeneralParametersForm
|
||||
|
||||
parameters.register(GeneralParametersForm, ugettext_lazy("General"))
|
||||
events.declare(BASE_EVENTS)
|
||||
|
||||
|
||||
@events.observe("TopNotifications")
|
||||
def check_for_new_version(request, include_all):
|
||||
"""
|
||||
@@ -78,3 +28,5 @@ def check_for_new_version(request, include_all):
|
||||
"text": _("One or more updates are available"),
|
||||
"level": "info",
|
||||
}]
|
||||
|
||||
default_app_config = "modoboa.core.apps.CoreConfig"
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Core config for admin."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
BASE_EVENTS = [
|
||||
"CanCreate",
|
||||
|
||||
"AccountCreated",
|
||||
"AccountAutoCreated",
|
||||
"AccountModified",
|
||||
"AccountDeleted",
|
||||
"AccountExported",
|
||||
"AccountImported",
|
||||
"PasswordUpdated",
|
||||
"ExtraAccountActions",
|
||||
"RoleChanged",
|
||||
"GetExtraRoles",
|
||||
"GetExtraRolePermissions",
|
||||
"PasswordChange",
|
||||
"UserCanSetRole",
|
||||
|
||||
"InitialDataLoaded",
|
||||
|
||||
"UserMenuDisplay",
|
||||
"AdminMenuDisplay",
|
||||
"GetStaticContent",
|
||||
|
||||
"UserLogin",
|
||||
"UserLogout",
|
||||
|
||||
"GetAnnouncement",
|
||||
|
||||
"TopNotifications",
|
||||
"ExtraAdminContent",
|
||||
|
||||
"ExtraUprefsRoutes",
|
||||
"ExtraUprefsJS",
|
||||
|
||||
"GetExtraParameters",
|
||||
"ExtraFormFields",
|
||||
"SaveExtraFormFields",
|
||||
]
|
||||
|
||||
|
||||
def load_core_settings():
|
||||
"""Load core settings.
|
||||
|
||||
This function must be manually called (see :file:`urls.py`) in
|
||||
order to load base settings.
|
||||
"""
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from modoboa.lib import parameters, events
|
||||
from .app_settings import GeneralParametersForm
|
||||
|
||||
parameters.register(GeneralParametersForm, ugettext_lazy("General"))
|
||||
events.declare(BASE_EVENTS)
|
||||
|
||||
|
||||
class CoreConfig(AppConfig):
|
||||
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.core"
|
||||
verbose_name = "Modoboa core"
|
||||
|
||||
def ready(self):
|
||||
load_core_settings()
|
||||
@@ -36,7 +36,7 @@ SITE_ID = 1
|
||||
|
||||
# Security settings
|
||||
|
||||
X_FRAME_OPTIONS = "DENY"
|
||||
X_FRAME_OPTIONS = "SAMEORIGIN"
|
||||
|
||||
# Application definition
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ from optparse import make_option
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.models import Log
|
||||
from modoboa.lib import parameters
|
||||
|
||||
@@ -39,7 +38,6 @@ class Command(BaseCommand):
|
||||
l.addHandler(logging.StreamHandler())
|
||||
self.verbose = options["verbose"]
|
||||
|
||||
load_core_settings()
|
||||
log_maximum_age = int(parameters.get_admin("LOG_MAXIMUM_AGE"))
|
||||
self.__vprint("Deleting logs older than %d days..." % log_maximum_age)
|
||||
limit = timezone.now() - datetime.timedelta(log_maximum_age)
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.admin.app_settings import load_admin_settings
|
||||
from modoboa.core import load_core_settings, PERMISSIONS
|
||||
from modoboa.core import PERMISSIONS
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.models import User, ObjectAccess
|
||||
from modoboa.lib.cryptutils import random_key
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib import models as lib_models
|
||||
from modoboa.lib.permissions import add_permissions_to_group
|
||||
from modoboa.limits.app_settings import load_limits_settings
|
||||
import modoboa.relaydomains.models as relay_models
|
||||
|
||||
|
||||
@@ -28,10 +26,6 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Command entry point."""
|
||||
load_core_settings()
|
||||
load_admin_settings()
|
||||
load_limits_settings()
|
||||
|
||||
if not User.objects.filter(is_superuser=True).count():
|
||||
admin = User(username="admin", is_superuser=True)
|
||||
admin.set_password("password")
|
||||
|
||||
@@ -135,7 +135,7 @@ class User(PermissionsMixin):
|
||||
try:
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME")
|
||||
except parameters.NotDefined:
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.apps import load_core_settings
|
||||
load_core_settings()
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME")
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import ModoboaException
|
||||
from modoboa.lib.sysutils import guess_extension_name
|
||||
|
||||
from . import db_utils
|
||||
|
||||
|
||||
_params = {'A': {}, 'U': {}}
|
||||
|
||||
@@ -91,6 +93,8 @@ class AdminParametersForm(GenericParametersForm):
|
||||
def _load_initial_values(self):
|
||||
from .models import Parameter
|
||||
|
||||
if not db_utils.db_table_exists("lib_parameter"):
|
||||
return
|
||||
names = [
|
||||
"%s.%s" % (self.app, name.upper()) for name in self.fields.keys()
|
||||
]
|
||||
@@ -132,6 +136,8 @@ class UserParametersForm(GenericParametersForm):
|
||||
super(UserParametersForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def _load_initial_values(self):
|
||||
if not db_utils.db_table_exists("lib_userparameter"):
|
||||
return
|
||||
if self.user is None:
|
||||
return
|
||||
from .models import UserParameter
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "modoboa.limits.apps.LimitsConfig"
|
||||
|
||||
@@ -3,14 +3,9 @@
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.form_utils import SeparatorField
|
||||
from modoboa.lib.parameters import AdminParametersForm
|
||||
|
||||
EVENTS = [
|
||||
'GetExtraLimitTemplates'
|
||||
]
|
||||
|
||||
|
||||
class ParametersForm(AdminParametersForm):
|
||||
app = "limits"
|
||||
@@ -73,11 +68,3 @@ class ParametersForm(AdminParametersForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AdminParametersForm, self).__init__(*args, **kwargs)
|
||||
self._load_extra_parameters('A')
|
||||
|
||||
|
||||
def load_limits_settings():
|
||||
"""Load settings."""
|
||||
parameters.register(ParametersForm, _("Limits"))
|
||||
events.declare(EVENTS)
|
||||
from . import controls
|
||||
from . import general_callbacks
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
"""App config for limits."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
EVENTS = [
|
||||
'GetExtraLimitTemplates'
|
||||
]
|
||||
|
||||
|
||||
def load_limits_settings():
|
||||
"""Load settings."""
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import events, parameters
|
||||
from .app_settings import ParametersForm
|
||||
|
||||
parameters.register(ParametersForm, _("Limits"))
|
||||
events.declare(EVENTS)
|
||||
from . import controls
|
||||
from . import general_callbacks
|
||||
|
||||
|
||||
class LimitsConfig(AppConfig):
|
||||
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.limits"
|
||||
verbose_name = "Modoboa admin limits"
|
||||
|
||||
def ready(self):
|
||||
load_limits_settings()
|
||||
@@ -122,7 +122,6 @@ def create_pool(user):
|
||||
owner = get_object_owner(user)
|
||||
if owner.group not in ['SuperAdmins', 'Resellers']:
|
||||
return
|
||||
|
||||
if user.group == 'DomainAdmins':
|
||||
check_limit(owner, 'domain_admins_limit')
|
||||
inc_limit_usage(owner, 'domain_admins_limit')
|
||||
|
||||
@@ -5,21 +5,10 @@ Relay domains settings definition.
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.form_utils import SeparatorField
|
||||
|
||||
|
||||
EVENTS = [
|
||||
"RelayDomainCreated",
|
||||
"RelayDomainDeleted",
|
||||
"RelayDomainModified",
|
||||
"RelayDomainAliasCreated",
|
||||
"RelayDomainAliasDeleted",
|
||||
"ExtraRelayDomainForm",
|
||||
"FillRelayDomainInstances"
|
||||
]
|
||||
|
||||
|
||||
class AdminParametersForm(parameters.AdminParametersForm):
|
||||
|
||||
"""Admin parameters definition."""
|
||||
@@ -34,12 +23,3 @@ class AdminParametersForm(parameters.AdminParametersForm):
|
||||
help_text=ugettext_lazy('Path to the master.cf configuration file'),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
|
||||
def load_relaydomains_settings():
|
||||
"""Load application settings."""
|
||||
parameters.register(
|
||||
AdminParametersForm, ugettext_lazy("Relay domains")
|
||||
)
|
||||
events.declare(EVENTS)
|
||||
from . import general_callbacks
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
EVENTS = [
|
||||
"RelayDomainCreated",
|
||||
"RelayDomainDeleted",
|
||||
"RelayDomainModified",
|
||||
"RelayDomainAliasCreated",
|
||||
"RelayDomainAliasDeleted",
|
||||
"ExtraRelayDomainForm",
|
||||
"FillRelayDomainInstances"
|
||||
]
|
||||
|
||||
|
||||
def load_relaydomains_settings():
|
||||
"""Load application settings."""
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import events, parameters
|
||||
from .app_settings import AdminParametersForm
|
||||
|
||||
parameters.register(AdminParametersForm, _("Relay domains"))
|
||||
events.declare(EVENTS)
|
||||
from . import general_callbacks
|
||||
|
||||
|
||||
class RelayDomainsConfig(AppConfig):
|
||||
|
||||
"""App configuration."""
|
||||
@@ -11,4 +33,5 @@ class RelayDomainsConfig(AppConfig):
|
||||
verbose_name = "Modoboa relay domains"
|
||||
|
||||
def ready(self):
|
||||
load_relaydomains_settings()
|
||||
from . import handlers
|
||||
|
||||
@@ -3,6 +3,6 @@ from django.conf.urls import patterns, url
|
||||
urlpatterns = patterns(
|
||||
'modoboa.relaydomains.views',
|
||||
|
||||
url(r'^relaydomains/scan_services/$', 'scan_for_services',
|
||||
url(r'^scan_services/$', 'scan_for_services',
|
||||
name="service_scan"),
|
||||
)
|
||||
|
||||
+5
-11
@@ -1,27 +1,21 @@
|
||||
from django.conf import settings
|
||||
from django.conf.urls import patterns, include, url
|
||||
|
||||
from modoboa.admin.app_settings import load_admin_settings
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.lib import parameters, events
|
||||
from modoboa.limits.app_settings import load_limits_settings
|
||||
from modoboa.relaydomains.app_settings import load_relaydomains_settings
|
||||
|
||||
|
||||
load_core_settings()
|
||||
load_admin_settings()
|
||||
load_limits_settings()
|
||||
load_relaydomains_settings()
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', 'modoboa.lib.web_utils.topredirection', name="topredirection"),
|
||||
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog',
|
||||
{'packages': ('modoboa', ), }),
|
||||
('', include('modoboa.core.urls', namespace="core")),
|
||||
('', include('modoboa.admin.urls', namespace="admin")),
|
||||
('', include('modoboa.relaydomains.urls', namespace="relaydomains")),
|
||||
url('^user/forward/', 'modoboa.admin.views.user.forward',
|
||||
name='user_forward'),
|
||||
('admin/', include('modoboa.admin.urls', namespace="admin")),
|
||||
('relaydomains/',
|
||||
include('modoboa.relaydomains.urls', namespace="relaydomains")),
|
||||
)
|
||||
|
||||
urlpatterns += patterns(
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
django==1.8.7
|
||||
django<=1.8.99
|
||||
django-reversion==1.9.3
|
||||
dj-database-url
|
||||
pycrypto
|
||||
|
||||
Reference in New Issue
Block a user