def _authenticate_newstyle(self, environ, username, identity): """Authenticate against a new-style auth backend.""" user = User(username) if not self.backend.authenticate_user(user, identity, ['syncNode']): user = None else: if self.config.get('auth.check_node'): if user.get('syncNode') != environ.get('HTTP_HOST'): user = None return user
def create_user(self, user_name, password, email): """Creates a user. Returns a user object on success.""" if not self.allow_new_users: raise BackendError("Creation of new users is disabled") # no unicode user_name = user_name.encode('utf8') password = password.encode('utf8') email = email.encode('utf8') #First make sure the username isn't taken. There'll still be a race #condition, but it's pretty small test_user = User() test_user['username'] = user_name dn = self._get_dn(test_user) if dn is not None: return False user_id = self._get_next_user_id() password_hash = ssha(password) key = '%s%s' % (random.randint(0, 9999999), user_name) key = sha1(key).hexdigest() user = { 'cn': user_name, 'sn': user_name, 'uid': user_name, 'uidNumber': str(user_id), 'userPassword': password_hash, 'primaryNode': 'weave:', 'accountStatus': '1', 'account-enabled': 'Yes', 'mail': email, 'mail-verified': key, 'objectClass': ['dataStore', 'inetOrgPerson'] } dn = "uidNumber=%i,%s" % (user_id, self.users_root) #need a copy with some of the info for the return value userobj = User() userobj['username'] = user['uid'] userobj['userid'] = user['uidNumber'] userobj['mail'] = email userobj['dn'] = dn #need to turn the user hash into tuples user = user.items() with self._conn() as conn: try: res, __ = conn.add_s(dn, user) except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e: self.logger.debug('Could not create the user.') raise BackendError(str(e))
def create_user(self, username, password, email, **extra_fields): """Creates a user. Returns True on success.""" if not self.allow_new_users: raise BackendError("Creation of new users is disabled") password_hash = sscrypt(password) values = { 'username': username, 'password': password_hash, 'mail': email, } for field in ('userid', 'accountStatus', 'mailVerified', 'syncNode'): if field in extra_fields: values[field] = extra_fields[field] query = insert(users).values(**values) try: res = safe_execute(self._engine, query) except IntegrityError: #Name already exists return False if res.rowcount != 1: return False #need a copy with some of the info for the return value userobj = User() userobj['username'] = username userobj['userid'] = res.lastrowid userobj['mail'] = email return userobj
def setUp(self): # loading the app self.appdir, self.config, self.auth = initenv() self.app = TestApp(make_app(self.config)) # adding a user if needed self.email = '*****@*****.**' % random.randint(1, 1000) self.user_name = extract_username(self.email) self.user = User(self.user_name) self.user_id = self.auth.get_user_id(self.user) self.password = '******' * 9 if self.user_id is None: self.auth.create_user(self.user_name, self.password, self.email) self.user_id = self.auth.get_user_id(self.user) # for the ldap backend, filling available_nodes if self.auth.__class__.__name__ == 'LDAPAuth': query = ('insert into available_nodes (node, ct, actives) values ' ' ("weave:localhost", 10, 10)') self.auth._engine.execute(query) try: self.nodes = load_and_configure(self.config, 'nodes') except KeyError: logger.debug(traceback.format_exc()) logger.debug("No node library in place") self.nodes = None try: self.reset = load_and_configure(self.config, 'reset_codes') except Exception: logger.debug(traceback.format_exc()) logger.debug("No reset code library in place") self.reset = None
def create_user(self, user_name, password, email): """Creates a user""" if not self.allow_new_users: raise BackendError("Creation of new users is disabled") user = User() if user_name in self._users: return False id_ = random.randint(1, 2000) ids = self._users.values() while id_ in ids: id_ = random.randint(1, 2000) self._users[user_name] = { 'userid': id_, 'password': password, 'mail': email, 'username': user_name, 'primaryNode': '' } user['username'] = user_name user['userid'] = id_ user['mail'] = email return user
def login_as_user(): username = input("Username: ") user = User(username, True if username == 'admin' else False) if bool(user.admin): show_admin_menu(user) else: show_user_menu(user)
def test_create_user(self): # creating a user email = '*****@*****.**' % (time.time(), random.randint(1, 100)) name = extract_username(email) user_url = '/user/1.0/%s' % name try: # the user already exists payload = {'email': email, 'password': '******' * 9} payload = json.dumps(payload) res = self.app.put(self.root, params=payload, status=400) self.assertEquals(res.json, ERROR_INVALID_WRITE) # missing the password payload = {'email': email} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, status=400) self.assertEquals(res.json, ERROR_MISSING_PASSWORD) # malformed e-mail payload = {'email': 'bademailhere', 'password': '******' * 9} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, status=400) self.assertEquals(res.json, ERROR_NO_EMAIL_ADDRESS) # weak password payload = {'email': email, 'password': '******'} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, status=400) self.assertEquals(res.json, ERROR_WEAK_PASSWORD) # weak password #2 payload = {'email': email, 'password': '******'} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, status=400) self.assertEquals(res.json, ERROR_WEAK_PASSWORD) # the user name does not match the email payload = {'email': '*****@*****.**', 'password': '******' * 9} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, status=400) self.assertEquals(res.json, ERROR_USERNAME_EMAIL_MISMATCH) # everything is there res = self.app.get(user_url) self.assertFalse(json.loads(res.body)) payload = {'email': email, 'password': '******' * 9, 'captcha-challenge': 'xxx', 'captcha-response': 'xxx'} payload = json.dumps(payload) res = self.app.put(user_url, params=payload) self.assertEquals(res.body, name) res = self.app.get(user_url) self.assertTrue(json.loads(res.body)) finally: self.auth.delete_user(User(name), 'x' * 9)
def _create_user(self, username, password, email=None, syncNode=None): """Create a user in the DB, and return the user object.""" if not email: email = '*****@*****.**' if not syncNode: syncNode = 'http://sync1.example.com' self.auth.create_user(username, password, email) user = self.auth.get_user_info(User(username), ['syncNode']) self.auth.admin_update_field(user, 'syncNode', syncNode) return user
def _authenticate_oldstyle(self, environ, username, identity): """Authenticate against an old-style auth backend.""" password = identity.get("password") if password is None: return None if hasattr(self.backend, 'check_node') and self.backend.check_node: host = environ.get('HTTP_HOST') user_id = self.backend.authenticate_user(username, password, host) else: user_id = self.backend.authenticate_user(username, password) if user_id is None: return None return User(username, user_id)
def _dispatch_request_with_match(self, request, match): """Dispatch a request according to a URL routing match.""" function = self._get_function(match['controller'], match['action']) if function is None: raise HTTPNotFound('Unknown URL %r' % request.path_info) # extracting all the info from the headers and the url request.sync_info = match # creating a user object to be passed around the request, if one hasn't # already been set if not hasattr(request, 'user'): request.user = User() if 'username' in request.sync_info: request.user['username'] = request.sync_info['username'] if 'user_id' in request.sync_info: request.user['userid'] = request.sync_info['user_id'] params = self._get_params(request) try: result = function(request, **params) except BackendError as err: err.request = request err_info = str(err) err_trace = traceback.format_exc() extra_info = [ '%s: %s' % (key, value) for key, value in self.get_infos(request).items() ] extra_info = '\n'.join(extra_info) error_log = '%s\n%s\n%s' % (err_info, err_trace, extra_info) hash = create_hash(error_log) self.logger.error(hash) self.logger.error(error_log) msg = json.dumps("application error: crash id %s" % hash) if err.retry_after is not None: if err.retry_after == 0: retry_after = None else: retry_after = err.retry_after else: retry_after = self.retry_after raise HTTPJsonServiceUnavailable(msg, retry_after=retry_after) # create the response object in case we get back a string response = self._create_response(request, result, function) return response
def load_emulator_scene(): print_info_message('\nYou are in emulator mode\n') for username in usernames: user = User(username) for i in range(1, 2): # time.sleep(random.random() * 2) # if not random.getrandbits(1): # read_message(user) publish_message(user) try: for message in listener.listen(): if message.get('type') == 'message': msg = ChatController.convert_to_message_object(message.get('data')) process_message(msg) except KeyboardInterrupt: pass
def check(self, request, match): """Checks if the current request/match can be viewed. For WhoAuthentication this just delegates to the authenticate() API method, and uses the challenge() method if the user is not authorized for the request. """ # Don't auth if it's not required by the match. if match.get('auth') != 'True': return # If something further up the stack has already dealt with auth, # then things are highly unlikely to work properly. if 'REMOTE_USER' in request.environ: msg = 'The webserver appears to have handled authentication '\ 'internally, which is not compatible with this product.' raise HTTPServerError(msg) # Authenticate the user. api = self._api_factory(request.environ) identity = api.authenticate() if identity is None: self._raise_challenge(request) # Check against the username matched from the url, if any. username = identity.get("username") if match.get("username") not in (None, username): cef_kwds = {"signature": AUTH_FAILURE} if username is not None: cef_kwds["username"] = username err = "Username Does Not Match URL" self.logger.cef(err, 7, request.environ, self.config, **cef_kwds) self._raise_challenge(request) # Adjust environ to record the successful auth. # The identity must somehow get "userid" and "username" keys, # either from the authenticator or from an mdprovider. request.environ.pop("HTTP_AUTHORIZATION", None) match["user_id"] = identity["userid"] request.remote_user = identity["username"] request.environ["REMOTE_USER"] = identity["username"] request.user = User(identity["username"], identity["userid"]) request.user.update(identity)
def do_password_reset(self, request): """Do a password reset.""" if self.reset is None: logger.debug('reset attempted, but no resetcode library installed') raise HTTPServiceUnavailable() user_name = request.POST.get('username') if user_name is not None: user_name = extract_username(user_name) if request.POST.keys() == ['username']: # setting up a password reset # XXX add support for captcha here via **data request.user = User(user_name) try: self.password_reset(request) except (HTTPServiceUnavailable, HTTPJsonBadRequest), e: return render_mako('password_failure.mako', error=e.detail) else: return render_mako('password_key_sent.mako') raise HTTPJsonBadRequest()
def test_change_password_with_header(self): body = 'newpasswordhere' # unknown user extra = [('X-Weave-Password-Reset', 'key')] self.app.post('/user/1.0/_xx_/password', params=body, headers=extra, status=404) # bad key extra = {'X-Weave-Password-Reset': 'key'} res = self.app.post(self.root + '/password', params=body, headers=extra, status=400) self.assertEquals(res.body, '10') user = User(self.user_name) self.auth.get_user_id(user) key = str(self.reset.generate_reset_code(user)) extra = {'X-Weave-Password-Reset': key} res = self.app.post(self.root + '/password', params=body, headers=extra) self.assertEqual(res.body, 'success')
def create_user(self, username, password, email): """Creates a user. Returns user on success, false otherwise.""" if not self.allow_new_users: raise BackendError("Creation of new users is disabled") payload = {'password': password, 'email': email} url = self._generate_url(username) status, body = self._proxy('PUT', url, payload) if status != 200: if body == ERROR_INVALID_WRITE: return False msg = 'Unable to create the user via sreg. ' msg += 'Received body:\n%s\n' % str(body) msg += 'Received status: %d' % status raise BackendError(msg, server=url) # the result is the username on success if body == username: user = User() user['username'] = username user['email'] = email return user else: return False
def test_shared_secret(self): # creating a user email = '*****@*****.**' % (time.time(), random.randint(1, 100)) name = extract_username(email) user_url = '/user/1.0/%s' % name # we want the captcha to fail app = get_app(self.app) app.config['captcha.use'] = True def _failed(self, *args, **kw): return FakeCaptchaResponse(False) captcha.submit = _failed extra = {'X-Weave-Secret': 'xxx'} try: # everything is there, but bad secret. This should # fallback to the captcha test and eventually fail res = self.app.get(user_url) self.assertFalse(json.loads(res.body)) payload = {'email': email, 'password': '******' * 9} payload = json.dumps(payload) res = self.app.put(user_url, params=payload, headers=extra, status=400) self.assertEquals(res.json, ERROR_INVALID_CAPTCHA) # let's use the real secret extra['X-Weave-Secret'] = 'CHANGEME' res = self.app.put(user_url, params=payload, headers=extra) self.assertEquals(res.body, name) res = self.app.get(user_url) self.assertTrue(json.loads(res.body)) finally: self.auth.delete_user(User(name), 'x' * 9)
def authenticate_user(self, request, config, username=None): """Authenticates a user and returns his id. "request" is the request received. The function makes sure that the user name found in the headers is compatible with the username if provided. It returns the user id from the database, if the password is the right one. """ environ = request.environ # If something further up the stack has already dealt with auth, # then things are highly unlikely to work properly. if 'REMOTE_USER' in environ: msg = 'The webserver appears to have handled authentication '\ 'internally, which is not compatible with this product.' raise HTTPServerError(msg) auth = environ.get('HTTP_AUTHORIZATION') if auth is not None: # for now, only supporting basic authentication # let's decipher the base64 encoded value if not auth.startswith('Basic '): self._log_cef('Authorization header contains unknown protocol', 7, environ) raise HTTPUnauthorized('Invalid token') auth = auth[len('Basic '):].strip() try: # Split in such a way as to preserve # passwords that contain ':'. user_name, password = base64.decodestring(auth).split(':', 1) except (binascii.Error, ValueError): self._log_cef('Authorization header is badly encoded', 7, environ) raise HTTPUnauthorized('Invalid token') # let's reject the call if the url is not owned by the user if (username is not None and user_name != username): self._log_cef('Username Does Not Match URL', 7, environ, config, user_name, AUTH_FAILURE) raise HTTPUnauthorized() # if this is an email, hash it. Save the original for logging and # debugging. remote_user_original = user_name try: user_name = extract_username(user_name) except UnicodeError: self._log_cef('Username contains invalid characters', 7, environ) raise HTTPBadRequest( 'Invalid characters specified in ' + 'username', {}, 'Username must be BIDI ' + 'compliant UTF-8') # let's try an authentication # the authenticate_user API takes a unicode UTF-8 for the password try: password = password.decode('utf8') except UnicodeDecodeError: self._log_cef('Password is not utf-8 encoded', 7, environ) raise HTTPUnauthorized() #first we need to figure out if this is old-style or new-style auth if hasattr(self.backend, 'generate_reset_code'): # XXX to be removed once we get the proper fix see bug #662859 if (hasattr(self.backend, 'check_node') and self.backend.check_node): user_id = self.backend.authenticate_user( user_name, password, environ.get('HTTP_HOST')) else: user_id = self.backend.authenticate_user( user_name, password) request.user = User(user_name, user_id) else: user = User(user_name) credentials = {"username": user_name, "password": password} attrs = [] check_node = self.config.get('auth.check_node') if check_node: attrs.append('syncNode') user_id = self.backend.authenticate_user( user, credentials, attrs) if not user_id: user_id = None user = None else: if (check_node and user.get('syncNode') != environ.get('HTTP_HOST')): self._log_cef('User authenticated to wrong node', 7, environ) user_id = None user = None request.user = user if user_id is None: err_user = user_name if remote_user_original is not None and \ user_name != remote_user_original: err_user += ' (%s)' % (remote_user_original) self._log_cef('User Authentication Failed', 5, environ, config, err_user, AUTH_FAILURE) raise HTTPUnauthorized() # we're all clear ! setting up REMOTE_USER request.remote_user = environ['REMOTE_USER'] = user_name # we also want to keep the password in clear text to reuse it # and remove it from the environ request.user_password = password request._authorization = environ['HTTP_AUTHORIZATION'] del environ['HTTP_AUTHORIZATION'] return user_id
def show_ec2_instances(username): instance_list = User.get_all_ec2_instances(username) if len(instance_list)!=0: return render_template("ec2_instances.html",instance_list=instance_list) else: return render_template("ec2_instances.html")
def authenticate_user(self, request, config, username=None): """Authenticates a user and returns his id. "request" is the request received. The function makes sure that the user name found in the headers is compatible with the username if provided. It returns the user id from the database, if the password is the right one. """ environ = request.environ if 'REMOTE_USER' in environ: # already authenticated return environ['REMOTE_USER'] auth = environ.get('HTTP_AUTHORIZATION') if auth is not None: # for now, only supporting basic authentication # let's decipher the base64 encoded value if not auth.startswith('Basic '): raise HTTPUnauthorized('Invalid token') auth = auth[len('Basic '):].strip() try: # Split in such a way as to preserve # passwords that contain ':'. user_name, password = base64.decodestring(auth).split(':', 1) except (binascii.Error, ValueError): raise HTTPUnauthorized('Invalid token') # let's reject the call if the url is not owned by the user if (username is not None and user_name != username): log_cef('Username Does Not Match URL', 7, environ, config, user_name, AUTH_FAILURE) raise HTTPUnauthorized() # if this is an email, hash it. Save the original for logging and # debugging. remote_user_original = user_name try: user_name = extract_username(user_name) except UnicodeError: raise HTTPBadRequest('Invalid characters specified in ' + 'username', {}, 'Username must be BIDI ' + 'compliant UTF-8') # let's try an authentication # the authenticate_user API takes a unicode UTF-8 for the password try: password = password.decode('utf8') except UnicodeDecodeError: raise HTTPUnauthorized() #first we need to figure out if this is old-style or new-style auth if hasattr(self.backend, 'generate_reset_code'): # XXX to be removed once we get the proper fix see bug #662859 if (hasattr(self.backend, 'check_node') and self.backend.check_node): user_id = self.backend.authenticate_user(user_name, password, environ.get('HTTP_HOST')) else: user_id = self.backend.authenticate_user(user_name, password) request.user = User(user_name, user_id) else: user = User(user_name) credentials = {"username": user_name, "password": password} user_id = self.backend.authenticate_user(user, credentials, ['syncNode']) if not user_id: user_id = None user = None else: if (self.config.get('auth.check_node') and user.get('syncNode') != environ.get('HTTP_HOST')): user_id = None user = None request.user = user if user_id is None: err_user = user_name if remote_user_original is not None and \ user_name != remote_user_original: err_user += ' (%s)' % (remote_user_original) log_cef('User Authentication Failed', 5, environ, config, err_user, AUTH_FAILURE) raise HTTPUnauthorized() # we're all clear ! setting up REMOTE_USER request.remote_user = environ['REMOTE_USER'] = user_name # we also want to keep the password in clear text to reuse it # and remove it from the environ request.user_password = password request._authorization = environ['HTTP_AUTHORIZATION'] del environ['HTTP_AUTHORIZATION'] return user_id
def _tests(self, mgr): # Clean it up first if needed. user1_del = User() user1_del['username'] = '******' user2_del = User() user2_del['username'] = '******' mgr.delete_user(user1_del) mgr.delete_user(user2_del) # Create some initial users. user1 = mgr.create_user('user1', u'password1', '*****@*****.**') user1_id = user1['userid'] user2 = mgr.create_user('user2', u'pásswørd1', '*****@*****.**') user2_id = user2['userid'] user3 = User() user3['username'] = '******' # Make sure it can't create an existing user. self.assertEquals(mgr.create_user('user1', 'password1', '*****@*****.**'), False) # Check it can successfully authenticate existing users. credentials1 = {"username": "******", "password": "******"} credentials2 = {"username": "******", "password": u"pásswørd1"} self.assertEquals(mgr.authenticate_user(user1, credentials1), user1_id) self.assertEquals(mgr.authenticate_user(user2, credentials2), user2_id) # Check that using a raw password works, but gives DeprecationWarning. with warnings.catch_warnings(record=True) as w: warnings.simplefilter("default") self.assertEquals(mgr.authenticate_user(user1, "password1"), user1_id) self.assertEquals(len(w), 1) self.assertTrue("dict of credentials" in str(w[0].message)) # Make sure that empty credentials doesn't do bad things. self.assertEquals(mgr.authenticate_user(user2, {}), None) # Start with an unpopulated User object. user1_new = User() self.assertEquals(user1_new.get('username', None), None) self.assertEquals(user1_new.get('mail', None), None) # We should be able to populate it by authenticating. self.assertEquals(mgr.authenticate_user(user1_new, credentials1), user1_id) self.assertEquals(user1_new['username'], 'user1') self.assertEquals(user1_new['userid'], user1_id) self.assertEquals(user1_new.get('mail', None), None) # If the User object is already populated, then it will only # authenticate correctly using that user's credentials. user2_new = User() user2_new["username"] = "******" self.assertEquals(mgr.authenticate_user(user2_new, credentials1), None) self.assertEquals(user2_new['username'], 'user2') self.assertEquals(mgr.authenticate_user(user2_new, credentials2), user2_id) self.assertEquals(user2_new['username'], 'user2') # We can load additional fields explicitly. user1_new = mgr.get_user_info(user1_new, ['mail', 'syncNode']) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') self.assertEquals(user1_new.get('primaryNode', ''), '') # We can't update a field using invalid credentials. badcreds = {"username": "******", "password": "******"} self.assertFalse(mgr.update_field(user1_new, badcreds, 'mail', '*****@*****.**')) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') # We can't update a field using someone else's credentials. self.assertFalse(mgr.update_field(user1_new, credentials2, 'mail', '*****@*****.**')) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') # But it'll work using the proper credentials. self.assertTrue(mgr.update_field(user1_new, credentials1, 'mail', '*****@*****.**')) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') # And it'll work using the admin interface. self.assertTrue(mgr.admin_update_field(user1_new, 'mail', '*****@*****.**')) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') # Updating a nonexistent user should fail. self.assertFalse(mgr.admin_update_field(user3, 'mail', 'foo')) # Did those changes persist? user1_new = User() self.assertEquals(user1_new.get('mail', None), None) user1_new['username'] = '******' user1_new = mgr.get_user_info(user1_new, ['mail', 'syncNode']) self.assertEquals(user1_new.get('mail', None), '*****@*****.**') # Changing password requires proper credentials. self.assertFalse(mgr.update_password(user1_new, badcreds, 'password2')) self.assertFalse(mgr.update_password(user1_new, credentials2, 'password2')) self.assertTrue(mgr.update_password(user1_new, credentials1, 'password2')) # The password change affects future authentications. self.assertEquals(mgr.authenticate_user(user1, credentials1), None) credentials1["password"] = "******" self.assertEquals(mgr.authenticate_user(user1, credentials1), user1_id) # Use the admin interface to change password without credentials. self.assertTrue(mgr.admin_update_password(user1_new, 'password3')) self.assertEquals(mgr.authenticate_user(user1, credentials1), None) credentials1["password"] = "******" self.assertEquals(mgr.authenticate_user(user1, credentials1), user1_id) # Users can be deleted, but only once. self.assertTrue(mgr.delete_user(user1)) self.assertFalse(mgr.delete_user(user1)) # Users can't log in after deletion, other users aren't affected. self.assertEquals(mgr.authenticate_user(user1, credentials1), None) self.assertEquals(mgr.authenticate_user(user2, credentials2), user2_id)
class UserController(object): def __init__(self, app): self.app = app self.strict_usernames = app.config.get('auth.strict_usernames', True) self.shared_secret = app.config.get('global.shared_secret') self.auth = self.app.auth.backend self.fallback_node = \ self.clean_location(app.config.get('nodes.fallback_node')) try: self.reset = load_and_configure(app.config, 'reset_codes') except Exception: logger.debug(traceback.format_exc()) logger.debug("No reset code library in place") self.reset = None def user_exists(self, request): if request.user.get('username') is None: raise HTTPNotFound() uid = self.auth.get_user_id(request.user) return text_response(int(uid is not None)) def return_fallback(self): if self.fallback_node is None: return json_response(None) return self.fallback_node def clean_location(self, location): if location is None: return None if not location.endswith('/'): location += '/' if not location.startswith('http'): location = 'https://%s' % location return location def user_node(self, request): """Returns the storage node root for the user""" # warning: # the client expects a string body not a json body # except when the node is 'null' # IF YOU ARE USING ACTUAL NODE ASSIGNMENT (odds are you're not) # There is now a separate assignment module: # http://hg.mozilla.org/services/server-node-assignment # Install that and point your server at it for # the node assignment call if request.user.get('username') is None: raise HTTPNotFound() if not self.auth.get_user_id(request.user): raise HTTPNotFound() return self.return_fallback() def password_reset(self, request, **data): """Sends an e-mail for a password reset request.""" if self.reset is None: logger.debug('reset attempted, but no resetcode library installed') raise HTTPServiceUnavailable() user_id = self.auth.get_user_id(request.user) if user_id is None: # user not found raise HTTPJsonBadRequest(ERROR_INVALID_USER) self.auth.get_user_info(request.user, ['mail']) if request.user.get('mail') is None: raise HTTPJsonBadRequest(ERROR_NO_EMAIL_ADDRESS) self._check_captcha(request, data) try: # the request looks fine, let's generate the reset code code = self.reset.generate_reset_code(request.user) data = { 'host': request.host_url, 'user_name': request.user['username'], 'code': code } body = render_mako('password_reset_mail.mako', **data) sender = request.config['smtp.sender'] host = request.config['smtp.host'] port = int(request.config['smtp.port']) user = request.config.get('smtp.user') password = request.config.get('smtp.password') subject = 'Resetting your Services password' res, msg = send_email(sender, request.user['mail'], subject, body, host, port, user, password) if not res: raise HTTPServiceUnavailable(msg) except AlreadySentError: #backend handled the reset code email. Keep going pass return text_response('success') def delete_password_reset(self, request, **data): """Forces a password reset clear""" if self.reset is None: logger.debug('reset attempted, but no resetcode library installed') raise HTTPServiceUnavailable() self._check_captcha(request, data) self.auth.get_user_id(request.user) self.reset.clear_reset_code(request.user) log_cef("User requested password reset clear", 9, request.environ, self.app.config, request.user.get('username'), PASSWD_RESET_CLR) return text_response('success') def _check_captcha(self, request, data): # check if captcha info are provided if not self.app.config['captcha.use']: return challenge = data.get('captcha-challenge') response = data.get('captcha-response') if challenge is not None and response is not None: resp = captcha.submit(challenge, response, self.app.config['captcha.private_key'], remoteip=request.remote_addr) if not resp.is_valid: raise HTTPJsonBadRequest(ERROR_INVALID_CAPTCHA) else: raise HTTPJsonBadRequest(ERROR_INVALID_CAPTCHA) def create_user(self, request): """Creates a user.""" if self.auth.get_user_id(request.user): raise HTTPJsonBadRequest(ERROR_INVALID_WRITE) username = request.user['username'] try: data = json.loads(request.body) except ValueError: raise HTTPJsonBadRequest(ERROR_MALFORMED_JSON) email = data.get('email') if email and not valid_email(email): raise HTTPJsonBadRequest(ERROR_NO_EMAIL_ADDRESS) # checking that the e-mail matches the username munged_email = extract_username(email) if munged_email != username and self.strict_usernames: raise HTTPJsonBadRequest(ERROR_USERNAME_EMAIL_MISMATCH) password = data.get('password') if not password: raise HTTPJsonBadRequest(ERROR_MISSING_PASSWORD) if not valid_password(username, password): raise HTTPJsonBadRequest(ERROR_WEAK_PASSWORD) # check if captcha info are provided or if we bypass it if (self.shared_secret is None or request.headers.get('X-Weave-Secret') != self.shared_secret): self._check_captcha(request, data) # all looks good, let's create the user if not self.auth.create_user(request.user['username'], password, email): raise HTTPInternalServerError('User creation failed.') return request.user['username'] def change_email(self, request): """Changes the user e-mail""" # the body is in plain text email = request.body if not valid_email(email): raise HTTPJsonBadRequest(ERROR_NO_EMAIL_ADDRESS) if not hasattr(request, 'user_password'): raise HTTPBadRequest() if not self.auth.update_field(request.user, request.user_password, 'mail', email): raise HTTPInternalServerError('User update failed.') return text_response(email) def change_password(self, request): """Changes the user's password Takes a classical authentication or a reset code """ # the body is in plain text utf8 string new_password = request.body.decode('utf8') if not valid_password(request.user.get('username'), new_password): raise HTTPBadRequest('Password should be at least 8 ' 'characters and not the same as your ' 'username') key = request.headers.get('X-Weave-Password-Reset') if key is not None: user_id = self.auth.get_user_id(request.user) if user_id is None: raise HTTPNotFound() if not self.reset.verify_reset_code(request.user, key): log_cef('Invalid Reset Code submitted', 5, request.environ, self.app.config, request.user['username'], 'InvalidResetCode', submitedtoken=key) raise HTTPJsonBadRequest(ERROR_INVALID_RESET_CODE) if not self.auth.admin_update_password(request.user, new_password, key): raise HTTPInternalServerError('Password change failed ' 'unexpectedly.') else: # classical auth self.app.auth.authenticate_user(request, self.app.config, request.user['username']) if request.user['userid'] is None: log_cef('User Authentication Failed', 5, request.environ, self.app.config, request.user['username'], AUTH_FAILURE) raise HTTPUnauthorized() if not self.auth.update_password( request.user, request.user_password, new_password): raise HTTPInternalServerError('Password change failed ' 'unexpectedly.') return text_response('success') def password_reset_form(self, request, **kw): """Returns a form for resetting the password""" if 'key' in kw or 'error' in kw: # we have a key, let's display the key controlling form return render_mako('password_reset_form.mako', **kw) elif not request.POST and not request.GET: # asking for the first time return render_mako('password_ask_reset_form.mako') raise HTTPBadRequest() def _repost(self, request, error): request.POST['error'] = error return self.password_reset_form(request, **dict(request.POST)) def do_password_reset(self, request): """Do a password reset.""" if self.reset is None: logger.debug('reset attempted, but no resetcode library installed') raise HTTPServiceUnavailable() user_name = request.POST.get('username') if user_name is not None: user_name = extract_username(user_name) if request.POST.keys() == ['username']: # setting up a password reset # XXX add support for captcha here via **data request.user = User(user_name) try: self.password_reset(request) except (HTTPServiceUnavailable, HTTPJsonBadRequest), e: return render_mako('password_failure.mako', error=e.detail) else: return render_mako('password_key_sent.mako') raise HTTPJsonBadRequest() # full form, the actual password reset password = request.POST.get('password') confirm = request.POST.get('confirm') key = request.POST.get('key') if key is None: raise HTTPJsonBadRequest() if user_name is None: return self._repost( request, 'Username not provided. Please check ' 'the link you used.') user = User(user_name) user_id = self.auth.get_user_id(user) if user_id is None: return self._repost(request, 'We are unable to locate your ' 'account') if password is None: return self._repost( request, 'Password not provided. ' 'Please check the link you used.') if password != confirm: return self._repost(request, 'Password and confirmation do ' 'not match') if not valid_password(user_name, password): return self._repost( request, 'Password should be at least 8 ' 'characters and not the same as your ' 'username') if not self.reset.verify_reset_code(user, key): return self._repost( request, 'Key does not match with username. ' 'Please request a new key.') # everything looks fine if not self.auth.admin_update_password(user, 'password', password): return self._repost(request, 'Password change failed ' 'unexpectedly.') self.reset.clear_reset_code(user) return render_mako('password_changed.mako')
def setup_utils(self): self.posts_util = Posts() self.friends_util = Friends() self.user_util = User()
def do_user(self, line): """user <username>""" User(line, self.db).run()