Skip to content

Commit

Permalink
fix: teauthentication and test api
Browse files Browse the repository at this point in the history
  • Loading branch information
drunest committed Sep 27, 2024
1 parent 70172d8 commit a1659c4
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 341 deletions.
11 changes: 6 additions & 5 deletions app/src/auto_validator/core/api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from rest_framework import mixins, parsers, routers, viewsets
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import AllowAny

from auto_validator.core.models import Hotkey, Server, UploadedFile, ValidatorInstance
from auto_validator.core.serializers import UploadedFileSerializer
from auto_validator.core.utils.decorators import get_user_ip, verify_signature_and_route_subnet
from auto_validator.core.utils.utils import get_user_ip

from .authentication import HotkeyAuthentication
from .utils.bot import trigger_bot_send_message
Expand All @@ -30,20 +30,21 @@ def perform_create(self, serializer):
channel_name = self.request.headers.get("SubnetID")
realm = self.request.headers.get("Realm")
ip_address = get_user_ip(self.request)
file_url = uploaded_file.get_full_url(self.request)
try:
hotkey = Hotkey.objects.get(hotkey=hotkey_str)
server = Server.objects.get(ip_address=ip_address)
subnetslot = ValidatorInstance.objects.get(hotkey=hotkey, server=server).subnet_slot
except ValidatorInstance.DoesNotExist:
raise ValidationError("Invalid Hotkey")
serializer.save(
raise AuthenticationFailed("Invalid Hotkey")
uploaded_file = serializer.save(
meta_info={
"note": note,
"hotkey": hotkey_str,
"subnet_name": subnetslot.subnet.name,
"netuid": subnetslot.netuid,
}
)
file_url = uploaded_file.get_full_url(self.request)
trigger_bot_send_message(
channel_name=channel_name, message=(f"{note}\n" f"New validator logs:\n" f"{file_url}"), realm=realm
)
Expand Down
17 changes: 11 additions & 6 deletions app/src/auto_validator/core/authentication.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import time

from bittensor import Keypair
from django.conf import settings
Expand All @@ -9,17 +10,23 @@

class HotkeyAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
if settings.TESTING:
# Bypass authentication during tests
return (None, None)

hotkey_address = request.headers.get("Hotkey")
nonce = request.headers.get("Nonce")
signature = request.headers.get("Signature")
method = request.method.upper()
url = request.build_absolute_uri()

if method == "GET":
return (None, None)

if not hotkey_address or not nonce or not signature:
raise exceptions.AuthenticationFailed("Missing authentication headers.")

nonce_float = float(nonce)
current_time = time.time()
if abs(current_time - nonce_float) > int(settings.SIGNATURE_EXPIRE_DURATION):
raise exceptions.AuthenticationFailed("Invalid nonce")

if not Hotkey.objects.filter(hotkey=hotkey_address).exists():
raise exceptions.AuthenticationFailed("Unauthorized hotkey.")

Expand All @@ -33,8 +40,6 @@ def authenticate(self, request):
client_headers = {k: v for k, v in client_headers.items() if v is not None}
headers_str = json.dumps(client_headers, sort_keys=True)

method = request.method.upper()
url = request.build_absolute_uri()
data_to_sign = f"{method}{url}{headers_str}"

if "file" in request.FILES:
Expand Down

This file was deleted.

13 changes: 9 additions & 4 deletions app/src/auto_validator/core/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

V1_FILES_URL = "/api/v1/files/"


@pytest.mark.django_db
def test_file_upload_with_valid_signature(api_client, wallet, validator_instance):
file_content = io.BytesIO(b"file content")
Expand All @@ -22,6 +23,7 @@ def test_file_upload_with_valid_signature(api_client, wallet, validator_instance
headers = {}
headers["Note"] = ""
headers["SubnetID"] = "1"
headers["Realm"] = "testserver"
headers["Nonce"] = str(time.time())
headers["Hotkey"] = wallet.hotkey.ss58_address
headers_str = json.dumps(headers, sort_keys=True)
Expand All @@ -40,7 +42,7 @@ def test_file_upload_with_valid_signature(api_client, wallet, validator_instance
assert response_data["file_size"] == 12
assert response_data["description"] == ""
assert re.match(
r"^/media/"
r"^http://testserver/media/"
+ validator_instance.subnet_slot.subnet.name
+ r"-"
+ str(validator_instance.subnet_slot.netuid)
Expand Down Expand Up @@ -69,6 +71,7 @@ def test_file_upload_with_invalid_signature(api_client, wallet, validator_instan
headers = {}
headers["Note"] = ""
headers["SubnetID"] = "1"
headers["Realm"] = "testserver"
headers["Nonce"] = str(time.time())
headers["Hotkey"] = wallet.hotkey.ss58_address
headers["Signature"] = "invalid_signature"
Expand All @@ -88,6 +91,7 @@ def test_file_upload_with_missing_hotkey(api_client):
headers = {}
headers["Note"] = ""
headers["SubnetID"] = "1"
headers["Realm"] = "testserver"
headers["Nonce"] = str(time.time())
headers["Hotkey"] = ""
headers["Signature"] = "invalid_signature"
Expand All @@ -107,12 +111,13 @@ def test_file_upload_with_invalid_hotkey(api_client, wallet):
headers = {}
headers["Note"] = ""
headers["SubnetID"] = "1"
headers["Realm"] = "testserver"
headers["Nonce"] = str(time.time())
headers["Hotkey"] = "123"
headers["Signature"] = "invalid_signature"
response = api_client.post(V1_FILES_URL, file_data, format="multipart", headers=headers)

assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR or status.HTTP_403_FORBIDDEN
assert response.status_code == status.HTTP_403_FORBIDDEN


@pytest.mark.django_db
Expand All @@ -133,11 +138,11 @@ def test_list_files(api_client, hotkey):
assert response_data[0]["file_name"] == "file1.txt"
assert response_data[0]["file_size"] == 1
assert response_data[0]["description"] == ""
assert re.match(r"^/media/file1.txt$", response_data[0]["url"])
assert re.match(r"^http://testserver/media/file1.txt$", response_data[0]["url"])
assert response_data[1]["file_name"] == "file2.txt"
assert response_data[1]["file_size"] == 2
assert response_data[1]["description"] == ""
assert re.match(r"^/media/file2.txt$", response_data[1]["url"])
assert re.match(r"^http://testserver/media/file2.txt$", response_data[1]["url"])


@pytest.mark.django_db
Expand Down
74 changes: 0 additions & 74 deletions app/src/auto_validator/core/utils/decorators.py

This file was deleted.

8 changes: 4 additions & 4 deletions app/src/auto_validator/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def configure_structlog():
SIGNATURE_EXPIRE_DURATION = env("SIGNATURE_EXPIRE_DURATION", default="300")


DISCORD_BOT_TOKEN = env("DISCORD_BOT_TOKEN")
GUILD_ID = env("GUILD_ID")
BOT_NAME = env("BOT_NAME")
CATEGORY_NAME = env("CATEGORY_NAME")
DISCORD_BOT_TOKEN = env("DISCORD_BOT_TOKEN", default="")
GUILD_ID = env("GUILD_ID", default="")
BOT_NAME = env("BOT_NAME", default="")
CATEGORY_NAME = env("CATEGORY_NAME", default="")
Loading

0 comments on commit a1659c4

Please sign in to comment.