Repository: ckan/ckan

Issue:
bulk_process page for non-existent organization throws Exception
```
Stacktrace (most recent call last):

  File "raven/middleware.py", line 35, in __call__
    iterable = self.application(environ, start_response)
  File "ckan/config/middleware.py", line 373, in __call__
    return self.app(environ, start_response)
  File "/usr/lib/ckan/demo/lib/python2.7/site-packages/paste/cascade.py", line 130, in __call__
    return self.apps[-1](environ, start_response)
  File "ckan/config/middleware.py", line 238, in __call__
    return self.app(environ, start_response)
  File "/usr/lib/ckan/demo/lib/python2.7/site-packages/paste/registry.py", line 379, in __call__
    app_iter = self.application(environ, start_response)
  File "/usr/lib/ckan/demo/lib/python2.7/site-packages/repoze/who/middleware.py", line 107, in __call__
    app_iter = app(environ, wrapper.wrap_start_response)
  File "webob/dec.py", line 147, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "webob/dec.py", line 208, in call_func
    return self.func(req, *args, **kwargs)
  File "fanstatic/publisher.py", line 234, in __call__
    return request.get_response(self.app)
  File "webob/request.py", line 1053, in get_response
    application, catch_exc_info=False)
  File "webob/request.py", line 1022, in call_application
    app_iter = application(self.environ, start_response)
  File "webob/dec.py", line 147, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "webob/dec.py", line 208, in call_func
    return self.func(req, *args, **kwargs)
  File "fanstatic/injector.py", line 54, in __call__
    response = request.get_response(self.app)
  File "webob/request.py", line 1053, in get_response
    application, catch_exc_info=False)
  File "webob/request.py", line 1022, in call_application
    app_iter = application(self.environ, start_response)
  File "beaker/middleware.py", line 73, in __call__
    return self.app(environ, start_response)
  File "beaker/middleware.py", line 155, in __call__
    return self.wrap_app(environ, session_start_response)
  File "routes/middleware.py", line 131, in __call__
    response = self.app(environ, start_response)
  File "pylons/wsgiapp.py", line 125, in __call__
    response = self.dispatch(controller, environ, start_response)
  File "pylons/wsgiapp.py", line 324, in dispatch
    return controller(environ, start_response)
  File "ckan/lib/base.py", line 346, in __call__
    res = WSGIController.__call__(self, environ, start_response)
  File "pylons/controllers/core.py", line 221, in __call__
    response = self._dispatch_call()
  File "pylons/controllers/core.py", line 172, in _dispatch_call
    response = self._inspect_call(func)
  File "pylons/controllers/core.py", line 107, in _inspect_call
    result = self._perform_call(func, args)
  File "ckan/controllers/group.py", line 368, in bulk_process
    raise Exception('Must be an organization')

```

Especially annoying for large sites.



Discussion:

Resolving patch:
diff --git a/ckan/controllers/group.py b/ckan/controllers/group.py
--- a/ckan/controllers/group.py
+++ b/ckan/controllers/group.py
@@ -364,6 +364,9 @@ def bulk_process(self, id):
 
         group_type = self._get_group_type(id.split('@')[0])
 
+        if group_type is None:
+            abort(404, _('Organization not found'))
+
         if group_type != 'organization':
             # FIXME: better error
             raise Exception('Must be an organization')


Test patch:
diff --git a/ckan/new_tests/controllers/test_group.py b/ckan/new_tests/controllers/test_group.py
new file mode 100644
--- /dev/null
+++ b/ckan/new_tests/controllers/test_group.py
@@ -0,0 +1,15 @@
+from nose.tools import assert_equal, assert_true
+
+from routes import url_for
+
+import ckan.new_tests.helpers as helpers
+import ckan.model as model
+
+
+class TestPackageControllerNew(helpers.FunctionalTestBase):
+
+    def test_bulk_process_throws_404_for_nonexistent_org(self):
+        app = self._get_test_app()
+        bulk_process_url = url_for(controller='organization',
+                                   action='bulk_process', id='does-not-exist')
+        response = app.get(url=bulk_process_url, status=404)