Changeset 8779 for main/waeup.kofa/trunk


Ignore:
Timestamp:
23 Jun 2012, 06:32:56 (12 years ago)
Author:
Henrik Bettermann
Message:

Add password request page for first-time login withot email address and pwd activation code.

To do: What happens if a wrong email address has been entered. Solution: We need to remember if a student has logged in.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/students
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py

    r8737 r8779  
    3939from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
    4040from waeup.kofa.browser.layout import jsaction, action, UtilityView
     41from waeup.kofa.browser.interfaces import ICaptchaManager
    4142from waeup.kofa.interfaces import (
    4243    IKofaObject, IUserAccount, IExtFileStore, IPasswordValidator, IContactForm,
     
    5354    IStudentAccommodation, IStudentStudyLevel,
    5455    ICourseTicket, ICourseTicketAdd, IStudentPaymentsContainer,
    55     IStudentOnlinePayment, IBedTicket, IStudentsUtils
     56    IStudentOnlinePayment, IBedTicket, IStudentsUtils, IStudentRequestPW
    5657    )
    5758from waeup.kofa.students.catalog import search
    58 from waeup.kofa.students.workflow import (ADMITTED, PAID,
     59from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
    5960    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED)
    6061from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
     
    6364from waeup.kofa.hostels.hostel import NOT_OCCUPIED
    6465from waeup.kofa.utils.helpers import get_current_principal, to_timezone
     66
     67grok.context(IKofaObject) # Make IKofaObject the default context
    6568
    6669# Save function used for save methods in pages
     
    19151918            mapping = {'a':self.student_id}))
    19161919        return
     1920
     1921class StudentRequestPasswordPage(KofaAddFormPage):
     1922    """Captcha'd registration page for applicants.
     1923    """
     1924    grok.name('requestpw')
     1925    grok.require('waeup.Anonymous')
     1926    grok.template('requestpw')
     1927    form_fields = grok.AutoFields(IStudentRequestPW).select(
     1928        'firstname','reg_number','email')
     1929    label = _('Request password for first-time login')
     1930
     1931    def update(self):
     1932        # Handle captcha
     1933        self.captcha = getUtility(ICaptchaManager).getCaptcha()
     1934        self.captcha_result = self.captcha.verify(self.request)
     1935        self.captcha_code = self.captcha.display(self.captcha_result.error_code)
     1936        return
     1937
     1938    def _redirect(self, email, password, student_id):
     1939        # Forward only email to landing page in base package.
     1940        self.redirect(self.url(self.context, 'requestpw_complete',
     1941            data = dict(email=email)))
     1942        return
     1943
     1944    def _pw_used(self):
     1945        # XXX: False if password has been used
     1946        return True
     1947
     1948    @action(_('Get login credentials'), style='primary')
     1949    def get_credentials(self, **data):
     1950        if not self.captcha_result.is_valid:
     1951            # Captcha will display error messages automatically.
     1952            # No need to flash something.
     1953            return
     1954        reg_number = data.get('reg_number','')
     1955        firstname = data.get('firstname','')
     1956        cat = getUtility(ICatalog, name='students_catalog')
     1957        results = list(
     1958            cat.searchResults(reg_number=(reg_number, reg_number)))
     1959        if results:
     1960            student = results[0]
     1961            if getattr(student,'firstname',None) is None:
     1962                self.flash(_('An error occurred.'))
     1963                return
     1964            elif student.firstname.lower() != firstname.lower():
     1965                # Don't tell the truth here. Anonymous must not
     1966                # know that a record was found and only the firstname
     1967                # verification failed.
     1968                self.flash(_('No student record found.'))
     1969                return
     1970            elif student.password is not None and self._pw_used:
     1971                self.flash(_('Your password has already been set and used. '
     1972                             'Please proceed to the login page.'))
     1973                return
     1974            # Store email address but nothing else.
     1975            student.email = data['email']
     1976            notify(grok.ObjectModifiedEvent(student))
     1977        else:
     1978            # No record found, this is the truth.
     1979            self.flash(_('No student record found.'))
     1980            return
     1981
     1982        kofa_utils = getUtility(IKofaUtils)
     1983        password = kofa_utils.genPassword()
     1984        IUserAccount(student).setPassword(password)
     1985        # Send email with credentials
     1986        login_url = self.url(grok.getSite(), 'login')
     1987        msg = _('You have successfully requested a password for the')
     1988        if kofa_utils.sendCredentials(IUserAccount(student),
     1989            password, login_url, msg):
     1990            email_sent = student.email
     1991        else:
     1992            email_sent = None
     1993        self._redirect(email=email_sent, password=password,
     1994            student_id=student.student_id)
     1995        return
     1996
     1997class StudentRequestPasswordEmailSent(KofaPage):
     1998    """Landing page after successful password request.
     1999
     2000    """
     2001    grok.name('requestpw_complete')
     2002    grok.require('waeup.Public')
     2003    grok.template('requestpwmailsent')
     2004    label = _('Your password request was successful.')
     2005
     2006    def update(self, email=None, student_id=None, password=None):
     2007        self.email = email
     2008        self.password = password
     2009        self.student_id = student_id
     2010        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py

    r8736 r8779  
    281281        )
    282282
     283class IStudentRequestPW(IStudent):
     284    """Representation of an student for first-time password request.
     285
     286    This interface is used when students use the requestpw page to
     287    login for the the first time.
     288    """
     289    reg_number = schema.TextLine(
     290        title = u'Registration Number',
     291        required = True,
     292        )
     293
     294    firstname = schema.TextLine(
     295        title = _(u'First Name'),
     296        required = True,
     297        )
     298
     299    email = schema.ASCIILine(
     300        title = _(u'Email Address'),
     301        required = True,
     302        constraint=validate_email,
     303        )
     304
    283305class IStudentStudyCourse(IKofaObject):
    284306    """A container for student study levels.
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py

    r8765 r8779  
    18441844
    18451845    def test_change_password_request(self):
    1846         self.browser.open('http://localhost/app/sendpw')
     1846        self.browser.open('http://localhost/app/changepw')
    18471847        self.browser.getControl(name="form.identifier").value = '123'
    18481848        self.browser.getControl(name="form.email").value = 'aa@aa.ng'
     
    18871887        self.browser.open(self.edit_clearance_path)
    18881888        self.assertTrue('Employer' in self.browser.contents)
     1889
     1890class StudentRequestPWTests(StudentsFullSetup):
     1891    # Tests for student registration
     1892
     1893    layer = FunctionalLayer
     1894
     1895    def test_request_pw(self):
     1896        # Student with wrong reg_number can't be found.
     1897        self.browser.open('http://localhost/app/requestpw')
     1898        self.browser.getControl(name="form.firstname").value = 'Anna'
     1899        self.browser.getControl(name="form.reg_number").value = 'anynumber'
     1900        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
     1901        self.browser.getControl("Get login credentials").click()
     1902        self.assertTrue('No student record found.'
     1903            in self.browser.contents)
     1904        # Anonymous is not informed that firstname verification failed.
     1905        # It seems that the record doesn't exist.
     1906        self.browser.open('http://localhost/app/requestpw')
     1907        self.browser.getControl(name="form.firstname").value = 'Johnny'
     1908        self.browser.getControl(name="form.reg_number").value = '123'
     1909        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
     1910        self.browser.getControl("Get login credentials").click()
     1911        self.assertTrue('No student record found.'
     1912            in self.browser.contents)
     1913        # Even with the correct firstname we can't register if a
     1914        # password has been set and used.
     1915        self.browser.getControl(name="form.firstname").value = 'Anna'
     1916        self.browser.getControl(name="form.reg_number").value = '123'
     1917        self.browser.getControl("Get login credentials").click()
     1918        self.assertTrue('Your password has already been set and used.'
     1919            in self.browser.contents)
     1920        self.browser.open('http://localhost/app/requestpw')
     1921        self.app['students'][self.student_id].password = None
     1922        # The firstname field, used for verification, is not case-sensitive.
     1923        self.browser.getControl(name="form.firstname").value = 'aNNa'
     1924        self.browser.getControl(name="form.reg_number").value = '123'
     1925        self.browser.getControl(name="form.email").value = 'new@yy.zz'
     1926        self.browser.getControl("Get login credentials").click()
     1927        # Yeah, we succeded ...
     1928        self.assertTrue('Your password request was successful.'
     1929            in self.browser.contents)
     1930        # ... and  student can be found in the catalog via the email address
     1931        cat = queryUtility(ICatalog, name='students_catalog')
     1932        results = list(
     1933            cat.searchResults(
     1934            email=('new@yy.zz', 'new@yy.zz')))
     1935        self.assertEqual(self.student,results[0])
     1936        return
Note: See TracChangeset for help on using the changeset viewer.