From 8225b18a2a86d6bbe1b668240c382ac85ddad83e Mon Sep 17 00:00:00 2001 From: "afanasyev.aa" Date: Sat, 5 Apr 2025 23:49:07 +0900 Subject: [PATCH] added api/pk/satellite, authorisation endpointsm, pagination --- .gitignore | 58 ++++++++ api/__pycache__/admin.cpython-313.pyc | Bin 494 -> 684 bytes api/__pycache__/models.cpython-313.pyc | Bin 1783 -> 3029 bytes api/__pycache__/serializers.cpython-313.pyc | Bin 5097 -> 5632 bytes api/__pycache__/urls.cpython-313.pyc | Bin 1105 -> 1604 bytes api/__pycache__/views.cpython-313.pyc | Bin 7854 -> 11842 bytes api/admin.py | 6 +- .../0004_satellite_telemetrypacket.py | 35 +++++ api/models.py | 13 ++ api/permissions.py | 8 ++ api/serializers.py | 10 ++ api/urls.py | 26 ++-- api/views.py | 129 ++++++++++++++++-- db.sqlite3 | Bin 372736 -> 397312 bytes testapi/__pycache__/settings.cpython-313.pyc | Bin 2937 -> 3574 bytes testapi/settings.py | 25 +++- 16 files changed, 284 insertions(+), 26 deletions(-) create mode 100644 .gitignore create mode 100644 api/migrations/0004_satellite_telemetrypacket.py create mode 100644 api/permissions.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4bb0ce1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd +*.so +*.egg-info/ +*.egg +*.log + +# Environments +.env +.env.* +venv/ +venv*/ +ENV/ +.envrc + +# Django +*.sqlite3 +db.sqlite3 +media/ +staticfiles/ +*.pot +*.pyc + +# Migrations (если хочешь игнорировать сгенерированные миграции) +# migrations/ +# */migrations/ + +# IDEs +.vscode/ +.idea/ +*.swp + +# OS +.DS_Store +Thumbs.db + +# Tests +.coverage +htmlcov/ +*.cover +*.py,cover +.cache/ +.tox/ + +# Git +*.orig + +# Docker +*.pid +*.pid.lock +docker-compose.override.yml + +# Build +dist/ +build/ diff --git a/api/__pycache__/admin.cpython-313.pyc b/api/__pycache__/admin.cpython-313.pyc index a19afddd3516cc59e435eb5f40957b539025a7e7..57f224a18fa76cd9ce45d167069a6727b1a804e5 100644 GIT binary patch literal 684 zcmbVJze~eF6n@v_k~Yv*=_L50pi7o+Iuvoy#T063bjuQ(BSzDtyqrTvCs!B$2>%=* zML7@z2kEACa`R3sHKToS-@W&}`@Xx!&8k%kWPI&?h8qOnO%?Odev?^ScJ9Fimvq1( zNSff5T&+`bG}Ig&b%!E#3^W`Q%_exHzcRO2?ES_fpJ$%7E1gyROQkQRqD!farBvoZ z73wyfsu67>s2>cYWU6MisnE|dhQjJ03!(v!(nQo0^QW%3K4)BW*ab*@U}j`wyvv~Q WoWbNGgUMuHCS#7P49Z2kKq&x?`5ZX_ diff --git a/api/__pycache__/models.cpython-313.pyc b/api/__pycache__/models.cpython-313.pyc index 23cd3586c3131b5ec406b45f86c9fa0095c83e05..e6a5112c61178ece214380cbe40581904bb39477 100644 GIT binary patch delta 811 zcmaJ<&rj1}819d?tY5pXGq??w&4Bz^2O16-HtVSqwza?4Q+vXnM6AW>lCCC^cvK7^(Kr&1R+jh;t-K$VoDv~I? zx>X1|8=$)RqHN=at-5GLeSSnnBE8Cyr|ku}=ppJmY5d7^+i?9B*SK?Rfx zk#>m^m*@(h2~Y=BgM(*ao+E=m6)05(A__hv4T+>Iq{~6Pgl$~M4%vBVK6#3r?hu@Q z?nWSiMSW4{NCAXEA=n1vs^#$Ob3l;{4Skc+VA72ZGDVrtg=xA+YF=0!#P8Rv<%WYT zeD0#;)atnDnDy-d740q4>6^>LApvi1H3HtW9WqAS3~ZY_P*Ej+uRA_RPojZN-F!o> zex)Tl+K8`>9O}of|-kRh#uGCs!&lav)-I z1v9^#B8Zg+BtVuG^8kr9h8qI%9jvzmUAoyOdkLxPCWDlKh!~I(KCqJSOiZk^QQWK(LL(EK<8oUB^wF3^kP&iCMHm2&jy8kyuNj zaHML4=+dpDm+l_Zt$zwB4MGpdP;|1ki!b)q%!gZWZWrda6FBrEp4v7;0&p)-pJw@tD^HENEGr z)kG|65|*?a&QTudu%6cnxDf75)4fGpTm=TV4)lzXI$oU=o&K+b-8j&BUHCK=vv3BR zO<2(==u#5pjP#71`GhSPnHg*`Vdo8g23tzlvQeDDUP)Nl5cP#5`oNI%#UxUUoL)(y zB}15zbva?L8rd1_3S-qAF14<0R$sF>u*nhFH{JGYdJVv)NaV*DHLVlZvU?9OGF|kI zh0aKMsy?zDH`FRq?F*{e_(ig`{La!t2i_A^?h*DwceyW!fWs7J-cuTckeksF=wKTS#f zq*aHMPQq>*Q;kigXLb=OveHxCA?YwR$ud21`F1n`Qewwy#8IO|Rj(XJ>i%G0HTU|b z2P(PpKdc!J$E&;xHtEq_q>@79OcHzYG?zQ+P9^hk4~gWZ*~C;&F#Fam=6acMc&e9W zO6YrhG(*)BV~q~f6P)NhsGh{sIP&sqhal6RIB^P&jNT7>Q#U3&Uo$KaP8h`?a)7Z8bE`kUp(KqSPI}x z<}2rW7qsk$%&(l+FFFDIi1|zBPsa-z!-b8}!q#sq0sK4yw6R0vqFRmgk1%?<# zC5B+u80H|ci63P7*@D?EnV~`~5Frk@5N8Z4SV*1=F2o(fWy%CG9juEdh7F`dMhHce zH-;UHC|?W*SX2e3R-e6yC!JqY;3ddFO~zX+1&JjYFBw4`w#g<;+JYhhMX4#7$t9Wj zc`m6rsU@kCqnIKmzh@GiEYEBiP$gObmoC<~DJ{)Ru`0;6yCs+cRvV9ytzs+5&rZ$L zuj0taEH23}s?@I%g0bNG^e3-pmS*B`;m=-m2+}1t6tUxPK66fX4jSME-BevR&u!D9(9o= z`X&oUhr|V8mCG!uAg0s>QN8P;W|u_GE{j@RX0Zf{UEq|xAa8YD-szIO(`9*=%Pg*7 hL6r+?j@Q*ZFR6K6R`b5h;`4!@gP*C9yGR`96ac_xhi(7> diff --git a/api/__pycache__/views.cpython-313.pyc b/api/__pycache__/views.cpython-313.pyc index a7c45b310316906a13ea751a89bfa45a484f145e..0c475326503a106fae1a2da9b4564e884ad03bb0 100644 GIT binary patch literal 11842 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 delta 2220 zcmb7FeQZ-z6utwbPSaT8UlvxX~RY7iafH^q3(IsgHsI{Q z4I`)WL`%HY3omm|(1ll&c6OMU0p;0sL_Cn1fx@)l(b$Nw>bf6)4dM;I(H}vtn!}DK;b3 zhG0NwU_JUtTFu_k+tu|*)UnU?J+zfQ)UTr*tcACkT7Z@`0FL}4x>%5RscVql#$M<5 zQYE{`S29CsKmC!7mA1ASNtrcc^rVfRCBl_N=^|gAGPyriob`XC{-X6}_s#AL^s?@v z?y~WcF%{TzhYzt&O53U}eNE(AQ{{k9ah>{|175|AdJ2;pUe$n)DGlSapG_F-!e&g< zjo?D?EQ6iBX%N)1!^6&33G9ZUopvldG<-_wD7#!1*RR1)6pFZk`N};L4PbiJVlOg& zgi(Y5!WckSKPyJUv8iM%F(XN8V3rR6BXF~*PMCS8b*F!bb}A)pb_>l|Wx49!W+p zg`fLj#Z*DtU=o7K%QAWZ#@nQZu+z#Kw%=kd;{vpc&L}1^0v~pdM9yaaEoo zWLz;?%HGr14m-%CahVKo0YwXKr}?>y)RD<$7a1*EF;@%?3BlS&c2EXXEi|AGXu3Fw zt0gWnO*SfO$u#w9he6)l?7plfESD7?6PpO}krzsa6G_K(Vs0iJI{~j28)1KMNujG? z=MNQ+Ox(m$g88tBm1X(9L_~t6{fD4UUS(0w!x$=STnQF-Sk_fmoquuGzS;@<^3DNR zA&CG-$X!ld(n}YG`i#(!78)`_b6RM=(3UzZG^d2ej}9)n8qW;9KlH)y(ZM@>-8a1D zt&ulI?(l0CE9~>T&MH&YO}8t2Dc<*B(I{k$?zGXpL@4eE{-;mvOI5dBS(mQpxyAR~ zRUrSHgx~wC{tCZ^T(vm-U5cxn6i}8@k>EgCMT(2T8gVtnh0uY3(pgcQM%7zTTu4^j zEz<?bQo| z1id71@@%5Ai;lAsmCrP~fhkm@U-k1rd5Yx-L#)w{ zhka*WLxWJ%*Y*U)9YDaIE~kWZiTz?}ita&k4&ndghVl40h|eMXW0Hr^ix7k)?d;tu zT|Uu6kmx}g{SOIRS+ii)@5O!cNwN`PZk?A7gWmHW1iGdXq5#mUUKq04*o>46%}hlk z{Nq9Svp)nson?NTb7xVZx_@f|tj?GB8d|G0;w5w-MA>IHmtNi+r(Q4n_Oa{mH}qk{ zi_WzeP$Mr`kFQ!_+Deat*JVq{8g=?qcmr-(T4es9DyO%$%vEb?FGUxQ qIjffHPH8ia^=Zd?q;xq8GM', PredictionDeleteView.as_view(), name='delete_prediction'), - path('token/', obtain_auth_token), - path("history/", PredictionHistoryListView.as_view()), - path("history//", PredictionHistoryDetailView.as_view()), - path("history//delete/", PredictionHistoryDeleteView.as_view()), + path('token', obtain_auth_token, name = 'get_token'), + path("history", PredictionHistoryListView.as_view(), name='view_history_list'), + path("history//", PredictionHistoryDetailView.as_view(), name='view_history_detail'), + path("history//delete/", PredictionHistoryDeleteView.as_view(), name='delete_history'), + path("/telemetry/", TelemetryListCreateView.as_view(), name="create_telemetry"), + path('csrf/', get_csrf, name='api-csrf'), + path('login/', login_view, name='api-login'), + path('logout/', logout_view, name='api-logout'), + path('session/', SessionView.as_view(), name='api-session'), # new + path('whoami/', WhoAmIView.as_view(), name='api-whoami'), # new ] diff --git a/api/views.py b/api/views.py index a4420fc..a0e4d91 100644 --- a/api/views.py +++ b/api/views.py @@ -11,6 +11,15 @@ from django.utils.decorators import method_decorator from rest_framework.permissions import AllowAny from .services.tawhiri import TawhiriClient from django.contrib.auth import get_user_model +from .models import Satellite, TelemetryPacket +from .serializers import TelemetryPacketSerializer +from .permissions import ReadOnlyOrAuthenticated +import time +from django.http import JsonResponse +from rest_framework.authentication import SessionAuthentication, BasicAuthentication +from django.contrib.auth import authenticate, login, logout +import json +from django.middleware.csrf import get_token User = get_user_model() @@ -24,6 +33,8 @@ def get_prediction_from_tawhiri(params): else: raise Exception(f"Tawhiri error: {response.status_code} {response.text}") + + class PredictionCreateView(APIView): permission_classes = [IsAuthenticated] @@ -39,19 +50,20 @@ class PredictionCreateView(APIView): try: prediction_result = TawhiriClient.get_prediction(validated_data) + print(prediction_result) except requests.RequestException as e: - print("❌ Tawhiri error:", str(e), e.response.text if e.response else "no response") + print("Tawhiri error:", str(e), e.response.text if e.response else "no response") return Response({"error": f"Tawhiri error: {str(e)}"}, status=status.HTTP_502_BAD_GATEWAY) prediction = Prediction.objects.create(result=prediction_result) UserPrediction.objects.create(user=request.user, prediction=prediction, created_at=timezone.now()) - return Response({ "id": prediction.id, "created_at": prediction.created_at, "result": prediction_result }, status=status.HTTP_201_CREATED) + class PredictionListView(APIView): def get(self, request): user_id = request.query_params.get('user_id') @@ -66,17 +78,6 @@ class PredictionListView(APIView): ) return Response(PredictionSerializer(predictions, many=True).data) -class PredictionDeleteView(APIView): - def delete(self, request, pk): - try: - prediction = Prediction.objects.get(pk=pk) - prediction.deleted_at = timezone.now() - prediction.save() - return Response({"deleted": True}) - except Prediction.DoesNotExist: - return Response({"error": "Not found"}, status=404) - - class PredictionHistoryListView(generics.ListAPIView): permission_classes = [permissions.IsAuthenticated] @@ -89,6 +90,7 @@ class PredictionHistoryListView(generics.ListAPIView): ) + class PredictionHistoryDetailView(generics.RetrieveAPIView): permission_classes = [permissions.IsAuthenticated] serializer_class = PredictionDetailSerializer @@ -100,6 +102,7 @@ class PredictionHistoryDetailView(generics.RetrieveAPIView): ) + class PredictionHistoryDeleteView(generics.DestroyAPIView): permission_classes = [permissions.IsAuthenticated] @@ -114,5 +117,103 @@ class PredictionHistoryDeleteView(generics.DestroyAPIView): instance.save() + +class TelemetryListCreateView(generics.ListCreateAPIView): + serializer_class = TelemetryPacketSerializer + permission_classes = [permissions.AllowAny] + + def get_queryset(self): + qs = TelemetryPacket.objects.filter(satellite_id=self.kwargs["pk"]) + + from_ts = self.request.query_params.get("from") + till_ts = self.request.query_params.get("till") + + if from_ts: + qs = qs.filter(timestamp__gte=int(from_ts)) + if till_ts: + qs = qs.filter(timestamp__lte=int(till_ts)) + + return qs.order_by("-timestamp") + + + + def post(self, request, pk): + serializer = TelemetryPacketSerializer(data=request.data) + if not serializer.is_valid(): + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + validated_data = serializer.validated_data + + TelemetryPacket.objects.create(timestamp = time.time(), + satellite=Satellite.objects.get(id=pk), + lat=validated_data["lat"], + lon=validated_data["lon"], + alt=validated_data["alt"], + payload=validated_data['payload'], + ) + return Response(serializer.errors, status=status.HTTP_201_CREATED) + + +class SessionView(APIView): + authentication_classes = [SessionAuthentication, BasicAuthentication] + permission_classes = [IsAuthenticated] + + @staticmethod + def get(request, format=None): + return JsonResponse({'isAuthenticated': True}) + + +class WhoAmIView(APIView): + authentication_classes = [SessionAuthentication, BasicAuthentication] + permission_classes = [IsAuthenticated] + + @staticmethod + def get(request, format=None): + return JsonResponse({'username': request.user.username}) + + +def get_csrf(request): + response = JsonResponse({'detail': 'CSRF cookie set'}) + response['X-CSRFToken'] = get_token(request) + return response + + +def login_view(request): + data = json.loads(request.body) + username = data.get('username') + password = data.get('password') + + if username is None or password is None: + return JsonResponse({'detail': 'Please provide username and password.'}, status=400) + + user = authenticate(username=username, password=password) + + if user is None: + return JsonResponse({'detail': 'Invalid credentials.'}, status=400) + + login(request, user) + return JsonResponse({'detail': 'Successfully logged in.'}) + + +def logout_view(request): + if not request.user.is_authenticated: + return JsonResponse({'detail': 'You\'re not logged in.'}, status=400) + + logout(request) + return JsonResponse({'detail': 'Successfully logged out.'}) + + + #class PredictionCreateView(APIView): - #permission_classes = [IsAuthenticated] \ No newline at end of file + #permission_classes = [IsAuthenticated] + +# class TelemetryPacket(models.Model): +# id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) +# satellite = models.ForeignKey(Satellite, on_delete=models.CASCADE, related_name="telemetry") +# timestamp = models.BigIntegerField() # unix time +# lat = models.FloatField() +# lon = models.FloatField() +# alt = models.FloatField() +# payload = models.JSONField(null=True, blank=True) +# created_at = models.DateTimeField(auto_now_add=True) +# fields = ['id', 'timestamp', 'lat', 'lon', 'alt', 'payload'] \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index 41a74d0e402f6ebfef4234d9dbe4a32d20f1ecef..cd0c5f4e9c094de7d8b24a64a56d208897803b75 100644 GIT binary patch delta 7322 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 JIf?uDe*ltf!q&kWM3v}vRstXId$g1oD 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 D+unNc diff --git a/testapi/__pycache__/settings.cpython-313.pyc b/testapi/__pycache__/settings.cpython-313.pyc index b7622bf9141e2bebbbfd219d320d3d372858111c..0b832d5978ed1daf8c661da0d05e951954d91fdf 100644 GIT binary patch delta 913 zcmZWnO-~b16n)c{enAVg(+_BAsR*SB%oGubNQ`6qkYeqWxkE%_oKzS}1GLTS;75(Y z#OMkarv3mES1w#N{sVVz>aLlUi7R&{Bqr{BEg%u!q&An`!@P|-vU+Oq_vU z&crjMANq(3`oVSI4DQKpgn;D?afZ0T1751~fUgt%oj4F@coSh^ka!?KymYpY!Vf_* z07GPO7D5n)VTkYyT%Z`CxJWU|Sx5lJNRVQPHiRg`V4=qk=cBRl`UJCXV5_cNxxnSh ze6-eE~wMSMddZv_cCW$319qTX< zmRiz{>D-e{EK>VweRhLQh!QA5IxXJ8Nkx=WbTsJh4vW{aB4A|+3v>wR-ZQC^kZ=-b z(kjSj zEN5Hb4aBzW$UpY}dBZ!?KTL=p=C5g%`Gdk&9sch5i{+w#VHr*aMwE3!?4R`c;Re~ fBR`$OHV4BEoW$+0I{qdbCE>4oTmKdB*tVW z)?3Vp1(};~GWRfUUdP(Q$jHChn%$Lg@>Y%}CQatayEucG{WK*f8*^1p{>XKBvIdVi zmp;%Fj6hthJ~@*oltqj|N^bIFo~??qj*JgDZ9XtFsk43HVBj?Uz|5@7_K}xMh^djU INEfI902HM@TL1t6 diff --git a/testapi/settings.py b/testapi/settings.py index 9409c61..ba898ed 100644 --- a/testapi/settings.py +++ b/testapi/settings.py @@ -41,7 +41,7 @@ INSTALLED_APPS = [ 'rest_framework.authtoken', 'drf_spectacular', 'corsheaders', - 'api' + 'api.apps.ApiConfig', ] MIDDLEWARE = [ @@ -55,6 +55,13 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] +CORS_ALLOWED_ORIGINS = [ + 'http://localhost:5173', + 'http://127.0.0.1:5173', +] + +CORS_EXPOSE_HEADERS = ['Content-Type', 'X-CSRFToken'] +CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_ALL_ORIGINS = True ROOT_URLCONF = 'testapi.urls' @@ -140,6 +147,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' REST_FRAMEWORK = { # ВАШИ НАСТРОЙКИ + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 100, 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', @@ -147,5 +156,17 @@ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', #'rest_framework.permissions.AllowAny', - ] + ], + 'DEFAULT_RENDERER_CLASSES': [ + 'rest_framework.renderers.JSONRenderer', + ], + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.SessionAuthentication', + ], } + +CSRF_COOKIE_SAMESITE = 'Lax' +SESSION_COOKIE_SAMESITE = 'Lax' +CSRF_COOKIE_HTTPONLY = True +SESSION_COOKIE_HTTPONLY = True +CSRF_TRUSTED_ORIGINS = ['http://localhost:5173'] \ No newline at end of file