apache-airflow-providers-fab 3.1.0rc1__py3-none-any.whl → 3.2.0rc1__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.
- airflow/providers/fab/__init__.py +1 -1
- airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.py +3 -1
- airflow/providers/fab/auth_manager/api_fastapi/datamodels/roles.py +13 -7
- airflow/providers/fab/auth_manager/api_fastapi/datamodels/users.py +68 -0
- airflow/providers/fab/auth_manager/api_fastapi/openapi/v2-fab-auth-manager-generated.yaml +485 -18
- airflow/providers/fab/auth_manager/api_fastapi/routes/login.py +2 -4
- airflow/providers/fab/auth_manager/api_fastapi/routes/users.py +133 -0
- airflow/providers/fab/auth_manager/api_fastapi/services/login.py +1 -2
- airflow/providers/fab/auth_manager/api_fastapi/services/users.py +219 -0
- airflow/providers/fab/auth_manager/cli_commands/db_command.py +2 -2
- airflow/providers/fab/auth_manager/cli_commands/permissions_command.py +6 -2
- airflow/providers/fab/auth_manager/cli_commands/user_command.py +3 -3
- airflow/providers/fab/auth_manager/fab_auth_manager.py +18 -51
- airflow/providers/fab/auth_manager/models/__init__.py +6 -6
- airflow/providers/fab/auth_manager/security_manager/override.py +97 -84
- airflow/providers/fab/auth_manager/views/user.py +12 -0
- airflow/providers/fab/cli/__init__.py +18 -0
- airflow/providers/fab/{auth_manager/cli_commands → cli}/definition.py +50 -2
- airflow/providers/fab/get_provider_info.py +8 -0
- airflow/providers/fab/version_compat.py +1 -0
- airflow/providers/fab/www/app.py +2 -7
- airflow/providers/fab/www/extensions/init_appbuilder.py +3 -2
- airflow/providers/fab/www/extensions/init_views.py +11 -7
- airflow/providers/fab/www/package-lock.json +764 -572
- airflow/providers/fab/www/package.json +12 -9
- airflow/providers/fab/www/static/dist/{743.0c0bf201ae17e66a9a3f.js → 743.8fb7d21632ed892227fe.js} +2 -2
- airflow/providers/fab/www/static/dist/{airflowDefaultTheme.ef6fc04c9b6920cd75c9.js → airflowDefaultTheme.51e5d14856ee1ebc83ca.js} +1 -1
- airflow/providers/fab/www/static/dist/{flash.eaaf777ec1b3628cf7be.js → flash.865b6940c00b2a9041b3.js} +1 -1
- airflow/providers/fab/www/static/dist/{loadingDots.76f4332c0a932c3dc08f.js → loadingDots.07f5b9805847242736e1.js} +1 -1
- airflow/providers/fab/www/static/dist/main.8cffe40bcf7cca998f4e.js +2 -0
- airflow/providers/fab/www/static/dist/manifest.json +13 -13
- airflow/providers/fab/www/static/dist/{materialIcons.ad07a489b2f0fc1a96bf.js → materialIcons.4fe84ae36604d84dec78.js} +1 -1
- airflow/providers/fab/www/static/dist/moment.0ec3ee3fb60dc999b1fd.js +1 -0
- airflow/providers/fab/www/static/js/main.js +11 -0
- airflow/providers/fab/www/templates/airflow/main.html +1 -0
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/METADATA +10 -10
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/RECORD +50 -46
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/licenses/3rd-party-licenses/LICENSES-ui.txt +1 -1
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/licenses/NOTICE +1 -1
- airflow/providers/fab/www/static/dist/main.bc1f701c3d133e2a3bab.js +0 -2
- airflow/providers/fab/www/static/dist/moment.5b85b4f6be2fe9c405ac.js +0 -1
- /airflow/providers/fab/www/static/dist/{743.0c0bf201ae17e66a9a3f.js.LICENSE.txt → 743.8fb7d21632ed892227fe.js.LICENSE.txt} +0 -0
- /airflow/providers/fab/www/static/dist/{airflowDefaultTheme.ef6fc04c9b6920cd75c9.css → airflowDefaultTheme.51e5d14856ee1ebc83ca.css} +0 -0
- /airflow/providers/fab/www/static/dist/{flash.eaaf777ec1b3628cf7be.css → flash.865b6940c00b2a9041b3.css} +0 -0
- /airflow/providers/fab/www/static/dist/{loadingDots.76f4332c0a932c3dc08f.css → loadingDots.07f5b9805847242736e1.css} +0 -0
- /airflow/providers/fab/www/static/dist/{main.bc1f701c3d133e2a3bab.css → main.8cffe40bcf7cca998f4e.css} +0 -0
- /airflow/providers/fab/www/static/dist/{main.bc1f701c3d133e2a3bab.js.LICENSE.txt → main.8cffe40bcf7cca998f4e.js.LICENSE.txt} +0 -0
- /airflow/providers/fab/www/static/dist/{materialIcons.ad07a489b2f0fc1a96bf.css → materialIcons.4fe84ae36604d84dec78.css} +0 -0
- /airflow/providers/fab/www/static/dist/{runtime.254c277d91ce3ac79c64.js → runtime.45b36fb8335446865b53.js} +0 -0
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/entry_points.txt +0 -0
- {apache_airflow_providers_fab-3.1.0rc1.dist-info → apache_airflow_providers_fab-3.2.0rc1.dist-info}/licenses/LICENSE +0 -0
|
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
|
|
|
29
29
|
|
|
30
30
|
__all__ = ["__version__"]
|
|
31
31
|
|
|
32
|
-
__version__ = "3.
|
|
32
|
+
__version__ = "3.2.0"
|
|
33
33
|
|
|
34
34
|
if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
|
|
35
35
|
"3.0.2"
|
|
@@ -120,7 +120,9 @@ def post_user() -> APIResponse:
|
|
|
120
120
|
raise BadRequest(detail=detail)
|
|
121
121
|
|
|
122
122
|
if not roles_to_add: # No roles provided, use the F.A.B's default registered user role.
|
|
123
|
-
|
|
123
|
+
r = security_manager.find_role(security_manager.auth_user_registration_role)
|
|
124
|
+
if r:
|
|
125
|
+
roles_to_add.append(r)
|
|
124
126
|
|
|
125
127
|
user = security_manager.add_user(role=roles_to_add, **data)
|
|
126
128
|
if not user:
|
|
@@ -21,30 +21,36 @@ from pydantic import Field
|
|
|
21
21
|
from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class
|
|
24
|
+
class Action(BaseModel):
|
|
25
25
|
"""Outgoing representation of an action (permission name)."""
|
|
26
26
|
|
|
27
27
|
name: str
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class Resource(BaseModel):
|
|
31
31
|
"""Outgoing representation of a resource."""
|
|
32
32
|
|
|
33
33
|
name: str
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
class
|
|
36
|
+
class ActionResource(BaseModel):
|
|
37
37
|
"""Pairing of an action with a resource."""
|
|
38
38
|
|
|
39
|
-
action:
|
|
40
|
-
resource:
|
|
39
|
+
action: Action
|
|
40
|
+
resource: Resource
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Role(BaseModel):
|
|
44
|
+
"""Lightweight role reference used by /users schemas."""
|
|
45
|
+
|
|
46
|
+
name: str
|
|
41
47
|
|
|
42
48
|
|
|
43
49
|
class RoleBody(StrictBaseModel):
|
|
44
50
|
"""Incoming payload for creating/updating a role."""
|
|
45
51
|
|
|
46
52
|
name: str = Field(min_length=1)
|
|
47
|
-
permissions: list[
|
|
53
|
+
permissions: list[ActionResource] = Field(
|
|
48
54
|
default_factory=list, alias="actions", validation_alias="actions"
|
|
49
55
|
)
|
|
50
56
|
|
|
@@ -53,7 +59,7 @@ class RoleResponse(BaseModel):
|
|
|
53
59
|
"""Outgoing representation of a role and its permissions."""
|
|
54
60
|
|
|
55
61
|
name: str
|
|
56
|
-
permissions: list[
|
|
62
|
+
permissions: list[ActionResource] = Field(default_factory=list, serialization_alias="actions")
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
class RoleCollectionResponse(BaseModel):
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
# or more contributor license agreements. See the NOTICE file
|
|
3
|
+
# distributed with this work for additional information
|
|
4
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
# to you under the Apache License, Version 2.0 (the
|
|
6
|
+
# "License"); you may not use this file except in compliance
|
|
7
|
+
# with the License. You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from pydantic import Field, SecretStr
|
|
20
|
+
|
|
21
|
+
from airflow.api_fastapi.common.types import UtcDateTime
|
|
22
|
+
from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel
|
|
23
|
+
from airflow.providers.fab.auth_manager.api_fastapi.datamodels.roles import Role
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class UserBody(StrictBaseModel):
|
|
27
|
+
"""Incoming payload for creating a user."""
|
|
28
|
+
|
|
29
|
+
username: str = Field(min_length=1)
|
|
30
|
+
email: str = Field(min_length=1)
|
|
31
|
+
first_name: str = Field(min_length=1)
|
|
32
|
+
last_name: str = Field(min_length=1)
|
|
33
|
+
roles: list[Role] | None = None
|
|
34
|
+
password: SecretStr
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class UserPatchBody(StrictBaseModel):
|
|
38
|
+
"""Incoming payload for updating a user (all fields optional)."""
|
|
39
|
+
|
|
40
|
+
username: str | None = Field(default=None, min_length=1)
|
|
41
|
+
email: str | None = Field(default=None, min_length=1)
|
|
42
|
+
first_name: str | None = Field(default=None, min_length=1)
|
|
43
|
+
last_name: str | None = Field(default=None, min_length=1)
|
|
44
|
+
roles: list[Role] | None = None
|
|
45
|
+
password: SecretStr | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class UserResponse(BaseModel):
|
|
49
|
+
"""Outgoing representation of a user (no password)."""
|
|
50
|
+
|
|
51
|
+
username: str
|
|
52
|
+
email: str
|
|
53
|
+
first_name: str
|
|
54
|
+
last_name: str
|
|
55
|
+
roles: list[Role] | None = None
|
|
56
|
+
active: bool | None = None
|
|
57
|
+
last_login: UtcDateTime | None = None
|
|
58
|
+
login_count: int | None = None
|
|
59
|
+
fail_login_count: int | None = None
|
|
60
|
+
created_on: UtcDateTime | None = None
|
|
61
|
+
changed_on: UtcDateTime | None = None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class UserCollectionResponse(BaseModel):
|
|
65
|
+
"""Response model for a collection of users."""
|
|
66
|
+
|
|
67
|
+
users: list[UserResponse]
|
|
68
|
+
total_entries: int
|
|
@@ -398,21 +398,304 @@ paths:
|
|
|
398
398
|
application/json:
|
|
399
399
|
schema:
|
|
400
400
|
$ref: '#/components/schemas/HTTPValidationError'
|
|
401
|
+
/auth/fab/v1/users:
|
|
402
|
+
post:
|
|
403
|
+
tags:
|
|
404
|
+
- FabAuthManager
|
|
405
|
+
summary: Create User
|
|
406
|
+
operationId: create_user
|
|
407
|
+
security:
|
|
408
|
+
- OAuth2PasswordBearer: []
|
|
409
|
+
- HTTPBearer: []
|
|
410
|
+
requestBody:
|
|
411
|
+
required: true
|
|
412
|
+
content:
|
|
413
|
+
application/json:
|
|
414
|
+
schema:
|
|
415
|
+
$ref: '#/components/schemas/UserBody'
|
|
416
|
+
responses:
|
|
417
|
+
'200':
|
|
418
|
+
description: Successful Response
|
|
419
|
+
content:
|
|
420
|
+
application/json:
|
|
421
|
+
schema:
|
|
422
|
+
$ref: '#/components/schemas/UserResponse'
|
|
423
|
+
'400':
|
|
424
|
+
content:
|
|
425
|
+
application/json:
|
|
426
|
+
schema:
|
|
427
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
428
|
+
description: Bad Request
|
|
429
|
+
'401':
|
|
430
|
+
content:
|
|
431
|
+
application/json:
|
|
432
|
+
schema:
|
|
433
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
434
|
+
description: Unauthorized
|
|
435
|
+
'403':
|
|
436
|
+
content:
|
|
437
|
+
application/json:
|
|
438
|
+
schema:
|
|
439
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
440
|
+
description: Forbidden
|
|
441
|
+
'409':
|
|
442
|
+
content:
|
|
443
|
+
application/json:
|
|
444
|
+
schema:
|
|
445
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
446
|
+
description: Conflict
|
|
447
|
+
'500':
|
|
448
|
+
content:
|
|
449
|
+
application/json:
|
|
450
|
+
schema:
|
|
451
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
452
|
+
description: Internal Server Error
|
|
453
|
+
'422':
|
|
454
|
+
description: Validation Error
|
|
455
|
+
content:
|
|
456
|
+
application/json:
|
|
457
|
+
schema:
|
|
458
|
+
$ref: '#/components/schemas/HTTPValidationError'
|
|
459
|
+
get:
|
|
460
|
+
tags:
|
|
461
|
+
- FabAuthManager
|
|
462
|
+
summary: Get Users
|
|
463
|
+
description: List users with pagination and ordering.
|
|
464
|
+
operationId: get_users
|
|
465
|
+
security:
|
|
466
|
+
- OAuth2PasswordBearer: []
|
|
467
|
+
- HTTPBearer: []
|
|
468
|
+
parameters:
|
|
469
|
+
- name: order_by
|
|
470
|
+
in: query
|
|
471
|
+
required: false
|
|
472
|
+
schema:
|
|
473
|
+
type: string
|
|
474
|
+
description: Field to order by. Prefix with '-' for descending.
|
|
475
|
+
default: id
|
|
476
|
+
title: Order By
|
|
477
|
+
description: Field to order by. Prefix with '-' for descending.
|
|
478
|
+
- name: offset
|
|
479
|
+
in: query
|
|
480
|
+
required: false
|
|
481
|
+
schema:
|
|
482
|
+
type: integer
|
|
483
|
+
minimum: 0
|
|
484
|
+
description: Number of items to skip before starting to collect results.
|
|
485
|
+
default: 0
|
|
486
|
+
title: Offset
|
|
487
|
+
description: Number of items to skip before starting to collect results.
|
|
488
|
+
- name: limit
|
|
489
|
+
in: query
|
|
490
|
+
required: false
|
|
491
|
+
schema:
|
|
492
|
+
type: integer
|
|
493
|
+
minimum: 0
|
|
494
|
+
default: 100
|
|
495
|
+
title: Limit
|
|
496
|
+
responses:
|
|
497
|
+
'200':
|
|
498
|
+
description: Successful Response
|
|
499
|
+
content:
|
|
500
|
+
application/json:
|
|
501
|
+
schema:
|
|
502
|
+
$ref: '#/components/schemas/UserCollectionResponse'
|
|
503
|
+
'400':
|
|
504
|
+
content:
|
|
505
|
+
application/json:
|
|
506
|
+
schema:
|
|
507
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
508
|
+
description: Bad Request
|
|
509
|
+
'401':
|
|
510
|
+
content:
|
|
511
|
+
application/json:
|
|
512
|
+
schema:
|
|
513
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
514
|
+
description: Unauthorized
|
|
515
|
+
'403':
|
|
516
|
+
content:
|
|
517
|
+
application/json:
|
|
518
|
+
schema:
|
|
519
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
520
|
+
description: Forbidden
|
|
521
|
+
'422':
|
|
522
|
+
description: Validation Error
|
|
523
|
+
content:
|
|
524
|
+
application/json:
|
|
525
|
+
schema:
|
|
526
|
+
$ref: '#/components/schemas/HTTPValidationError'
|
|
527
|
+
/auth/fab/v1/users/{username}:
|
|
528
|
+
get:
|
|
529
|
+
tags:
|
|
530
|
+
- FabAuthManager
|
|
531
|
+
summary: Get User
|
|
532
|
+
description: Get a user by username.
|
|
533
|
+
operationId: get_user
|
|
534
|
+
security:
|
|
535
|
+
- OAuth2PasswordBearer: []
|
|
536
|
+
- HTTPBearer: []
|
|
537
|
+
parameters:
|
|
538
|
+
- name: username
|
|
539
|
+
in: path
|
|
540
|
+
required: true
|
|
541
|
+
schema:
|
|
542
|
+
type: string
|
|
543
|
+
minLength: 1
|
|
544
|
+
title: Username
|
|
545
|
+
responses:
|
|
546
|
+
'200':
|
|
547
|
+
description: Successful Response
|
|
548
|
+
content:
|
|
549
|
+
application/json:
|
|
550
|
+
schema:
|
|
551
|
+
$ref: '#/components/schemas/UserResponse'
|
|
552
|
+
'401':
|
|
553
|
+
content:
|
|
554
|
+
application/json:
|
|
555
|
+
schema:
|
|
556
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
557
|
+
description: Unauthorized
|
|
558
|
+
'403':
|
|
559
|
+
content:
|
|
560
|
+
application/json:
|
|
561
|
+
schema:
|
|
562
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
563
|
+
description: Forbidden
|
|
564
|
+
'404':
|
|
565
|
+
content:
|
|
566
|
+
application/json:
|
|
567
|
+
schema:
|
|
568
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
569
|
+
description: Not Found
|
|
570
|
+
'422':
|
|
571
|
+
description: Validation Error
|
|
572
|
+
content:
|
|
573
|
+
application/json:
|
|
574
|
+
schema:
|
|
575
|
+
$ref: '#/components/schemas/HTTPValidationError'
|
|
576
|
+
patch:
|
|
577
|
+
tags:
|
|
578
|
+
- FabAuthManager
|
|
579
|
+
summary: Update User
|
|
580
|
+
description: Update an existing user.
|
|
581
|
+
operationId: update_user
|
|
582
|
+
security:
|
|
583
|
+
- OAuth2PasswordBearer: []
|
|
584
|
+
- HTTPBearer: []
|
|
585
|
+
parameters:
|
|
586
|
+
- name: username
|
|
587
|
+
in: path
|
|
588
|
+
required: true
|
|
589
|
+
schema:
|
|
590
|
+
type: string
|
|
591
|
+
minLength: 1
|
|
592
|
+
title: Username
|
|
593
|
+
- name: update_mask
|
|
594
|
+
in: query
|
|
595
|
+
required: false
|
|
596
|
+
schema:
|
|
597
|
+
anyOf:
|
|
598
|
+
- type: string
|
|
599
|
+
- type: 'null'
|
|
600
|
+
description: Comma-separated list of fields to update
|
|
601
|
+
title: Update Mask
|
|
602
|
+
description: Comma-separated list of fields to update
|
|
603
|
+
requestBody:
|
|
604
|
+
required: true
|
|
605
|
+
content:
|
|
606
|
+
application/json:
|
|
607
|
+
schema:
|
|
608
|
+
$ref: '#/components/schemas/UserPatchBody'
|
|
609
|
+
responses:
|
|
610
|
+
'200':
|
|
611
|
+
description: Successful Response
|
|
612
|
+
content:
|
|
613
|
+
application/json:
|
|
614
|
+
schema:
|
|
615
|
+
$ref: '#/components/schemas/UserResponse'
|
|
616
|
+
'400':
|
|
617
|
+
content:
|
|
618
|
+
application/json:
|
|
619
|
+
schema:
|
|
620
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
621
|
+
description: Bad Request
|
|
622
|
+
'401':
|
|
623
|
+
content:
|
|
624
|
+
application/json:
|
|
625
|
+
schema:
|
|
626
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
627
|
+
description: Unauthorized
|
|
628
|
+
'403':
|
|
629
|
+
content:
|
|
630
|
+
application/json:
|
|
631
|
+
schema:
|
|
632
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
633
|
+
description: Forbidden
|
|
634
|
+
'404':
|
|
635
|
+
content:
|
|
636
|
+
application/json:
|
|
637
|
+
schema:
|
|
638
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
639
|
+
description: Not Found
|
|
640
|
+
'409':
|
|
641
|
+
content:
|
|
642
|
+
application/json:
|
|
643
|
+
schema:
|
|
644
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
645
|
+
description: Conflict
|
|
646
|
+
'422':
|
|
647
|
+
description: Validation Error
|
|
648
|
+
content:
|
|
649
|
+
application/json:
|
|
650
|
+
schema:
|
|
651
|
+
$ref: '#/components/schemas/HTTPValidationError'
|
|
652
|
+
delete:
|
|
653
|
+
tags:
|
|
654
|
+
- FabAuthManager
|
|
655
|
+
summary: Delete User
|
|
656
|
+
description: Delete a user by username.
|
|
657
|
+
operationId: delete_user
|
|
658
|
+
security:
|
|
659
|
+
- OAuth2PasswordBearer: []
|
|
660
|
+
- HTTPBearer: []
|
|
661
|
+
parameters:
|
|
662
|
+
- name: username
|
|
663
|
+
in: path
|
|
664
|
+
required: true
|
|
665
|
+
schema:
|
|
666
|
+
type: string
|
|
667
|
+
minLength: 1
|
|
668
|
+
title: Username
|
|
669
|
+
responses:
|
|
670
|
+
'204':
|
|
671
|
+
description: Successful Response
|
|
672
|
+
'401':
|
|
673
|
+
content:
|
|
674
|
+
application/json:
|
|
675
|
+
schema:
|
|
676
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
677
|
+
description: Unauthorized
|
|
678
|
+
'403':
|
|
679
|
+
content:
|
|
680
|
+
application/json:
|
|
681
|
+
schema:
|
|
682
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
683
|
+
description: Forbidden
|
|
684
|
+
'404':
|
|
685
|
+
content:
|
|
686
|
+
application/json:
|
|
687
|
+
schema:
|
|
688
|
+
$ref: '#/components/schemas/HTTPExceptionResponse'
|
|
689
|
+
description: Not Found
|
|
690
|
+
'422':
|
|
691
|
+
description: Validation Error
|
|
692
|
+
content:
|
|
693
|
+
application/json:
|
|
694
|
+
schema:
|
|
695
|
+
$ref: '#/components/schemas/HTTPValidationError'
|
|
401
696
|
components:
|
|
402
697
|
schemas:
|
|
403
|
-
|
|
404
|
-
properties:
|
|
405
|
-
action:
|
|
406
|
-
$ref: '#/components/schemas/ActionResponse'
|
|
407
|
-
resource:
|
|
408
|
-
$ref: '#/components/schemas/ResourceResponse'
|
|
409
|
-
type: object
|
|
410
|
-
required:
|
|
411
|
-
- action
|
|
412
|
-
- resource
|
|
413
|
-
title: ActionResourceResponse
|
|
414
|
-
description: Pairing of an action with a resource.
|
|
415
|
-
ActionResponse:
|
|
698
|
+
Action:
|
|
416
699
|
properties:
|
|
417
700
|
name:
|
|
418
701
|
type: string
|
|
@@ -420,8 +703,20 @@ components:
|
|
|
420
703
|
type: object
|
|
421
704
|
required:
|
|
422
705
|
- name
|
|
423
|
-
title:
|
|
706
|
+
title: Action
|
|
424
707
|
description: Outgoing representation of an action (permission name).
|
|
708
|
+
ActionResource:
|
|
709
|
+
properties:
|
|
710
|
+
action:
|
|
711
|
+
$ref: '#/components/schemas/Action'
|
|
712
|
+
resource:
|
|
713
|
+
$ref: '#/components/schemas/Resource'
|
|
714
|
+
type: object
|
|
715
|
+
required:
|
|
716
|
+
- action
|
|
717
|
+
- resource
|
|
718
|
+
title: ActionResource
|
|
719
|
+
description: Pairing of an action with a resource.
|
|
425
720
|
HTTPExceptionResponse:
|
|
426
721
|
properties:
|
|
427
722
|
detail:
|
|
@@ -454,7 +749,7 @@ components:
|
|
|
454
749
|
- access_token
|
|
455
750
|
title: LoginResponse
|
|
456
751
|
description: API Token serializer for responses.
|
|
457
|
-
|
|
752
|
+
Resource:
|
|
458
753
|
properties:
|
|
459
754
|
name:
|
|
460
755
|
type: string
|
|
@@ -462,8 +757,18 @@ components:
|
|
|
462
757
|
type: object
|
|
463
758
|
required:
|
|
464
759
|
- name
|
|
465
|
-
title:
|
|
760
|
+
title: Resource
|
|
466
761
|
description: Outgoing representation of a resource.
|
|
762
|
+
Role:
|
|
763
|
+
properties:
|
|
764
|
+
name:
|
|
765
|
+
type: string
|
|
766
|
+
title: Name
|
|
767
|
+
type: object
|
|
768
|
+
required:
|
|
769
|
+
- name
|
|
770
|
+
title: Role
|
|
771
|
+
description: Lightweight role reference used by /users schemas.
|
|
467
772
|
RoleBody:
|
|
468
773
|
properties:
|
|
469
774
|
name:
|
|
@@ -472,7 +777,7 @@ components:
|
|
|
472
777
|
title: Name
|
|
473
778
|
actions:
|
|
474
779
|
items:
|
|
475
|
-
$ref: '#/components/schemas/
|
|
780
|
+
$ref: '#/components/schemas/ActionResource'
|
|
476
781
|
type: array
|
|
477
782
|
title: Actions
|
|
478
783
|
additionalProperties: false
|
|
@@ -504,7 +809,7 @@ components:
|
|
|
504
809
|
title: Name
|
|
505
810
|
actions:
|
|
506
811
|
items:
|
|
507
|
-
$ref: '#/components/schemas/
|
|
812
|
+
$ref: '#/components/schemas/ActionResource'
|
|
508
813
|
type: array
|
|
509
814
|
title: Actions
|
|
510
815
|
type: object
|
|
@@ -512,6 +817,168 @@ components:
|
|
|
512
817
|
- name
|
|
513
818
|
title: RoleResponse
|
|
514
819
|
description: Outgoing representation of a role and its permissions.
|
|
820
|
+
UserBody:
|
|
821
|
+
properties:
|
|
822
|
+
username:
|
|
823
|
+
type: string
|
|
824
|
+
minLength: 1
|
|
825
|
+
title: Username
|
|
826
|
+
email:
|
|
827
|
+
type: string
|
|
828
|
+
minLength: 1
|
|
829
|
+
title: Email
|
|
830
|
+
first_name:
|
|
831
|
+
type: string
|
|
832
|
+
minLength: 1
|
|
833
|
+
title: First Name
|
|
834
|
+
last_name:
|
|
835
|
+
type: string
|
|
836
|
+
minLength: 1
|
|
837
|
+
title: Last Name
|
|
838
|
+
roles:
|
|
839
|
+
anyOf:
|
|
840
|
+
- items:
|
|
841
|
+
$ref: '#/components/schemas/Role'
|
|
842
|
+
type: array
|
|
843
|
+
- type: 'null'
|
|
844
|
+
title: Roles
|
|
845
|
+
password:
|
|
846
|
+
type: string
|
|
847
|
+
format: password
|
|
848
|
+
title: Password
|
|
849
|
+
writeOnly: true
|
|
850
|
+
additionalProperties: false
|
|
851
|
+
type: object
|
|
852
|
+
required:
|
|
853
|
+
- username
|
|
854
|
+
- email
|
|
855
|
+
- first_name
|
|
856
|
+
- last_name
|
|
857
|
+
- password
|
|
858
|
+
title: UserBody
|
|
859
|
+
description: Incoming payload for creating a user.
|
|
860
|
+
UserCollectionResponse:
|
|
861
|
+
properties:
|
|
862
|
+
users:
|
|
863
|
+
items:
|
|
864
|
+
$ref: '#/components/schemas/UserResponse'
|
|
865
|
+
type: array
|
|
866
|
+
title: Users
|
|
867
|
+
total_entries:
|
|
868
|
+
type: integer
|
|
869
|
+
title: Total Entries
|
|
870
|
+
type: object
|
|
871
|
+
required:
|
|
872
|
+
- users
|
|
873
|
+
- total_entries
|
|
874
|
+
title: UserCollectionResponse
|
|
875
|
+
description: Response model for a collection of users.
|
|
876
|
+
UserPatchBody:
|
|
877
|
+
properties:
|
|
878
|
+
username:
|
|
879
|
+
anyOf:
|
|
880
|
+
- type: string
|
|
881
|
+
minLength: 1
|
|
882
|
+
- type: 'null'
|
|
883
|
+
title: Username
|
|
884
|
+
email:
|
|
885
|
+
anyOf:
|
|
886
|
+
- type: string
|
|
887
|
+
minLength: 1
|
|
888
|
+
- type: 'null'
|
|
889
|
+
title: Email
|
|
890
|
+
first_name:
|
|
891
|
+
anyOf:
|
|
892
|
+
- type: string
|
|
893
|
+
minLength: 1
|
|
894
|
+
- type: 'null'
|
|
895
|
+
title: First Name
|
|
896
|
+
last_name:
|
|
897
|
+
anyOf:
|
|
898
|
+
- type: string
|
|
899
|
+
minLength: 1
|
|
900
|
+
- type: 'null'
|
|
901
|
+
title: Last Name
|
|
902
|
+
roles:
|
|
903
|
+
anyOf:
|
|
904
|
+
- items:
|
|
905
|
+
$ref: '#/components/schemas/Role'
|
|
906
|
+
type: array
|
|
907
|
+
- type: 'null'
|
|
908
|
+
title: Roles
|
|
909
|
+
password:
|
|
910
|
+
anyOf:
|
|
911
|
+
- type: string
|
|
912
|
+
format: password
|
|
913
|
+
writeOnly: true
|
|
914
|
+
- type: 'null'
|
|
915
|
+
title: Password
|
|
916
|
+
additionalProperties: false
|
|
917
|
+
type: object
|
|
918
|
+
title: UserPatchBody
|
|
919
|
+
description: Incoming payload for updating a user (all fields optional).
|
|
920
|
+
UserResponse:
|
|
921
|
+
properties:
|
|
922
|
+
username:
|
|
923
|
+
type: string
|
|
924
|
+
title: Username
|
|
925
|
+
email:
|
|
926
|
+
type: string
|
|
927
|
+
title: Email
|
|
928
|
+
first_name:
|
|
929
|
+
type: string
|
|
930
|
+
title: First Name
|
|
931
|
+
last_name:
|
|
932
|
+
type: string
|
|
933
|
+
title: Last Name
|
|
934
|
+
roles:
|
|
935
|
+
anyOf:
|
|
936
|
+
- items:
|
|
937
|
+
$ref: '#/components/schemas/Role'
|
|
938
|
+
type: array
|
|
939
|
+
- type: 'null'
|
|
940
|
+
title: Roles
|
|
941
|
+
active:
|
|
942
|
+
anyOf:
|
|
943
|
+
- type: boolean
|
|
944
|
+
- type: 'null'
|
|
945
|
+
title: Active
|
|
946
|
+
last_login:
|
|
947
|
+
anyOf:
|
|
948
|
+
- type: string
|
|
949
|
+
format: date-time
|
|
950
|
+
- type: 'null'
|
|
951
|
+
title: Last Login
|
|
952
|
+
login_count:
|
|
953
|
+
anyOf:
|
|
954
|
+
- type: integer
|
|
955
|
+
- type: 'null'
|
|
956
|
+
title: Login Count
|
|
957
|
+
fail_login_count:
|
|
958
|
+
anyOf:
|
|
959
|
+
- type: integer
|
|
960
|
+
- type: 'null'
|
|
961
|
+
title: Fail Login Count
|
|
962
|
+
created_on:
|
|
963
|
+
anyOf:
|
|
964
|
+
- type: string
|
|
965
|
+
format: date-time
|
|
966
|
+
- type: 'null'
|
|
967
|
+
title: Created On
|
|
968
|
+
changed_on:
|
|
969
|
+
anyOf:
|
|
970
|
+
- type: string
|
|
971
|
+
format: date-time
|
|
972
|
+
- type: 'null'
|
|
973
|
+
title: Changed On
|
|
974
|
+
type: object
|
|
975
|
+
required:
|
|
976
|
+
- username
|
|
977
|
+
- email
|
|
978
|
+
- first_name
|
|
979
|
+
- last_name
|
|
980
|
+
title: UserResponse
|
|
981
|
+
description: Outgoing representation of a user (no password).
|
|
515
982
|
ValidationError:
|
|
516
983
|
properties:
|
|
517
984
|
loc:
|
|
@@ -18,10 +18,8 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
|
-
from fastapi import Body
|
|
22
|
-
from
|
|
23
|
-
from starlette.requests import Request # noqa: TC002
|
|
24
|
-
from starlette.responses import RedirectResponse
|
|
21
|
+
from fastapi import Body, Request, status
|
|
22
|
+
from fastapi.responses import RedirectResponse
|
|
25
23
|
|
|
26
24
|
from airflow.api_fastapi.app import get_auth_manager
|
|
27
25
|
from airflow.api_fastapi.auth.managers.base_auth_manager import COOKIE_NAME_JWT_TOKEN
|