You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by gc...@apache.org on 2022/08/19 21:03:27 UTC

[allura] branch master updated (d0da40cb7 -> 2a3b937c9)

This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git


    from d0da40cb7 remove some "with context" from template imports
     new 7c1ec7599 [#8451] record blocking users in audit log
     new 7e37d1e38 [#8451] record project creation in audit log
     new c633705fe [#8451] record forum add/delete in audit log
     new 35b995e9e [#8451] record tool renames in audit log
     new 929e0d190 [#8451] record wiki set homepage and update options in audit log
     new 1608b7983 [#8451] log ticket options in audit log
     new dc54969a5 [#8451] log blog options in audit log
     new 2a3b937c9 [#8451] log repo external url, other options, and SVN import in audit log

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Allura/allura/app.py                               | 12 +++++++--
 Allura/allura/lib/plugin.py                        |  3 +++
 Allura/allura/lib/repository.py                    |  6 +++++
 Allura/allura/tasks/repo_tasks.py                  |  2 ++
 Allura/allura/tests/functional/test_admin.py       |  8 +++++-
 ForgeBlog/forgeblog/main.py                        | 18 ++++++++++---
 ForgeDiscussion/forgediscussion/forum_main.py      |  6 +++++
 .../tests/functional/test_forum_admin.py           |  8 ++++++
 ForgeDiscussion/forgediscussion/utils.py           |  4 ++-
 ForgeSVN/forgesvn/svn_main.py                      |  9 +++++++
 ForgeTracker/forgetracker/tracker_main.py          |  6 ++++-
 ForgeWiki/forgewiki/wiki_main.py                   | 31 +++++++++++++++++++---
 12 files changed, 100 insertions(+), 13 deletions(-)


[allura] 06/08: [#8451] log ticket options in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 1608b7983b48ce5a9edb418cb5f69f87ff8c610c
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Mon Aug 8 19:24:44 2022 +0000

    [#8451] log ticket options in audit log
---
 ForgeTracker/forgetracker/tracker_main.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 9a49feca7..2ead3dac3 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1704,8 +1704,12 @@ class TrackerAdminController(DefaultAdminController):
     @validate(W.options_admin, error_handler=options)
     def set_options(self, **kw):
         require_access(self.app, 'configure')
+        mount_point = self.app.config.options['mount_point']
         for k, val in kw.items():
-            self.app.config.options[k] = val
+            if self.app.config.options.get(k) != val:
+                M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                    mount_point, k, self.app.config.options.get(k), bool(val)))
+                self.app.config.options[k] = val
         flash('Options updated')
         redirect(six.ensure_text(request.referer or '/'))
 


[allura] 04/08: [#8451] record tool renames in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 35b995e9e2688a21804fdeba7c533ab1af96ed35
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Aug 5 21:03:18 2022 +0000

    [#8451] record tool renames in audit log
---
 Allura/allura/app.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 16989d251..49145ab2e 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -944,7 +944,12 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
 
         """
         require_access(self.app, 'configure')
+        old_label = self.app.config.options['mount_label']
         self.app.config.options['mount_label'] = mount_label
+        model.AuditLog.log('updated label: "{}" => "{}" for {}'.format(
+            old_label,
+            mount_label,
+            self.app.config.options['mount_point']))
         g.post_event('project_menu_updated')
         redirect(six.ensure_text(request.referer or '/'))
 


[allura] 08/08: [#8451] log repo external url, other options, and SVN import in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 2a3b937c9fc89c099e60099b59f50f7bdb43b170
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Mon Aug 8 20:16:18 2022 +0000

    [#8451] log repo external url, other options, and SVN import in audit log
---
 Allura/allura/lib/repository.py   | 6 ++++++
 Allura/allura/tasks/repo_tasks.py | 2 ++
 ForgeSVN/forgesvn/svn_main.py     | 9 +++++++++
 3 files changed, 17 insertions(+)

diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 84441912d..6967032b6 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -315,6 +315,9 @@ class RepoAdminController(DefaultAdminController):
         external_checkout_url = (post_data.get('external_checkout_url') or '').strip()
         if 'external_checkout_url' not in c.form_errors:
             if (self.app.config.options.get('external_checkout_url') or '') != external_checkout_url:
+                M.AuditLog.log('{}: set "{}" {} => {}'.format(
+                    self.app.config.options['mount_point'], "external_checkout_url",
+                    self.app.config.options.get('external_checkout_url'), external_checkout_url))
                 self.app.config.options.external_checkout_url = external_checkout_url
                 flash_msgs.append("External checkout URL successfully changed.")
         else:
@@ -322,6 +325,9 @@ class RepoAdminController(DefaultAdminController):
 
         merge_disabled = bool(post_data.get('merge_disabled'))
         if merge_disabled != self.app.config.options.get('merge_disabled', False):
+            M.AuditLog.log('{}: set "{}" {} => {}'.format(
+                self.app.config.options['mount_point'], "merge_disabled",
+                self.app.config.options.get('merge_disabled', False), merge_disabled))
             self.app.config.options.merge_disabled = merge_disabled
             flash_msgs.append('One-click merge {}.'.format('disabled' if merge_disabled else 'enabled'))
 
diff --git a/Allura/allura/tasks/repo_tasks.py b/Allura/allura/tasks/repo_tasks.py
index 7292a0889..17f26788c 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -44,6 +44,8 @@ def clone(cloned_from_path, cloned_from_name, cloned_from_url):
             c.user, c.app.repo, 'created',
             text='Repository {}/{} created'.format(
                 c.project.shortname, c.app.config.options.mount_point))
+        M.AuditLog.log('{}: import completed from "{}"'.format(
+            c.app.config.options['mount_point'], cloned_from_url))
     except Exception:
         g.post_event('repo_clone_task_failed', cloned_from_url,
                      cloned_from_path, traceback.format_exc())
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index 1e632d5d3..c3326210c 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -135,6 +135,9 @@ class SVNRepoAdminController(RepoAdminController):
                                                 self.app.repo.name,
                                                 checkout_url)):
             if (self.app.config.options.get('checkout_url') or '') != checkout_url:
+                M.AuditLog.log('{}: set "{}" {} => {}'.format(
+                    self.app.config.options['mount_point'], "checkout_url",
+                    self.app.config.options.get('checkout_url'), checkout_url))
                 self.app.config.options.checkout_url = checkout_url
                 flash("Checkout URL successfully changed")
         else:
@@ -142,6 +145,9 @@ class SVNRepoAdminController(RepoAdminController):
                   checkout_url, "error")
         if 'external_checkout_url' not in c.form_errors:
             if (self.app.config.options.get('external_checkout_url') or '') != external_checkout_url:
+                M.AuditLog.log('{}: set "{}" {} => {}'.format(
+                    self.app.config.options['mount_point'], "external_checkout_url",
+                    self.app.config.options.get('external_checkout_url'), external_checkout_url))
                 self.app.config.options.external_checkout_url = external_checkout_url
                 flash("External checkout URL successfully changed")
         else:
@@ -174,6 +180,9 @@ class SVNImportController(BaseController, AdminControllerMixin):
                     cloned_from_path=None,
                     cloned_from_name=None,
                     cloned_from_url=checkout_url)
+                M.AuditLog.log('{}: import initiated from "{}"'.format(
+                    self.app.config.options['mount_point'], checkout_url))
+
             M.Notification.post_user(
                 c.user, self.app.repo, 'importing',
                 text='''Repository import scheduled,


[allura] 05/08: [#8451] record wiki set homepage and update options in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 929e0d19043a47c2b6cb5306857d5f8c66bc808a
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Aug 5 21:28:16 2022 +0000

    [#8451] record wiki set homepage and update options in audit log
---
 ForgeWiki/forgewiki/wiki_main.py | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 6648e7c13..bd13c81a4 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -932,12 +932,17 @@ class WikiAdminController(DefaultAdminController):
     @expose()
     @require_post()
     def set_home(self, new_home):
+        old_home = self.app.root_page_name
         self.app.root_page_name = new_home
         self.app.upsert_root(new_home)
         flash('Home updated')
         mount_base = c.project.url() + \
             self.app.config.options.mount_point + '/'
         url = h.really_unicode(mount_base) + h.really_unicode(new_home) + '/'
+        M.AuditLog.log('set home page: "{}" => "{}" for {}'.format(
+            old_home,
+            new_home,
+            self.app.config.options['mount_point']))
         redirect(h.urlquote(url))
 
     @without_trailing_slash
@@ -945,9 +950,27 @@ class WikiAdminController(DefaultAdminController):
     @require_post()
     def set_options(self, show_discussion=False, show_left_bar=False, show_right_bar=False,
                     allow_email_posting=False):
-        self.app.show_discussion = show_discussion
-        self.app.show_left_bar = show_left_bar
-        self.app.show_right_bar = show_right_bar
-        self.app.allow_email_posting = allow_email_posting
+        mount_point = self.app.config.options['mount_point']
+
+        if self.app.show_discussion != bool(show_discussion):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "Show Discussion", self.app.show_discussion, bool(show_discussion)))
+            self.app.show_discussion = show_discussion
+
+        if self.app.show_left_bar != bool(show_left_bar):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "Show left Bar", self.app.show_left_bar, bool(show_left_bar)))
+            self.app.show_left_bar = show_left_bar
+
+        if self.app.show_right_bar != bool(show_right_bar):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "Show metadata", self.app.show_right_bar, bool(show_right_bar)))
+            self.app.show_right_bar = show_right_bar
+
+        if self.app.allow_email_posting != bool(allow_email_posting):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "Allow posting replies via email", self.app.allow_email_posting, bool(allow_email_posting)))
+            self.app.allow_email_posting = allow_email_posting
+
         flash('Wiki options updated')
         redirect(six.ensure_text(request.referer or '/'))


[allura] 02/08: [#8451] record project creation in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 7e37d1e388aaa1d24d414b1a372ae8a88d47b584
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Aug 5 19:31:18 2022 +0000

    [#8451] record project creation in audit log
---
 Allura/allura/lib/plugin.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index fb379b24d..30bf65286 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -1051,6 +1051,9 @@ class ProjectRegistrationProvider:
                 'private', False),
             apps=apps or [] if 'tools' in project_template else None)
 
+        M.AuditLog(project_id=p._id, user_id=user._id, message='Project Created!',
+                   url=neighborhood.url_prefix + 'add_project')
+
         # Setup defaults from neighborhood project template if applicable
         offset = p.next_mount_point(include_hidden=True)
         if 'groups' in project_template:


[allura] 01/08: [#8451] record blocking users in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 7c1ec759982216cbb54b8d547758e5f02921d0db
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Aug 5 19:05:44 2022 +0000

    [#8451] record blocking users in audit log
---
 Allura/allura/app.py                         | 7 +++++--
 Allura/allura/tests/functional/test_admin.py | 8 +++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index d40668e1b..16989d251 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -868,10 +868,13 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
         user = model.User.by_username(username)
         if not user:
             return dict(error='User "%s" not found' % username)
-        ace = model.ACE.deny(
-            model.ProjectRole.by_user(user, upsert=True)._id, perm, reason)
+        ace = model.ACE.deny(model.ProjectRole.by_user(user, upsert=True)._id, perm, reason)
         if not model.ACL.contains(ace, self.app.acl):
             self.app.acl.append(ace)
+            model.AuditLog.log('blocked user "{}" from {} for reason: "{}"'.format(
+                username,
+                self.app.config.options['mount_point'],
+                reason))
             return dict(user_id=str(user._id), username=user.username, reason=reason)
         return dict(error='User "%s" already blocked' % user.username)
 
diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index 3a300e8c1..8237bf332 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -211,9 +211,15 @@ class TestProjectAdmin(TestController):
             r.json, dict(user_id=str(user._id), username='test-admin', reason='Comment'))
         user = M.User.by_username('test-admin')
         admin_role = M.ProjectRole.by_user(user)
-        app = M.Project.query.get(shortname='test').app_instance('wiki')
+        project = M.Project.query.get(shortname='test')
+        app = project.app_instance('wiki')
         ace = M.ACL.contains(M.ACE.deny(admin_role._id, 'read'), app.acl)
         assert_equals(ace.reason, 'Comment')
+        audit_log = M.AuditLog.query.find(
+            {'project_id': project._id}).sort('_id', -1).first()
+        assert 'blocked user "test-admin"' in audit_log.message
+        assert 'for reason: "Comment"' in audit_log.message
+
         r = self.app.get('/admin/wiki/permissions')
         assert '<input type="checkbox" name="user_id" value="%s">test-admin (Comment)' % user._id in r
 


[allura] 03/08: [#8451] record forum add/delete in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit c633705fe2ed053b19ca79f31d0648312cac0dd8
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Aug 5 20:53:41 2022 +0000

    [#8451] record forum add/delete in audit log
---
 ForgeDiscussion/forgediscussion/forum_main.py                     | 6 ++++++
 .../forgediscussion/tests/functional/test_forum_admin.py          | 8 ++++++++
 ForgeDiscussion/forgediscussion/utils.py                          | 4 +++-
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index fca6fc899..262b5a196 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -319,8 +319,14 @@ class ForumAdminController(DefaultAdminController):
             forum = DM.Forum.query.get(_id=ObjectId(str(f['id'])))
             if f.get('delete'):
                 forum.deleted = True
+                M.AuditLog.log('deleted forum "{}" from {}'.format(
+                    forum.name,
+                    self.app.config.options['mount_point']))
             elif f.get('undelete'):
                 forum.deleted = False
+                M.AuditLog.log('undeleted forum "{}" from {}'.format(
+                    forum.name,
+                    self.app.config.options['mount_point']))
             else:
                 if '.' in f['shortname'] or '/' in f['shortname'] or ' ' in f['shortname']:
                     flash('Shortname cannot contain space . or /', 'error')
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 6da55ea5c..ca14d1c37 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -36,6 +36,7 @@ class TestForumAdmin(TestController):
         self.app.get('/discussion/')
 
     def test_forum_CRUD(self):
+        project = M.Project.query.get(shortname='test')
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
         form['add_forum.shortname'] = 'testforum'
@@ -51,6 +52,8 @@ class TestForumAdmin(TestController):
                                   'forum-0.shortname': 'NewTestForum',
                                   'forum-0.description': 'My desc',
                                   'forum-0.monitoring_email': ''})
+        audit_log = M.AuditLog.query.find({'project_id': project._id}).sort('_id', -1).first()
+        assert 'created forum "Test Forum"' in audit_log.message
         r = self.app.get('/admin/discussion/forums')
         assert 'New Test Forum' in r
         assert 'My desc' in r
@@ -129,6 +132,7 @@ class TestForumAdmin(TestController):
         assert 'error' in r
 
     def test_delete_undelete(self):
+        project = M.Project.query.get(shortname='test')
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
         form['add_forum.shortname'] = 'testforum'
@@ -148,6 +152,8 @@ class TestForumAdmin(TestController):
         r = self.app.get('/admin/discussion/forums')
         soup_form = r.html.find('form', action='update_forums')
         assert len(soup_form.findAll('input', {'value': 'Delete'})) == 1
+        audit_log = M.AuditLog.query.find({'project_id': project._id}).sort('_id', -1).first()
+        assert 'deleted forum "Test Forum"' in audit_log.message
         r = self.app.post('/admin/discussion/update_forums',
                           params={'forum-0.undelete': 'on',
                                   'forum-0.id': str(frm._id),
@@ -156,6 +162,8 @@ class TestForumAdmin(TestController):
         r = self.app.get('/admin/discussion/forums')
         soup_form = r.html.find('form', action='update_forums')
         assert len(soup_form.findAll('input', {'value': 'Delete'})) == 2
+        audit_log = M.AuditLog.query.find({'project_id': project._id}).sort('_id', -1).first()
+        assert 'undeleted forum "Test Forum"' in audit_log.message
 
     def test_members_only(self):
         # make a forum anyone can see
diff --git a/ForgeDiscussion/forgediscussion/utils.py b/ForgeDiscussion/forgediscussion/utils.py
index 1169caf9f..f830ae9f5 100644
--- a/ForgeDiscussion/forgediscussion/utils.py
+++ b/ForgeDiscussion/forgediscussion/utils.py
@@ -20,7 +20,7 @@
 from bson import ObjectId
 from tg import flash
 from allura.lib import helpers as h
-from allura.model import ProjectRole, ACE, ALL_PERMISSIONS, DENY_ALL
+from allura.model import ProjectRole, ACE, ALL_PERMISSIONS, DENY_ALL, AuditLog
 from forgediscussion import model as DM
 
 
@@ -43,6 +43,8 @@ def create_forum(app, new_forum):
                  anon_posts=new_forum.get('anon_posts', False),
                  monitoring_email=new_forum.get('monitoring_email', None),
                  )
+    AuditLog.log('created forum "{}" for {}'.format(
+        f.name, app.config.options['mount_point']))
     if f.members_only and f.anon_posts:
         flash('You cannot have anonymous posts in a members only forum.',
               'warning')


[allura] 07/08: [#8451] log blog options in audit log

Posted by gc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gcruz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit dc54969a54085e75505b61e5539feaf5e5ddbef4
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Mon Aug 8 19:37:18 2022 +0000

    [#8451] log blog options in audit log
---
 ForgeBlog/forgeblog/main.py | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 40d474fef..59fe8e869 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -535,10 +535,20 @@ class BlogAdminController(DefaultAdminController):
     @expose()
     @require_post()
     def set_options(self, show_discussion=False, allow_email_posting=False):
-        self.app.config.options[
-            'show_discussion'] = show_discussion and True or False
-        self.app.config.options[
-            'AllowEmailPosting'] = allow_email_posting and True or False
+        mount_point = self.app.config.options['mount_point']
+
+        if self.app.config.options.get('show_discussion') != bool(show_discussion):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "show_discussion", self.app.config.options.get('show_discussion'),
+                bool(show_discussion)))
+            self.app.config.options['show_discussion'] = bool(show_discussion)
+
+        if self.app.config.options.get('AllowEmailPosting') != bool(allow_email_posting):
+            M.AuditLog.log('{}: set option "{}" {} => {}'.format(
+                mount_point, "AllowEmailPosting", self.app.config.options.get('AllowEmailPosting'),
+                bool(allow_email_posting)))
+            self.app.config.options['AllowEmailPosting'] = bool(allow_email_posting)
+
         flash('Blog options updated')
         redirect(six.ensure_text(request.referer or '/'))