forked from enviPath/enviPy
Add API key authentication to v1 API Also includes: - management command to create keys for users - Improvements to API tests Minor: - more robust way to start docker dev container. Reviewed-on: enviPath/enviPy#327 Co-authored-by: Tobias O <tobias.olenyi@envipath.com> Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
from django.conf import settings as s
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
|
|
from epdb.models import APIToken
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Create an API token for a user"
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
"--username",
|
|
required=True,
|
|
help="Username of the user who will own the token",
|
|
)
|
|
parser.add_argument(
|
|
"--name",
|
|
required=True,
|
|
help="Descriptive name for the token",
|
|
)
|
|
parser.add_argument(
|
|
"--expires-days",
|
|
type=int,
|
|
default=90,
|
|
help="Days until expiration (0 for no expiration)",
|
|
)
|
|
parser.add_argument(
|
|
"--inactive",
|
|
action="store_true",
|
|
help="Create the token as inactive",
|
|
)
|
|
parser.add_argument(
|
|
"--curl",
|
|
action="store_true",
|
|
help="Print a curl example using the token",
|
|
)
|
|
parser.add_argument(
|
|
"--base-url",
|
|
default=None,
|
|
help="Base URL for curl example (default SERVER_URL or http://localhost:8000)",
|
|
)
|
|
parser.add_argument(
|
|
"--endpoint",
|
|
default="/api/v1/compounds/",
|
|
help="Endpoint path for curl example",
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
username = options["username"]
|
|
name = options["name"]
|
|
expires_days = options["expires_days"]
|
|
|
|
if expires_days < 0:
|
|
raise CommandError("--expires-days must be >= 0")
|
|
|
|
if expires_days == 0:
|
|
expires_days = None
|
|
|
|
user_model = get_user_model()
|
|
try:
|
|
user = user_model.objects.get(username=username)
|
|
except user_model.DoesNotExist as exc:
|
|
raise CommandError(f"User not found for username '{username}'") from exc
|
|
|
|
token, raw_token = APIToken.create_token(user, name=name, expires_days=expires_days)
|
|
|
|
if options["inactive"]:
|
|
token.is_active = False
|
|
token.save(update_fields=["is_active"])
|
|
|
|
self.stdout.write(f"User: {user.username} ({user.email})")
|
|
self.stdout.write(f"Token name: {token.name}")
|
|
self.stdout.write(f"Token id: {token.id}")
|
|
if token.expires_at:
|
|
self.stdout.write(f"Expires at: {token.expires_at.isoformat()}")
|
|
else:
|
|
self.stdout.write("Expires at: never")
|
|
self.stdout.write(f"Active: {token.is_active}")
|
|
self.stdout.write("Raw token:")
|
|
self.stdout.write(raw_token)
|
|
|
|
if options["curl"]:
|
|
base_url = (
|
|
options["base_url"] or getattr(s, "SERVER_URL", None) or "http://localhost:8000"
|
|
)
|
|
endpoint = options["endpoint"]
|
|
endpoint = endpoint if endpoint.startswith("/") else f"/{endpoint}"
|
|
url = f"{base_url.rstrip('/')}{endpoint}"
|
|
curl_cmd = f'curl -H "Authorization: Bearer {raw_token}" "{url}"'
|
|
self.stdout.write("Curl:")
|
|
self.stdout.write(curl_cmd)
|