Random improvements
This commit is contained in:
parent
d2b96dac40
commit
4d9feb690f
1
TODO.md
1
TODO.md
|
@ -177,3 +177,4 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
|||
* ServiceBackend.validate() : used for server paths validation
|
||||
* ServiceBackend.grant_access() : used for granting access
|
||||
* bottom line: allow arbitrary backend methods (underscore method names that are not to be executed?)
|
||||
* HowTo?? Signals ? what?
|
||||
|
|
|
@ -39,8 +39,7 @@ class ChangeListDefaultFilter(object):
|
|||
defaults.append(key)
|
||||
# hack response cl context in order to hook default filter awaearness
|
||||
# into search_form.html template
|
||||
response = super(ChangeListDefaultFilter, self).changelist_view(request,
|
||||
extra_context=extra_context)
|
||||
response = super(ChangeListDefaultFilter, self).changelist_view(request, extra_context)
|
||||
if hasattr(response, 'context_data') and 'cl' in response.context_data:
|
||||
response.context_data['cl'].default_changelist_filters = defaults
|
||||
return response
|
||||
|
@ -100,7 +99,7 @@ class ChangeViewActionsMixin(object):
|
|||
kwargs['extra_context'] = {}
|
||||
obj = self.get_object(request, unquote(object_id))
|
||||
kwargs['extra_context']['object_tools_items'] = [
|
||||
action.__dict__ for action in self.get_change_view_actions(obj=obj)
|
||||
action.__dict__ for action in self.get_change_view_actions(obj)
|
||||
]
|
||||
return super(ChangeViewActionsMixin, self).change_view(request, object_id, **kwargs)
|
||||
|
||||
|
@ -116,11 +115,11 @@ class ChangeAddFieldsMixin(object):
|
|||
|
||||
def get_prepopulated_fields(self, request, obj=None):
|
||||
if not obj:
|
||||
return super(ChangeAddFieldsMixin, self).get_prepopulated_fields(request, obj=obj)
|
||||
return super(ChangeAddFieldsMixin, self).get_prepopulated_fields(request, obj)
|
||||
return {}
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
fields = super(ChangeAddFieldsMixin, self).get_readonly_fields(request, obj=obj)
|
||||
fields = super(ChangeAddFieldsMixin, self).get_readonly_fields(request, obj)
|
||||
if obj:
|
||||
return fields + self.change_readonly_fields
|
||||
return fields
|
||||
|
@ -131,7 +130,7 @@ class ChangeAddFieldsMixin(object):
|
|||
return self.add_fieldsets
|
||||
elif self.add_fields:
|
||||
return [(None, {'fields': self.add_fields})]
|
||||
return super(ChangeAddFieldsMixin, self).get_fieldsets(request, obj=obj)
|
||||
return super(ChangeAddFieldsMixin, self).get_fieldsets(request, obj)
|
||||
|
||||
def get_inline_instances(self, request, obj=None):
|
||||
""" add_inlines and inline.parent_object """
|
||||
|
@ -139,7 +138,7 @@ class ChangeAddFieldsMixin(object):
|
|||
self.inlines = type(self).inlines
|
||||
else:
|
||||
self.inlines = self.add_inlines or self.inlines
|
||||
inlines = super(ChangeAddFieldsMixin, self).get_inline_instances(request, obj=obj)
|
||||
inlines = super(ChangeAddFieldsMixin, self).get_inline_instances(request, obj)
|
||||
for inline in inlines:
|
||||
inline.parent_object = obj
|
||||
return inlines
|
||||
|
@ -200,7 +199,7 @@ class ChangePasswordAdminMixin(object):
|
|||
related.append(rel)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = self.change_password_form(user, request.POST, related=related)
|
||||
form = self.change_password_form(user, request.POST, related)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
change_message = self.construct_change_message(request, form, None)
|
||||
|
@ -210,7 +209,7 @@ class ChangePasswordAdminMixin(object):
|
|||
update_session_auth_hash(request, form.user) # This is safe
|
||||
return HttpResponseRedirect('..')
|
||||
else:
|
||||
form = self.change_password_form(user, related=related)
|
||||
form = self.change_password_form(user, related)
|
||||
|
||||
fieldsets = [
|
||||
(user._meta.verbose_name.capitalize(), {
|
||||
|
|
|
@ -3,6 +3,7 @@ from rest_framework.response import Response
|
|||
from rest_framework.reverse import reverse
|
||||
|
||||
from .. import settings
|
||||
from ..core import services, accounts
|
||||
|
||||
|
||||
class APIRoot(views.APIView):
|
||||
|
@ -15,6 +16,10 @@ class APIRoot(views.APIView):
|
|||
'<%s>; rel="%s"' % (root_url, 'api-root'),
|
||||
'<%s>; rel="%s"' % (token_url, 'api-get-auth-token'),
|
||||
]
|
||||
body = {
|
||||
'accountancy': [],
|
||||
'services': [],
|
||||
}
|
||||
if not request.user.is_anonymous():
|
||||
list_name = '{basename}-list'
|
||||
detail_name = '{basename}-detail'
|
||||
|
@ -30,17 +35,34 @@ class APIRoot(views.APIView):
|
|||
kwargs = {}
|
||||
url = reverse(url_name, request=request, format=format, kwargs=kwargs)
|
||||
links.append('<%s>; rel="%s"' % (url, url_name))
|
||||
model = viewset.model
|
||||
group = None
|
||||
if model in services:
|
||||
group = 'services'
|
||||
menu = services[model].menu
|
||||
elif model in accounts:
|
||||
group = 'accountancy'
|
||||
menu = accounts[model].menu
|
||||
if group and menu:
|
||||
body[group].append({
|
||||
'url': url,
|
||||
'name': basename,
|
||||
'verbose_name': model._meta.verbose_name,
|
||||
'verbose_name_plural': model._meta.verbose_name_plural,
|
||||
})
|
||||
headers = {
|
||||
'Link': ', '.join(links)
|
||||
}
|
||||
body = {
|
||||
name.lower(): getattr(settings, name, None) for name in self.names
|
||||
}
|
||||
body.update({
|
||||
name.lower(): getattr(settings, name, None)
|
||||
for name in self.names
|
||||
})
|
||||
return Response(body, headers=headers)
|
||||
|
||||
def metadata(self, request):
|
||||
ret = super(APIRoot, self).metadata(request)
|
||||
ret['settings'] = {
|
||||
name.lower(): getattr(settings, name, None) for name in self.names
|
||||
name.lower(): getattr(settings, name, None)
|
||||
for name in self.names
|
||||
}
|
||||
return ret
|
||||
|
|
|
@ -11,11 +11,15 @@ from . import settings, validators, utils
|
|||
|
||||
class Domain(models.Model):
|
||||
name = models.CharField(_("name"), max_length=256, unique=True,
|
||||
validators=[validators.validate_domain_name, validators.validate_allowed_domain],
|
||||
help_text=_("Domain or subdomain name."))
|
||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
||||
related_name='domains', blank=True, help_text=_("Automatically selected for subdomains."))
|
||||
top = models.ForeignKey('domains.Domain', null=True, related_name='subdomain_set', editable=False)
|
||||
help_text=_("Domain or subdomain name."),
|
||||
validators=[
|
||||
validators.validate_domain_name,
|
||||
validators.validate_allowed_domain
|
||||
])
|
||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"), blank=True,
|
||||
related_name='domains', help_text=_("Automatically selected for subdomains."))
|
||||
top = models.ForeignKey('domains.Domain', null=True, related_name='subdomain_set',
|
||||
editable=False)
|
||||
serial = models.IntegerField(_("serial"), default=utils.generate_zone_serial,
|
||||
help_text=_("Serial number"))
|
||||
|
||||
|
@ -88,17 +92,24 @@ class Domain(models.Model):
|
|||
# Update serial and insert at 0
|
||||
value = record.value.split()
|
||||
value[2] = str(self.serial)
|
||||
records.insert(0,
|
||||
AttrDict(type=record.SOA, ttl=record.get_ttl(), value=' '.join(value))
|
||||
)
|
||||
records.insert(0, AttrDict(
|
||||
type=record.SOA,
|
||||
ttl=record.get_ttl(),
|
||||
value=' '.join(value)
|
||||
))
|
||||
else:
|
||||
records.append(
|
||||
AttrDict(type=record.type, ttl=record.get_ttl(), value=record.value)
|
||||
)
|
||||
records.append(AttrDict(
|
||||
type=record.type,
|
||||
ttl=record.get_ttl(),
|
||||
value=record.value
|
||||
))
|
||||
if self.is_top:
|
||||
if Record.NS not in types:
|
||||
for ns in settings.DOMAINS_DEFAULT_NS:
|
||||
records.append(AttrDict(type=Record.NS, value=ns))
|
||||
records.append(AttrDict(
|
||||
type=Record.NS,
|
||||
value=ns
|
||||
))
|
||||
if Record.SOA not in types:
|
||||
soa = [
|
||||
"%s." % settings.DOMAINS_DEFAULT_NAME_SERVER,
|
||||
|
@ -109,27 +120,42 @@ class Domain(models.Model):
|
|||
settings.DOMAINS_DEFAULT_EXPIRATION,
|
||||
settings.DOMAINS_DEFAULT_MIN_CACHING_TIME
|
||||
]
|
||||
records.insert(0, AttrDict(type=Record.SOA, value=' '.join(soa)))
|
||||
records.insert(0, AttrDict(
|
||||
type=Record.SOA,
|
||||
value=' '.join(soa)
|
||||
))
|
||||
is_a = not types or Record.A in types or Record.AAAA in types
|
||||
if Record.MX not in types and is_a:
|
||||
for mx in settings.DOMAINS_DEFAULT_MX:
|
||||
records.append(AttrDict(type=Record.MX, value=mx))
|
||||
records.append(AttrDict(
|
||||
type=Record.MX,
|
||||
value=mx
|
||||
))
|
||||
if (Record.A not in types and Record.AAAA not in types) and is_a:
|
||||
records.append(AttrDict(type=Record.A, value=settings.DOMAINS_DEFAULT_A))
|
||||
records.append(AttrDict(
|
||||
type=Record.A,
|
||||
value=settings.DOMAINS_DEFAULT_A
|
||||
))
|
||||
result = ''
|
||||
for record in records:
|
||||
name = '{name}.{spaces}'.format(
|
||||
name=self.name, spaces=' ' * (37-len(self.name))
|
||||
name=self.name,
|
||||
spaces=' ' * (37-len(self.name))
|
||||
)
|
||||
ttl = record.get('ttl', settings.DOMAINS_DEFAULT_TTL)
|
||||
ttl = '{spaces}{ttl}'.format(
|
||||
spaces=' ' * (7-len(ttl)), ttl=ttl
|
||||
spaces=' ' * (7-len(ttl)),
|
||||
ttl=ttl
|
||||
)
|
||||
type = '{type} {spaces}'.format(
|
||||
type=record.type, spaces=' ' * (7-len(record.type))
|
||||
type=record.type,
|
||||
spaces=' ' * (7-len(record.type))
|
||||
)
|
||||
result += '{name} {ttl} IN {type} {value}\n'.format(
|
||||
name=name, ttl=ttl, type=type, value=record.value
|
||||
name=name,
|
||||
ttl=ttl,
|
||||
type=type,
|
||||
value=record.value
|
||||
)
|
||||
return result
|
||||
|
||||
|
|
|
@ -39,13 +39,7 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
""" Checks if everything is consistent """
|
||||
instance = super(DomainSerializer, self).full_clean(instance)
|
||||
if instance and instance.name:
|
||||
records = self.init_data['records']
|
||||
records = self.init_data.get('records', [])
|
||||
domain = domain_for_validation(instance, records)
|
||||
try:
|
||||
validators.validate_zone(domain.render_zone())
|
||||
except ValidationError as err:
|
||||
self._errors = {
|
||||
'all': err.message
|
||||
}
|
||||
return None
|
||||
validators.validate_zone(domain.render_zone())
|
||||
return instance
|
||||
|
|
|
@ -51,7 +51,7 @@ class Miscellaneous(models.Model):
|
|||
verbose_name_plural = _("miscellaneous")
|
||||
|
||||
def __unicode__(self):
|
||||
return self.identifier or str(self.service)
|
||||
return self.identifier or self.description[:32] or str(self.service)
|
||||
|
||||
@cached_property
|
||||
def active(self):
|
||||
|
|
|
@ -21,7 +21,9 @@ from .models import SystemUser
|
|||
|
||||
|
||||
class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
list_display = ('username', 'account_link', 'shell', 'display_home', 'display_active', 'display_main')
|
||||
list_display = (
|
||||
'username', 'account_link', 'shell', 'display_home', 'display_active', 'display_main'
|
||||
)
|
||||
list_filter = ('is_active', 'shell', IsMainListFilter)
|
||||
fieldsets = (
|
||||
(None, {
|
||||
|
|
|
@ -24,8 +24,9 @@ class SystemUser(models.Model):
|
|||
""" System users """
|
||||
username = models.CharField(_("username"), max_length=64, unique=True,
|
||||
help_text=_("Required. 64 characters or fewer. Letters, digits and ./-/_ only."),
|
||||
validators=[validators.RegexValidator(r'^[\w.-]+$',
|
||||
_("Enter a valid username."), 'invalid')])
|
||||
validators=[
|
||||
validators.RegexValidator(r'^[\w.-]+$', _("Enter a valid username."))
|
||||
])
|
||||
password = models.CharField(_("password"), max_length=128)
|
||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
||||
related_name='systemusers')
|
||||
|
@ -82,7 +83,10 @@ class SystemUser(models.Model):
|
|||
return settings.SYSTEMUSERS_HOME % context
|
||||
|
||||
def get_home(self):
|
||||
return os.path.join(self.home or self.get_base_home(), self.directory)
|
||||
return os.path.join(
|
||||
self.home or self.get_base_home(),
|
||||
self.directory
|
||||
)
|
||||
|
||||
|
||||
services.register(SystemUser)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
from ..utils.python import AttrDict
|
||||
|
||||
|
||||
class Register(object):
|
||||
def __init__(self):
|
||||
self._registry = {}
|
||||
|
@ -5,17 +8,22 @@ class Register(object):
|
|||
def __contains__(self, key):
|
||||
return key in self._registry
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._registry[key]
|
||||
|
||||
def register(self, model, **kwargs):
|
||||
if model in self._registry:
|
||||
raise KeyError("%s already registered" % str(model))
|
||||
plural = kwargs.get('verbose_name_plural', model._meta.verbose_name_plural)
|
||||
self._registry[model] = {
|
||||
self._registry[model] = AttrDict(**{
|
||||
'verbose_name': kwargs.get('verbose_name', model._meta.verbose_name),
|
||||
'verbose_name_plural': plural,
|
||||
'menu': kwargs.get('menu', True)
|
||||
}
|
||||
})
|
||||
|
||||
def get(self):
|
||||
def get(self, *args):
|
||||
if args:
|
||||
return self._registry[arg[0]]
|
||||
return self._registry
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue