Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9337)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9338)
@@ -298,4 +298,50 @@
         return
 
+class LoginAsStudentStep1(KofaEditFormPage):
+    """ View to temporarily set a student password.
+    """
+    grok.context(IStudent)
+    grok.name('loginasstep1')
+    grok.require('waeup.loginAsStudent')
+    grok.template('loginasstep1')
+    pnav = 4
+
+    def label(self):
+        return _(u'Set temporary password for ${a}',
+            mapping = {'a':self.context.display_fullname})
+
+    @action('Set password now', style='primary')
+    def setPassword(self, *args, **data):
+        kofa_utils = getUtility(IKofaUtils)
+        password = kofa_utils.genPassword()
+        self.context.setTempPassword(self.request.principal.id, password)
+        self.context.writeLogMessage(
+            self, 'temp_password generated: %s' % password)
+        args = {'password':password}
+        self.redirect(self.url(self.context) +
+            '/loginasstep2?%s' % urlencode(args))
+        return
+
+class LoginAsStudentStep2(KofaPage):
+    """ View to temporarily login as student with a temporary password.
+    """
+    grok.context(IStudent)
+    grok.name('loginasstep2')
+    grok.require('waeup.Public')
+    grok.template('loginasstep2')
+    login_button = _('Login now')
+    pnav = 4
+
+    def label(self):
+        return _(u'Login as ${a}',
+            mapping = {'a':self.context.student_id})
+
+    def update(self, SUBMIT=None, password=None):
+        self.password = password
+        if SUBMIT is not None:
+            self.flash(_('You successfully logged in as student.'))
+            self.redirect(self.url(self.context))
+        return
+
 class StudentBaseDisplayFormPage(KofaDisplayFormPage):
     """ Page to display student base data
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep1.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep1.pt	(revision 9338)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep1.pt	(revision 9338)
@@ -0,0 +1,18 @@
+<form i18n:domain="waeup.kofa" method="post">
+  <p i18n:translate="login_as_intro_1">
+    Kofa is creating a temporary student password which will replace the
+    original password chosen by the student. The password will be valid
+    for
+    <span i18n:name="minutes"
+          tal:replace=view/context/temp_password_minutes></span>
+    minutes. The student can't login
+    during this time period. After expiration the student can login
+    with the original password again.
+  </p>
+  <br />
+  <div tal:condition="view/availableActions">
+    <input tal:repeat="action view/actions"
+           tal:replace="structure action/render"
+           />
+  </div>
+</form>
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep2.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep2.pt	(revision 9338)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/loginasstep2.pt	(revision 9338)
@@ -0,0 +1,13 @@
+<form action="." tal:attributes="action request/URL" method="post"
+      enctype="multipart/form-data">
+  <p i18n:translate="login_as_intro_2">
+    The random password
+    "<span i18n:name="password"
+          tal:replace=view/password></span>"
+    has been set. You can proceed by clicking the button below.
+  </p>
+  <input type="hidden" name="form.login" tal:attributes="value view/context/student_id" />
+  <input type="hidden" name="form.password"   tal:attributes="value view/password" />
+  <input class="btn primary" type="submit" name="SUBMIT"
+    tal:attributes="value view/login_button" />
+</form>
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 9337)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 9338)
@@ -1467,4 +1467,53 @@
         self.assertTrue('The requested form is locked' in self.browser.contents)
 
+    def test_login_as_student(self):
+        # StudentImpersonators can login as student
+        # Create clearance officer
+        self.app['users'].addUser('mrofficer', 'mrofficersecret')
+        self.app['users']['mrofficer'].email = 'mrofficer@foo.ng'
+        self.app['users']['mrofficer'].title = 'Harry Actor'
+        prmglobal = IPrincipalRoleManager(self.app)
+        prmglobal.assignRoleToPrincipal('waeup.StudentImpersonator', 'mrofficer')
+        prmglobal.assignRoleToPrincipal('waeup.StudentsManager', 'mrofficer')
+        # Login as student impersonator
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = 'mrofficer'
+        self.browser.getControl(name="form.password").value = 'mrofficersecret'
+        self.browser.getControl("Login").click()
+        self.assertMatches('...You logged in...', self.browser.contents)
+        self.browser.open(self.student_path)
+        self.browser.getLink("Login as").click()
+        self.browser.getControl("Set password now").click()
+        temp_password = self.browser.getControl(name='form.password').value
+        self.browser.getControl("Login now").click()
+        self.assertMatches(
+            '...You successfully logged in as...', self.browser.contents)
+        # We are logged in as student and can see the 'My Data' tab
+        self.assertMatches(
+            '...<a href="#" class="dropdown-toggle">My Data</a>...',
+            self.browser.contents)
+        self.browser.getLink("Logout").click()
+        # The student can't login with the original password ...
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.student_id
+        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl("Login").click()
+        self.assertMatches(
+            '...Your account has been temporarily deactivated...',
+            self.browser.contents)
+        # ... but with the temporary password
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.student_id
+        self.browser.getControl(name="form.password").value = temp_password
+        self.browser.getControl("Login").click()
+        self.assertMatches('...You logged in...', self.browser.contents)
+        # Creation of temp_password is properly logged
+        logfile = os.path.join(
+            self.app['datacenter'].storage, 'logs', 'students.log')
+        logcontent = open(logfile).read()
+        self.assertTrue(
+            'mrofficer - students.browser.LoginAsStudentStep1 - K1000000 - '
+            'temp_password generated: %s' % temp_password in logcontent)
+
 class StudentUITests(StudentsFullSetup):
     # Tests for Student class views and pages
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 9337)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 9338)
@@ -175,4 +175,13 @@
     target = 'trigtrans'
 
+class StudentLoginAsActionButton(ManageActionButton):
+    grok.order(3)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.loginAsStudent')
+    icon = 'actionicon_mask.png'
+    text = _(u'Login as student')
+    target = 'loginasstep1'
+
 class AdmissionSlipActionButton(ManageActionButton):
     grok.order(4)
