nexo-schemas 0.0.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. nexo/schemas/__init__.py +0 -0
  2. nexo/schemas/application.py +292 -0
  3. nexo/schemas/connection.py +134 -0
  4. nexo/schemas/data.py +27 -0
  5. nexo/schemas/document.py +237 -0
  6. nexo/schemas/error/__init__.py +476 -0
  7. nexo/schemas/error/constants.py +50 -0
  8. nexo/schemas/error/descriptor.py +354 -0
  9. nexo/schemas/error/enums.py +40 -0
  10. nexo/schemas/error/metadata.py +15 -0
  11. nexo/schemas/error/spec.py +312 -0
  12. nexo/schemas/exception/__init__.py +0 -0
  13. nexo/schemas/exception/exc.py +911 -0
  14. nexo/schemas/exception/factory.py +1928 -0
  15. nexo/schemas/exception/handlers.py +110 -0
  16. nexo/schemas/google.py +14 -0
  17. nexo/schemas/key/__init__.py +0 -0
  18. nexo/schemas/key/rsa.py +131 -0
  19. nexo/schemas/metadata.py +21 -0
  20. nexo/schemas/mixins/__init__.py +0 -0
  21. nexo/schemas/mixins/filter.py +140 -0
  22. nexo/schemas/mixins/general.py +65 -0
  23. nexo/schemas/mixins/hierarchy.py +19 -0
  24. nexo/schemas/mixins/identity.py +387 -0
  25. nexo/schemas/mixins/parameter.py +50 -0
  26. nexo/schemas/mixins/service.py +40 -0
  27. nexo/schemas/mixins/sort.py +111 -0
  28. nexo/schemas/mixins/timestamp.py +192 -0
  29. nexo/schemas/model.py +240 -0
  30. nexo/schemas/operation/__init__.py +0 -0
  31. nexo/schemas/operation/action/__init__.py +9 -0
  32. nexo/schemas/operation/action/base.py +14 -0
  33. nexo/schemas/operation/action/resource.py +371 -0
  34. nexo/schemas/operation/action/status.py +8 -0
  35. nexo/schemas/operation/action/system.py +6 -0
  36. nexo/schemas/operation/action/websocket.py +6 -0
  37. nexo/schemas/operation/base.py +289 -0
  38. nexo/schemas/operation/constants.py +18 -0
  39. nexo/schemas/operation/context.py +68 -0
  40. nexo/schemas/operation/dependency.py +26 -0
  41. nexo/schemas/operation/enums.py +168 -0
  42. nexo/schemas/operation/extractor.py +36 -0
  43. nexo/schemas/operation/mixins.py +53 -0
  44. nexo/schemas/operation/request.py +1066 -0
  45. nexo/schemas/operation/resource.py +839 -0
  46. nexo/schemas/operation/system.py +55 -0
  47. nexo/schemas/operation/websocket.py +55 -0
  48. nexo/schemas/pagination.py +67 -0
  49. nexo/schemas/parameter.py +60 -0
  50. nexo/schemas/payload.py +116 -0
  51. nexo/schemas/resource.py +64 -0
  52. nexo/schemas/response.py +1041 -0
  53. nexo/schemas/security/__init__.py +0 -0
  54. nexo/schemas/security/api_key.py +63 -0
  55. nexo/schemas/security/authentication.py +848 -0
  56. nexo/schemas/security/authorization.py +922 -0
  57. nexo/schemas/security/enums.py +32 -0
  58. nexo/schemas/security/impersonation.py +179 -0
  59. nexo/schemas/security/token.py +402 -0
  60. nexo/schemas/security/types.py +17 -0
  61. nexo/schemas/success/__init__.py +0 -0
  62. nexo/schemas/success/descriptor.py +100 -0
  63. nexo/schemas/success/enums.py +23 -0
  64. nexo/schemas/user_agent.py +46 -0
  65. nexo_schemas-0.0.16.dist-info/METADATA +87 -0
  66. nexo_schemas-0.0.16.dist-info/RECORD +69 -0
  67. nexo_schemas-0.0.16.dist-info/WHEEL +5 -0
  68. nexo_schemas-0.0.16.dist-info/licenses/LICENSE +21 -0
  69. nexo_schemas-0.0.16.dist-info/top_level.txt +1 -0
