diff --git a/selfprivacy_api/resources/api_auth/app_tokens.py b/selfprivacy_api/resources/api_auth/app_tokens.py index f8604d0..05ebf91 100644 --- a/selfprivacy_api/resources/api_auth/app_tokens.py +++ b/selfprivacy_api/resources/api_auth/app_tokens.py @@ -70,7 +70,7 @@ class Tokens(Resource): "token_name", type=str, required=True, help="Token to delete" ) args = parser.parse_args() - token_name = args["token"] + token_name = args["token_name"] if is_token_name_pair_valid( token_name, request.headers.get("Authorization").split(" ")[1] ): @@ -100,7 +100,10 @@ class Tokens(Resource): token = request.headers.get("Authorization").split(" ")[1] if not is_token_valid(token): return {"message": "Token not found"}, 404 - return refresh_token(token) + new_token = refresh_token(token) + if new_token is None: + return {"message": "Token not found"}, 404 + return {"token": new_token}, 200 api.add_resource(Tokens, "/tokens") diff --git a/selfprivacy_api/utils/auth.py b/selfprivacy_api/utils/auth.py index 925dfb5..fb802ea 100644 --- a/selfprivacy_api/utils/auth.py +++ b/selfprivacy_api/utils/auth.py @@ -125,11 +125,13 @@ def delete_token(token_name): def refresh_token(token): """Change the token field of the existing token""" + new_token = _generate_token() with WriteUserData(UserDataFiles.TOKENS) as tokens: for t in tokens["tokens"]: if t["token"] == token: - t["token"] = _generate_token() - break + t["token"] = new_token + return new_token + return None def is_recovery_token_exists(): diff --git a/tests/conftest.py b/tests/conftest.py index 302fdb7..674e017 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,10 +2,13 @@ import pytest from flask import testing from selfprivacy_api.app import create_app +@pytest.fixture +def tokens_file(mocker, shared_datadir): + mock = mocker.patch("selfprivacy_api.utils.TOKENS_FILE", shared_datadir / "tokens.json") + return mock @pytest.fixture -def app(mocker, shared_datadir): - mocker.patch("selfprivacy_api.utils.TOKENS_FILE", shared_datadir / "tokens.json") +def app(): app = create_app( { "ENABLE_SWAGGER": "1", @@ -16,7 +19,7 @@ def app(mocker, shared_datadir): @pytest.fixture -def client(app): +def client(app, tokens_file): return app.test_client() @@ -45,17 +48,17 @@ class WrongAuthClient(testing.FlaskClient): @pytest.fixture -def authorized_client(app): +def authorized_client(app, tokens_file): app.test_client_class = AuthorizedClient return app.test_client() @pytest.fixture -def wrong_auth_client(app): +def wrong_auth_client(app, tokens_file): app.test_client_class = WrongAuthClient return app.test_client() @pytest.fixture -def runner(app): +def runner(app, tokens_file): return app.test_cli_runner() diff --git a/tests/data/tokens.json b/tests/data/tokens.json index 9d35420..9be9d02 100644 --- a/tests/data/tokens.json +++ b/tests/data/tokens.json @@ -2,7 +2,12 @@ "tokens": [ { "token": "TEST_TOKEN", - "name": "Test Token", + "name": "test_token", + "date": "2022-01-14 08:31:10.789314" + }, + { + "token": "TEST_TOKEN2", + "name": "test_token2", "date": "2022-01-14 08:31:10.789314" } ] diff --git a/tests/test_auth.py b/tests/test_auth.py new file mode 100644 index 0000000..9fc617a --- /dev/null +++ b/tests/test_auth.py @@ -0,0 +1,90 @@ +# pylint: disable=redefined-outer-name +# pylint: disable=unused-argument +import json +import pytest + +TOKENS_FILE_CONTETS = { + "tokens": [ + { + "token": "TEST_TOKEN", + "name": "test_token", + "date": "2022-01-14 08:31:10.789314", + }, + { + "token": "TEST_TOKEN2", + "name": "test_token2", + "date": "2022-01-14 08:31:10.789314", + }, + ] +} + + +def read_json(file_path): + with open(file_path, "r", encoding="utf-8") as file: + return json.load(file) + + +def write_json(file_path, data): + with open(file_path, "w", encoding="utf-8") as file: + json.dump(data, file, indent=4) + + +def test_get_tokens_info(authorized_client, tokens_file): + response = authorized_client.get("/auth/tokens") + assert response.status_code == 200 + assert response.json == [ + {"name": "test_token", "date": "2022-01-14 08:31:10.789314"}, + {"name": "test_token2", "date": "2022-01-14 08:31:10.789314"}, + ] + + +def test_get_tokens_unauthorized(client, tokens_file): + response = client.get("/auth/tokens") + assert response.status_code == 401 + + +def test_delete_token_unauthorized(client, tokens_file): + response = client.delete("/auth/tokens") + assert response.status_code == 401 + assert read_json(tokens_file) == TOKENS_FILE_CONTETS + + +def test_delete_token(authorized_client, tokens_file): + response = authorized_client.delete( + "/auth/tokens", json={"token_name": "test_token2"} + ) + assert response.status_code == 200 + assert read_json(tokens_file) == { + "tokens": [ + { + "token": "TEST_TOKEN", + "name": "test_token", + "date": "2022-01-14 08:31:10.789314", + } + ] + } + +def test_delete_self_token(authorized_client, tokens_file): + response = authorized_client.delete( + "/auth/tokens", json={"token_name": "test_token"} + ) + assert response.status_code == 400 + assert read_json(tokens_file) == TOKENS_FILE_CONTETS + +def test_delete_nonexistent_token(authorized_client, tokens_file): + response = authorized_client.delete( + "/auth/tokens", json={"token_name": "test_token3"} + ) + assert response.status_code == 404 + assert read_json(tokens_file) == TOKENS_FILE_CONTETS + +def test_refresh_token_unauthorized(client, tokens_file): + response = client.post("/auth/tokens") + assert response.status_code == 401 + assert read_json(tokens_file) == TOKENS_FILE_CONTETS + +def test_refresh_token(authorized_client, tokens_file): + response = authorized_client.post("/auth/tokens") + assert response.status_code == 200 + new_token = response.json["token"] + assert read_json(tokens_file)["tokens"][0]["token"] == new_token