-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
758b2ba
commit 02250a9
Showing
29 changed files
with
459 additions
and
263 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.. warning:: | ||
This project still in early development! **DO NOT USE IN PRODUCTION!** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.. _usage_api: | ||
|
||
.. include:: ../_include/head.rst | ||
|
||
.. include:: ../_include/warn_develop.rst | ||
|
||
=== | ||
API | ||
=== | ||
|
||
To use the API you have to create an API key: `ui/settings/api_keys <http://localhost:8000/ui/settings/api_keys>`_ | ||
|
||
You can see the available API-endpoints in the built-in API-docs: `ui/api_docs <http://localhost:8000/ui/api_docs>`_ (*swagger*) | ||
|
||
Requests must have the API key set in the :code:`X-Api-Key` header. | ||
|
||
Examples | ||
******** | ||
|
||
.. code-block:: bash | ||
# add another api key | ||
curl -X 'POST' 'http://localhost:8000/api/key' -H 'accept: application/json' -H "X-Api-Key: <KEY>" | ||
> {"token":"ansible-2024-01-20-16-50-51","key":"r6yTsF9G.9qOt8ivfvFbpIkBh228tgAZjaNtnmDpw"} | ||
# list own api keys | ||
curl -X 'GET' 'http://localhost:8000/api/key' -H 'accept: application/json' -H "X-Api-Key: <KEY>" | ||
> {"tokens":["ansible-2024-01-20-16-50-51","ansible-2024-01-20-16-10-42"]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ pyyaml | |
ua-parser | ||
user-agents | ||
django-user-agents | ||
django-auto-logout | ||
|
||
## api | ||
djangorestframework==3.* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
from django.contrib import admin | ||
|
||
from aw.models import Job, JobExecution, JobPermission, JobPermissionMemberUser, JobPermissionMemberGroup | ||
from aw.models import Job, JobExecution, JobPermission, JobPermissionMemberUser, JobPermissionMemberGroup, AwAPIKey | ||
|
||
admin.site.register(Job) | ||
admin.site.register(JobExecution) | ||
admin.site.register(JobPermission) | ||
admin.site.register(JobPermissionMemberUser) | ||
admin.site.register(JobPermissionMemberGroup) | ||
admin.site.register(AwAPIKey) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,11 @@ | ||
from time import time | ||
from typing import Callable | ||
|
||
from django.core.exceptions import ObjectDoesNotExist | ||
from django.urls import path | ||
from rest_framework.views import APIView | ||
from rest_framework.response import Response | ||
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, extend_schema | ||
|
||
from aw.model.api import APIKey | ||
from aw.utils.http import deny_request | ||
|
||
|
||
def endpoint_wrapper(func) -> Callable: | ||
def wrapper(request, *args, **kwargs): | ||
bad, deny = deny_request(request) | ||
if bad: | ||
return deny | ||
|
||
return func(request, *args, **kwargs) | ||
|
||
return wrapper | ||
|
||
|
||
class KeyRead(APIView): | ||
http_method_names = ['get'] | ||
|
||
@staticmethod | ||
@endpoint_wrapper | ||
@extend_schema( | ||
summary='Return a list of all existing API keys of the current user.', | ||
parameters=None, | ||
) | ||
def get(request): | ||
return Response({'tokens': [key.name for key in APIKey.objects.filter(user=request.user)]}) | ||
|
||
|
||
class KeyWrite(APIView): | ||
http_method_names = ['post', 'delete'] | ||
|
||
@staticmethod | ||
@endpoint_wrapper | ||
@extend_schema( | ||
summary='Create a new API key.', | ||
) | ||
def post(request): | ||
token, secret = APIKey.objects.create_key( | ||
name=f'{request.user}-{time()}', | ||
user=request.user, | ||
) | ||
return Response({'token': token, 'secret': secret}) | ||
|
||
@staticmethod | ||
@endpoint_wrapper | ||
@extend_schema( | ||
summary='Delete one of the existing API keys of the current user.', | ||
) | ||
def delete(request): | ||
req_key = request.query_params.get('token', None) | ||
|
||
if req_key is None: | ||
return Response({'msg': 'No API key provided'}) | ||
|
||
try: | ||
results = APIKey.objects.filter(user=request.user, name=req_key) | ||
if len(results) == 1: | ||
results.delete() | ||
return Response({'msg': f"API key '{req_key}' revoked"}) | ||
|
||
except ObjectDoesNotExist: | ||
pass | ||
|
||
return Response(data={'msg': f"API key '{req_key}' not found"}, status=404) | ||
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView | ||
|
||
from aw.api_endpoints.key import KeyReadWrite, KeyDelete | ||
|
||
urlpatterns_api = [ | ||
path('api/key', KeyRead.as_view()), | ||
path('api/key/<str:token>', KeyWrite.as_view()), | ||
path('api/key', KeyReadWrite.as_view()), | ||
path('api/key/<str:token>', KeyDelete.as_view()), | ||
path('api/_schema/', SpectacularAPIView.as_view(), name='_schema'), | ||
path('api', SpectacularSwaggerView.as_view(url_name='_schema'), name='swagger-ui'), | ||
path('api/_docs', SpectacularSwaggerView.as_view(url_name='_schema'), name='swagger-ui'), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from django.conf import settings | ||
from django.contrib.auth.models import AnonymousUser | ||
from django.core.exceptions import ObjectDoesNotExist | ||
from rest_framework.permissions import IsAuthenticated | ||
from rest_framework_api_key.permissions import BaseHasAPIKey | ||
|
||
from aw.model.api import AwAPIKey | ||
|
||
|
||
class HasAwAPIKey(BaseHasAPIKey): | ||
model = AwAPIKey | ||
|
||
|
||
API_PERMISSION = [IsAuthenticated | HasAwAPIKey] | ||
|
||
|
||
# see: rest_framework_api_key.permissions.BaseHasAPIKey:get_from_header | ||
def get_api_user(request) -> settings.AUTH_USER_MODEL: | ||
if isinstance(request.user, AnonymousUser): | ||
try: | ||
return AwAPIKey.objects.get_from_key( | ||
request.META.get(getattr(settings, 'API_KEY_CUSTOM_HEADER')) | ||
).user | ||
|
||
except ObjectDoesNotExist: | ||
# invalid api key | ||
pass | ||
|
||
return request.user |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
from django.core.exceptions import ObjectDoesNotExist | ||
from rest_framework.views import APIView | ||
from rest_framework import serializers | ||
from rest_framework.response import Response | ||
from drf_spectacular.utils import extend_schema, OpenApiResponse | ||
|
||
from aw.utils.util import datetime_w_tz | ||
from aw.config.hardcoded import KEY_TIME_FORMAT | ||
from aw.model.api import AwAPIKey | ||
from aw.api_endpoints.base import API_PERMISSION, get_api_user | ||
|
||
|
||
# todo: allow user to add comment to easier identify token | ||
class KeyReadResponse(serializers.Serializer): | ||
tokens = serializers.ListSerializer(child=serializers.CharField()) | ||
|
||
|
||
class KeyWriteResponse(serializers.Serializer): | ||
token = serializers.CharField() | ||
secret = serializers.CharField() | ||
|
||
|
||
class KeyReadWrite(APIView): | ||
http_method_names = ['post', 'get'] | ||
serializer_class = KeyReadResponse | ||
permission_classes = API_PERMISSION | ||
|
||
@staticmethod | ||
@extend_schema( | ||
request=None, | ||
responses={200: KeyReadResponse}, | ||
summary='Return a list of all existing API keys of the current user.', | ||
) | ||
def get(request): | ||
return Response({'tokens': [key.name for key in AwAPIKey.objects.filter(user=get_api_user(request))]}) | ||
|
||
@extend_schema( | ||
request=None, | ||
responses={200: OpenApiResponse(KeyWriteResponse, description='Returns generated API token & key')}, | ||
summary='Create a new API key.', | ||
) | ||
def post(self, request): | ||
self.serializer_class = KeyWriteResponse | ||
user = get_api_user(request) | ||
token = f'{user}-{datetime_w_tz().strftime(KEY_TIME_FORMAT)}' | ||
_, key = AwAPIKey.objects.create_key( | ||
name=token, | ||
user=user, | ||
) | ||
return Response({'token': token, 'key': key}) | ||
|
||
|
||
class KeyDeleteResponse(serializers.Serializer): | ||
msg = serializers.CharField() | ||
|
||
|
||
class KeyDelete(APIView): | ||
http_method_names = ['post', 'delete'] | ||
serializer_class = KeyDeleteResponse | ||
permission_classes = API_PERMISSION | ||
_schema_responses = { | ||
200: OpenApiResponse(response=KeyDeleteResponse, description='API key deleted'), | ||
404: OpenApiResponse(response=KeyDeleteResponse, description='API key does not exist'), | ||
} | ||
_schema_summary = 'Delete one of the existing API keys of the current user.' | ||
|
||
@extend_schema( | ||
request=None, | ||
responses=_schema_responses, | ||
summary=_schema_summary, | ||
) | ||
def delete(self, request, token: str): | ||
try: | ||
results = AwAPIKey.objects.filter(user=get_api_user(request), name=token) | ||
|
||
if len(results) == 1: | ||
results.delete() | ||
return Response({'msg': f"API key '{token}' deleted"}) | ||
|
||
except ObjectDoesNotExist: | ||
pass | ||
|
||
return Response(data={'msg': f"API key '{token}' not found"}, status=404) | ||
|
||
@extend_schema( | ||
request=None, | ||
responses=_schema_responses, | ||
summary=_schema_summary, | ||
operation_id='del', | ||
) | ||
def post(self, request, token: str): | ||
return self.delete(request, token) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# pylint: disable=W0611 | ||
from aw.model.job import JobError, JobExecution, Job, JobPermission, JobPermissionMemberGroup, \ | ||
JobPermissionMemberUser, JobExecutionResult | ||
from aw.model.api import AwAPIKey |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.