Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/reports.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/reports.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/reports.py	(revision 12900)
@@ -21,9 +21,11 @@
 from zope.component import getUtility, queryUtility
 from zope.location.location import located
+from zope.security import checkPermission
 from waeup.kofa.interfaces import IJobManager, IKofaUtils
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.browser.layout import KofaPage
-from waeup.kofa.reports import IReportsContainer, IReportGenerator
-from waeup.kofa.reports import get_generators
+from waeup.kofa.utils.helpers import get_current_principal
+from waeup.kofa.reports import (
+    IReportsContainer, IReportGenerator, get_generators)
 
 
@@ -36,5 +38,5 @@
     grok.name('index')
     grok.context(IReportsContainer)
-    grok.require('waeup.manageReports')
+    grok.require('waeup.handleReports')
     label = _('Reports')
 
@@ -54,5 +56,9 @@
             grok.getSite().logger.info(
                 '%s - report %s discarded' % (ob_class, job_id))
-        self.entries = self._generate_entries(user_id=None)
+        if not checkPermission('waeup.manageReports', self.context):
+            user = get_current_principal()
+            self.entries = self._generate_entries(user_id=user.id)
+        else:
+            self.entries = self._generate_entries(user_id=None)
         if job_id and DOWNLOAD:
             self.redirect(self._report_url(job_id))
@@ -114,5 +120,5 @@
     grok.name('create')
     grok.context(IReportsContainer)
-    grok.require('waeup.manageReports')
+    grok.require('waeup.handleReports')
     label = _('Create report')
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/tests/test_permissions.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/tests/test_permissions.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/tests/test_permissions.py	(revision 12900)
@@ -26,13 +26,19 @@
 import shutil
 import tempfile
+from zc.async.testing import wait_for_result
 from zope.app.testing.functional import HTTPCaller as http
-from zope.component import createObject
+from zope.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.component import createObject, getUtility
 from zope.component.hooks import setSite, clearSite
 from zope.security.interfaces import Unauthorized
 from zope.testbrowser.testing import Browser
+from waeup.kofa.interfaces import IJobManager
 from waeup.kofa.app import University
 from waeup.kofa.testing import (
     FunctionalLayer, FunctionalTestCase, get_all_loggers, remove_new_loggers,
     remove_logger)
+from waeup.kofa.tests.test_async import FunctionalAsyncTestCase
+
+
 
 manager_pages = [
@@ -63,5 +69,5 @@
     ]
 
-class PermissionTest(FunctionalTestCase):
+class PermissionTest(FunctionalAsyncTestCase, FunctionalTestCase):
     """Here we try to request all pages and check, whether they are
     accessible.
@@ -92,4 +98,5 @@
         dept.certificates.addCertificate(cert)
         cert.addCertCourse(course)
+        self.app = app
 
         self.browser = Browser()
@@ -110,4 +117,31 @@
         except Unauthorized:
             return False
+        return
+
+    def wait_for_report_job_completed(self, number):
+        # helper function waiting until the current export job is completed
+        manager = getUtility(IJobManager)
+        job_id = self.app['reports'].running_report_jobs[number][0]
+        job = manager.get(job_id)
+        wait_for_result(job)
+        return job_id
+
+    def stored_in_reports(self, job_id):
+        # tell whether job_id is stored in reports's running jobs list
+        for entry in list(self.app['reports'].running_report_jobs):
+            if entry[0] == job_id:
+                return True
+        return False
+
+    def trigger_report_creation(self, session):
+        self.browser.open('http://localhost/app/reports')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.browser.getLink("Create new report").click()
+        self.browser.getControl(name="generator").value = ['student_stats']
+        self.browser.getControl("Configure").click()
+        self.browser.getControl(name="breakdown").value = ['depcode']
+        self.browser.getControl(name="mode").value = ['All']
+        self.browser.getControl(name="session").value = [session]
+        self.browser.getControl("Create").click()
         return
 
@@ -122,2 +156,58 @@
             self.fail('Path %s cannot be accessed by anonymous.' % path)
         return
+
+    def testReportsPermissions(self):
+        # Create reports officer
+        self.app['users'].addUser('mrofficer', 'mrofficer')
+        self.app['users']['mrofficer'].email = 'mrofficer@foo.ng'
+        self.app['users']['mrofficer'].title = 'Otto Report'
+        prmglobal = IPrincipalRoleManager(self.app)
+        prmglobal.assignRoleToPrincipal('waeup.ReportsOfficer', 'mrofficer')
+        # Create reports manager
+        self.app['users'].addUser('mrmanager', 'mrmanager')
+        self.app['users']['mrmanager'].email = 'mrmanager@foo.ng'
+        self.app['users']['mrmanager'].title = 'Manfred Report'
+        prmglobal.assignRoleToPrincipal('waeup.ReportsManager', 'mrmanager')
+        # The reports officer creates a report which the reports manager
+        # can see.
+        self.browser.open('http://localhost/app/login')
+        self.browser.getControl(name="form.login").value = 'mrofficer'
+        self.browser.getControl(name="form.password").value = 'mrofficer'
+        self.browser.getControl("Login").click()
+        self.trigger_report_creation('2004')
+        job_id = self.wait_for_report_job_completed(0)
+        self.browser.open('http://localhost/app/reports')
+        self.assertTrue(
+            'Student Statistics (depcode, 2004, All, 0)'
+            in self.browser.contents)
+        self.browser.open('http://localhost/app/logout')
+        # The reports manager creates a report which the reports officer
+        # can't see.
+        self.browser.open('http://localhost/app/login')
+        self.browser.getControl(name="form.login").value = 'mrmanager'
+        self.browser.getControl(name="form.password").value = 'mrmanager'
+        self.browser.getControl("Login").click()
+        self.trigger_report_creation('2005')
+        job_id = self.wait_for_report_job_completed(1)
+        self.browser.open('http://localhost/app/reports')
+        # Manager can see both reports.
+        self.assertTrue(
+            'Student Statistics (depcode, 2004, All, 0)'
+            in self.browser.contents)
+        self.assertTrue(
+            'Student Statistics (depcode, 2005, All, 0)'
+            in self.browser.contents)
+        self.browser.open('http://localhost/app/logout')
+        self.browser.open('http://localhost/app/login')
+        self.browser.getControl(name="form.login").value = 'mrofficer'
+        self.browser.getControl(name="form.password").value = 'mrofficer'
+        self.browser.getControl("Login").click()
+        self.browser.open('http://localhost/app/reports')
+        # Officer can only see his report.
+        self.assertTrue(
+            'Student Statistics (depcode, 2004, All, 0)'
+            in self.browser.contents)
+        self.assertFalse(
+            'Student Statistics (depcode, 2005, All, 0)'
+            in self.browser.contents)
+        return
Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 12900)
@@ -344,5 +344,5 @@
     """
     grok.order(4)
