Added account report
This commit is contained in:
parent
7382018f94
commit
e962e5d7b2
31
TODO.md
31
TODO.md
|
@ -14,35 +14,17 @@
|
||||||
* use Code: https://github.com/django/django/blob/master/django/forms/forms.py#L415 for domain.refresh_serial()
|
* use Code: https://github.com/django/django/blob/master/django/forms/forms.py#L415 for domain.refresh_serial()
|
||||||
* Permissions .filter_queryset()
|
* Permissions .filter_queryset()
|
||||||
|
|
||||||
* git deploy in addition to FTP?
|
|
||||||
* env vars instead of multiple settings files: https://devcenter.heroku.com/articles/config-vars ?
|
* env vars instead of multiple settings files: https://devcenter.heroku.com/articles/config-vars ?
|
||||||
* optional chroot shell?
|
|
||||||
|
|
||||||
* make sure prefetch_related() is used correctly
|
|
||||||
Remember that, as always with QuerySets, any subsequent chained methods which imply a different database query will ignore previously cached results, and retrieve data using a fresh database query.
|
|
||||||
* profile select_related vs prefetch_related
|
|
||||||
|
|
||||||
|
|
||||||
* Log changes from rest api (serialized objects)
|
* Log changes from rest api (serialized objects)
|
||||||
* passlib; nano /usr/local/lib/python2.7/dist-packages/passlib/ext/django/utils.py SortedDict -> collections.OrderedDict
|
|
||||||
* pip install pyinotify
|
|
||||||
|
|
||||||
* Timezone awareness on monitoring system (reading server-side logs with different TZ than orchestra) maybe a settings value? (use UTC internally, timezone.localtime() when interacting with servers)
|
|
||||||
|
|
||||||
* EMAIL backend operations which contain stderr messages (because under certain failures status code is still 0)
|
* EMAIL backend operations which contain stderr messages (because under certain failures status code is still 0)
|
||||||
|
|
||||||
* Settings dictionary like DRF2 in order to better override large settings like WEBSITES_APPLICATIONS.etc
|
* Settings dictionary like DRF2 in order to better override large settings like WEBSITES_APPLICATIONS.etc
|
||||||
|
|
||||||
* DOCUMENT: orchestration.middleware: we need to know when an operation starts and ends in order to perform bulk server updates and also to wait for related objects to be saved (base object is saved first and then related)
|
|
||||||
orders.signales: we perform changes right away because data model state can change under monitoring and other periodik task, and we should keep orders consistency under any situation.
|
|
||||||
dependency collector with max_recursion that matches the number of dots on service.match and service.metric
|
|
||||||
|
|
||||||
|
|
||||||
* backend logs with hal logo
|
* backend logs with hal logo
|
||||||
* Use logs for storing monitored values
|
|
||||||
* set_password orchestration method?
|
* set_password orchestration method?
|
||||||
|
|
||||||
|
|
||||||
* make account_link to autoreplace account on change view.
|
* make account_link to autoreplace account on change view.
|
||||||
|
|
||||||
* LAST version of this shit http://wkhtmltopdf.org/downloads.html
|
* LAST version of this shit http://wkhtmltopdf.org/downloads.html
|
||||||
|
@ -50,12 +32,9 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
||||||
* translations
|
* translations
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
with translation.override('en'):
|
with translation.override('en'):
|
||||||
* Plurals!
|
|
||||||
|
|
||||||
* help_text on readonly_fields specialy Bill.state. (eg. A bill is in OPEN state when bla bla )
|
* help_text on readonly_fields specialy Bill.state. (eg. A bill is in OPEN state when bla bla )
|
||||||
|
|
||||||
* underescore *every* private function
|
|
||||||
|
|
||||||
* create log file at /var/log/orchestra.log and rotate
|
* create log file at /var/log/orchestra.log and rotate
|
||||||
|
|
||||||
* order.register_at
|
* order.register_at
|
||||||
|
@ -71,7 +50,7 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
||||||
|
|
||||||
* move icons to apps, and use appconfig to cleanup config stuff
|
* move icons to apps, and use appconfig to cleanup config stuff
|
||||||
|
|
||||||
* when using modeladmin to store shit like self.account, make sure to have a cleanslate in each request
|
* when using modeladmin to store shit like self.account, make sure to have a cleanslate in each request?
|
||||||
|
|
||||||
* jabber with mailbox accounts (dovecto mail notification)
|
* jabber with mailbox accounts (dovecto mail notification)
|
||||||
|
|
||||||
|
@ -114,10 +93,8 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
||||||
* ignore_fields = ()
|
* ignore_fields = ()
|
||||||
* based on a merge set of save(update_fields)
|
* based on a merge set of save(update_fields)
|
||||||
|
|
||||||
* textwrap.dedent( \\)
|
|
||||||
* parmiko write to a channel instead of transfering files? http://sysadmin.circularvale.com/programming/paramiko-channel-hangs/
|
* parmiko write to a channel instead of transfering files? http://sysadmin.circularvale.com/programming/paramiko-channel-hangs/
|
||||||
|
|
||||||
|
|
||||||
* proforma without billing contact?
|
* proforma without billing contact?
|
||||||
|
|
||||||
* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python manage.py test orchestra.apps.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest
|
* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python manage.py test orchestra.apps.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest
|
||||||
|
@ -140,12 +117,8 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
||||||
|
|
||||||
* consider removing mailbox support on forward (user@pangea.org instead)
|
* consider removing mailbox support on forward (user@pangea.org instead)
|
||||||
|
|
||||||
* remove ordering in account admin and others admininlines
|
|
||||||
|
|
||||||
* Databases.User add reverse M2M databases widget (like mailbox.addresses)
|
* Databases.User add reverse M2M databases widget (like mailbox.addresses)
|
||||||
|
|
||||||
* Change (correct) permissions periodically on the web server, to ensure security ?
|
|
||||||
|
|
||||||
* Root owned logs on user's home ? yes
|
* Root owned logs on user's home ? yes
|
||||||
|
|
||||||
* reconsider binding webapps to systemusers (pangea multiple users wordpress-ftp, moodle-pangea, etc)
|
* reconsider binding webapps to systemusers (pangea multiple users wordpress-ftp, moodle-pangea, etc)
|
||||||
|
@ -191,3 +164,5 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
|
||||||
* Fix ftp traffic
|
* Fix ftp traffic
|
||||||
|
|
||||||
* Resource graph for each related object
|
* Resource graph for each related object
|
||||||
|
|
||||||
|
* contacts filter by email_usage fix exact for contains
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect, render
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin.decorators import action_with_confirmation
|
from orchestra.admin.decorators import action_with_confirmation
|
||||||
|
from orchestra.core import services
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
|
@ -33,3 +35,19 @@ def list_contacts(modeladmin, request, queryset):
|
||||||
url += '?account__in=%s' % ','.join(map(str, ids))
|
url += '?account__in=%s' % ','.join(map(str, ids))
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
list_contacts.verbose_name = _("List contacts")
|
list_contacts.verbose_name = _("List contacts")
|
||||||
|
|
||||||
|
|
||||||
|
def service_report(modeladmin, request, queryset):
|
||||||
|
accounts = []
|
||||||
|
for account in queryset:
|
||||||
|
items = []
|
||||||
|
for service in services.get():
|
||||||
|
if service != type(account):
|
||||||
|
items.append((service._meta, service.objects.filter(account=account)))
|
||||||
|
sorted(items, key=lambda i: i[0].verbose_name_plural.lower())
|
||||||
|
accounts.append((account, items))
|
||||||
|
context = {
|
||||||
|
'accounts': accounts,
|
||||||
|
'date': timezone.now().today()
|
||||||
|
}
|
||||||
|
return render(request, 'admin/accounts/account/service_report.html', context)
|
||||||
|
|
|
@ -18,7 +18,7 @@ from orchestra.core import services, accounts
|
||||||
from orchestra.forms import UserChangeForm
|
from orchestra.forms import UserChangeForm
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
from .actions import disable, list_contacts
|
from .actions import disable, list_contacts, service_report
|
||||||
from .filters import HasMainUserListFilter
|
from .filters import HasMainUserListFilter
|
||||||
from .forms import AccountCreationForm
|
from .forms import AccountCreationForm
|
||||||
from .models import Account
|
from .models import Account
|
||||||
|
@ -61,8 +61,8 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
|
||||||
filter_horizontal = ()
|
filter_horizontal = ()
|
||||||
change_readonly_fields = ('username', 'main_systemuser_link')
|
change_readonly_fields = ('username', 'main_systemuser_link')
|
||||||
change_form_template = 'admin/accounts/account/change_form.html'
|
change_form_template = 'admin/accounts/account/change_form.html'
|
||||||
actions = [disable, list_contacts]
|
actions = [disable, list_contacts, service_report]
|
||||||
change_view_actions = [disable]
|
change_view_actions = [disable, service_report]
|
||||||
list_select_related = ('billcontact',)
|
list_select_related = ('billcontact',)
|
||||||
ordering = ()
|
ordering = ()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
{% load utils %}
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}Service Report{% endblock %}</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
{% block head %}{% endblock %}
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
max-width: 670px;
|
||||||
|
margin: 20 auto !important;
|
||||||
|
float: none !important;
|
||||||
|
font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #2E2E2E;
|
||||||
|
}
|
||||||
|
#date {
|
||||||
|
float: right;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.account-content {
|
||||||
|
margin: 0px 0px 40px 20px;
|
||||||
|
}
|
||||||
|
.item-title {
|
||||||
|
list-style-type: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.items-ul {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 5px 0px 10px 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="date">Service report generated on {{ date | date }}</div>
|
||||||
|
{% for account, items in accounts %}
|
||||||
|
<h3>{{ account.get_full_name }} ({{ account.username }})</h3>
|
||||||
|
<hr>
|
||||||
|
<div class="account-content">
|
||||||
|
{{ account.get_type_display }} account registered on {{ account.date_joined | date }}<br>
|
||||||
|
<ul class="items-ul">
|
||||||
|
{% for opts, related in items %}
|
||||||
|
<li class="item-title">{{ opts.verbose_name_plural|capfirst }}</li>
|
||||||
|
<ul>
|
||||||
|
{% for obj in related %}
|
||||||
|
<li>{{ obj }}{% if not obj|isactive %} (disabled){% endif %}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -2,6 +2,8 @@ from django import forms
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||||
|
|
||||||
|
from orchestra.forms.widgets import ShowTextWidget
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,7 @@ function install_requirements () {
|
||||||
django-debug-toolbar==1.2.1 \
|
django-debug-toolbar==1.2.1 \
|
||||||
django-nose==1.2 \
|
django-nose==1.2 \
|
||||||
sqlparse \
|
sqlparse \
|
||||||
|
pyinotify \
|
||||||
--allow-external orchestra-orm --allow-unverified orchestra-orm"
|
--allow-external orchestra-orm --allow-unverified orchestra-orm"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -56,3 +56,8 @@ def is_checkbox(field):
|
||||||
@register.filter
|
@register.filter
|
||||||
def admin_url(obj):
|
def admin_url(obj):
|
||||||
return change_url(obj)
|
return change_url(obj)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def isactive(obj):
|
||||||
|
return getattr(obj, 'is_active', True)
|
||||||
|
|
Loading…
Reference in New Issue