-
Notifications
You must be signed in to change notification settings - Fork 1
Add query endpoint for trusted users #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7d506aa
1097166
6d45602
2105678
719ed0c
4bb05c5
7523741
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -32,4 +32,23 @@ server { | |||||||||||||
| proxy_read_timeout 60s; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| set_real_ip_from 172.0.17.0/24; | ||||||||||||||
| real_ip_header X-Forwarded-For; | ||||||||||||||
| real_ip_recursive on; | ||||||||||||||
|
|
||||||||||||||
| location /api/query { | ||||||||||||||
| # allow ISIS VPN traffic | ||||||||||||||
| allow 130.246.0.0/16; | ||||||||||||||
| deny all; | ||||||||||||||
|
|
||||||||||||||
| proxy_pass http://web:8000; | ||||||||||||||
| proxy_set_header Host $host; | ||||||||||||||
| proxy_set_header X-Real-IP $remote_addr; | ||||||||||||||
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||||||||||||||
| proxy_set_header X-Forwarded-Proto $scheme; | ||||||||||||||
|
|
||||||||||||||
| proxy_connect_timeout 60s; | ||||||||||||||
| proxy_send_timeout 60s; | ||||||||||||||
| proxy_read_timeout 60s; | ||||||||||||||
|
Comment on lines
+50
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess these numbers are quite generous
Suggested change
|
||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add extra closing
Suggested change
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,10 +15,13 @@ | |||||||||||||||||||||||||||||||||||||
| import django_filters | ||||||||||||||||||||||||||||||||||||||
| from rest_framework.reverse import reverse | ||||||||||||||||||||||||||||||||||||||
| from django.http import HttpResponse | ||||||||||||||||||||||||||||||||||||||
| from django.db import connections | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||
| import datetime | ||||||||||||||||||||||||||||||||||||||
| import hashlib | ||||||||||||||||||||||||||||||||||||||
| import services.plots as plotsfile | ||||||||||||||||||||||||||||||||||||||
| from os import environ | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| OS_NAMES = ["Linux", "Windows NT", "Darwin"] | ||||||||||||||||||||||||||||||||||||||
| UTC = datetime.tzinfo("UTC") | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -328,6 +331,47 @@ def by_root(request, format=None): | |||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @api_view(("POST",)) | ||||||||||||||||||||||||||||||||||||||
| def query(request, format=None): | ||||||||||||||||||||||||||||||||||||||
| if not verify_token(request): | ||||||||||||||||||||||||||||||||||||||
| return response.Response(status=401, data="UNAUTHORIZED") | ||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For improved readability
Suggested change
|
||||||||||||||||||||||||||||||||||||||
| sql_err, sql = get_parameter(request, "sql") | ||||||||||||||||||||||||||||||||||||||
| if sql_err: | ||||||||||||||||||||||||||||||||||||||
| return response.Response(status=400, data=f"Invalid Parameters: {sql_err}") | ||||||||||||||||||||||||||||||||||||||
| conn = connections["readonly"] | ||||||||||||||||||||||||||||||||||||||
| with conn.cursor() as cur: | ||||||||||||||||||||||||||||||||||||||
| cur.execute(sql) | ||||||||||||||||||||||||||||||||||||||
| res = cur.fetchall() | ||||||||||||||||||||||||||||||||||||||
| return response.Response(res) | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+339
to
+345
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exception handling for db operations
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def get_bearer_token(request): | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| Expect: Authorization: Bearer <token> | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| auth = request.headers.get("Authorization", "") | ||||||||||||||||||||||||||||||||||||||
| if not auth: | ||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||
| parts = auth.split(None, 1) # ["Bearer", "<token>"] | ||||||||||||||||||||||||||||||||||||||
| if len(parts) != 2 or parts[0].lower() != "bearer": | ||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||
| return parts[1].strip() or None | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def get_parameter(request, param): | ||||||||||||||||||||||||||||||||||||||
| val = request.POST.get(param) | ||||||||||||||||||||||||||||||||||||||
| err = "" | ||||||||||||||||||||||||||||||||||||||
| if not val: | ||||||||||||||||||||||||||||||||||||||
| err = f"No {param} parameter provided" | ||||||||||||||||||||||||||||||||||||||
| return err, val | ||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To work better with
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def verify_token(request) -> bool: | ||||||||||||||||||||||||||||||||||||||
| token = get_bearer_token(request) | ||||||||||||||||||||||||||||||||||||||
| secret = environ.get("QUERY_SECRET_KEY", "") | ||||||||||||||||||||||||||||||||||||||
| return token == secret | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| class FeatureViewSet(viewsets.ModelViewSet): | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| A viewset that provides the standard actions, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apply the above defined
query_limitrate limiting allowing short bursts with delays to be queued further