-    grok.require('waeup.manageReports')
+    grok.require('waeup.handleReports')
 
     link = u'reports'
Index: main/waeup.kofa/trunk/src/waeup/kofa/permissions.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/permissions.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/permissions.py	(revision 12900)
@@ -502,4 +502,5 @@
                      'waeup.editUser',
                      'waeup.loginAsStudent',
+                     'waeup.handleReports',
                      'waeup.manageReports',
                      'waeup.manageJobs',
@@ -545,4 +546,5 @@
                      #'waeup.editUser',
                      #'waeup.loginAsStudent',
+                     'waeup.handleReports',
                      'waeup.manageReports',
                      #'waeup.manageJobs',
Index: main/waeup.kofa/trunk/src/waeup/kofa/permissions.txt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/permissions.txt	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/permissions.txt	(revision 12900)
@@ -39,8 +39,8 @@
     >>> from waeup.kofa.permissions import get_waeup_roles
     >>> len(list(get_waeup_roles()))
-    25
+    26
 
     >>> len(list(get_waeup_roles(also_local=True)))
-    46
+    47
 
 
@@ -68,4 +68,5 @@
      u'waeup.PortalManager',
      u'waeup.ReportsManager',
+     u'waeup.ReportsOfficer',
      u'waeup.Student',
      u'waeup.StudentImpersonator',
Index: main/waeup.kofa/trunk/src/waeup/kofa/reports.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/reports.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/reports.py	(revision 12900)
@@ -139,15 +139,32 @@
     """
 
+class HandleReports(grok.Permission):
+    """The HandleReports permission allows to add any kind of report
+    and to view and remove own reports, i.e. reports which were created by
+    the logged-in user.
+    """
+    grok.name('waeup.handleReports')
+
 class ManageReports(grok.Permission):
-    """The ManageReports permission allows to view, add and remove reports.
+    """The ManageReports permission allows to view, add and remove also
+    the reports of other users. It requires the permission to handle reports.
     """
     grok.name('waeup.manageReports')
 
+class ReportsOfficer(grok.Role):
+    """The Reports Officer has the permission to to view, add and remove
+    **own** reports.
+    """
+    grok.name('waeup.ReportsOfficer')
+    grok.title(u'Reports Officer')
+    grok.permissions('waeup.handleReports')
+
 class ReportsManager(grok.Role):
-    """The ReportsManager has the permission to manage reports.
+    """The Reports Manager has the permission to to view, add and remove
+    **all** reports.
     """
     grok.name('waeup.ReportsManager')
     grok.title(u'Reports Manager')
-    grok.permissions('waeup.manageReports')
+    grok.permissions('waeup.handleReports', 'waeup.manageReports')
 
 def get_generators():
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py	(revision 12900)
@@ -225,5 +225,5 @@
     grok.context(LevelReportGenerator)
     grok.name('index.html')
-    grok.require('waeup.manageReports')
+    grok.require('waeup.handleReports')
 
     label = _('Create level report')
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/reports/student_statistics.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/reports/student_statistics.py	(revision 12898)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/reports/student_statistics.py	(revision 12900)
@@ -215,5 +215,5 @@
     grok.context(StudentStatisticsReportGenerator)
     grok.name('index.html')
-    grok.require('waeup.manageReports')
+    grok.require('waeup.handleReports')
 
     label = _('Create student statistics report')
