예제 #1
0
    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))
예제 #3
0
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'])
예제 #4
0
 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))
예제 #5
0
 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)
예제 #6
0
    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'))
예제 #7
0
    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
예제 #8
0
    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')
예제 #9
0
    def test_check_token_empty(self) -> None:
        """Check that an empty token fails."""

        with self.assertRaises(ValueError):
            token.check_token('*****@*****.**', '', 'login')
예제 #10
0
    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')