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):