Implemented enable admin action0
This commit is contained in:
parent
6a34ba8fd2
commit
4adfd4c83a
8
TODO.md
8
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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -8,42 +8,28 @@
|
|||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
|
||||
› {% trans 'Disable accounts' %}
|
||||
› {% if disable%}{% blocktrans %}Disable {{ objects_name }}{% endblocktrans %}{% else %}{% blocktrans %}Enable {{ objects_name }}{% endblocktrans %}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if perms_lacking %}
|
||||
<p>{% 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 %}</p>
|
||||
<ul>
|
||||
{% for obj in perms_lacking %}
|
||||
<li>{{ obj }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% elif protected %}
|
||||
<p>{% blocktrans %}Deleting the selected {{ objects_name }} would require deleting the following protected related objects:{% endblocktrans %}</p>
|
||||
<ul>
|
||||
{% for obj in protected %}
|
||||
<li>{{ obj }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{% 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 %}</p>
|
||||
<h2>{% trans "Objects" %}</h2>
|
||||
{% for deletable_object in deletable_objects %}
|
||||
<ul>{{ deletable_object|unordered_list }}</ul>
|
||||
{% endfor %}
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<div>
|
||||
{% for obj in queryset %}
|
||||
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
||||
{% endfor %}
|
||||
<input type="hidden" name="action" value="disable_selected" />
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% if disable%}<p>{% blocktrans %}Are you sure you want to disable selected {{ objects_name }}?{% endblocktrans %}</p>
|
||||
{% else %}<p>{% blocktrans %}Are you sure you want to enable selected {{ objects_name }}?{% endblocktrans %}</p>
|
||||
{% endif %}
|
||||
<h2>{% trans "Objects" %}</h2>
|
||||
{% for deletable_object in deletable_objects %}
|
||||
<ul>{{ deletable_object|unordered_list }}</ul>
|
||||
{% endfor %}
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<div>
|
||||
{% for obj in queryset %}
|
||||
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
||||
{% endfor %}
|
||||
<input type="hidden" name="action" value="{{ action_name }}" />
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
state = bill.get_payment_state_display().upper()
|
||||
title = ''
|
||||
if bill.closed_amends:
|
||||
state += '*'
|
||||
state = '<strike>%s*</strike>' % state
|
||||
title = _("This bill has been amended, this value may not be valid.")
|
||||
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
||||
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
|
||||
|
|
|
@ -78,7 +78,10 @@ class Domain(models.Model):
|
|||
@property
|
||||
def is_top(self):
|
||||
# don't cache, don't replace by top_id
|
||||
return not bool(self.top)
|
||||
try:
|
||||
return not bool(self.top)
|
||||
except Domain.DoesNotExist:
|
||||
return False
|
||||
|
||||
@property
|
||||
def subdomains(self):
|
||||
|
|
|
@ -11,7 +11,7 @@ from .helpers import markdown_formated_changes
|
|||
from .models import Queue, Ticket
|
||||
|
||||
|
||||
def change_ticket_state_factory(action, final_state):
|
||||
def change_ticket_state_factory(action, verbose_name, final_state):
|
||||
context = {
|
||||
'action': action,
|
||||
'form': ChangeReasonForm()
|
||||
|
@ -40,30 +40,31 @@ def change_ticket_state_factory(action, final_state):
|
|||
'count': queryset.count(),
|
||||
'state': final_state.lower()
|
||||
}
|
||||
msg = _("%s selected tickets are now %s.") % context
|
||||
msg = _("%(count)s selected tickets are now %(state)s.") % context
|
||||
modeladmin.message_user(request, msg)
|
||||
else:
|
||||
context['form'] = form
|
||||
# action_with_confirmation must display form validation errors
|
||||
return True
|
||||
change_ticket_state.url_name = action
|
||||
change_ticket_state.verbose_name = action
|
||||
change_ticket_state.short_description = _('%s selected tickets') % action.capitalize()
|
||||
change_ticket_state.tool_description = verbose_name
|
||||
change_ticket_state.short_description = _('%s selected tickets') % verbose_name
|
||||
change_ticket_state.help_text = _('Mark ticket as %s.') % final_state.lower()
|
||||
change_ticket_state.__name__ = action
|
||||
return change_ticket_state
|
||||
|
||||
|
||||
action_map = {
|
||||
Ticket.RESOLVED: 'resolve',
|
||||
Ticket.REJECTED: 'reject',
|
||||
Ticket.CLOSED: 'close'
|
||||
Ticket.RESOLVED: ('resolve', _("Resolve")),
|
||||
Ticket.REJECTED: ('reject', _("Reject")),
|
||||
Ticket.CLOSED: ('close', _("Close")),
|
||||
}
|
||||
|
||||
|
||||
thismodule = sys.modules[__name__]
|
||||
for state, name in action_map.items():
|
||||
action = change_ticket_state_factory(name, state)
|
||||
for state, names in action_map.items():
|
||||
name, verbose_name = names
|
||||
action = change_ticket_state_factory(name, verbose_name, state)
|
||||
setattr(thismodule, '%s_tickets' % name, action)
|
||||
|
||||
|
||||
|
@ -89,6 +90,7 @@ def take_tickets(modeladmin, request, queryset):
|
|||
msg = _("%(count)s selected tickets are now owned by %(user)s.") % context
|
||||
modeladmin.message_user(request, msg)
|
||||
take_tickets.url_name = 'take'
|
||||
take_tickets.tool_description = _("Take")
|
||||
take_tickets.short_description = _("Take selected tickets")
|
||||
take_tickets.help_text = _("Make yourself owner of the ticket.")
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ class MessageReadOnlyInline(admin.TabularInline):
|
|||
content_html.short_description = _("Content")
|
||||
content_html.allow_tags = True
|
||||
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
|
@ -125,11 +124,10 @@ class TicketAdmin(ExtendedModelAdmin):
|
|||
)
|
||||
list_display_links = ('unbold_id', 'bold_subject')
|
||||
list_filter = (
|
||||
MyTicketsListFilter, 'queue__name', 'priority', TicketStateListFilter,
|
||||
MyTicketsListFilter, 'queue', 'priority', TicketStateListFilter,
|
||||
)
|
||||
default_changelist_filters = (
|
||||
('my_tickets', lambda r: 'True' if not r.user.is_superuser else 'False'),
|
||||
('state', 'OPEN')
|
||||
('state', 'OPEN'),
|
||||
)
|
||||
date_hierarchy = 'created_at'
|
||||
search_fields = (
|
||||
|
@ -298,7 +296,7 @@ class QueueAdmin(admin.ModelAdmin):
|
|||
def num_tickets(self, queue):
|
||||
num = queue.tickets__count
|
||||
url = reverse('admin:issues_ticket_changelist')
|
||||
url += '?my_tickets=False&queue=%i' % queue.pk
|
||||
url += '?queue=%i' % queue.pk
|
||||
return '<a href="%s">%d</a>' % (url, num)
|
||||
num_tickets.short_description = _("Tickets")
|
||||
num_tickets.admin_order_field = 'tickets__count'
|
||||
|
|
|
@ -12,19 +12,12 @@ class MyTicketsListFilter(SimpleListFilter):
|
|||
def lookups(self, request, model_admin):
|
||||
return (
|
||||
('True', _("My Tickets")),
|
||||
('False', _("All")),
|
||||
)
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
if self.value() == 'True':
|
||||
return queryset.involved_by(request.user)
|
||||
|
||||
def choices(self, cl):
|
||||
""" Remove default All """
|
||||
choices = iter(super(MyTicketsListFilter, self).choices(cl))
|
||||
next(choices)
|
||||
return choices
|
||||
|
||||
|
||||
class TicketStateListFilter(SimpleListFilter):
|
||||
title = 'State'
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import datetime
|
||||
from django.utils.timezone import utc
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('issues', '0002_auto_20150709_1018'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='message',
|
||||
name='created_on',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 20, 10, 27, 45, 766388, tzinfo=utc), verbose_name='created at'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,5 +1,6 @@
|
|||
from django.conf import settings as djsettings
|
||||
from django.db import models
|
||||
from django.db.models import query, Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.contrib.contacts import settings as contacts_settings
|
||||
|
@ -32,6 +33,12 @@ class Queue(models.Model):
|
|||
super(Queue, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TicketQuerySet(query.QuerySet):
|
||||
def involved_by(self, user, *args, **kwargs):
|
||||
qset = Q(creator=user) | Q(owner=user) | Q(messages__author=user)
|
||||
return self.filter(qset, *args, **kwargs).distinct()
|
||||
|
||||
|
||||
class Ticket(models.Model):
|
||||
HIGH = 'HIGH'
|
||||
MEDIUM = 'MEDIUM'
|
||||
|
@ -65,13 +72,13 @@ class Ticket(models.Model):
|
|||
queue = models.ForeignKey(Queue, related_name='tickets', null=True, blank=True)
|
||||
subject = models.CharField(_("subject"), max_length=256)
|
||||
description = models.TextField(_("description"))
|
||||
priority = models.CharField(_("priority"), max_length=32, choices=PRIORITIES,
|
||||
default=MEDIUM)
|
||||
priority = models.CharField(_("priority"), max_length=32, choices=PRIORITIES, default=MEDIUM)
|
||||
state = models.CharField(_("state"), max_length=32, choices=STATES, default=NEW)
|
||||
created_at = models.DateTimeField(_("created"), auto_now_add=True, db_index=True)
|
||||
updated_at = models.DateTimeField(_("modified"), auto_now=True)
|
||||
cc = models.TextField("CC", help_text=_("emails to send a carbon copy to"),
|
||||
blank=True)
|
||||
cc = models.TextField("CC", help_text=_("emails to send a carbon copy to"), blank=True)
|
||||
|
||||
objects = TicketQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
ordering = ['-updated_at']
|
||||
|
@ -158,7 +165,7 @@ class Message(models.Model):
|
|||
related_name='ticket_messages')
|
||||
author_name = models.CharField(_("author name"), max_length=256, blank=True)
|
||||
content = models.TextField(_("content"))
|
||||
created_on = models.DateTimeField(_("created on"), auto_now_add=True)
|
||||
created_at = models.DateTimeField(_("created at"), auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
get_latest_by = 'id'
|
||||
|
|
|
@ -13,8 +13,8 @@ class QueueSerializer(serializers.HyperlinkedModelSerializer):
|
|||
class MessageSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = Message
|
||||
fields = ('id', 'author', 'author_name', 'content', 'created_on')
|
||||
read_only_fields = ('author', 'author_name', 'created_on')
|
||||
fields = ('id', 'author', 'author_name', 'content', 'created_at')
|
||||
read_only_fields = ('author', 'author_name', 'created_at')
|
||||
|
||||
def get_identity(self, data):
|
||||
return data.get('id')
|
||||
|
|
|
@ -18,7 +18,7 @@ Issue #{{ ticket.id }} has been updated by {{ ticket_message.author }}.
|
|||
-----------------------------------------------------------------
|
||||
Issue #{{ ticket.pk }}: {{ ticket.subject }}
|
||||
|
||||
* Author: {{ ticket.created_by }}
|
||||
* Author: {{ ticket.creator_name }}
|
||||
* Status: {{ ticket.get_state_display }}
|
||||
* Priority: {{ ticket.get_priority_display }}
|
||||
* Visibility: {{ ticket.get_visibility_display }}
|
||||
|
|
|
@ -41,7 +41,7 @@ Issue #{{ ticket.id }} has been updated by {{ ticket_message.author }}.
|
|||
<h1><a href="http://{{ site.domain }}{% url 'admin:issues_ticket_change' ticket.id %}">Issue #{{ ticket.pk }}: {{ ticket.subject }}</a></h1>
|
||||
|
||||
<ul>
|
||||
<li>Author: {{ ticket.created_by }}</li>
|
||||
<li>Author: {{ ticket.creator_name }}</li>
|
||||
<li>Status: {{ ticket.get_state_display }}</li>
|
||||
<li>Priority: {{ ticket.get_priority_display }}</li>
|
||||
<li>Visibility: {{ ticket.get_visibility_display }}</li>
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib.auth.admin import UserAdmin
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable
|
||||
from orchestra.admin.actions import disable, enable
|
||||
from orchestra.admin.utils import admin_link
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||
|
@ -58,7 +58,7 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
|
|||
add_form = ListCreationForm
|
||||
list_select_related = ('account', 'address_domain',)
|
||||
filter_by_account_fields = ['address_domain']
|
||||
actions = (disable, list_accounts)
|
||||
actions = (disable, enable, list_accounts)
|
||||
|
||||
address_domain_link = admin_link('address_domain', order='address_domain__name')
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.utils.safestring import mark_safe
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable
|
||||
from orchestra.admin.actions import disable, enable
|
||||
from orchestra.admin.utils import admin_link, change_url
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||
|
@ -74,7 +74,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
|||
add_form = MailboxCreationForm
|
||||
form = MailboxChangeForm
|
||||
list_prefetch_related = ('addresses__domain',)
|
||||
actions = (disable, list_accounts)
|
||||
actions = (disable, enable, list_accounts)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MailboxAdmin, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable
|
||||
from orchestra.admin.actions import disable, enable
|
||||
from orchestra.admin.utils import change_url
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||
|
@ -24,7 +24,7 @@ class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMi
|
|||
plugin = SoftwareService
|
||||
plugin_field = 'service'
|
||||
plugin_title = 'Software as a Service'
|
||||
actions = (disable, list_accounts)
|
||||
actions = (disable, enable, list_accounts)
|
||||
|
||||
def display_url(self, saas):
|
||||
site_domain = saas.get_site_domain()
|
||||
|
|
|
@ -21,6 +21,7 @@ class DrupalMuController(ServiceController):
|
|||
|
||||
def save(self, webapp):
|
||||
context = self.get_context(webapp)
|
||||
# TODO set password
|
||||
self.append(textwrap.dedent("""\
|
||||
mkdir %(drupal_path)s
|
||||
chown -R www-data %(drupal_path)s
|
||||
|
@ -35,6 +36,7 @@ class DrupalMuController(ServiceController):
|
|||
|
||||
def delete(self, webapp):
|
||||
context = self.get_context(webapp)
|
||||
# TODO delete tables
|
||||
self.append("rm -fr %(app_path)s" % context)
|
||||
|
||||
def get_context(self, webapp):
|
||||
|
|
|
@ -22,8 +22,9 @@ class WordpressMuController(ServiceController):
|
|||
model = 'saas.SaaS'
|
||||
default_route_match = "saas.service == 'wordpress'"
|
||||
doc_settings = (settings,
|
||||
('SAAS_WORDPRESS_ADMIN_PASSWORD', 'SAAS_WORDPRESS_MAIN_URL')
|
||||
('SAAS_WORDPRESS_ADMIN_PASSWORD', 'SAAS_WORDPRESS_MAIN_URL', 'SAAS_WORDPRESS_VERIFY_SSL')
|
||||
)
|
||||
VERIFY = settings.SAAS_WORDPRESS_VERIFY_SSL
|
||||
|
||||
def login(self, session):
|
||||
main_url = self.get_main_url()
|
||||
|
@ -33,9 +34,10 @@ class WordpressMuController(ServiceController):
|
|||
'pwd': settings.SAAS_WORDPRESS_ADMIN_PASSWORD,
|
||||
'redirect_to': '/wp-admin/'
|
||||
}
|
||||
response = session.post(login_url, data=login_data)
|
||||
sys.stdout.write("Login URL: %s\n" % login_url)
|
||||
response = session.post(login_url, data=login_data, verify=self.VERIFY)
|
||||
if response.url != main_url + '/wp-admin/':
|
||||
raise IOError("Failure login to remote application")
|
||||
raise IOError("Failure login to remote application (%s)" % login_url)
|
||||
|
||||
def get_main_url(self):
|
||||
main_url = settings.SAAS_WORDPRESS_MAIN_URL
|
||||
|
@ -54,7 +56,8 @@ class WordpressMuController(ServiceController):
|
|||
'<a href="http://[\.\-\w]+/wp-admin/network/site-info\.php\?id=([0-9]+)"\s+'
|
||||
'class="edit">%s</a>' % saas.name
|
||||
)
|
||||
content = session.get(search).content.decode('utf8')
|
||||
sys.stdout.write("Search URL: %s\n" % search)
|
||||
content = session.get(search, verify=self.VERIFY).content.decode('utf8')
|
||||
# Get id
|
||||
ids = regex.search(content)
|
||||
if not ids and not blog_id:
|
||||
|
@ -85,7 +88,8 @@ class WordpressMuController(ServiceController):
|
|||
except RuntimeError:
|
||||
url = self.get_main_url()
|
||||
url += '/wp-admin/network/site-new.php'
|
||||
content = session.get(url).content.decode('utf8')
|
||||
sys.stdout.write("Create URL: %s\n" % url)
|
||||
content = session.get(url, verify=self.VERIFY).content.decode('utf8')
|
||||
|
||||
wpnonce = re.compile('name="_wpnonce_add-blog"\s+value="([^"]*)"')
|
||||
wpnonce = wpnonce.search(content).groups()[0]
|
||||
|
@ -99,7 +103,7 @@ class WordpressMuController(ServiceController):
|
|||
}
|
||||
|
||||
# Validate response
|
||||
response = session.post(url, data=data)
|
||||
response = session.post(url, data=data, verify=self.VERIFY)
|
||||
self.validate_response(response)
|
||||
blog_id = re.compile(r'<link id="wp-admin-canonical" rel="canonical" href="http(?:[^ ]+)/wp-admin/network/site-new.php\?id=([0-9]+)" />')
|
||||
content = response.content.decode('utf8')
|
||||
|
@ -124,8 +128,9 @@ class WordpressMuController(ServiceController):
|
|||
delete = self.get_main_url()
|
||||
delete += '/wp-admin/network/sites.php?action=confirm&action2=deleteblog'
|
||||
delete += '&id=%d&_wpnonce=%s' % (id, wpnonce)
|
||||
sys.stdout.write("Search URL: %s\n" % delete)
|
||||
|
||||
content = session.get(delete).content.decode('utf8')
|
||||
content = session.get(delete, verify=self.VERIFY).content.decode('utf8')
|
||||
wpnonce = re.compile('name="_wpnonce"\s+value="([^"]*)"')
|
||||
wpnonce = wpnonce.search(content).groups()[0]
|
||||
data = {
|
||||
|
@ -136,7 +141,8 @@ class WordpressMuController(ServiceController):
|
|||
}
|
||||
delete = self.get_main_url()
|
||||
delete += '/wp-admin/network/sites.php?action=deleteblog'
|
||||
response = session.post(delete, data=data)
|
||||
sys.stdout.write("Delete URL: %s\n" % delete)
|
||||
response = session.post(delete, data=data, verify=self.VERIFY)
|
||||
self.validate_response(response)
|
||||
|
||||
def save(self, saas):
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
from .options import SoftwareService
|
||||
|
||||
from .. import settings
|
||||
|
||||
|
||||
class DrupalService(SoftwareService):
|
||||
name = 'drupal'
|
||||
verbose_name = "Drupal"
|
||||
icon = 'orchestra/icons/apps/Drupal.png'
|
||||
site_domain = settings.SAAS_MOODLE_DOMAIN
|
||||
|
|
|
@ -65,6 +65,11 @@ SAAS_WORDPRESS_DB_NAME = Setting('SAAS_WORDPRESS_DB_NAME',
|
|||
help_text=_("Needed for domain mapping when <tt>SAAS_WORDPRESS_ALLOW_CUSTOM_URL</tt> is enabled."),
|
||||
)
|
||||
|
||||
SAAS_WORDPRESS_VERIFY_SSL = Setting('SAAS_WORDPRESS_VERIFY_SSL',
|
||||
True,
|
||||
help_text=_("Verify SSL certificate on the HTTP requests performed by the backend."),
|
||||
)
|
||||
|
||||
|
||||
# DokuWiki
|
||||
|
||||
|
@ -119,6 +124,11 @@ SAAS_DRUPAL_SITES_PATH = Setting('WEBSITES_DRUPAL_SITES_PATH',
|
|||
'/home/httpd/htdocs/drupal-mu/sites/%(site_name)s',
|
||||
)
|
||||
|
||||
SAAS_DRUPAL_DOMAIN = Setting('SAAS_DRUPAL_DOMAIN',
|
||||
'%(site_name)s.drupal.{}'.format(ORCHESTRA_BASE_DOMAIN),
|
||||
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default.",
|
||||
)
|
||||
|
||||
|
||||
# PhpList
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.contrib import admin
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import disable, enable
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
||||
|
@ -42,7 +43,7 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende
|
|||
form = SystemUserChangeForm
|
||||
ordering = ('-id',)
|
||||
change_view_actions = (set_permission, create_link)
|
||||
actions = (delete_selected, list_accounts) + change_view_actions
|
||||
actions = (disable, enable, delete_selected, list_accounts) + change_view_actions
|
||||
|
||||
def display_main(self, user):
|
||||
return user.is_main
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.utils.encoding import force_text
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.actions import disable
|
||||
from orchestra.admin.actions import disable, enable
|
||||
from orchestra.admin.utils import admin_link, change_url
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
||||
|
@ -76,7 +76,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
filter_by_account_fields = ['domains']
|
||||
list_prefetch_related = ('domains', 'content_set__webapp')
|
||||
search_fields = ('name', 'account__username', 'domains__name', 'content__webapp__name')
|
||||
actions = (disable, list_accounts)
|
||||
actions = (disable, enable, list_accounts)
|
||||
|
||||
def display_domains(self, website):
|
||||
domains = []
|
||||
|
|
Loading…
Reference in New Issue