@@ -0,0 +1,922 @@
1
+ import httpx
2
+ from abc import ABC, abstractmethod
3
+ from collections.abc import Iterable, Sequence
4
+ from Crypto.PublicKey.RSA import RsaKey
5
+ from datetime import timedelta
6
+ from enum import StrEnum
7
+ from fastapi import status, HTTPException, Security, Query
8
+ from fastapi.requests import HTTPConnection, Request
9
+ from fastapi.security import (
10
+ APIKeyHeader,
11
+ HTTPAuthorizationCredentials,
12
+ HTTPBearer,
13
+ )
14
+ from fastapi.websockets import WebSocket
15
+ from pydantic import BaseModel, Field
16
+ from typing import (
17
+ Annotated,
18
+ Callable,
19
+ Generator,
20
+ Generic,
21
+ Literal,
22
+ Self,
23
+ TypeGuard,
24
+ TypeVar,
25
+ overload,
26
+ )
27
+ from nexo.enums.connection import Header, Protocol, OptProtocol
28
+ from nexo.types.misc import BytesOrStr
29
+ from nexo.types.string import ListOfStrs, OptStr
30
+ from .enums import Domain, OptDomain
31
+ from .token import TenantToken, SystemToken, AnyToken, TokenFactory
32
+
33
+
34
+ class Scheme(StrEnum):
35
+ API_KEY = "api_key"
36
+ BEARER_TOKEN = "bearer_token"
37
+
38
+ @classmethod
39
+ def choices(cls) -> ListOfStrs:
40
+ return [e.value for e in cls]
41
+
42
+
43
+ SchemeT = TypeVar("SchemeT", bound=Scheme)
44
+ OptScheme = Scheme | None
45
+
46
+
47
+ class Source(StrEnum):
48
+ HEADER = "header"
49
+ QUERY = "query"
50
+ STATE = "state"
51
+
52
+ @classmethod
53
+ def choices(cls) -> ListOfStrs:
54
+ return [e.value for e in cls]
55
+
56
+
57
+ OptSource = Source | None
58
+
59
+
60
+ class GenericAuthorization(ABC, BaseModel, Generic[SchemeT]):
61
+ scheme: SchemeT = Field(..., description="Authorization's scheme")
62
+ credentials: Annotated[str, Field(..., description="Authorization's credentials")]
63
+
64
+ @overload
65
+ @classmethod
66
+ def from_state(
67
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
68
+ ) -> Self | None: ...
69
+ @overload
70
+ @classmethod
71
+ def from_state(
72
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
73
+ ) -> Self: ...
74
+ @classmethod
75
+ def from_state(
76
+ cls, conn: HTTPConnection, *, auto_error: bool = True
77
+ ) -> Self | None:
78
+ authorization = getattr(conn.state, "authorization", None)
79
+ if isinstance(authorization, cls):
80
+ return authorization
81
+
82
+ if auto_error:
83
+ raise HTTPException(
84
+ status_code=status.HTTP_401_UNAUTHORIZED,
85
+ detail="Invalid or unable to determine authorization in state",
86
+ )
87
+
88
+ return None
89
+
90
+ @classmethod
91
+ @abstractmethod
92
+ def from_header(
93
+ cls, conn: HTTPConnection, *, auto_error: bool = True
94
+ ) -> Self | None:
95
+ """Extract authorization from Header"""
96
+
97
+ @classmethod
98
+ @abstractmethod
99
+ def from_query(
100
+ cls, conn: HTTPConnection, *, auto_error: bool = True
101
+ ) -> Self | None:
102
+ """Extract authorization from Query"""
103
+
104
+ @overload
105
+ @classmethod
106
+ def extract(
107
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
108
+ ) -> Self | None: ...
109
+ @overload
110
+ @classmethod
111
+ def extract(
112
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
113
+ ) -> Self: ...
114
+ @classmethod
115
+ def extract(cls, conn: HTTPConnection, *, auto_error: bool = True) -> Self | None:
116
+ authorization = cls.from_state(conn, auto_error=auto_error)
117
+ if authorization is not None:
118
+ return authorization
119
+
120
+ authorization = cls.from_header(conn, auto_error=auto_error)
121
+ if authorization is not None:
122
+ return authorization
123
+
124
+ authorization = cls.from_query(conn, auto_error=auto_error)
125
+ if authorization is not None:
126
+ return authorization
127
+
128
+ if auto_error:
129
+ raise HTTPException(
130
+ status_code=status.HTTP_401_UNAUTHORIZED,
131
+ detail="Invalid or unable to determine authorization",
132
+ )
133
+
134
+ return None
135
+
136
+ @overload
137
+ @classmethod
138
+ def as_dependency(
139
+ cls,
140
+ protocol: None = None,
141
+ *,
142
+ auto_error: Literal[False],
143
+ ) -> Callable[
144
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
145
+ Self | None,
146
+ ]: ...
147
+ @overload
148
+ @classmethod
149
+ def as_dependency(
150
+ cls,
151
+ protocol: None = None,
152
+ *,
153
+ auto_error: Literal[True] = True,
154
+ ) -> Callable[
155
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr], Self
156
+ ]: ...
157
+ @overload
158
+ @classmethod
159
+ def as_dependency(
160
+ cls,
161
+ protocol: Literal[Protocol.HTTP],
162
+ *,
163
+ auto_error: Literal[False],
164
+ ) -> Callable[
165
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
166
+ Self | None,
167
+ ]: ...
168
+ @overload
169
+ @classmethod
170
+ def as_dependency(
171
+ cls,
172
+ protocol: Literal[Protocol.HTTP],
173
+ *,
174
+ auto_error: Literal[True] = True,
175
+ ) -> Callable[[Request, HTTPAuthorizationCredentials | None, OptStr], Self]: ...
176
+ @overload
177
+ @classmethod
178
+ def as_dependency(
179
+ cls, protocol: Literal[Protocol.WEBSOCKET], *, auto_error: Literal[False]
180
+ ) -> Callable[[WebSocket, OptStr, OptStr], Self | None]: ...
181
+ @overload
182
+ @classmethod
183
+ def as_dependency(
184
+ cls, protocol: Literal[Protocol.WEBSOCKET], *, auto_error: Literal[True] = True
185
+ ) -> Callable[[WebSocket, OptStr, OptStr], Self]: ...
186
+ @classmethod
187
+ def as_dependency(
188
+ cls, protocol: OptProtocol = None, *, auto_error: bool = True
189
+ ) -> (
190
+ Callable[
191
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
192
+ Self | None,
193
+ ]
194
+ | Callable[
195
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
196
+ Self,
197
+ ]
198
+ | Callable[
199
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
200
+ Self | None,
201
+ ]
202
+ | Callable[
203
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
204
+ Self,
205
+ ]
206
+ | Callable[[WebSocket, OptStr, OptStr], Self | None]
207
+ | Callable[[WebSocket, OptStr, OptStr], Self]
208
+ ):
209
+ def _dependency(
210
+ conn: HTTPConnection,
211
+ # These are for documentation purpose only
212
+ bearer: Annotated[
213
+ HTTPAuthorizationCredentials | None,
214
+ Security(HTTPBearer(auto_error=False)),
215
+ ],
216
+ api_key: Annotated[
217
+ OptStr,
218
+ Security(APIKeyHeader(name=Header.X_API_KEY.value, auto_error=False)),
219
+ ],
220
+ ) -> Self | None:
221
+ return cls.extract(conn, auto_error=auto_error)
222
+
223
+ def _request_dependency(
224
+ request: Request,
225
+ # These are for documentation purpose only
226
+ bearer: Annotated[
227
+ HTTPAuthorizationCredentials | None,
228
+ Security(HTTPBearer(auto_error=False)),
229
+ ],
230
+ api_key: Annotated[
231
+ OptStr,
232
+ Security(APIKeyHeader(name=Header.X_API_KEY.value, auto_error=False)),
233
+ ],
234
+ ) -> Self | None:
235
+ return cls.extract(request, auto_error=auto_error)
236
+
237
+ def _websocket_dependency(
238
+ websocket: WebSocket,
239
+ # These are for documentation purpose only
240
+ bearer: Annotated[
241
+ OptStr,
242
+ Query(
243
+ alias=Header.AUTHORIZATION.value,
244
+ description="Authorization Query",
245
+ ),
246
+ ] = None,
247
+ api_key: Annotated[
248
+ OptStr,
249
+ Query(alias=Header.X_API_KEY.value, description="API Key Query"),
250
+ ] = None,
251
+ ) -> Self | None:
252
+ return cls.extract(websocket, auto_error=auto_error)
253
+
254
+ if protocol is None:
255
+ return _dependency
256
+ elif protocol is Protocol.HTTP:
257
+ return _request_dependency
258
+ elif protocol is Protocol.WEBSOCKET:
259
+ return _websocket_dependency
260
+
261
+ @overload
262
+ def parse_token(
263
+ self,
264
+ domain: Literal[Domain.TENANT],
265
+ *,
266
+ key: BytesOrStr | RsaKey,
267
+ audience: str | Iterable[str] | None = None,
268
+ subject: OptStr = None,
269
+ issuer: str | Sequence[str] | None = None,
270
+ leeway: float | timedelta = 0,
271
+ ) -> TenantToken: ...
272
+ @overload
273
+ def parse_token(
274
+ self,
275
+ domain: Literal[Domain.SYSTEM],
276
+ *,
277
+ key: BytesOrStr | RsaKey,
278
+ audience: str | Iterable[str] | None = None,
279
+ subject: OptStr = None,
280
+ issuer: str | Sequence[str] | None = None,
281
+ leeway: float | timedelta = 0,
282
+ ) -> SystemToken: ...
283
+ @overload
284
+ def parse_token(
285
+ self,
286
+ domain: None = None,
287
+ *,
288
+ key: BytesOrStr | RsaKey,
289
+ audience: str | Iterable[str] | None = None,
290
+ subject: OptStr = None,
291
+ issuer: str | Sequence[str] | None = None,
292
+ leeway: float | timedelta = 0,
293
+ ) -> AnyToken: ...
294
+ def parse_token(
295
+ self,
296
+ domain: OptDomain = None,
297
+ *,
298
+ key: BytesOrStr | RsaKey,
299
+ audience: str | Iterable[str] | None = None,
300
+ subject: OptStr = None,
301
+ issuer: str | Sequence[str] | None = None,
302
+ leeway: float | timedelta = 0,
303
+ ) -> AnyToken:
304
+ if self.scheme is not Scheme.BEARER_TOKEN:
305
+ raise ValueError(
306
+ f"Authorization scheme must be '{Scheme.BEARER_TOKEN}' to parse token"
307
+ )
308
+ return TokenFactory.from_string(
309
+ self.credentials,
310
+ domain,
311
+ key=key,
312
+ audience=audience,
313
+ subject=subject,
314
+ issuer=issuer,
315
+ leeway=leeway,
316
+ )
317
+
318
+
319
+ class BaseAuthorization(GenericAuthorization[Scheme]):
320
+ scheme: Annotated[Scheme, Field(..., description="Authorization's scheme")]
321
+
322
+ @overload
323
+ @classmethod
324
+ def from_header(
325
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
326
+ ) -> Self | None: ...
327
+ @overload
328
+ @classmethod
329
+ def from_header(
330
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
331
+ ) -> Self: ...
332
+ @classmethod
333
+ def from_header(
334
+ cls, conn: HTTPConnection, *, auto_error: bool = True
335
+ ) -> Self | None:
336
+ token = conn.headers.get(Header.AUTHORIZATION, "")
337
+ scheme, _, credentials = token.partition(" ")
338
+ if token and scheme and credentials and scheme.lower() == "bearer":
339
+ return cls(scheme=Scheme.BEARER_TOKEN, credentials=credentials)
340
+
341
+ api_key = conn.headers.get(Header.X_API_KEY)
342
+ if api_key is not None:
343
+ return cls(scheme=Scheme.API_KEY, credentials=api_key)
344
+
345
+ if auto_error:
346
+ raise HTTPException(
347
+ status_code=status.HTTP_401_UNAUTHORIZED,
348
+ detail="Invalid or unable to determine authorization from Headers",
349
+ )
350
+
351
+ return None
352
+
353
+ @overload
354
+ @classmethod
355
+ def from_query(
356
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
357
+ ) -> Self | None: ...
358
+ @overload
359
+ @classmethod
360
+ def from_query(
361
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
362
+ ) -> Self: ...
363
+ @classmethod
364
+ def from_query(
365
+ cls, conn: HTTPConnection, *, auto_error: bool = True
366
+ ) -> Self | None:
367
+ token = conn.query_params.get(Header.AUTHORIZATION.value, None)
368
+ if token is not None:
369
+ return cls(scheme=Scheme.BEARER_TOKEN, credentials=token)
370
+
371
+ api_key = conn.query_params.get(Header.X_API_KEY.value)
372
+ if api_key is not None:
373
+ return cls(scheme=Scheme.API_KEY, credentials=api_key)
374
+
375
+ if auto_error:
376
+ raise HTTPException(
377
+ status_code=status.HTTP_401_UNAUTHORIZED,
378
+ detail="Invalid or unable to determine authorization from Headers",
379
+ )
380
+
381
+ return None
382
+
383
+
384
+ class APIKeyAuthorization(GenericAuthorization[Literal[Scheme.API_KEY]]):
385
+ scheme: Annotated[
386
+ Literal[Scheme.API_KEY],
387
+ Field(Scheme.API_KEY, description="Authorization's scheme"),
388
+ ] = Scheme.API_KEY
389
+
390
+ @overload
391
+ @classmethod
392
+ def from_header(
393
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
394
+ ) -> Self | None: ...
395
+ @overload
396
+ @classmethod
397
+ def from_header(
398
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
399
+ ) -> Self: ...
400
+ @classmethod
401
+ def from_header(
402
+ cls, conn: HTTPConnection, *, auto_error: bool = True
403
+ ) -> Self | None:
404
+ api_key = conn.headers.get(Header.X_API_KEY)
405
+ if api_key is not None:
406
+ return cls(scheme=Scheme.API_KEY, credentials=api_key)
407
+
408
+ if auto_error:
409
+ raise HTTPException(
410
+ status_code=status.HTTP_401_UNAUTHORIZED,
411
+ detail=f"Invalid or unable to determine authorization from {Header.X_API_KEY} Header",
412
+ )
413
+
414
+ return None
415
+
416
+ @overload
417
+ @classmethod
418
+ def from_query(
419
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
420
+ ) -> Self | None: ...
421
+ @overload
422
+ @classmethod
423
+ def from_query(
424
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
425
+ ) -> Self: ...
426
+ @classmethod
427
+ def from_query(
428
+ cls, conn: HTTPConnection, *, auto_error: bool = True
429
+ ) -> Self | None:
430
+ api_key = conn.query_params.get(Header.X_API_KEY.value)
431
+ if api_key is not None:
432
+ return cls(scheme=Scheme.API_KEY, credentials=api_key)
433
+
434
+ if auto_error:
435
+ raise HTTPException(
436
+ status_code=status.HTTP_401_UNAUTHORIZED,
437
+ detail=f"Invalid or unable to determine authorization from {Header.X_API_KEY} Query",
438
+ )
439
+
440
+ return None
441
+
442
+
443
+ class BearerTokenAuthorization(GenericAuthorization[Literal[Scheme.BEARER_TOKEN]]):
444
+ scheme: Annotated[
445
+ Literal[Scheme.BEARER_TOKEN],
446
+ Field(Scheme.BEARER_TOKEN, description="Authorization's scheme"),
447
+ ] = Scheme.BEARER_TOKEN
448
+
449
+ @overload
450
+ @classmethod
451
+ def from_header(
452
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
453
+ ) -> Self | None: ...
454
+ @overload
455
+ @classmethod
456
+ def from_header(
457
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
458
+ ) -> Self: ...
459
+ @classmethod
460
+ def from_header(
461
+ cls, conn: HTTPConnection, *, auto_error: bool = True
462
+ ) -> Self | None:
463
+ token = conn.headers.get(Header.AUTHORIZATION, "")
464
+ scheme, _, credentials = token.partition(" ")
465
+ if token and scheme and credentials and scheme.lower() == "bearer":
466
+ return cls(scheme=Scheme.BEARER_TOKEN, credentials=credentials)
467
+
468
+ if auto_error:
469
+ raise HTTPException(
470
+ status_code=status.HTTP_401_UNAUTHORIZED,
471
+ detail=f"Invalid or unable to determine authorization from {Header.AUTHORIZATION} Header",
472
+ )
473
+
474
+ return None
475
+
476
+ @overload
477
+ @classmethod
478
+ def from_query(
479
+ cls, conn: HTTPConnection, *, auto_error: Literal[False]
480
+ ) -> Self | None: ...
481
+ @overload
482
+ @classmethod
483
+ def from_query(
484
+ cls, conn: HTTPConnection, *, auto_error: Literal[True] = True
485
+ ) -> Self: ...
486
+ @classmethod
487
+ def from_query(
488
+ cls, conn: HTTPConnection, *, auto_error: bool = True
489
+ ) -> Self | None:
490
+ token = conn.query_params.get(Header.AUTHORIZATION.value, None)
491
+ if token is not None:
492
+ return cls(scheme=Scheme.BEARER_TOKEN, credentials=token)
493
+
494
+ if auto_error:
495
+ raise HTTPException(
496
+ status_code=status.HTTP_401_UNAUTHORIZED,
497
+ detail=f"Invalid or unable to determine authorization from {Header.AUTHORIZATION} Query",
498
+ )
499
+
500
+ return None
501
+
502
+
503
+ AnyAuthorization = BaseAuthorization | BearerTokenAuthorization | APIKeyAuthorization
504
+ AnyAuthorizationT = TypeVar("AnyAuthorizationT", bound=AnyAuthorization)
505
+ OptAnyAuthorization = AnyAuthorization | None
506
+ OptAnyAuthorizationT = TypeVar("OptAnyAuthorizationT", bound=OptAnyAuthorization)
507
+
508
+
509
+ def is_bearer_token(
510
+ authorization: AnyAuthorization,
511
+ ) -> TypeGuard[BearerTokenAuthorization]:
512
+ return authorization.scheme is Scheme.BEARER_TOKEN
513
+
514
+
515
+ def is_api_key(authorization: AnyAuthorization) -> TypeGuard[APIKeyAuthorization]:
516
+ return authorization.scheme is Scheme.API_KEY
517
+
518
+
519
+ class AuthorizationMixin(BaseModel, Generic[OptAnyAuthorizationT]):
520
+ authorization: OptAnyAuthorizationT = Field(
521
+ ...,
522
+ description="Authorization",
523
+ )
524
+
525
+
526
+ class APIKeyAuth(httpx.Auth):
527
+ def __init__(self, api_key: str) -> None:
528
+ self._auth_header = self._build_auth_header(api_key)
529
+
530
+ def auth_flow(
531
+ self, request: httpx.Request
532
+ ) -> Generator[httpx.Request, httpx.Response, None]:
533
+ request.headers[Header.X_API_KEY.value] = self._auth_header
534
+ yield request
535
+
536
+ def _build_auth_header(self, api_key: str) -> str:
537
+ return api_key
538
+
539
+
540
+ class BearerTokenAuth(httpx.Auth):
541
+ def __init__(self, token: str) -> None:
542
+ self._auth_header = self._build_auth_header(token)
543
+
544
+ def auth_flow(
545
+ self, request: httpx.Request
546
+ ) -> Generator[httpx.Request, httpx.Response, None]:
547
+ request.headers[Header.AUTHORIZATION] = self._auth_header
548
+ yield request
549
+
550
+ def _build_auth_header(self, token: str) -> str:
551
+ return f"Bearer {token}"
552
+
553
+
554
+ AnyHTTPXAuthorization = APIKeyAuth | BearerTokenAuth
555
+
556
+
557
+ class AuthorizationFactory:
558
+ @overload
559
+ @classmethod
560
+ def extract(
561
+ cls,
562
+ scheme: None = None,
563
+ source: OptSource = None,
564
+ *,
565
+ conn: HTTPConnection,
566
+ auto_error: Literal[False],
567
+ ) -> BaseAuthorization | None: ...
568
+ @overload
569
+ @classmethod
570
+ def extract(
571
+ cls,
572
+ scheme: Literal[Scheme.API_KEY],
573
+ source: OptSource = None,
574
+ *,
575
+ conn: HTTPConnection,
576
+ auto_error: Literal[False],
577
+ ) -> APIKeyAuthorization | None: ...
578
+ @overload
579
+ @classmethod
580
+ def extract(
581
+ cls,
582
+ scheme: Literal[Scheme.BEARER_TOKEN],
583
+ source: OptSource = None,
584
+ *,
585
+ conn: HTTPConnection,
586
+ auto_error: Literal[False],
587
+ ) -> BearerTokenAuthorization | None: ...
588
+ @overload
589
+ @classmethod
590
+ def extract(
591
+ cls,
592
+ scheme: None = None,
593
+ source: OptSource = None,
594
+ *,
595
+ conn: HTTPConnection,
596
+ auto_error: Literal[True] = True,
597
+ ) -> BaseAuthorization: ...
598
+ @overload
599
+ @classmethod
600
+ def extract(
601
+ cls,
602
+ scheme: Literal[Scheme.API_KEY],
603
+ source: OptSource = None,
604
+ *,
605
+ conn: HTTPConnection,
606
+ auto_error: Literal[True] = True,
607
+ ) -> APIKeyAuthorization: ...
608
+ @overload
609
+ @classmethod
610
+ def extract(
611
+ cls,
612
+ scheme: Literal[Scheme.BEARER_TOKEN],
613
+ source: OptSource = None,
614
+ *,
615
+ conn: HTTPConnection,
616
+ auto_error: Literal[True] = True,
617
+ ) -> BearerTokenAuthorization: ...
618
+ @classmethod
619
+ def extract(
620
+ cls,
621
+ scheme: OptScheme = None,
622
+ source: OptSource = None,
623
+ *,
624
+ conn: HTTPConnection,
625
+ auto_error: bool = True,
626
+ ) -> OptAnyAuthorization:
627
+ if scheme is None:
628
+ if source is None:
629
+ return BaseAuthorization.extract(conn, auto_error=auto_error)
630
+ elif source is Source.HEADER:
631
+ return BaseAuthorization.from_header(conn, auto_error=auto_error)
632
+ elif source is Source.QUERY:
633
+ return BaseAuthorization.from_query(conn, auto_error=auto_error)
634
+ elif source is Source.STATE:
635
+ return BaseAuthorization.from_state(conn, auto_error=auto_error)
636
+ elif scheme is Scheme.API_KEY:
637
+ if source is None:
638
+ return APIKeyAuthorization.extract(conn, auto_error=auto_error)
639
+ elif source is Source.HEADER:
640
+ return APIKeyAuthorization.from_header(conn, auto_error=auto_error)
641
+ elif source is Source.QUERY:
642
+ return APIKeyAuthorization.from_query(conn, auto_error=auto_error)
643
+ elif source is Source.STATE:
644
+ return APIKeyAuthorization.from_state(conn, auto_error=auto_error)
645
+ elif scheme is Scheme.BEARER_TOKEN:
646
+ if source is None:
647
+ return BearerTokenAuthorization.extract(conn, auto_error=auto_error)
648
+ elif source is Source.HEADER:
649
+ return BearerTokenAuthorization.from_header(conn, auto_error=auto_error)
650
+ elif source is Source.QUERY:
651
+ return BearerTokenAuthorization.from_query(conn, auto_error=auto_error)
652
+ elif source is Source.STATE:
653
+ return BearerTokenAuthorization.from_state(conn, auto_error=auto_error)
654
+
655
+ @overload
656
+ @classmethod
657
+ def as_dependency(
658
+ cls,
659
+ protocol: None = None,
660
+ *,
661
+ scheme: None = None,
662
+ auto_error: Literal[False],
663
+ ) -> Callable[
664
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
665
+ BaseAuthorization | None,
666
+ ]: ...
667
+ @overload
668
+ @classmethod
669
+ def as_dependency(
670
+ cls,
671
+ protocol: None = None,
672
+ *,
673
+ scheme: Literal[Scheme.API_KEY],
674
+ auto_error: Literal[False],
675
+ ) -> Callable[
676
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
677
+ APIKeyAuthorization | None,
678
+ ]: ...
679
+ @overload
680
+ @classmethod
681
+ def as_dependency(
682
+ cls,
683
+ protocol: None = None,
684
+ *,
685
+ scheme: Literal[Scheme.BEARER_TOKEN],
686
+ auto_error: Literal[False],
687
+ ) -> Callable[
688
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
689
+ BearerTokenAuthorization | None,
690
+ ]: ...
691
+ @overload
692
+ @classmethod
693
+ def as_dependency(
694
+ cls,
695
+ protocol: None = None,
696
+ *,
697
+ scheme: None = None,
698
+ auto_error: Literal[True] = True,
699
+ ) -> Callable[
700
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
701
+ BaseAuthorization,
702
+ ]: ...
703
+ @overload
704
+ @classmethod
705
+ def as_dependency(
706
+ cls,
707
+ protocol: None = None,
708
+ *,
709
+ scheme: Literal[Scheme.API_KEY],
710
+ auto_error: Literal[True] = True,
711
+ ) -> Callable[
712
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
713
+ APIKeyAuthorization,
714
+ ]: ...
715
+ @overload
716
+ @classmethod
717
+ def as_dependency(
718
+ cls,
719
+ protocol: None = None,
720
+ *,
721
+ scheme: Literal[Scheme.BEARER_TOKEN],
722
+ auto_error: Literal[True] = True,
723
+ ) -> Callable[
724
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
725
+ BearerTokenAuthorization,
726
+ ]: ...
727
+
728
+ @overload
729
+ @classmethod
730
+ def as_dependency(
731
+ cls,
732
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
733
+ *,
734
+ scheme: None = None,
735
+ auto_error: Literal[False],
736
+ ) -> Callable[
737
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
738
+ BaseAuthorization | None,
739
+ ]: ...
740
+ @overload
741
+ @classmethod
742
+ def as_dependency(
743
+ cls,
744
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
745
+ *,
746
+ scheme: Literal[Scheme.API_KEY],
747
+ auto_error: Literal[False],
748
+ ) -> Callable[
749
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
750
+ APIKeyAuthorization | None,
751
+ ]: ...
752
+ @overload
753
+ @classmethod
754
+ def as_dependency(
755
+ cls,
756
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
757
+ *,
758
+ scheme: Literal[Scheme.BEARER_TOKEN],
759
+ auto_error: Literal[False],
760
+ ) -> Callable[
761
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
762
+ BearerTokenAuthorization | None,
763
+ ]: ...
764
+ @overload
765
+ @classmethod
766
+ def as_dependency(
767
+ cls,
768
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
769
+ *,
770
+ scheme: None = None,
771
+ auto_error: Literal[True] = True,
772
+ ) -> Callable[
773
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
774
+ BaseAuthorization,
775
+ ]: ...
776
+ @overload
777
+ @classmethod
778
+ def as_dependency(
779
+ cls,
780
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
781
+ *,
782
+ scheme: Literal[Scheme.API_KEY],
783
+ auto_error: Literal[True] = True,
784
+ ) -> Callable[
785
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
786
+ APIKeyAuthorization,
787
+ ]: ...
788
+ @overload
789
+ @classmethod
790
+ def as_dependency(
791
+ cls,
792
+ protocol: Literal[Protocol.HTTP] = Protocol.HTTP,
793
+ *,
794
+ scheme: Literal[Scheme.BEARER_TOKEN],
795
+ auto_error: Literal[True] = True,
796
+ ) -> Callable[
797
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
798
+ BearerTokenAuthorization,
799
+ ]: ...
800
+
801
+ @overload
802
+ @classmethod
803
+ def as_dependency(
804
+ cls,
805
+ protocol: Literal[Protocol.WEBSOCKET],
806
+ *,
807
+ scheme: None = None,
808
+ auto_error: Literal[False],
809
+ ) -> Callable[[WebSocket, OptStr, OptStr], BaseAuthorization | None]: ...
810
+ @overload
811
+ @classmethod
812
+ def as_dependency(
813
+ cls,
814
+ protocol: Literal[Protocol.WEBSOCKET],
815
+ *,
816
+ scheme: Literal[Scheme.API_KEY],
817
+ auto_error: Literal[False],
818
+ ) -> Callable[[WebSocket, OptStr, OptStr], APIKeyAuthorization | None]: ...
819
+ @overload
820
+ @classmethod
821
+ def as_dependency(
822
+ cls,
823
+ protocol: Literal[Protocol.WEBSOCKET],
824
+ *,
825
+ scheme: Literal[Scheme.BEARER_TOKEN],
826
+ auto_error: Literal[False],
827
+ ) -> Callable[[WebSocket, OptStr, OptStr], BearerTokenAuthorization | None]: ...
828
+ @overload
829
+ @classmethod
830
+ def as_dependency(
831
+ cls,
832
+ protocol: Literal[Protocol.WEBSOCKET],
833
+ *,
834
+ scheme: None = None,
835
+ auto_error: Literal[True] = True,
836
+ ) -> Callable[[WebSocket, OptStr, OptStr], BaseAuthorization]: ...
837
+ @overload
838
+ @classmethod
839
+ def as_dependency(
840
+ cls,
841
+ protocol: Literal[Protocol.WEBSOCKET],
842
+ *,
843
+ scheme: Literal[Scheme.API_KEY],
844
+ auto_error: Literal[True] = True,
845
+ ) -> Callable[[WebSocket, OptStr, OptStr], APIKeyAuthorization]: ...
846
+ @overload
847
+ @classmethod
848
+ def as_dependency(
849
+ cls,
850
+ protocol: Literal[Protocol.WEBSOCKET],
851
+ *,
852
+ scheme: Literal[Scheme.BEARER_TOKEN],
853
+ auto_error: Literal[True] = True,
854
+ ) -> Callable[[WebSocket, OptStr, OptStr], BearerTokenAuthorization]: ...
855
+
856
+ @classmethod
857
+ def as_dependency(
858
+ cls,
859
+ protocol: OptProtocol = None,
860
+ *,
861
+ scheme: OptScheme = None,
862
+ auto_error: bool = True,
863
+ ) -> (
864
+ Callable[
865
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
866
+ OptAnyAuthorization,
867
+ ]
868
+ | Callable[
869
+ [HTTPConnection, HTTPAuthorizationCredentials | None, OptStr],
870
+ AnyAuthorization,
871
+ ]
872
+ | Callable[
873
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
874
+ OptAnyAuthorization,
875
+ ]
876
+ | Callable[
877
+ [Request, HTTPAuthorizationCredentials | None, OptStr],
878
+ AnyAuthorization,
879
+ ]
880
+ | Callable[[WebSocket, OptStr, OptStr], OptAnyAuthorization]
881
+ | Callable[[WebSocket, OptStr, OptStr], AnyAuthorization]
882
+ ):
883
+ if scheme is None:
884
+ return BaseAuthorization.as_dependency(protocol, auto_error=auto_error)
885
+ elif scheme is Scheme.API_KEY:
886
+ return APIKeyAuthorization.as_dependency(protocol, auto_error=auto_error)
887
+ elif scheme is Scheme.BEARER_TOKEN:
888
+ return BearerTokenAuthorization.as_dependency(
889
+ protocol, auto_error=auto_error
890
+ )
891
+
892
+ @overload
893
+ @classmethod
894
+ def httpx_auth(
895
+ cls,
896
+ scheme: Literal[Scheme.API_KEY],
897
+ *,
898
+ authorization: str | APIKeyAuthorization,
899
+ ) -> APIKeyAuth: ...
900
+ @overload
901
+ @classmethod
902
+ def httpx_auth(
903
+ cls,
904
+ scheme: Literal[Scheme.BEARER_TOKEN] = Scheme.BEARER_TOKEN,
905
+ *,
906
+ authorization: str | BearerTokenAuthorization,
907
+ ) -> BearerTokenAuth: ...
908
+ @classmethod
909
+ def httpx_auth(
910
+ cls,
911
+ scheme: Scheme = Scheme.BEARER_TOKEN,
912
+ *,
913
+ authorization: str | AnyAuthorization,
914
+ ) -> AnyHTTPXAuthorization:
915
+ if isinstance(authorization, str):
916
+ token = authorization
917
+ else:
918
+ token = authorization.credentials
919
+ if scheme is Scheme.API_KEY:
920
+ return APIKeyAuth(token)
921
+ elif scheme is Scheme.BEARER_TOKEN:
922
+ return BearerTokenAuth(token)