def test_main(self) -> None: """Overall test.""" user_id = self.user.user_id self.user.profile.locale = 'fr' self.user.profile.name = 'Pascal' self._assert_user_receives_campaign() template_vars = self._variables nps_form_urlstring = template_vars.pop('npsFormUrl') self.assertLessEqual({'baseUrl', 'firstName', 'productName'}, template_vars.keys()) self.assertEqual('Pascal', template_vars['firstName']) self.assertEqual('https://www.bob-emploi.fr', template_vars['baseUrl']) self.assertEqual('Bob', template_vars['productName']) nps_form_url = parse.urlparse(nps_form_urlstring) self.assertEqual( 'https://www.bob-emploi.fr/api/nps', parse.urlunparse(nps_form_url[:4] + ('', ) + nps_form_url[5:])) nps_form_args = parse.parse_qs(nps_form_url.query) self.assertEqual({'user', 'token', 'redirect'}, nps_form_args.keys()) self.assertEqual([user_id], nps_form_args['user']) auth_token.check_token(user_id, nps_form_args['token'][0], role='nps') self.assertEqual(['https://www.bob-emploi.fr/retours?hl=fr'], nps_form_args['redirect'])
def test_main(self) -> None: """Overall test.""" user_id = self.user.user_id self.user.profile.locale = 'fr' self.user.profile.name = 'Pascal' self.user.projects[0].diagnostic.category_id = 'stuck-market' self._assert_user_receives_campaign() template_vars = self._variables ffs_form_urlstring = template_vars.pop('ffsFormUrl') self.assertLessEqual({'baseUrl', 'firstName', 'productName'}, template_vars.keys()) self.assertEqual('Pascal', template_vars['firstName']) self.assertEqual('https://www.bob-emploi.fr', template_vars['baseUrl']) self.assertEqual('Bob', template_vars['productName']) ffs_form_url = parse.urlparse(ffs_form_urlstring) self.assertEqual( 'https://www.bob-emploi.fr/api/first-followup-survey', parse.urlunparse(ffs_form_url[:4] + ('',) + ffs_form_url[5:])) ffs_form_args = parse.parse_qs(ffs_form_url.query) self.assertEqual({'user', 'token', 'redirect'}, ffs_form_args.keys()) self.assertEqual([user_id], ffs_form_args['user']) auth_token.check_token(user_id, ffs_form_args['token'][0], role='first-followup-survey') self.assertEqual(1, len(ffs_form_args['redirect'])) ffs_redirect = parse.urlparse(ffs_form_args['redirect'][0]) self.assertEqual( 'https://www.bob-emploi.fr/first-followup-survey', parse.urlunparse(ffs_redirect[:4] + ('',) + ffs_redirect[5:])) self.assertEqual({ 'mainChallenge': ['stuck-market'], 'hl': ['fr'], 'gender': ['MASCULINE'], }, parse.parse_qs(ffs_redirect.query))
def delete_user( user_data: user_pb2.User, token: str, *, user_db: Optional[mongo.UsersDatabase] = None) -> Optional[str]: """Delete a user.""" if not user_db: user_db = _get_user_db() filter_user: Optional[dict[str, Any]] if user_data.user_id: try: auth_token.check_token(user_data.user_id, token, role='unsubscribe') except ValueError: try: auth_token.check_token(user_data.user_id, token, role='auth') except ValueError: flask.abort( 403, i18n.flask_translate("Mauvais jeton d'authentification")) filter_user = {'_id': safe_object_id(user_data.user_id)} elif user_data.profile.email: try: auth_token.check_google_token(token, re.compile('@bayesimpact.org')) except i18n.TranslatableException: try: auth_token.check_admin_token(token) except ValueError: flask.abort( 403, i18n.flask_translate( 'Accès refusé, action seulement pour le super-administrateur.' )) filter_user = user_db.user.find_one( {'hashedEmail': auth.hash_user_email(user_data.profile.email)}, {'_id': 1}) else: flask.abort( 400, i18n.flask_translate( 'Impossible de supprimer un utilisateur sans son ID.')) if not filter_user: return None user_proto = get_user_data(str(filter_user['_id']), collection=user_db.user) if not auth.delete_user(user_proto, user_db): flask.abort( 500, i18n.flask_translate( 'Erreur serveur, impossible de supprimer le compte.')) return str(filter_user['_id'])
def _decorated_fun(*args: Any, **kwargs: Any) -> Any: auth_token = flask.request.args.get('token') user_id = flask.request.args.get('user') if not user_id or not auth_token: flask.abort(422, i18n.flask_translate('Paramètres manquants.')) try: token.check_token(user_id, auth_token, role=role) except ValueError: flask.abort(403, i18n.flask_translate('Accès non autorisé.')) return func(*args, **dict(kwargs, user_id=user_id))
def _decorated_fun(*args: Any, **kwargs: Any) -> Any: auth_token = flask.request.headers.get('Authorization', '').replace('Bearer ', '') if not auth_token: auth_token = flask.request.args.get('token', '') if not auth_token: auth_token = flask.request.cookies.get( _AUTH_TOKEN_COOKIE_NAME, '') if not auth_token: flask.abort(401, i18n.flask_translate('Token manquant')) user_id = get_user_id(*args, **kwargs) try: token.check_token(user_id, auth_token, role=role) except ValueError: flask.abort(403, i18n.flask_translate('Unauthorized token')) return func(*args, **kwargs)
def test_create_logged_url(self) -> None: """Test the create logged url function.""" user_id = '02499e64387edfcc2ab7a948' base_url = 'https://www.bob-emploi.fr/project/0/wow-baker?' regex = re.compile( rf'^{re.escape(base_url)}authToken=(\d+\.[a-f0-9]+)&userId={user_id}$' ) logged_url = campaign.create_logged_url(user_id, '/project/0/wow-baker') self.assertRegex(logged_url, regex) match_token = regex.match(logged_url) assert match_token token = match_token.group(1) self.assertTrue(auth_token.check_token(user_id, token, role='auth'))
def _email_authenticate( self, auth_request: auth_pb2.AuthRequest) -> auth_pb2.AuthResponse: instant = int(time.time()) response = auth_pb2.AuthResponse() response.hash_salt = token.timestamped_hash(instant, auth_request.email) user_dict = self._user_collection.find_one( {'hashedEmail': hash_user_email(auth_request.email)}) if not user_dict: return self._email_register(auth_request, response) user_object_id = user_dict['_id'] user_id = str(user_object_id) user_auth_dict = self._user_db.user_auth.find_one( {'_id': user_object_id}) if not auth_request.hashed_password: # User exists but did not send a password: probably just getting some fresh salt. return response if not user_auth_dict: if not auth_request.auth_token: # User is trying to connect with a password, but never created one. self.send_auth_token(user_dict) _abort_failed_login() try: token.check_token(user_id, auth_request.auth_token, role='auth') except ValueError as error: logging.info('Invalid token:\n %s', error) _abort_on_bad_auth() # User that already uses an SSO account is now trying to add a password. _parse_user_from_mongo(user_dict, response.authenticated_user) self._user_db.user_auth.insert_one({ '_id': user_object_id, 'hashedPassword': auth_request.hashed_password, }) response.auth_token = token.create_token(user_id, 'auth') response.authenticated_user.has_account = True response.authenticated_user.has_password = True response.is_password_updated = True self._handle_returning_user(response, force_update=True) return response if auth_request.user_id: # User is a guest using a pre-existing email account: # maybe they're using the same password. if auth_request.hashed_password != user_auth_dict.get( 'hashedPassword', ''): return response _parse_user_from_mongo(user_dict, response.authenticated_user) return response if auth_request.auth_token: self._reset_password(auth_request, user_id, user_auth_dict, user_dict) _parse_user_from_mongo(user_dict, response.authenticated_user) response.auth_token = token.create_token(user_id, 'auth') return response if not auth_request.hash_salt: # User exists but has not sent salt: probably just getting some fresh salt. return response # Check that salt is valid. salt = auth_request.hash_salt try: if not token.assert_valid_salt(salt, auth_request.email, instant): return response except ValueError as error: logging.info('Salt has not been generated by this server:\n %s', error) _abort_on_bad_auth() stored_hashed_password = user_auth_dict.get('hashedPassword', '') _check_password(stored_hashed_password, salt, auth_request.hashed_password) _parse_user_from_mongo(user_dict, response.authenticated_user) response.auth_token = token.create_token(user_id, 'auth') # Update the password. if auth_request.new_hashed_password: self._user_db.user_auth.replace_one( {'_id': user_object_id}, {'hashedPassword': auth_request.new_hashed_password}) response.is_password_updated = True user_dict['_id'] = user_id self.send_update_confirmation(user_dict) self._handle_returning_user(response) return response
def test_check_token_wrong_role(self) -> None: """check_token fails if wrong role.""" login_token = token.create_token('*****@*****.**', 'login') with self.assertRaises(ValueError): token.check_token('*****@*****.**', login_token, 'unsubscribe')
def test_check_token_empty(self) -> None: """Check that an empty token fails.""" with self.assertRaises(ValueError): token.check_token('*****@*****.**', '', 'login')
def test_check_token(self) -> None: """Basic usage of check_token (round trip with create_token).""" login_token = token.create_token('*****@*****.**', 'login') token.check_token('*****@*****.**', login_token, 'login')