unittest_registration.py 7.31 KB
Newer Older
Sylvain Thénault's avatar
Sylvain Thénault committed
1
2
3
import cgi
import re
import urlparse
4
from contextlib import contextmanager
5

6
from cubicweb.crypto import encrypt, decrypt
Sylvain Thénault's avatar
Sylvain Thénault committed
7
from cubicweb.devtools.testlib import MAILBOX, CubicWebTC
8
9


Sylvain Thénault's avatar
Sylvain Thénault committed
10
class RegistrationTC(CubicWebTC):
11

Florent's avatar
Florent committed
12
13
    captcha_value = u'captcha value'

Katia Saurfelt's avatar
WIp    
Katia Saurfelt committed
14
15
16
    data = {'firstname-subject': 'Toto', 'surname-subject': 'Toto',
            'email_address-subject': 'toto@secondweb.fr',
            'login-subject': 'toto',
17
18
            'upassword-subject': 'toto',
            'upassword-subject-confirm': 'toto',
Florent's avatar
Florent committed
19
            'captcha': captcha_value}
20
21

    def setup_database(self):
22
        self.config.global_set_option('registration-cypher-seed', u'dummy cypher key')
23
24
        super(RegistrationTC, self).setup_database()

25
    def _check_user_not_created(self):
26
27
28
29
        with self.admin_access.repo_cnx() as cnx:
            rset = cnx.execute('CWUser X WHERE X login %(login)s',
                               {'login': self.data['login-subject']})
            self.assertFalse(rset)
30
31
32
33

    def _check_error(self, req, path,
                     expected_path='registration',
                     expected_errors=None,
34
                     expected_msg=None,
35
                     expected_formvalues=None):
36
        path, params = self.expect_redirect_handle_request(req, path)
Sylvain Thénault's avatar
Sylvain Thénault committed
37
        self.assertEqual(path, expected_path)
38
39
40
        if expected_msg:
            self.assertMessageEqual(req, params, expected_msg)
        forminfo = req.session.data.get('registration')
41
42
43
        if forminfo is None:
            self.failIf(expected_errors or expected_formvalues)
        else:
Sylvain Thénault's avatar
Sylvain Thénault committed
44
45
            self.assertEqual(forminfo['eidmap'], {})
            self.assertEqual(forminfo['values'], expected_formvalues or {})
46
            error = forminfo['error']
Sylvain Thénault's avatar
Sylvain Thénault committed
47
48
            self.assertEqual(error.entity, None)
            self.assertEqual(error.errors, expected_errors or {})
49
50
51
52
53

    def _posted_form(self, *skipkeys):
        data = self.data.copy()
        for key in skipkeys:
            data.pop(key, None)
Sylvain Thénault's avatar
Sylvain Thénault committed
54
        if '__errorurl' not in skipkeys:
55
56
57
            data['__errorurl'] = 'registration'
        return data

58
    def test_registration_form(self):
59
60
61
        with self.admin_access.web_request() as req:
            req.form = {'firstname-subject': u'Toto'}
            pageinfo = self.view('registration', req=req, rset=None)
62

63
        # check form field names
64
        names = pageinfo.etree.xpath('//form[@id="registrationForm"]//input[@type!="hidden"]/@name')
Sylvain Thénault's avatar
Sylvain Thénault committed
65
        self.assertEqual(set(names), set(self.data))
66

67
        # check form field value
68
        firstname = pageinfo.etree.xpath('//input[@name="firstname-subject"]/@value')
Sylvain Thénault's avatar
Sylvain Thénault committed
69
        self.assertEqual(firstname, [req.form['firstname-subject']])
70
71

    def test_send_mail_ok(self):
72
73
74
        with self.new_access(u'anon').web_request() as req:
            req.form = self._posted_form()
            req.session.data['captcha'] = self.captcha_value
75
            path, params = self.expect_redirect_handle_request(req, 'registration_sendmail')
76
            self.assertEqual(path, '')
Sylvain Thénault's avatar
Sylvain Thénault committed
77
78
79
80
            self.assertMessageEqual(
                req, params,
                'Your registration email has been sent. '
                'Follow instructions in there to activate your account.')
81
82
83
84
85
86
87
            # check email contains activation url...
            URL_RE = re.compile('(%s[^.]+)$' % self.config['base-url'], re.M)
            text = MAILBOX[-1].message.get_payload(decode=True)
            url = URL_RE.search(text).group(1)
            # ... and the registration key contains all data
            key = dict(cgi.parse_qsl(urlparse.urlsplit(url)[3]))['key']
            d = self._posted_form('upassword-subject-confirm')
