diff --git a/TODO.md b/TODO.md
index ed996aea..33c40a68 100644
--- a/TODO.md
+++ b/TODO.md
@@ -467,3 +467,6 @@ with open(file) as handler:
# SAVE INISTIAL PASSWORD from all services, and just use it to create the service, never update it
+
+
+# Don't use system groups for unixmailbackends
diff --git a/orchestra/admin/forms.py b/orchestra/admin/forms.py
index efb6db3c..bbd8747a 100644
--- a/orchestra/admin/forms.py
+++ b/orchestra/admin/forms.py
@@ -3,7 +3,6 @@ from functools import partial
from django import forms
from django.contrib.admin import helpers
-from django.contrib.auth.hashers import identify_hasher
from django.core import validators
from django.forms.models import modelformset_factory, BaseModelFormSet
from django.template import Template, Context
@@ -136,9 +135,11 @@ class AdminPasswordChangeForm(forms.Form):
ix = '_%i' % ix
password = self.cleaned_data.get('password%s' % ix)
if password:
+ # lazy loading because of passlib
+ from django.contrib.auth.hashers import identify_hasher
self.password_provided = True
try:
- hasher = identify_hasher(password)
+ identify_hasher(password)
except ValueError:
raise forms.ValidationError(
self.error_messages['bad_hash'],
@@ -161,7 +162,7 @@ class AdminPasswordChangeForm(forms.Form):
password = self.cleaned_data[field_name]
if password:
if self.raw:
- self.password = password
+ self.user.password = password
else:
self.user.set_password(password)
if commit:
diff --git a/orchestra/contrib/miscellaneous/admin.py b/orchestra/contrib/miscellaneous/admin.py
index 1c5efd63..a54b8be3 100644
--- a/orchestra/contrib/miscellaneous/admin.py
+++ b/orchestra/contrib/miscellaneous/admin.py
@@ -26,7 +26,7 @@ class MiscServicePlugin(PluginModelAdapter):
class MiscServiceAdmin(ExtendedModelAdmin):
list_display = (
- 'name', 'verbose_name', 'num_instances', 'has_identifier', 'has_amount', 'is_active'
+ 'display_name', 'display_verbose_name', 'num_instances', 'has_identifier', 'has_amount', 'is_active'
)
list_editable = ('is_active',)
list_filter = ('has_identifier', 'has_amount', IsActiveListFilter)
@@ -37,6 +37,18 @@ class MiscServiceAdmin(ExtendedModelAdmin):
change_readonly_fields = ('name',)
actions = (disable, enable)
+ def display_name(self, misc):
+ return '%s' % (misc.description, misc.name)
+ display_name.short_description = _("name")
+ display_name.allow_tags = True
+ display_name.admin_order_field = 'name'
+
+ def display_verbose_name(self, misc):
+ return '%s' % (misc.description, misc.verbose_name)
+ display_verbose_name.short_description = _("verbose name")
+ display_verbose_name.allow_tags = True
+ display_verbose_name.admin_order_field = 'verbose_name'
+
def num_instances(self, misc):
""" return num slivers as a link to slivers changelist view """
num = misc.instances__count
diff --git a/orchestra/contrib/saas/backends/wordpressmu.py b/orchestra/contrib/saas/backends/wordpressmu.py
index c659c073..9fb5a47e 100644
--- a/orchestra/contrib/saas/backends/wordpressmu.py
+++ b/orchestra/contrib/saas/backends/wordpressmu.py
@@ -1,6 +1,7 @@
import re
import sys
import textwrap
+import time
from functools import partial
from urllib.parse import urlparse
@@ -27,6 +28,15 @@ class WordpressMuController(ServiceController):
)
VERIFY = settings.SAAS_WORDPRESS_VERIFY_SSL
+ def with_retry(self, method, *args, retries=1, sleep=0.5, **kwargs):
+ for i in range(retries):
+ try:
+ return method(*args, **kwargs)
+ except requests.exceptions.ConnectionError:
+ if i >= retries:
+ raise
+ time.sleep(sleep)
+
def login(self, session):
main_url = self.get_main_url()
login_url = main_url + '/wp-login.php'
@@ -36,7 +46,7 @@ class WordpressMuController(ServiceController):
'redirect_to': '/wp-admin/'
}
sys.stdout.write("Login URL: %s\n" % login_url)
- response = session.post(login_url, data=login_data, verify=self.VERIFY)
+ response = self.with_retry(session.post, login_url, data=login_data, verify=self.VERIFY)
if response.url != main_url + '/wp-admin/':
raise IOError("Failure login to remote application (%s)" % login_url)
@@ -59,7 +69,7 @@ class WordpressMuController(ServiceController):
'class="edit">%s' % saas.name
)
sys.stdout.write("Search URL: %s\n" % search)
- content = session.get(search, verify=self.VERIFY).content.decode('utf8')
+ content = self.with_retry(session.get, search, verify=self.VERIFY).content.decode('utf8')
# Get id
ids = regex.search(content)
if not ids and not blog_id:
@@ -84,7 +94,7 @@ class WordpressMuController(ServiceController):
url = self.get_main_url()
url += '/wp-admin/network/site-new.php'
sys.stdout.write("Create URL: %s\n" % url)
- content = session.get(url, verify=self.VERIFY).content.decode('utf8')
+ content = self.with_retry(session.get, url, verify=self.VERIFY).content.decode('utf8')
wpnonce = re.compile('name="_wpnonce_add-blog"\s+value="([^"]*)"')
try:
@@ -101,7 +111,7 @@ class WordpressMuController(ServiceController):
}
# Validate response
- response = session.post(url, data=data, verify=self.VERIFY)
+ response = self.with_retry(session.post, url, data=data, verify=self.VERIFY)
self.validate_response(response)
blog_id = re.compile(r'')
content = response.content.decode('utf8')
@@ -120,7 +130,7 @@ class WordpressMuController(ServiceController):
action_url = re.search(url_regex, content).groups()[0].replace("&", '&')
sys.stdout.write("%s confirm URL: %s\n" % (action, action_url))
- content = session.get(action_url, verify=self.VERIFY).content.decode('utf8')
+ content = self.with_retry(session.get, action_url, verify=self.VERIFY).content.decode('utf8')
wpnonce = re.compile('name="_wpnonce"\s+value="([^"]*)"')
try:
wpnonce = wpnonce.search(content).groups()[0]
@@ -135,7 +145,7 @@ class WordpressMuController(ServiceController):
action_url = self.get_main_url()
action_url += '/wp-admin/network/sites.php?action=%sblog' % action
sys.stdout.write("%s URL: %s\n" % (action, action_url))
- response = session.post(action_url, data=data, verify=self.VERIFY)
+ response = self.with_retry(session.post, action_url, data=data, verify=self.VERIFY)
self.validate_response(response)
def is_active(self, content):