You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by je...@apache.org on 2015/11/18 17:06:06 UTC
[07/16] allura git commit: [#7999] ticket:856 Disable users
[#7999] ticket:856 Disable users
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/caa56721
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/caa56721
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/caa56721
Branch: refs/heads/ib/7999a
Commit: caa56721ff9fb85853802e5bf709ce0a76577cdb
Parents: 65ea094
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Nov 4 15:26:02 2015 +0200
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Mon Nov 16 14:18:36 2015 +0200
----------------------------------------------------------------------
Allura/allura/controllers/site_admin.py | 7 ++--
Allura/allura/scripts/delete_projects.py | 38 ++++++++++++++++----
.../templates/site_admin_delete_projects.html | 4 +++
.../allura/tests/functional/test_site_admin.py | 9 +++++
Allura/allura/tests/test_delete_projects.py | 33 +++++++++++++++--
5 files changed, 79 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/caa56721/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index cec6b3a..c74203a 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -322,8 +322,9 @@ class SiteAdminController(object):
@without_trailing_slash
@expose('jinja:allura:templates/site_admin_delete_projects.html')
@validate(validators=dict(projects=validators.UnicodeString(if_empty=None),
- reason=validators.UnicodeString(if_empty=None)))
- def delete_projects(self, projects=None, reason=None, **kw):
+ reason=validators.UnicodeString(if_empty=None),
+ disable_users=validators.StringBool(if_empty=False)))
+ def delete_projects(self, projects=None, reason=None, disable_users=False, **kw):
if request.method == "POST":
if not projects:
flash(u'No projects specified', 'warning')
@@ -338,6 +339,8 @@ class SiteAdminController(object):
task_params = u' '.join(task_params)
if reason:
task_params = u'-r {} {}'.format(pipes.quote(reason), task_params)
+ if disable_users:
+ task_params = u'--disable-users {}'.format(task_params)
DeleteProjects.post(task_params)
flash(u'Delete scheduled for %s' % projects, 'ok')
redirect('delete_projects')
http://git-wip-us.apache.org/repos/asf/allura/blob/caa56721/Allura/allura/scripts/delete_projects.py
----------------------------------------------------------------------
diff --git a/Allura/allura/scripts/delete_projects.py b/Allura/allura/scripts/delete_projects.py
index 0cd1ca8..cedf87b 100644
--- a/Allura/allura/scripts/delete_projects.py
+++ b/Allura/allura/scripts/delete_projects.py
@@ -20,9 +20,11 @@ import logging
from ming.odm import Mapper, session
from pylons import app_globals as g
+from webob import Request
from allura.scripts import ScriptTask
from allura import model as M
+from allura.lib.plugin import AuthenticationProvider
from allura.tasks.index_tasks import solr_del_project_artifacts
@@ -37,9 +39,7 @@ class DeleteProjects(ScriptTask):
proj = cls.get_project(proj)
if proj:
log.info('Purging %s%s. Reason: %s', proj.neighborhood.url_prefix, proj.shortname, options.reason)
- pid = proj._id
- cls.purge_project(proj)
- g.post_event('project_deleted', project_id=pid, reason=options.reason)
+ cls.purge_project(proj, options)
@classmethod
def get_project(cls, proj):
@@ -55,20 +55,42 @@ class DeleteProjects(ScriptTask):
return p
@classmethod
- def purge_project(cls, project):
+ def purge_project(cls, project, options):
pid = project._id
solr_del_project_artifacts.post(pid)
+ if options.disable_users:
+ # Disable users if necessary BEFORE removing all project-related documents
+ cls.disable_users(project, options)
app_config_ids = [ac._id for ac in M.AppConfig.query.find(dict(project_id=pid))]
for m in Mapper.all_mappers():
- cls = m.mapped_class
+ mcls = m.mapped_class
if 'project_id' in m.property_index:
# Purge the things directly related to the project
- cls.query.remove(dict(project_id=pid))
+ mcls.query.remove(dict(project_id=pid))
elif 'app_config_id' in m.property_index:
# ... and the things related to its apps
- cls.query.remove(dict(app_config_id={'$in': app_config_ids}))
+ mcls.query.remove(dict(app_config_id={'$in': app_config_ids}))
project.delete()
session(project).flush()
+ g.post_event('project_deleted', project_id=pid, reason=options.reason)
+
+ @classmethod
+ def disable_users(cls, project, options):
+ provider = AuthenticationProvider.get(Request.blank('/'))
+ users = project.admins() + project.users_with_role('Developer')
+ for user in users:
+ if user.disabled:
+ continue
+ log.info(u'Disabling user %s', user.username)
+ provider.disable_user(user, audit=False)
+ msg = u'Account disabled because project {}{} is deleted. Reason: {}'.format(
+ project.neighborhood.url_prefix,
+ project.shortname,
+ options.reason)
+ M.AuditLog.log_user(msg, user=user)
+ # `users` can contain duplicates. Make sure changes are visible
+ # to next iterations, so that `user.disabled` check works.
+ session(user).expunge(user)
@classmethod
def parser(cls):
@@ -77,6 +99,8 @@ class DeleteProjects(ScriptTask):
help='Project to delete in a form nbhd_prefix/shortname')
parser.add_argument('-r', '--reason', type=str,
help='Reason why these projects being deleted')
+ parser.add_argument('--disable-users', action='store_true', default=False,
+ help='Disable all project members')
return parser
http://git-wip-us.apache.org/repos/asf/allura/blob/caa56721/Allura/allura/templates/site_admin_delete_projects.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin_delete_projects.html b/Allura/allura/templates/site_admin_delete_projects.html
index bae6a05..3f15ec1 100644
--- a/Allura/allura/templates/site_admin_delete_projects.html
+++ b/Allura/allura/templates/site_admin_delete_projects.html
@@ -38,6 +38,10 @@
<textarea name="reason"></textarea>
</div>
<div class="grid-18">
+ <input id="disable_users" name="disable_users" type="checkbox">
+ <label for="disable_users">Disable all project members</label>
+ </div>
+ <div class="grid-18">
<input type="submit" value="Delete">
</div>
{{lib.csrf_token()}}
http://git-wip-us.apache.org/repos/asf/allura/blob/caa56721/Allura/allura/tests/functional/test_site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index f6c1a31..fed8fa4 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -602,6 +602,15 @@ class TestDeleteProjects(TestController):
form.submit()
dp.post.assert_called_once_with('p/test adobe/adobe-1 p/test2')
+ @patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
+ def test_admins_and_devs_are_disabled(self, dp):
+ r = self.app.get('/nf/admin/delete_projects')
+ form = self.form(r)
+ form['projects'] = 'p/test p/test2'
+ form['disable_users'] = True
+ form.submit()
+ dp.post.assert_called_once_with('--disable-users p/test p/test2')
+
@task
def test_task(*args, **kw):
http://git-wip-us.apache.org/repos/asf/allura/blob/caa56721/Allura/allura/tests/test_delete_projects.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_delete_projects.py b/Allura/allura/tests/test_delete_projects.py
index f8cc62e..784a5b9 100644
--- a/Allura/allura/tests/test_delete_projects.py
+++ b/Allura/allura/tests/test_delete_projects.py
@@ -15,11 +15,12 @@
# specific language governing permissions and limitations
# under the License.
-from ming.odm import session, Mapper
+from ming.odm import session, Mapper, ThreadLocalODMSession
from mock import patch
+from pylons import app_globals as g
from alluratest.controller import TestController
-
+from allura.tests.decorators import audits, out_audits
from allura import model as M
from allura.scripts import delete_projects
@@ -31,7 +32,7 @@ class TestDeleteProjects(TestController):
n = M.Neighborhood.query.get(name='Projects')
admin = M.User.by_username('test-admin')
self.p_shortname = 'test-delete'
- n.register_project(self.p_shortname, admin)
+ self.proj = n.register_project(self.p_shortname, admin)
def run_script(self, options):
cls = delete_projects.DeleteProjects
@@ -92,3 +93,29 @@ class TestDeleteProjects(TestController):
assert p is None, 'Project is not deleted'
log.info.assert_called_once_with('Purging %s%s. Reason: %s', '/p/', 'test-delete', 'The Reason')
post_event.assert_called_once_with('project_deleted', project_id=pid, reason='The Reason')
+
+ def _disable_users(self, disable):
+ dev = M.User.by_username('test-user')
+ self.proj.add_user(dev, ['Developer'])
+ ThreadLocalODMSession.flush_all()
+ g.credentials.clear()
+ proj = u'p/{}'.format(self.p_shortname)
+ msg = u'Account disabled because project /{} is deleted. Reason: The Reason'.format(proj)
+ opts = ['-r', 'The Reason', proj]
+ if disable:
+ opts.insert(0, '--disable-users')
+ _audit = audits if disable else out_audits
+ with _audit(msg):
+ self.run_script(opts)
+ admin = M.User.by_username('test-admin')
+ dev = M.User.by_username('test-user')
+ assert admin.disabled is disable
+ assert dev.disabled is disable
+
+ @patch('allura.model.auth.request', autospec=True)
+ def test_disable_users(self, req):
+ req.url = None
+ self._disable_users(disable=True)
+
+ def test_not_disable_users(self):
+ self._disable_users(disable=False)