1from __future__ import annotations
2
3import binascii
4import os
5import uuid
6from datetime import datetime
7from uuid import UUID
8
9from plain import postgres
10from plain.postgres import types
11
12__all__ = ["APIKey"]
13
14
15def generate_token() -> str:
16 return binascii.hexlify(os.urandom(20)).decode()
17
18
19@postgres.register_model
20class APIKey(postgres.Model):
21 uuid: UUID = types.UUIDField(default=uuid.uuid4)
22 created_at: datetime = types.DateTimeField(auto_now_add=True)
23 updated_at: datetime = types.DateTimeField(auto_now=True)
24 expires_at: datetime | None = types.DateTimeField(required=False, allow_null=True)
25 last_used_at: datetime | None = types.DateTimeField(required=False, allow_null=True)
26
27 name: str = types.TextField(max_length=255, required=False)
28
29 token: str = types.TextField(max_length=40, default=generate_token)
30
31 api_version: str = types.TextField(max_length=255, required=False)
32
33 query: postgres.QuerySet[APIKey] = postgres.QuerySet()
34
35 model_options = postgres.Options(
36 constraints=[
37 postgres.UniqueConstraint(
38 fields=["uuid"], name="plainapi_apikey_unique_uuid"
39 ),
40 postgres.UniqueConstraint(
41 fields=["token"], name="plainapi_apikey_unique_token"
42 ),
43 ],
44 )
45
46 def __str__(self) -> str:
47 return self.name or str(self.uuid)