diff --git a/TODO.md b/TODO.md
index 135d1726..7a3ab562 100644
--- a/TODO.md
+++ b/TODO.md
@@ -437,3 +437,11 @@ mkhomedir_helper or create ssh homes with bash.rc and such
# Warning websites with ssl options without https protocol
# Schedule cancellation
+
+# Multiple domains wordpress
+
+# TODO: separate ports for fpm version
+
+# Reversion
+# implement re-enable account
+# Disable/enable saas and VPS
diff --git a/orchestra/admin/actions.py b/orchestra/admin/actions.py
index 8b15ff3a..e97d7e40 100644
--- a/orchestra/admin/actions.py
+++ b/orchestra/admin/actions.py
@@ -1,3 +1,5 @@
+from functools import partial
+
from django.contrib import admin
from django.core.mail import send_mass_mail
from django.shortcuts import render
@@ -108,23 +110,36 @@ class SendEmail(object):
return render(request, self.template, self.context)
-@action_with_confirmation()
-def disable(modeladmin, request, queryset):
+def base_disable(modeladmin, request, queryset, disable=True):
num = 0
+ action_name = _("disabled") if disable else _("enabled")
for obj in queryset:
- obj.disable()
- modeladmin.log_change(request, obj, _("Disabled"))
+ obj.disable() if disable else obj.enable()
+ modeladmin.log_change(request, obj, action_name.capitalize())
num += 1
opts = modeladmin.model._meta
context = {
+ 'action_name': action_name,
'verbose_name': opts.verbose_name,
'verbose_name_plural': opts.verbose_name_plural,
'num': num
}
msg = ungettext(
- _("Selected %(verbose_name)s and related services has been disabled.") % context,
- _("%(num)s selected %(verbose_name_plural)s and related services have been disabled.") % context,
+ _("Selected %(verbose_name)s and related services has been %(action_name)s.") % context,
+ _("%(num)s selected %(verbose_name_plural)s and related services have been %(action_name)s.") % context,
num)
modeladmin.message_user(request, msg)
+
+
+@action_with_confirmation()
+def disable(modeladmin, request, queryset):
+ return base_disable(modeladmin, request, queryset)
disable.url_name = 'disable'
disable.short_description = _("Disable")
+
+
+@action_with_confirmation()
+def enable(modeladmin, request, queryset):
+ return base_disable(modeladmin, request, queryset, disable=False)
+enable.url_name = 'enable'
+enable.short_description = _("Enable")
diff --git a/orchestra/admin/options.py b/orchestra/admin/options.py
index c9a63fcd..50361e18 100644
--- a/orchestra/admin/options.py
+++ b/orchestra/admin/options.py
@@ -149,7 +149,7 @@ class ChangeViewActionsMixin(object):
kwargs['extra_context']['object_tools_items'] = [
action.__dict__ for action in self.get_change_view_actions(obj)
]
- return super(ChangeViewActionsMixin, self).change_view(request, object_id, **kwargs)
+ return super().change_view(request, object_id, **kwargs)
class ChangeAddFieldsMixin(object):
diff --git a/orchestra/contrib/accounts/actions.py b/orchestra/contrib/accounts/actions.py
index 2dc16117..f05b610a 100644
--- a/orchestra/contrib/accounts/actions.py
+++ b/orchestra/contrib/accounts/actions.py
@@ -1,3 +1,5 @@
+from functools import partial, wraps
+
from django.contrib import messages
from django.contrib.admin import helpers
from django.contrib.admin.utils import NestedObjects, quote
@@ -186,21 +188,21 @@ def delete_related_services(modeladmin, request, queryset):
delete_related_services.short_description = _("Delete related services")
-def disable_selected(modeladmin, request, queryset):
+def disable_selected(modeladmin, request, queryset, disable=True):
opts = modeladmin.model._meta
app_label = opts.app_label
-
+ verbose_action_name = _("disabled") if disable else _("enabled")
# The user has already confirmed the deletion.
# Do the disable and return a None to display the change list view again.
if request.POST.get('post'):
n = 0
for account in queryset:
- account.disable()
- modeladmin.log_change(request, account, _("Disabled"))
+ account.disable() if disable else account.enable()
+ modeladmin.log_change(request, account, verbose_action_name.capitalize())
n += 1
modeladmin.message_user(request, ungettext(
- _("One account has been successfully disabled."),
- _("%i accounts have been successfully disabled.") % n,
+ _("One account has been successfully %s.") % verbose_action_name,
+ _("%i accounts have been successfully %s.") % (n, verbose_action_name),
n)
)
return None
@@ -248,6 +250,8 @@ def disable_selected(modeladmin, request, queryset):
context = dict(
admin_site.each_context(request),
+ action_name='disable_selected' if disable else 'enable_selected',
+ disable=disable,
title=_("Are you sure?"),
objects_name=objects_name,
deletable_objects=display,
@@ -259,5 +263,11 @@ def disable_selected(modeladmin, request, queryset):
template = 'admin/%s/%s/disable_selected_confirmation.html' % (app_label, opts.model_name)
return TemplateResponse(request, template, context)
disable_selected.short_description = _("Disable selected accounts")
-disable_selected.url = 'disable'
+disable_selected.url_name = 'disable'
disable_selected.tool_description = _("Disable")
+
+
+enable_selected = partial(disable_selected, disable=False)
+enable_selected.__name__ = 'enable_selected'
+enable_selected.url_name = 'enable'
+enable_selected.tool_description = _("Enable")
diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py
index 5abb40d7..f9f039e1 100644
--- a/orchestra/contrib/accounts/admin.py
+++ b/orchestra/contrib/accounts/admin.py
@@ -20,7 +20,8 @@ from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query
from orchestra.core import services, accounts
from orchestra.forms import UserChangeForm
-from .actions import list_contacts, service_report, delete_related_services, disable_selected
+from .actions import (list_contacts, service_report, delete_related_services, disable_selected,
+ enable_selected)
from .filters import HasMainUserListFilter
from .forms import AccountCreationForm
from .models import Account
@@ -64,9 +65,10 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
change_readonly_fields = ('username', 'main_systemuser_link', 'is_active')
change_form_template = 'admin/accounts/account/change_form.html'
actions = (
- disable_selected, delete_related_services, list_contacts, service_report, SendEmail()
+ disable_selected, enable_selected, delete_related_services, list_contacts, service_report,
+ SendEmail()
)
- change_view_actions = (disable_selected, service_report)
+ change_view_actions = (disable_selected, service_report, enable_selected)
ordering = ()
main_systemuser_link = admin_link('main_systemuser')
@@ -111,6 +113,14 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
else:
super(AccountAdmin, self).save_model(request, obj, form, change)
+ def get_change_view_actions(self, obj=None):
+ views = super().get_change_view_actions(obj=obj)
+ if obj is not None:
+ if obj.is_active:
+ return [view for view in views if view.url_name != 'enable']
+ return [view for view in views if view.url_name != 'disable']
+ return views
+
def get_actions(self, request):
actions = super(AccountAdmin, self).get_actions(request)
if 'delete_selected' in actions:
diff --git a/orchestra/contrib/accounts/models.py b/orchestra/contrib/accounts/models.py
index a0d264e6..3fe5327a 100644
--- a/orchestra/contrib/accounts/models.py
+++ b/orchestra/contrib/accounts/models.py
@@ -83,6 +83,11 @@ class Account(auth.AbstractBaseUser):
self.save(update_fields=('is_active',))
self.notify_related()
+ def enable(self):
+ self.is_active = True
+ self.save(update_fields=('is_active',))
+ self.notify_related()
+
def get_services_to_disable(self):
for rel in self._meta.get_all_related_objects():
source = getattr(rel, 'related_model', rel.model)
diff --git a/orchestra/contrib/accounts/templates/admin/accounts/account/disable_selected_confirmation.html b/orchestra/contrib/accounts/templates/admin/accounts/account/disable_selected_confirmation.html
index 0479bc20..7ada7249 100644
--- a/orchestra/contrib/accounts/templates/admin/accounts/account/disable_selected_confirmation.html
+++ b/orchestra/contrib/accounts/templates/admin/accounts/account/disable_selected_confirmation.html
@@ -8,42 +8,28 @@
{% trans 'Home' %}
› {{ opts.app_config.verbose_name }}
› {{ opts.verbose_name_plural|capfirst }}
-› {% trans 'Disable accounts' %}
+› {% if disable%}{% blocktrans %}Disable {{ objects_name }}{% endblocktrans %}{% else %}{% blocktrans %}Enable {{ objects_name }}{% endblocktrans %}{% endif %}
{% endblock %}
{% block content %}
-{% if perms_lacking %}
-
{% blocktrans %}Disabling the selected {{ objects_name }} would result in disabling related objects, but your account doesn't have permission to disable the following types of objects:{% endblocktrans %}
-
- {% for obj in perms_lacking %}
-
{{ obj }}
- {% endfor %}
-
-{% elif protected %}
-
{% blocktrans %}Deleting the selected {{ objects_name }} would require deleting the following protected related objects:{% endblocktrans %}
-
- {% for obj in protected %}
-
{{ obj }}
- {% endfor %}
-
-{% else %}
-
{% blocktrans %}Are you sure you want to disable the selected {{ objects_name }}? All of the following objects and their related items will be disabled:{% endblocktrans %}
-
{% trans "Objects" %}
- {% for deletable_object in deletable_objects %}
-
{{ deletable_object|unordered_list }}
- {% endfor %}
-
+{% if disable%}
{% blocktrans %}Are you sure you want to disable selected {{ objects_name }}?{% endblocktrans %}
+{% else %}
{% blocktrans %}Are you sure you want to enable selected {{ objects_name }}?{% endblocktrans %}
{% endif %}
+
{% trans "Objects" %}
+{% for deletable_object in deletable_objects %}
+