selfprivacy-rest-api/tests/test_graphql/test_api_recovery.py

515 lines
18 KiB
Python
Raw Normal View History

2022-06-29 17:39:46 +00:00
# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
# pylint: disable=missing-function-docstring
import datetime
2023-01-06 10:59:59 +00:00
from tests.common import (
generate_api_query,
mnemonic_to_hex,
read_json,
write_json,
assert_recovery_recent,
)
from tests.test_graphql.common import (
assert_empty,
assert_data,
assert_ok,
assert_token_valid,
graphql_get_devices,
set_client_token,
)
2022-06-29 17:39:46 +00:00
API_RECOVERY_QUERY = """
recoveryKey {
exists
valid
creationDate
expirationDate
usesLeft
}
"""
2022-07-07 13:53:19 +00:00
def request_recovery_status(client):
return client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
def graphql_recovery_status(client):
response = request_recovery_status(client)
data = assert_data(response)
status = data["api"]["recoveryKey"]
assert status is not None
return status
def graphql_get_new_recovery_key(client):
response = client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
},
)
assert_ok(response, "getNewRecoveryApiKey")
key = response.json()["data"]["getNewRecoveryApiKey"]["key"]
assert key is not None
assert key.split(" ").__len__() == 18
return key
def graphql_use_recovery_key(client, key, device_name):
response = client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
"key": key,
"deviceName": device_name,
},
},
},
)
assert_ok(response, "useRecoveryApiKey")
token = response.json()["data"]["useRecoveryApiKey"]["token"]
assert token is not None
assert_token_valid(client, token)
set_client_token(client, token)
assert "new_test_token" in [
device["name"] for device in graphql_get_devices(client)
]
return token
def test_graphql_recovery_key_status_unauthorized(client, tokens_file):
response = request_recovery_status(client)
assert_empty(response)
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
2022-06-29 17:39:46 +00:00
def test_graphql_recovery_key_status_when_none_exists(authorized_client, tokens_file):
status = graphql_recovery_status(authorized_client)
assert status["exists"] is False
assert status["valid"] is False
assert status["creationDate"] is None
assert status["expirationDate"] is None
assert status["usesLeft"] is None
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
2022-06-29 17:39:46 +00:00
API_RECOVERY_KEY_GENERATE_MUTATION = """
2022-07-08 15:28:08 +00:00
mutation TestGenerateRecoveryKey($limits: RecoveryKeyLimitsInput) {
2022-06-29 17:39:46 +00:00
getNewRecoveryApiKey(limits: $limits) {
success
message
code
key
}
}
"""
API_RECOVERY_KEY_USE_MUTATION = """
mutation TestUseRecoveryKey($input: UseRecoveryKeyInput!) {
useRecoveryApiKey(input: $input) {
success
message
code
token
}
}
"""
2022-07-07 13:53:19 +00:00
2022-06-29 17:39:46 +00:00
def test_graphql_generate_recovery_key(client, authorized_client, tokens_file):
key = graphql_get_new_recovery_key(authorized_client)
status = graphql_recovery_status(authorized_client)
assert status["exists"] is True
assert status["valid"] is True
assert_recovery_recent(status["creationDate"])
assert status["expirationDate"] is None
assert status["usesLeft"] is None
2022-06-29 17:39:46 +00:00
graphql_use_recovery_key(client, key, "new_test_token")
# And again
graphql_use_recovery_key(client, key, "new_test_token2")
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
def test_graphql_generate_recovery_key_with_expiration_date(
client, authorized_client, tokens_file
):
2022-06-29 17:39:46 +00:00
expiration_date = datetime.datetime.now() + datetime.timedelta(minutes=5)
2022-07-07 13:53:19 +00:00
expiration_date_str = expiration_date.strftime("%Y-%m-%dT%H:%M:%S.%f")
2022-06-29 17:39:46 +00:00
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"expirationDate": expiration_date_str,
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["success"] is True
assert response.json()["data"]["getNewRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["getNewRecoveryApiKey"]["key"] is not None
2022-07-07 13:53:19 +00:00
assert (
response.json()["data"]["getNewRecoveryApiKey"]["key"].split(" ").__len__()
== 18
2022-07-07 13:53:19 +00:00
)
2022-06-29 17:39:46 +00:00
assert read_json(tokens_file)["recovery_token"] is not None
key = response.json()["data"]["getNewRecoveryApiKey"]["key"]
2022-07-07 13:53:19 +00:00
assert read_json(tokens_file)["recovery_token"]["expiration"] == expiration_date_str
2022-06-29 17:39:46 +00:00
assert read_json(tokens_file)["recovery_token"]["token"] == mnemonic_to_hex(key)
time_generated = read_json(tokens_file)["recovery_token"]["date"]
assert time_generated is not None
assert (
2022-07-08 15:28:08 +00:00
datetime.datetime.strptime(time_generated, "%Y-%m-%dT%H:%M:%S.%f")
2022-07-07 13:53:19 +00:00
- datetime.timedelta(seconds=5)
< datetime.datetime.now()
2022-06-29 17:39:46 +00:00
)
# Try to get token status
response = authorized_client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["api"]["recoveryKey"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["exists"] is True
assert response.json()["data"]["api"]["recoveryKey"]["valid"] is True
assert response.json()["data"]["api"]["recoveryKey"][
2022-07-08 15:28:08 +00:00
"creationDate"
] == time_generated.replace("Z", "")
2022-07-07 13:53:19 +00:00
assert (
response.json()["data"]["api"]["recoveryKey"]["expirationDate"]
2022-07-07 13:53:19 +00:00
== expiration_date_str
)
assert response.json()["data"]["api"]["recoveryKey"]["usesLeft"] is None
2022-06-29 17:39:46 +00:00
# Try to use token
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": key,
2022-07-08 15:28:08 +00:00
"deviceName": "new_test_token",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is True
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["useRecoveryApiKey"]["token"] is not None
2022-07-07 13:53:19 +00:00
assert (
response.json()["data"]["useRecoveryApiKey"]["token"]
2022-07-07 13:53:19 +00:00
== read_json(tokens_file)["tokens"][2]["token"]
)
2022-06-29 17:39:46 +00:00
# Try to use token again
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": key,
2022-07-08 15:28:08 +00:00
"deviceName": "new_test_token2",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is True
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["useRecoveryApiKey"]["token"] is not None
2022-07-07 13:53:19 +00:00
assert (
response.json()["data"]["useRecoveryApiKey"]["token"]
2022-07-07 13:53:19 +00:00
== read_json(tokens_file)["tokens"][3]["token"]
)
2022-06-29 17:39:46 +00:00
# Try to use token after expiration date
new_data = read_json(tokens_file)
2022-07-08 15:28:08 +00:00
new_data["recovery_token"]["expiration"] = (
datetime.datetime.now() - datetime.timedelta(minutes=5)
).strftime("%Y-%m-%dT%H:%M:%S.%f")
2022-06-29 17:39:46 +00:00
write_json(tokens_file, new_data)
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": key,
2022-07-08 15:28:08 +00:00
"deviceName": "new_test_token3",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is False
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 404
assert response.json()["data"]["useRecoveryApiKey"]["token"] is None
2022-06-29 17:39:46 +00:00
assert read_json(tokens_file)["tokens"] == new_data["tokens"]
# Try to get token status
response = authorized_client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["api"]["recoveryKey"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["exists"] is True
assert response.json()["data"]["api"]["recoveryKey"]["valid"] is False
2022-07-07 13:53:19 +00:00
assert (
response.json()["data"]["api"]["recoveryKey"]["creationDate"] == time_generated
)
assert (
response.json()["data"]["api"]["recoveryKey"]["expirationDate"]
2022-07-07 13:53:19 +00:00
== new_data["recovery_token"]["expiration"]
)
assert response.json()["data"]["api"]["recoveryKey"]["usesLeft"] is None
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
def test_graphql_generate_recovery_key_with_expiration_in_the_past(
authorized_client, tokens_file
):
2022-06-29 17:39:46 +00:00
expiration_date = datetime.datetime.now() - datetime.timedelta(minutes=5)
2022-07-07 13:53:19 +00:00
expiration_date_str = expiration_date.strftime("%Y-%m-%dT%H:%M:%S.%f")
2022-06-29 17:39:46 +00:00
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"expirationDate": expiration_date_str,
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["success"] is False
assert response.json()["data"]["getNewRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["code"] == 400
assert response.json()["data"]["getNewRecoveryApiKey"]["key"] is None
2022-06-29 17:39:46 +00:00
assert "recovery_token" not in read_json(tokens_file)
2022-07-07 13:53:19 +00:00
def test_graphql_generate_recovery_key_with_invalid_time_format(
authorized_client, tokens_file
):
2022-06-29 17:39:46 +00:00
expiration_date = "invalid_time_format"
expiration_date_str = expiration_date
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"expirationDate": expiration_date_str,
},
},
},
)
assert_empty(response)
2022-06-29 17:39:46 +00:00
assert "recovery_token" not in read_json(tokens_file)
2022-07-07 13:53:19 +00:00
def test_graphql_generate_recovery_key_with_limited_uses(
authorized_client, tokens_file
):
2022-06-29 17:39:46 +00:00
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"expirationDate": None,
"uses": 2,
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["success"] is True
assert response.json()["data"]["getNewRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["getNewRecoveryApiKey"]["key"] is not None
2022-06-29 17:39:46 +00:00
mnemonic_key = response.json()["data"]["getNewRecoveryApiKey"]["key"]
2022-06-29 17:39:46 +00:00
key = mnemonic_to_hex(mnemonic_key)
assert read_json(tokens_file)["recovery_token"]["token"] == key
assert read_json(tokens_file)["recovery_token"]["uses_left"] == 2
# Try to get token status
response = authorized_client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["api"]["recoveryKey"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["exists"] is True
assert response.json()["data"]["api"]["recoveryKey"]["valid"] is True
assert response.json()["data"]["api"]["recoveryKey"]["creationDate"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["expirationDate"] is None
assert response.json()["data"]["api"]["recoveryKey"]["usesLeft"] == 2
2022-06-29 17:39:46 +00:00
# Try to use token
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": mnemonic_key,
"deviceName": "test_token1",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is True
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["useRecoveryApiKey"]["token"] is not None
2022-06-29 17:39:46 +00:00
# Try to get token status
response = authorized_client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["api"]["recoveryKey"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["exists"] is True
assert response.json()["data"]["api"]["recoveryKey"]["valid"] is True
assert response.json()["data"]["api"]["recoveryKey"]["creationDate"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["expirationDate"] is None
assert response.json()["data"]["api"]["recoveryKey"]["usesLeft"] == 1
2022-06-29 17:39:46 +00:00
# Try to use token
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": mnemonic_key,
"deviceName": "test_token2",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is True
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 200
assert response.json()["data"]["useRecoveryApiKey"]["token"] is not None
2022-06-29 17:39:46 +00:00
# Try to get token status
response = authorized_client.post(
2022-06-29 17:39:46 +00:00
"/graphql",
2022-07-07 13:53:19 +00:00
json={"query": generate_api_query([API_RECOVERY_QUERY])},
2022-06-29 17:39:46 +00:00
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["api"]["recoveryKey"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["exists"] is True
assert response.json()["data"]["api"]["recoveryKey"]["valid"] is False
assert response.json()["data"]["api"]["recoveryKey"]["creationDate"] is not None
assert response.json()["data"]["api"]["recoveryKey"]["expirationDate"] is None
assert response.json()["data"]["api"]["recoveryKey"]["usesLeft"] == 0
2022-06-29 17:39:46 +00:00
# Try to use token
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_USE_MUTATION,
"variables": {
"input": {
2022-07-07 13:53:19 +00:00
"key": mnemonic_key,
"deviceName": "test_token3",
2022-06-29 17:39:46 +00:00
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["useRecoveryApiKey"]["success"] is False
assert response.json()["data"]["useRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["useRecoveryApiKey"]["code"] == 404
assert response.json()["data"]["useRecoveryApiKey"]["token"] is None
2022-07-07 13:53:19 +00:00
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
def test_graphql_generate_recovery_key_with_negative_uses(
authorized_client, tokens_file
):
2022-06-29 17:39:46 +00:00
# Try to get token status
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"uses": -1,
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["success"] is False
assert response.json()["data"]["getNewRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["code"] == 400
assert response.json()["data"]["getNewRecoveryApiKey"]["key"] is None
2022-06-29 17:39:46 +00:00
2022-07-07 13:53:19 +00:00
2022-06-29 17:39:46 +00:00
def test_graphql_generate_recovery_key_with_zero_uses(authorized_client, tokens_file):
# Try to get token status
response = authorized_client.post(
"/graphql",
json={
"query": API_RECOVERY_KEY_GENERATE_MUTATION,
"variables": {
"limits": {
"uses": 0,
},
},
},
)
assert response.status_code == 200
assert response.json().get("data") is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["success"] is False
assert response.json()["data"]["getNewRecoveryApiKey"]["message"] is not None
assert response.json()["data"]["getNewRecoveryApiKey"]["code"] == 400
assert response.json()["data"]["getNewRecoveryApiKey"]["key"] is None