Katia Saurfelt's avatar
WIp    
Katia Saurfelt committed
88
89
90
            decrypred = decrypt(key, self.config['registration-cypher-seed'])
            decrypred['upassword-subject'] = decrypred['upassword-subject'].decode("utf8")
            self.assertDictEqual(decrypred, d)
91
92

    def test_send_mail_failure(self):
93
94
95
        for param, msg, val in (('login-subject', 'required field', None),
                                ('captcha', 'required field', None),
                                ('captcha', 'incorrect captcha value', 'abc')):
96
97
98
99
100
101
102
103
104
105
106
107
108
            with self.admin_access.web_request() as req:
                if val is None:
                    req.form = self._posted_form(param)
                else:
                    req.form = self._posted_form()
                    req.form[param] = val
                req.session.data['captcha'] = self.captcha_value
                self._check_error(req, 'registration_sendmail',
                                  expected_formvalues=req.form,
                                  expected_errors={param: msg})
                self.assertEqual(req.session.data.get('captcha'), None)

    @contextmanager
109
    def _confirm_req(self, key=None, overriden={}):
110
111
112
113
114
115
116
        with self.new_access(u'anon').web_request() as req:
            data = self._posted_form('upassword-subject-confirm')
            data.update(overriden)
            if key is None:
                key = encrypt(data, self.config['registration-cypher-seed'])
            req.form = {'key': key}
            yield req
Florent's avatar
Florent committed
117
118

    def test_confirm_ok(self):
119
        with self._confirm_req() as req:
120
            path, params = self.expect_redirect_handle_request(req, 'registration_confirm')
121
            self.assertEqual(path, '')
Sylvain Thénault's avatar
Sylvain Thénault committed
122
123
124
            self.assertMessageEqual(
                req, params,
                'Congratulations, your registration is complete. '
125
                'You can now <a href="{}">login</a>.'.format(req.build_url('login')))
126
127
        with self.admin_access.repo_cnx() as cnx:
            rset = cnx.execute('Any U WHERE U login %(login)s, U firstname %(firstname)s, '
Sylvain Thénault's avatar
Sylvain Thénault committed
128
129
130
                               'U surname %(surname)s, U use_email M, M address %(email_address)s',
                               dict((k.replace('-subject', ''), v)
                                    for k, v in self.data.items()))
131
            self.assertTrue(rset)
132

Florent's avatar
Florent committed
133
    def test_confirm_failure_login_already_used(self):
134
        # try to recreate a 'admin' user.
135
        with self._confirm_req(overriden={'login-subject': u'admin'}) as req:
136
137
138
            formvalues = self._posted_form('upassword-subject',
                                           'upassword-subject-confirm')
            formvalues['login-subject'] = 'admin'
Sylvain Thénault's avatar
Sylvain Thénault committed
139
140
141
142
143
            self._check_error(
                req, 'registration_confirm',
                expected_formvalues=formvalues,
                expected_errors={'login-subject':
                                 'the value "admin" is already used, use another one'})
144
145

    def test_confirm_failure_invalid_data(self):
146
        with self._confirm_req('dummykey') as req:
Sylvain Thénault's avatar
Sylvain Thénault committed
147
148
149
            self._check_error(
                req, 'registration_confirm', 'register',
                expected_msg='Invalid registration data. Please try registering again.')
Florent's avatar
Florent committed
150
151
152
        self._check_user_not_created()

    def test_confirm_failure_email_already_used(self):
153
154
155
        with self.admin_access.web_request() as req:
            self.create_user(req, 'test')
            req.execute('INSERT EmailAddress X: U use_email X, X address %(email_address)s '
Sylvain Thénault's avatar
Sylvain Thénault committed
156
157
                        'WHERE U login "test"',
                        {'email_address': self.data['email_address-subject']})
158
159
160
            req.cnx.commit()
        with self._confirm_req() as req:
            req.form['__errorurl'] = 'registration'
Florent's avatar
Florent committed
161
        self._check_user_not_created()
Sylvain Thénault's avatar
Sylvain Thénault committed
162

Sylvain Thénault's avatar
Sylvain Thénault committed
163

Sylvain Thénault's avatar
Sylvain Thénault committed
164
if __name__ == '__main__':
165
166
    import unittest
    unittest.main()