Skip to content
Snippets Groups Projects
test_api_login.py 7.11 KiB
Newer Older
# copyright 2022-2024 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact https://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import json

from test.util import ApiBaseTC, check_missing_custom_header_response


class ApiLoginTC(ApiBaseTC):
    def test_successful_login_returns_204(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": self.admlogin, "password": self.admpassword}),
            content_type="application/json",
            headers=self.custom_headers,
            status=204,
        )

        assert response.body == b""

    def test_wrong_password_returns_401(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": self.admlogin, "password": "INVALID PASSWORD"}),
            content_type="application/json",
            headers=self.custom_headers,
            status=401,
        ).json

        assert response == {
            "data": None,
            "message": "Invalid credentials",
            "title": "AuthenticationError",
        }

    def test_wrong_login_returns_401(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps(
                {"login": "a_login_that_does_not_exist", "password": "PASSWORD"}
            ),
            content_type="application/json",
            headers=self.custom_headers,
            status=401,
        ).json

        assert response == {
            "data": None,
            "message": "Invalid credentials",
            "title": "AuthenticationError",
        }

    def test_invalid_login_type(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": 5, "password": "PASSWORD"}),
            content_type="application/json",
            headers=self.custom_headers,
            status=400,
        ).json

        assert response == {
            "data": [
                {
                    "exception": "ValidationError",
                    "field": "login",
                    "message": "5 is not of type 'string'",
                }
            ],
            "message": "Your request could not be validated against the openapi "
            "specification.",
            "title": "OpenApiValidationError",
        }

    def test_invalid_password_type(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": "login", "password": 5}),
            content_type="application/json",
            headers=self.custom_headers,
            status=400,
        ).json

        assert response == {
            "data": [
                {
                    "exception": "ValidationError",
                    "field": "password",
                    "message": "5 is not of type 'string'",
                }
            ],
            "message": "Your request could not be validated against the openapi "
            "specification.",
            "title": "OpenApiValidationError",
        }

    def test_wrong_content_type_returns_400(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": self.admlogin, "password": self.admpassword}),
            content_type="text/plain",
            headers=self.custom_headers,
            status=400,
        ).json

        assert response == {
            "data": [
                {
                    "exception": "MediaTypeNotFound",
                    "message": "Content for the following mimetype not found: "
                    "text/plain. Valid mimetypes: ['application/json']",
                }
            ],
            "message": "Your request could not be validated against the openapi "
            "specification.",
            "title": "OpenApiValidationError",
        }

    def test_wrong_params_returns_400(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"test": "testing"}),
            content_type="application/json",
            headers=self.custom_headers,
            status=400,
        ).json

        assert response == {
            "data": [
                {
                    "exception": "ValidationError",
                    "field": "login/password",
                    "message": "'login' is a required property",
                },
                {
                    "exception": "ValidationError",
                    "field": "login/password",
                    "message": "'password' is a required property",
                },
            ],
            "message": "Your request could not be validated against the openapi "
            "specification.",
            "title": "OpenApiValidationError",
        }

    def test_missing_login_data_returns_400(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            content_type="application/json",
            headers=self.custom_headers,
            status=400,
        ).json

        assert response == {
            "data": [
                {
                    "exception": "MissingRequiredRequestBody",
                    "message": "Missing required request body",
                }
            ],
            "message": "Your request could not be validated against the openapi "
            "specification.",
            "title": "OpenApiValidationError",
        }

    def test_missing_custom_headers_returns_400(self):
        response = self.webapp.post(
            self.get_api_path("login"),
            status=400,
        ).json
        check_missing_custom_header_response(response)
        response = self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": self.admlogin, "password": self.admpassword}),
            content_type="application/json",
            status=400,
        ).json
        check_missing_custom_header_response(response)


class ApiLoginDisabledDefaultTC(ApiBaseTC):
    def includeme(self, config):
        config.include("cubicweb.pyramid.auth")
        config.include("cubicweb.pyramid.session")

    def test_login_is_disabled(self):
        """check that it is disabled when omitting from 'cubicweb.includes'"""
        self.webapp.post(
            self.get_api_path("login"),
            params=json.dumps({"login": self.admlogin, "password": self.admpassword}),
            content_type="application/json",
            headers=self.custom_headers,
            status=404,
        )