mirror of
https://github.com/suitenumerique/messages.git
synced 2026-04-25 17:15:21 +02:00
♻️(metrics) rename usage API params to be more generic (#589)
This commit is contained in:
@@ -267,10 +267,17 @@ class MailboxUsageMetricsApiView(APIView):
|
||||
domain = request.query_params.get("domain")
|
||||
account_email = request.query_params.get("account_email")
|
||||
account_type = request.query_params.get("account_type")
|
||||
custom_attr_key = request.query_params.get(
|
||||
"filter_by_maildomain_custom_attribute"
|
||||
)
|
||||
custom_attr_value = request.query_params.get("custom_attribute_value")
|
||||
account_id_key = request.query_params.get("account_id_key")
|
||||
account_id_value = request.query_params.get("account_id_value")
|
||||
|
||||
allowed_keys = settings.SCHEMA_CUSTOM_ATTRIBUTES_MAILDOMAIN.get(
|
||||
"properties", {}
|
||||
).keys()
|
||||
if account_id_key and account_id_key not in allowed_keys:
|
||||
return Response(
|
||||
{"error": "Invalid account_id_key."},
|
||||
status=400,
|
||||
)
|
||||
|
||||
if domain:
|
||||
queryset = queryset.filter(domain__name=domain)
|
||||
@@ -278,18 +285,18 @@ class MailboxUsageMetricsApiView(APIView):
|
||||
parts = account_email.rsplit("@", 1)
|
||||
if len(parts) == 2:
|
||||
queryset = queryset.filter(local_part=parts[0], domain__name=parts[1])
|
||||
if custom_attr_key and custom_attr_value:
|
||||
if account_id_key and account_id_value:
|
||||
queryset = queryset.filter(
|
||||
**{f"domain__custom_attributes__{custom_attr_key}": custom_attr_value}
|
||||
**{f"domain__custom_attributes__{account_id_key}": account_id_value}
|
||||
)
|
||||
|
||||
if account_type == "organization" and (
|
||||
not custom_attr_key or not custom_attr_value
|
||||
not account_id_key or not account_id_value
|
||||
):
|
||||
return Response(
|
||||
{
|
||||
"error": "filter_by_maildomain_custom_attribute and "
|
||||
"custom_attribute_value are required "
|
||||
"error": "account_id_key and "
|
||||
"account_id_value are required "
|
||||
"for account_type=organization."
|
||||
},
|
||||
status=400,
|
||||
@@ -312,8 +319,8 @@ class MailboxUsageMetricsApiView(APIView):
|
||||
return Response({"count": 0, "results": []})
|
||||
results = [
|
||||
{
|
||||
custom_attr_key: custom_attr_value,
|
||||
"account": {"type": "organization", "id": custom_attr_value},
|
||||
account_id_key: account_id_value,
|
||||
"account": {"type": "organization"},
|
||||
"metrics": {"storage_used": total},
|
||||
}
|
||||
]
|
||||
@@ -334,10 +341,10 @@ class MailboxUsageMetricsApiView(APIView):
|
||||
},
|
||||
"metrics": {"storage_used": row["domain_storage"]},
|
||||
}
|
||||
if custom_attr_key:
|
||||
result[custom_attr_key] = (
|
||||
if account_id_key:
|
||||
result[account_id_key] = (
|
||||
row["domain__custom_attributes"] or {}
|
||||
).get(custom_attr_key, "")
|
||||
).get(account_id_key, "")
|
||||
results.append(result)
|
||||
|
||||
else:
|
||||
@@ -351,9 +358,9 @@ class MailboxUsageMetricsApiView(APIView):
|
||||
"account": {"type": "mailbox", "email": email},
|
||||
"metrics": {"storage_used": mailbox.storage_used},
|
||||
}
|
||||
if custom_attr_key:
|
||||
result[custom_attr_key] = mailbox.domain.custom_attributes.get(
|
||||
custom_attr_key, ""
|
||||
if account_id_key:
|
||||
result[account_id_key] = mailbox.domain.custom_attributes.get(
|
||||
account_id_key, ""
|
||||
)
|
||||
results.append(result)
|
||||
|
||||
|
||||
@@ -31,9 +31,25 @@ def correctly_configured_header(settings):
|
||||
return {"HTTP_AUTHORIZATION": f"Bearer {settings.METRICS_API_KEY}"}
|
||||
|
||||
|
||||
CUSTOM_ATTRIBUTES_SCHEMA = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"org_id": {"type": "string"},
|
||||
"tenant": {"type": "string"},
|
||||
"region": {"type": "string"},
|
||||
"code": {"type": "string"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestMailboxUsageMetrics:
|
||||
"""Tests for the mailbox usage metrics endpoint."""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _set_custom_attributes_schema(self, settings):
|
||||
settings.SCHEMA_CUSTOM_ATTRIBUTES_MAILDOMAIN = CUSTOM_ATTRIBUTES_SCHEMA
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_requires_auth(self, api_client, url, correctly_configured_header):
|
||||
"""Requires valid API key for access."""
|
||||
@@ -450,7 +466,7 @@ class TestMailboxUsageMetrics:
|
||||
def test_filter_by_custom_attribute(
|
||||
self, api_client, url, correctly_configured_header, settings
|
||||
):
|
||||
"""Filter by group_by_maildomain_custom_attribute + account_id
|
||||
"""Filter by account_id_key + account_id_value
|
||||
matches domains whose custom_attributes contain the given value."""
|
||||
overhead = settings.METRICS_STORAGE_USED_OVERHEAD_BY_MESSAGE
|
||||
|
||||
@@ -469,8 +485,8 @@ class TestMailboxUsageMetrics:
|
||||
response = api_client.get(
|
||||
url,
|
||||
{
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"custom_attribute_value": "111",
|
||||
"account_id_key": "org_id",
|
||||
"account_id_value": "111",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -505,8 +521,8 @@ class TestMailboxUsageMetrics:
|
||||
response = api_client.get(
|
||||
url,
|
||||
{
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"custom_attribute_value": "111",
|
||||
"account_id_key": "org_id",
|
||||
"account_id_value": "111",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -526,8 +542,8 @@ class TestMailboxUsageMetrics:
|
||||
response = api_client.get(
|
||||
url,
|
||||
{
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"custom_attribute_value": "999",
|
||||
"account_id_key": "org_id",
|
||||
"account_id_value": "999",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -536,6 +552,59 @@ class TestMailboxUsageMetrics:
|
||||
assert data["count"] == 0
|
||||
assert data["results"] == []
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
"key",
|
||||
["org_id__gte", "contains", "account", "metrics", "unknown"],
|
||||
)
|
||||
def test_invalid_account_id_key(
|
||||
self, api_client, url, correctly_configured_header, key
|
||||
):
|
||||
"""account_id_key not declared in SCHEMA_CUSTOM_ATTRIBUTES_MAILDOMAIN
|
||||
is rejected."""
|
||||
response = api_client.get(
|
||||
url,
|
||||
{"account_id_key": key, "account_id_value": "111"},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_account_id_key_only_includes_attribute(
|
||||
self, api_client, url, correctly_configured_header, settings
|
||||
):
|
||||
"""Providing account_id_key without account_id_value returns the full
|
||||
list with the custom attribute included in each result."""
|
||||
overhead = settings.METRICS_STORAGE_USED_OVERHEAD_BY_MESSAGE
|
||||
|
||||
domain_a = MailDomainFactory(name="a.com", custom_attributes={"org_id": "111"})
|
||||
domain_b = MailDomainFactory(name="b.com", custom_attributes={"org_id": "222"})
|
||||
|
||||
mailbox_a = MailboxFactory(local_part="alice", domain=domain_a)
|
||||
mailbox_b = MailboxFactory(local_part="bob", domain=domain_b)
|
||||
|
||||
for mailbox in [mailbox_a, mailbox_b]:
|
||||
thread = ThreadFactory()
|
||||
ThreadAccessFactory(mailbox=mailbox, thread=thread)
|
||||
contact = ContactFactory(mailbox=mailbox)
|
||||
MessageFactory(thread=thread, sender=contact)
|
||||
|
||||
response = api_client.get(
|
||||
url,
|
||||
{"account_id_key": "org_id"},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
data = response.json()
|
||||
|
||||
assert data["count"] == 2
|
||||
results_by_email = {r["account"]["email"]: r for r in data["results"]}
|
||||
assert results_by_email["alice@a.com"]["org_id"] == "111"
|
||||
assert (
|
||||
results_by_email["alice@a.com"]["metrics"]["storage_used"] == 1 * overhead
|
||||
)
|
||||
assert results_by_email["bob@b.com"]["org_id"] == "222"
|
||||
assert results_by_email["bob@b.com"]["metrics"]["storage_used"] == 1 * overhead
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_organization_aggregates_storage(
|
||||
self, api_client, url, correctly_configured_header, settings
|
||||
@@ -561,8 +630,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "organization",
|
||||
"custom_attribute_value": "111",
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"account_id_value": "111",
|
||||
"account_id_key": "org_id",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -571,29 +640,29 @@ class TestMailboxUsageMetrics:
|
||||
assert data["count"] == 1
|
||||
result = data["results"][0]
|
||||
assert result["org_id"] == "111"
|
||||
assert result["account"] == {"type": "organization", "id": "111"}
|
||||
assert result["account"] == {"type": "organization"}
|
||||
assert result["metrics"]["storage_used"] == 2 * overhead
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_organization_requires_custom_attribute_filter(
|
||||
self, api_client, url, correctly_configured_header
|
||||
):
|
||||
"""account_type=organization without filter_by_maildomain_custom_attribute
|
||||
and custom_attribute_value returns 400."""
|
||||
# Missing filter_by_maildomain_custom_attribute
|
||||
"""account_type=organization without account_id_key
|
||||
and account_id_value returns 400."""
|
||||
# Missing account_id_key
|
||||
response = api_client.get(
|
||||
url,
|
||||
{"account_type": "organization", "custom_attribute_value": "111"},
|
||||
{"account_type": "organization", "account_id_value": "111"},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
# Missing custom_attribute_value
|
||||
# Missing account_id_value
|
||||
response = api_client.get(
|
||||
url,
|
||||
{
|
||||
"account_type": "organization",
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"account_id_key": "org_id",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -618,8 +687,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "organization",
|
||||
"custom_attribute_value": "999",
|
||||
"filter_by_maildomain_custom_attribute": "org_id",
|
||||
"account_id_value": "999",
|
||||
"account_id_key": "org_id",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -654,8 +723,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "maildomain",
|
||||
"custom_attribute_value": "t1",
|
||||
"filter_by_maildomain_custom_attribute": "tenant",
|
||||
"account_id_value": "t1",
|
||||
"account_id_key": "tenant",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -676,7 +745,7 @@ class TestMailboxUsageMetrics:
|
||||
def test_maildomain_excludes_other_custom_attribute(
|
||||
self, api_client, url, correctly_configured_header, settings
|
||||
):
|
||||
"""account_type=maildomain with filter_by_maildomain_custom_attribute
|
||||
"""account_type=maildomain with account_id_key
|
||||
only returns domains matching the given attribute value."""
|
||||
overhead = settings.METRICS_STORAGE_USED_OVERHEAD_BY_MESSAGE
|
||||
|
||||
@@ -694,8 +763,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "maildomain",
|
||||
"custom_attribute_value": "west",
|
||||
"filter_by_maildomain_custom_attribute": "region",
|
||||
"account_id_value": "west",
|
||||
"account_id_key": "region",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -765,8 +834,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "organization",
|
||||
"filter_by_maildomain_custom_attribute": "code",
|
||||
"custom_attribute_value": "X1",
|
||||
"account_id_key": "code",
|
||||
"account_id_value": "X1",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -814,8 +883,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "maildomain",
|
||||
"filter_by_maildomain_custom_attribute": "code",
|
||||
"custom_attribute_value": "X1",
|
||||
"account_id_key": "code",
|
||||
"account_id_value": "X1",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -861,8 +930,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "organization",
|
||||
"filter_by_maildomain_custom_attribute": "code",
|
||||
"custom_attribute_value": "X1",
|
||||
"account_id_key": "code",
|
||||
"account_id_value": "X1",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
@@ -902,8 +971,8 @@ class TestMailboxUsageMetrics:
|
||||
url,
|
||||
{
|
||||
"account_type": "maildomain",
|
||||
"filter_by_maildomain_custom_attribute": "code",
|
||||
"custom_attribute_value": "X1",
|
||||
"account_id_key": "code",
|
||||
"account_id_value": "X1",
|
||||
},
|
||||
**correctly_configured_header,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user