~sakuag333/mailman/lmtp-duplicate-id

« back to all changes in this revision

Viewing changes to src/mailman/rest/users.py

  • Committer: Barry Warsaw
  • Date: 2012-12-26 23:57:33 UTC
  • mfrom: (7191.1.4 lp1065447)
  • Revision ID: barry@list.org-20121226235733-1bccgsjdgmijeqw0
 * A user's password can be verified by POSTing to .../user/<id>/login.  The
   data must contain a single parameter `cleartext_password` and if this
   matches, a 204 (No Content) will be returned, otherwise a 403 (Forbidden)
   is returned.  (LP: #1065447)

Also:
 * Clean up the users.rst REST page so that it reads as better documentation.
   Move some tests into the unittests.
 * Fix (with a new test), the handling of ExistingAddressError when creating
   new users via REST.
 * Fix (with a new test), the crashing when .../users/<id>/addresses is
   referenced on a non-existing user.
 * Add hex_md5 as a deprecated passlib hash scheme for the test suite.  This
   allows us to test hash migration by creating an initial has as hex_md5
   (another crappy hash), and watching verified passwords get migrated to
   roundup_plaintext (and even crappier hash ;).

Show diffs side-by-side

added added

removed removed

Lines of Context:
119
119
        try:
120
120
            user = getUtility(IUserManager).create_user(**arguments)
121
121
        except ExistingAddressError as error:
122
 
            return http.bad_request([], b'Address already exists {0}'.format(
123
 
                error.email))
 
122
            return http.bad_request(
 
123
                [], b'Address already exists: {0}'.format(error.address))
124
124
        if password is None:
125
125
            # This will have to be reset since it cannot be retrieved.
126
126
            password = generate(int(config.passwords.password_length))
166
166
    @resource.child()
167
167
    def addresses(self, request, segments):
168
168
        """/users/<uid>/addresses"""
 
169
        if self._user is None:
 
170
            return http.not_found()
169
171
        return UserAddresses(self._user)
170
172
 
171
173
    @resource.DELETE()
226
228
        except ValueError as error:
227
229
            return http.bad_request([], str(error))
228
230
        return no_content()
 
231
 
 
232
    @resource.child('login')
 
233
    def login(self, request, segments):
 
234
        """Log the user in, sort of, by verifying a given password."""
 
235
        if self._user is None:
 
236
            return http.not_found()
 
237
        # We do not want to encrypt the plaintext password given in the POST
 
238
        # data.  That would hash the password, but we need to have the
 
239
        # plaintext in order to pass into passlib.
 
240
        validator = Validator(cleartext_password=GetterSetter(unicode))
 
241
        try:
 
242
            values = validator(request)
 
243
        except ValueError as error:
 
244
            return http.bad_request([], str(error))
 
245
        is_valid, new_hash = config.password_context.verify(
 
246
            values['cleartext_password'], self._user.password)
 
247
        if is_valid:
 
248
            if new_hash is not None:
 
249
                self._user.password = new_hash
 
250
            return no_content()
 
251
        return http.forbidden()