fastlifeweb 0.21.0__py3-none-any.whl → 0.22.1__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.
- CHANGELOG.md +11 -1
- fastlife/__init__.py +49 -13
- fastlife/adapters/__init__.py +1 -1
- fastlife/adapters/fastapi/__init__.py +9 -0
- fastlife/adapters/fastapi/form.py +26 -0
- fastlife/{request → adapters/fastapi}/form_data.py +1 -1
- fastlife/{request → adapters/fastapi}/localizer.py +4 -2
- fastlife/adapters/fastapi/request.py +33 -0
- fastlife/{routing → adapters/fastapi/routing}/route.py +3 -3
- fastlife/{routing → adapters/fastapi/routing}/router.py +1 -1
- fastlife/adapters/itsdangerous/__init__.py +3 -0
- fastlife/adapters/itsdangerous/session.py +50 -0
- fastlife/adapters/jinjax/jinjax_ext/inspectable_component.py +7 -7
- fastlife/adapters/jinjax/jinjax_ext/jinjax_doc.py +1 -1
- fastlife/adapters/jinjax/renderer.py +5 -5
- fastlife/adapters/jinjax/widget_factory/factory.py +13 -3
- fastlife/adapters/jinjax/widgets/base.py +1 -1
- fastlife/adapters/jinjax/widgets/model.py +1 -1
- fastlife/adapters/jinjax/widgets/sequence.py +1 -1
- fastlife/adapters/jinjax/widgets/union.py +1 -1
- fastlife/components/Form.jinja +1 -1
- fastlife/components/pydantic_form/FatalError.jinja +8 -0
- fastlife/config/__init__.py +3 -6
- fastlife/config/configurator.py +18 -16
- fastlife/config/resources.py +1 -2
- fastlife/config/views.py +2 -2
- fastlife/domain/model/asgi.py +3 -0
- fastlife/{request → domain/model}/form.py +13 -22
- fastlife/{request → domain/model}/request.py +10 -32
- fastlife/domain/model/security_policy.py +105 -0
- fastlife/middlewares/base.py +1 -1
- fastlife/middlewares/reverse_proxy/x_forwarded.py +1 -2
- fastlife/middlewares/session/__init__.py +2 -2
- fastlife/middlewares/session/middleware.py +4 -3
- fastlife/middlewares/session/serializer.py +0 -44
- fastlife/{services/policy.py → service/check_permission.py} +1 -1
- fastlife/{security → service}/csrf.py +2 -2
- fastlife/service/locale_negociator.py +23 -0
- fastlife/{config → service}/registry.py +13 -7
- fastlife/service/security_policy.py +100 -0
- fastlife/{services → service}/templates.py +1 -6
- fastlife/{services → service}/translations.py +3 -0
- fastlife/{config/settings.py → settings.py} +6 -12
- fastlife/shared_utils/infer.py +24 -1
- fastlife/{templates/constants.py → template_globals.py} +2 -2
- fastlife/testing/testclient.py +2 -2
- fastlife/views/__init__.py +1 -0
- fastlife/views/pydantic_form.py +6 -0
- {fastlifeweb-0.21.0.dist-info → fastlifeweb-0.22.1.dist-info}/METADATA +1 -1
- {fastlifeweb-0.21.0.dist-info → fastlifeweb-0.22.1.dist-info}/RECORD +57 -53
- tailwind.config.js +1 -1
- fastlife/request/__init__.py +0 -5
- fastlife/security/__init__.py +0 -1
- fastlife/security/policy.py +0 -188
- fastlife/services/locale_negociator.py +0 -26
- fastlife/templates/__init__.py +0 -7
- fastlife/templates/inline.py +0 -26
- /fastlife/{routing → adapters/fastapi/routing}/__init__.py +0 -0
- /fastlife/domain/model/{security.py → csrf.py} +0 -0
- /fastlife/{services → service}/__init__.py +0 -0
- {fastlifeweb-0.21.0.dist-info → fastlifeweb-0.22.1.dist-info}/WHEEL +0 -0
- {fastlifeweb-0.21.0.dist-info → fastlifeweb-0.22.1.dist-info}/entry_points.txt +0 -0
- {fastlifeweb-0.21.0.dist-info → fastlifeweb-0.22.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,19 +1,29 @@
|
|
1
|
-
CHANGELOG.md,sha256=
|
2
|
-
fastlife/__init__.py,sha256=
|
3
|
-
fastlife/adapters/__init__.py,sha256=
|
1
|
+
CHANGELOG.md,sha256=iMVndHirSKsb0IAqVoiHUmMU4uYt7fwML0j96qwPYUc,7049
|
2
|
+
fastlife/__init__.py,sha256=cPPHF7zBVBkUt6KsJyVNiamuRRjUeERQsPVoS6AB-YE,1779
|
3
|
+
fastlife/adapters/__init__.py,sha256=imPD1hImpgrYkvUJRhHA5kVyGAua7VbP2WGkhSWKJT8,93
|
4
|
+
fastlife/adapters/fastapi/__init__.py,sha256=1goV1FGFP04TGyskJBLKZam4Gvt1yoAvLMNs4ekWSSQ,243
|
5
|
+
fastlife/adapters/fastapi/form.py,sha256=csxsDI6RK-g41pMwFhaVQCLDhF7dAZzgUp-VcrC3NFY,823
|
6
|
+
fastlife/adapters/fastapi/form_data.py,sha256=2DQ0o-RvY6iROUKQjS-UJdNYEVSsNPd-AjpergI3w54,4473
|
7
|
+
fastlife/adapters/fastapi/localizer.py,sha256=XD1kCJuAlkGevivmvAJEcGMCBWMef9rAfTOGmt3PVWU,436
|
8
|
+
fastlife/adapters/fastapi/request.py,sha256=hvJS7qxH7ZyKRdwDalVXGU8ZH84NtSQuljnAZPyqogU,1100
|
9
|
+
fastlife/adapters/fastapi/routing/__init__.py,sha256=8EMnQE5n8oA4J9_c3nxzwKDVt3tefZ6fGH0d2owE8mo,195
|
10
|
+
fastlife/adapters/fastapi/routing/route.py,sha256=Y4LTTTgQAR5zPMV3hKBP-YYjEQC41UUIa5ZuPCPf2aY,1471
|
11
|
+
fastlife/adapters/fastapi/routing/router.py,sha256=jzrnU_Lyywu21e3spPaWQw8ujZh_Yy_EJOojcCi6ew4,499
|
12
|
+
fastlife/adapters/itsdangerous/__init__.py,sha256=7ocGY7v0cxooZBKQYjA2JkmzRqiBvcU1uzA84UsTVAI,84
|
13
|
+
fastlife/adapters/itsdangerous/session.py,sha256=9h_WRsXqZbytHZOv5B_K3OWD5mbfYzxHulXoOf6D2MI,1685
|
4
14
|
fastlife/adapters/jinjax/__init__.py,sha256=4JRAUwFGpTxYtRlg5sU79AahxyAiRMhllRFHoI-dnug,117
|
5
15
|
fastlife/adapters/jinjax/jinjax_ext/__init__.py,sha256=z6NWvHzTNEq6bVO4iJoTR6-y4A6UtS_VuSMV_tff1jY,49
|
6
16
|
fastlife/adapters/jinjax/jinjax_ext/docstring.py,sha256=Zlx0oSxsRU9vQvGoyScXf9uB1W8JaoreGoJK3Xi26RE,2791
|
7
17
|
fastlife/adapters/jinjax/jinjax_ext/inspectable_catalog.py,sha256=KHOYTT6UNA41QwyLNQVoG4trOVXYdChlRmqq_G1pv1s,2987
|
8
|
-
fastlife/adapters/jinjax/jinjax_ext/inspectable_component.py,sha256=
|
9
|
-
fastlife/adapters/jinjax/jinjax_ext/jinjax_doc.py,sha256=
|
10
|
-
fastlife/adapters/jinjax/renderer.py,sha256=
|
18
|
+
fastlife/adapters/jinjax/jinjax_ext/inspectable_component.py,sha256=Ye_0XIKPC2H2XAvqEc1Er3YWyvNyYS4chuVkTSY5bAk,2909
|
19
|
+
fastlife/adapters/jinjax/jinjax_ext/jinjax_doc.py,sha256=S4-JNQ2NehUdKkc6mzAWRE_oyuw3XYPkR53RArgpDFk,10218
|
20
|
+
fastlife/adapters/jinjax/renderer.py,sha256=8Pv2Ivg8iObPa-LeIfj764p2MEq78wzHqxZeLDIdLc8,5255
|
11
21
|
fastlife/adapters/jinjax/widget_factory/__init__.py,sha256=Dy_2xr_YDAyEF9WtNpjV-aYaehRO1iKEIHVFdfFeszw,59
|
12
22
|
fastlife/adapters/jinjax/widget_factory/base.py,sha256=TLEpYdekR4AeHhIie_DICc_oSvQaUaL8GlatqNiRewg,1046
|
13
23
|
fastlife/adapters/jinjax/widget_factory/bool_builder.py,sha256=ElIDb6rlUiwuDAetC22TreoMa9HDgoZ2euVV1VurFFY,1291
|
14
24
|
fastlife/adapters/jinjax/widget_factory/emailstr_builder.py,sha256=hO0_4yd0lZ8mLqAzM_FMecdtkSa03AIG13cvs6K9JPA,1532
|
15
25
|
fastlife/adapters/jinjax/widget_factory/enum_builder.py,sha256=agx67oUeVy5_BKzY4WV0DxT67R43Vy74CoeHl9PBvK4,1527
|
16
|
-
fastlife/adapters/jinjax/widget_factory/factory.py,sha256=
|
26
|
+
fastlife/adapters/jinjax/widget_factory/factory.py,sha256=zTa6zbpW5lAh_eHlhO6XBP2GbeDTHatymhMAJQ-alTI,5915
|
17
27
|
fastlife/adapters/jinjax/widget_factory/literal_builder.py,sha256=mrtWbDMKNFtw5ufJK3DnkkttGGk16EnDQhejyOd57Ys,1758
|
18
28
|
fastlife/adapters/jinjax/widget_factory/model_builder.py,sha256=WgIEUExtGO_s9AlNQlaTG_136ipe64MIJsNP0nlnsOc,2236
|
19
29
|
fastlife/adapters/jinjax/widget_factory/secretstr_builder.py,sha256=JJLqN74tUSTDDBYcRLDuqOLSL0P16S1Fp-SqTCdjjgg,1573
|
@@ -22,21 +32,21 @@ fastlife/adapters/jinjax/widget_factory/set_builder.py,sha256=kwtVLATkoOFTcKBKHk
|
|
22
32
|
fastlife/adapters/jinjax/widget_factory/simpletype_builder.py,sha256=olP66B9AMY1X8fgEAxhMdozWN_w1TtcIAIW6uPJRSng,1570
|
23
33
|
fastlife/adapters/jinjax/widget_factory/union_builder.py,sha256=qQOK3Y4I0Tg0XOzU_DwseaaKRmqQ7ORMfFyIHd6oysU,2841
|
24
34
|
fastlife/adapters/jinjax/widgets/__init__.py,sha256=HERnX9xiXUbTDz3XtlnHWABTBjhIq_kkBgWs5E6ZIMY,42
|
25
|
-
fastlife/adapters/jinjax/widgets/base.py,sha256=
|
35
|
+
fastlife/adapters/jinjax/widgets/base.py,sha256=jU-oklWuM6MPlNzBvYO0HtxUrUteb-Dh96OudPLFJx4,4120
|
26
36
|
fastlife/adapters/jinjax/widgets/boolean.py,sha256=GFvyO2Lz-vTJ8lpX2UrkJk7ymu0vU-xnBBEmyBKamJg,613
|
27
37
|
fastlife/adapters/jinjax/widgets/checklist.py,sha256=xsr_edMu1nTcNnMEs1AAS3U-ugK95pEqn5NV5hjTeI0,1747
|
28
38
|
fastlife/adapters/jinjax/widgets/dropdown.py,sha256=ou8U48txShr8IXdwF4_pBvTn1VcR9SazZKzbLcsN3_0,1458
|
29
39
|
fastlife/adapters/jinjax/widgets/hidden.py,sha256=IKcVYs6NjN8YjW-UTr3DRBong6Wrc0QLgcp8U9JoQmE,638
|
30
|
-
fastlife/adapters/jinjax/widgets/model.py,sha256=
|
31
|
-
fastlife/adapters/jinjax/widgets/sequence.py,sha256=
|
40
|
+
fastlife/adapters/jinjax/widgets/model.py,sha256=YBIEWa_6mnmrBnesXjLTrpJ4drUS2CIorNmhK24cz7Q,1298
|
41
|
+
fastlife/adapters/jinjax/widgets/sequence.py,sha256=XhIPRJyE9UXFetlDQA83N64kKlTqkj6WPcgPm6XF7mo,2559
|
32
42
|
fastlife/adapters/jinjax/widgets/text.py,sha256=uYdJ1bjA3-2vEumh2nnd264wAaHU758ZxEiN2BaqtcE,2143
|
33
|
-
fastlife/adapters/jinjax/widgets/union.py,sha256
|
43
|
+
fastlife/adapters/jinjax/widgets/union.py,sha256=roCoFA82dLjF1XFW6UYaV7SCQWdFsSAT8Ux7KEB6_Us,2602
|
34
44
|
fastlife/components/A.jinja,sha256=rjnOFNpM2SUeJ0P8FDe3jzc_1WlsL65Kv-tb6KMCEpw,1389
|
35
45
|
fastlife/components/Button.jinja,sha256=COtCjDpzGLNqtBUYsHw7gdUay4kff3KdLJFAzrEnMmo,2310
|
36
46
|
fastlife/components/Checkbox.jinja,sha256=47_E9uPdr3QKUvRVhNQA7VE0uh5FVslQM26cdF0WCtY,753
|
37
47
|
fastlife/components/CsrfToken.jinja,sha256=mS0q-3_hAevl_waWEPaN0QAYOBzMyzl-W1PSpEHUBA0,215
|
38
48
|
fastlife/components/Details.jinja,sha256=BKyhSU7bZdbd_deTjmAGcMbgUoQW3h8JSR3thH-2oJA,741
|
39
|
-
fastlife/components/Form.jinja,sha256=
|
49
|
+
fastlife/components/Form.jinja,sha256=Aukx9cVR8Af1nIsdHst3Qk7Bz34g1RpDhl7WOIcy0Tg,2094
|
40
50
|
fastlife/components/H1.jinja,sha256=ODwQMgwtuy2E2ShgamjFDlnCwOQQuuLIhvEzUF66nYM,375
|
41
51
|
fastlife/components/H2.jinja,sha256=LcBE2R_N50gio01nxH9qhp8_G1HxOT91xG_u8J8ae_Q,375
|
42
52
|
fastlife/components/H3.jinja,sha256=3PzxfQh07A35Og6dE5ow9BZdNp2Qnu7OuVeWREvD7Uo,375
|
@@ -1672,61 +1682,55 @@ fastlife/components/icons/solid/WrenchScrewdriver.jinja,sha256=bqF-g6PTJds_KK2cM
|
|
1672
1682
|
fastlife/components/icons/solid/XCircle.jinja,sha256=pO93hG8JImNOy94B62tN7fdzkzGvSsqkSkkZlkLaxeo,791
|
1673
1683
|
fastlife/components/icons/solid/XMark.jinja,sha256=c-ngdLuYwEMicwm4-Aj4xcEc1uQ_LrBoPhdDhQutEA8,705
|
1674
1684
|
fastlife/components/pydantic_form/Error.jinja,sha256=vVSb1BKyKLOD4IOAM7aCKSNh7aAlmoiZVgRuvDCwLIo,205
|
1685
|
+
fastlife/components/pydantic_form/FatalError.jinja,sha256=lFVlNrXzBR6ExMahq77h0tYlD46T2yUzsBwqO8Gn58g,338
|
1675
1686
|
fastlife/components/pydantic_form/Hint.jinja,sha256=8leBpfMGDmalc_KAjr2paTojr_rwq-luS6m_1BGj7Tw,202
|
1676
1687
|
fastlife/components/pydantic_form/Widget.jinja,sha256=PgguUpvhG6CY9AW6H8qQMjKqjlybjDCAaFFAOHzrzVQ,418
|
1677
|
-
fastlife/config/__init__.py,sha256=
|
1678
|
-
fastlife/config/configurator.py,sha256=
|
1688
|
+
fastlife/config/__init__.py,sha256=5qpuaVYqi-AS0GgsfggM6rFsSwXgrqrLBo9jH6dVroc,407
|
1689
|
+
fastlife/config/configurator.py,sha256=AC4s4iM_DPDkKDs7DP6GJFwMt-HFqFtAHUcBnr1BGkY,24707
|
1679
1690
|
fastlife/config/exceptions.py,sha256=9MdBnbfy-Aw-KaIFzju0Kh8Snk41-v9LqK2w48Tdy1s,1169
|
1680
1691
|
fastlife/config/openapiextra.py,sha256=rYoerrn9sni2XwnO3gIWqaz7M0aDZPhVLjzqhDxue0o,514
|
1681
|
-
fastlife/config/
|
1682
|
-
fastlife/config/
|
1683
|
-
fastlife/config/settings.py,sha256=t9goMfnc_oWrS_c3vgivIe0w6N2Byohcfol2CAnLiJs,3892
|
1684
|
-
fastlife/config/views.py,sha256=2YjkCN9da1ck20c69IZIozM1qRjAxWdSPjcxqupUX_o,2392
|
1692
|
+
fastlife/config/resources.py,sha256=u6OgnbHfGkC5idH-YPNkIPf8GJnZpJoGVZ-Ym022BCo,8533
|
1693
|
+
fastlife/config/views.py,sha256=9CZ0qNi8vKvQuGo1GgM6cwNK8WwHOxwIHqtikAOaOHY,2399
|
1685
1694
|
fastlife/domain/__init__.py,sha256=3zDDos5InVX0el9OO0lgSDGzdUNYIhlA6w4uhBh2pF8,29
|
1686
1695
|
fastlife/domain/model/__init__.py,sha256=aoBjaSpDscuFXvtknJHwiNyoJRUpE-v4X54h_wNuo2Y,27
|
1687
|
-
fastlife/domain/model/
|
1696
|
+
fastlife/domain/model/asgi.py,sha256=RSTnfTsofOmCaWzHNuRGowjlyHYmoDCrXFbvNY_B55k,129
|
1697
|
+
fastlife/domain/model/csrf.py,sha256=BUiWK-S7rVciWHO1qTkM8e_KxzpF6gGC4MMJK1v6iDo,414
|
1698
|
+
fastlife/domain/model/form.py,sha256=WriBT1qUUIbf5x5iewo9ChEcr6k0en8jMTD0iaei5Pk,3253
|
1699
|
+
fastlife/domain/model/request.py,sha256=hMbp1OWY1BIWmqFe-kEvwOOXBB6t1ylVaHR30UbQ0_Y,2596
|
1700
|
+
fastlife/domain/model/security_policy.py,sha256=iYBKXOYaXxM_n-rsyB25lO6RblSx9icTx1Bg-s3Iz9k,2942
|
1688
1701
|
fastlife/domain/model/template.py,sha256=z9oxdKme1hMPuvk7mBiKR_tuVY8TqH77aTYqMgvEGl8,876
|
1689
1702
|
fastlife/domain/model/types.py,sha256=64jJKFAi5x0e3vr8naHU1m_as0Qy8MS-s9CG0z6K1qc,381
|
1690
1703
|
fastlife/middlewares/__init__.py,sha256=C3DUOzR5EhlAv5Zq7h-Abyvkd7bUsJohTRSB2wpRYQE,220
|
1691
|
-
fastlife/middlewares/base.py,sha256=
|
1704
|
+
fastlife/middlewares/base.py,sha256=7FZE_1YU7wNew2u1qdYXjamosk4CXJmg1mJWGp6Xhc0,649
|
1692
1705
|
fastlife/middlewares/reverse_proxy/__init__.py,sha256=g1SoVDmenKzpAAPYHTEsWgdBByOxtLg9fGx6RV3i0ok,846
|
1693
|
-
fastlife/middlewares/reverse_proxy/x_forwarded.py,sha256=
|
1694
|
-
fastlife/middlewares/session/__init__.py,sha256=
|
1695
|
-
fastlife/middlewares/session/middleware.py,sha256=
|
1696
|
-
fastlife/middlewares/session/serializer.py,sha256=
|
1706
|
+
fastlife/middlewares/reverse_proxy/x_forwarded.py,sha256=PPDjcfwik5eoYaolSY1Y4x5QMKpDV0XrOP_i4Am0y30,1724
|
1707
|
+
fastlife/middlewares/session/__init__.py,sha256=ZhXWXs53A__F9wJKBJ87rW8Qyt5Mn866vhzKDxVZ4t0,1348
|
1708
|
+
fastlife/middlewares/session/middleware.py,sha256=ituZ5hNipDMkgCXNE4zbnmOcWEF151sucPo4I_FpY-I,3137
|
1709
|
+
fastlife/middlewares/session/serializer.py,sha256=nbJGiCJ_ryZxkW1I28kmK6hD3U98D4ZlUQA7B8_tngQ,635
|
1697
1710
|
fastlife/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1698
|
-
fastlife/
|
1699
|
-
fastlife/
|
1700
|
-
fastlife/
|
1701
|
-
fastlife/
|
1702
|
-
fastlife/
|
1703
|
-
fastlife/
|
1704
|
-
fastlife/
|
1705
|
-
fastlife/
|
1706
|
-
fastlife/
|
1707
|
-
fastlife/security/csrf.py,sha256=lQ6GcSrs6GiUN03hRJqlqw2a9CJ9Wkt1joLE9lszd6w,1870
|
1708
|
-
fastlife/security/policy.py,sha256=4WHu8xhR7tAdXUHpHY1kdVIdTOFsUl92R8IsIRyYMSU,5579
|
1709
|
-
fastlife/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1710
|
-
fastlife/services/locale_negociator.py,sha256=Np2O8s7xnYTpf5eCG7LvcfFJ2LV7p_k86NNrU9Lju88,846
|
1711
|
-
fastlife/services/policy.py,sha256=RfYGPjfEAAoHECUnZVLPZgN0iRanu8UKQSky6oAz81o,1687
|
1712
|
-
fastlife/services/templates.py,sha256=ICNznXw3lEEiMyU60uqmq1uu8IWjF2iro1l-8SE0w_8,2716
|
1713
|
-
fastlife/services/translations.py,sha256=dfLopdQnkMTaehth2guRVBOKxxt7paMp8SgoJ4z0Ilc,5664
|
1711
|
+
fastlife/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1712
|
+
fastlife/service/check_permission.py,sha256=-XD9qA11dLwen0bNCTy2Id_dCjzTJ0j7xuwB9IOtEY0,1695
|
1713
|
+
fastlife/service/csrf.py,sha256=wC1PaKOmZ3il0FF_kevxnlg9PxDqruRdLrNnOA3ZHrU,1886
|
1714
|
+
fastlife/service/locale_negociator.py,sha256=Dq0k7lvUWOmd0o2xJFneymOu-H9z-RpSYU_AZ2IYF-g,780
|
1715
|
+
fastlife/service/registry.py,sha256=B6n5b_b0RgxJj0qFOpnrJFmG7_MPtvShwV6yH9V6vi0,2098
|
1716
|
+
fastlife/service/security_policy.py,sha256=fOyhaLNI3EzW5p_s3ZcrDaf7cX-KEWb7fQANoQSk6yg,3050
|
1717
|
+
fastlife/service/templates.py,sha256=QPAIUbbZiekazz_jV3q4JCwQd6Q4KA6a4RDek2RWuhE,2548
|
1718
|
+
fastlife/service/translations.py,sha256=D-1D3pVNytEcps1u-0K7FmgQ8Wo6Yu4XVHvZrPhBmAI,5795
|
1719
|
+
fastlife/settings.py,sha256=q-rz4CEF2RQGow5-m-yZJOvdh3PPb2c1Q_ZLJGnu4VQ,3647
|
1714
1720
|
fastlife/shared_utils/__init__.py,sha256=i66ytuf-Ezo7jSiNQHIsBMVIcB-tDX0tg28-pUOlhzE,26
|
1715
|
-
fastlife/shared_utils/infer.py,sha256=
|
1721
|
+
fastlife/shared_utils/infer.py,sha256=0GflLkaWJ-4LZ1Ig3moR-_o55wwJ_p_vJ4xo-yi3lyA,1406
|
1716
1722
|
fastlife/shared_utils/resolver.py,sha256=Wb9cO2MWavpti63hju15xmwFMgaD5DsQaxikRpB39E8,3713
|
1717
|
-
fastlife/
|
1718
|
-
fastlife/templates/constants.py,sha256=MGdUjkF9hsPMN8rOS49eWbAApcb8FL-FAeFvJU8k90M,8387
|
1719
|
-
fastlife/templates/inline.py,sha256=PEG53QXSYie6MMOM7ty2zl_uvdE4TvrZJGrySSJTgvU,722
|
1723
|
+
fastlife/template_globals.py,sha256=rJ7XB9DlPubejs_GDlEyO9V98QZTJnmdTznlguYOyoc,8386
|
1720
1724
|
fastlife/testing/__init__.py,sha256=VpxkS3Zp3t_hH8dBiLaGFGhsvt511dhBS_8fMoFXdmU,99
|
1721
1725
|
fastlife/testing/dom.py,sha256=dVzDoZokn-ii681UaEwAr-khM5KE-CHgXSSLSo24oH0,4489
|
1722
1726
|
fastlife/testing/form.py,sha256=ST0xNCoUqz_oD92cWHzQ6CbJ5hFopvu_NNKpOfiuYWY,7874
|
1723
1727
|
fastlife/testing/session.py,sha256=LEFFbiR67_x_g-ioudkY0C7PycHdbDfaIaoo_G7GXQ8,2226
|
1724
|
-
fastlife/testing/testclient.py,sha256=
|
1725
|
-
fastlife/views/__init__.py,sha256=
|
1726
|
-
fastlife/views/pydantic_form.py,sha256=
|
1727
|
-
fastlifeweb-0.
|
1728
|
-
fastlifeweb-0.
|
1729
|
-
fastlifeweb-0.
|
1730
|
-
fastlifeweb-0.
|
1731
|
-
tailwind.config.js,sha256=
|
1732
|
-
fastlifeweb-0.
|
1728
|
+
fastlife/testing/testclient.py,sha256=JTIgeMKooA8L4gEodeC3gy4Lo27y3WNswSEIKLlVVPs,6745
|
1729
|
+
fastlife/views/__init__.py,sha256=zG8gveL8e2zBdYx6_9jtZfpQ6qJT-MFnBY3xXkLwHZI,22
|
1730
|
+
fastlife/views/pydantic_form.py,sha256=o7EUItciAGL1OSaGNHo-3BTrYAk34GuWE7zGikjiAGY,1486
|
1731
|
+
fastlifeweb-0.22.1.dist-info/METADATA,sha256=UO41tIM5bFp2QZF-GO1aXFa-k6FN85JShOEsFUsCuZA,3663
|
1732
|
+
fastlifeweb-0.22.1.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
|
1733
|
+
fastlifeweb-0.22.1.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
1734
|
+
fastlifeweb-0.22.1.dist-info/licenses/LICENSE,sha256=NlRX9Z-dcv8X1VFW9odlIQBbgNN9pcO94XzvKp2R16o,1075
|
1735
|
+
tailwind.config.js,sha256=EN3EahBDmQBbmJvkw3SdGWNOkfkzw0cg-QvBikOhkrw,1348
|
1736
|
+
fastlifeweb-0.22.1.dist-info/RECORD,,
|
tailwind.config.js
CHANGED
fastlife/request/__init__.py
DELETED
fastlife/security/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
"""Security features."""
|
fastlife/security/policy.py
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
"""Security policy."""
|
2
|
-
|
3
|
-
import abc
|
4
|
-
import logging
|
5
|
-
from collections.abc import Callable, Coroutine
|
6
|
-
from typing import Annotated, Any, Generic, Literal, TypeVar
|
7
|
-
from uuid import UUID
|
8
|
-
|
9
|
-
from fastapi import Depends, HTTPException
|
10
|
-
from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN
|
11
|
-
|
12
|
-
from fastlife import GenericRequest, get_request
|
13
|
-
from fastlife.config.registry import TRegistry
|
14
|
-
|
15
|
-
CheckPermissionHook = Callable[..., Coroutine[Any, Any, None]] | Callable[..., None]
|
16
|
-
CheckPermission = Callable[[str], CheckPermissionHook]
|
17
|
-
|
18
|
-
TUser = TypeVar("TUser")
|
19
|
-
|
20
|
-
log = logging.getLogger(__name__)
|
21
|
-
|
22
|
-
|
23
|
-
class Unauthorized(HTTPException):
|
24
|
-
"""An exception raised to stop a request exectution and return an HTTP Error."""
|
25
|
-
|
26
|
-
def __init__(
|
27
|
-
self,
|
28
|
-
status_code: int = HTTP_401_UNAUTHORIZED,
|
29
|
-
detail: str = "Unauthorized",
|
30
|
-
headers: dict[str, str] | None = None,
|
31
|
-
) -> None:
|
32
|
-
super().__init__(status_code, detail, headers)
|
33
|
-
|
34
|
-
|
35
|
-
class Forbidden(HTTPException):
|
36
|
-
"""An exception raised to stop a request exectution and return an HTTP Error."""
|
37
|
-
|
38
|
-
def __init__(
|
39
|
-
self,
|
40
|
-
status_code: int = HTTP_403_FORBIDDEN,
|
41
|
-
detail: str = "Forbidden",
|
42
|
-
headers: dict[str, str] | None = None,
|
43
|
-
) -> None:
|
44
|
-
super().__init__(status_code, detail, headers)
|
45
|
-
|
46
|
-
|
47
|
-
class BoolMeta(type):
|
48
|
-
def __bool__(cls) -> bool:
|
49
|
-
return cls.kind == "allowed" # type: ignore
|
50
|
-
|
51
|
-
def __repr__(cls) -> str:
|
52
|
-
return cls.reason # type: ignore
|
53
|
-
|
54
|
-
|
55
|
-
class HasPermission(int, metaclass=BoolMeta):
|
56
|
-
"""
|
57
|
-
A type used to know if a permission is allowed or not.
|
58
|
-
|
59
|
-
It behave has a boolean, but 3 possibilities exists defind has 3 sub-types
|
60
|
-
{class}`Allowed` {class}`Unauthenticated` or {class}`Denied`.
|
61
|
-
|
62
|
-
In many cases Unauthenticated call may redirect to a login page,
|
63
|
-
where authenticated user are not redirected. they have an error message,
|
64
|
-
or the frontend may use the information to adapt its interface.
|
65
|
-
"""
|
66
|
-
|
67
|
-
kind: Literal["allowed", "unauthenticated", "denied"]
|
68
|
-
reason: str
|
69
|
-
|
70
|
-
def __new__(cls, reason: str) -> "HasPermission":
|
71
|
-
instance = super().__new__(cls)
|
72
|
-
instance.reason = reason
|
73
|
-
return instance
|
74
|
-
|
75
|
-
def __repr__(self) -> str:
|
76
|
-
return self.reason
|
77
|
-
|
78
|
-
def __bool__(self) -> bool:
|
79
|
-
return self.kind == "allowed"
|
80
|
-
|
81
|
-
|
82
|
-
class Allowed(HasPermission):
|
83
|
-
"""Represent a permission check result that is allowed."""
|
84
|
-
|
85
|
-
kind = "allowed"
|
86
|
-
reason = "Allowed"
|
87
|
-
|
88
|
-
|
89
|
-
class Unauthenticated(HasPermission):
|
90
|
-
"""
|
91
|
-
Represent a permission check result that is not allowed due to
|
92
|
-
missing authentication mechanism.
|
93
|
-
"""
|
94
|
-
|
95
|
-
kind = "unauthenticated"
|
96
|
-
reason = "Authentication required"
|
97
|
-
|
98
|
-
|
99
|
-
class Denied(HasPermission):
|
100
|
-
"""
|
101
|
-
Represent a permission check result that is not allowed due to lack of permission.
|
102
|
-
"""
|
103
|
-
|
104
|
-
kind = "denied"
|
105
|
-
reason = "Access denied to this resource"
|
106
|
-
|
107
|
-
|
108
|
-
class AbstractSecurityPolicy(abc.ABC, Generic[TUser, TRegistry]):
|
109
|
-
"""Security policy base classe."""
|
110
|
-
|
111
|
-
Forbidden = Forbidden
|
112
|
-
"""The exception raised if the user identified is not granted."""
|
113
|
-
Unauthorized = Unauthorized
|
114
|
-
"""The exception raised if no user has been identified."""
|
115
|
-
|
116
|
-
request: GenericRequest[TRegistry]
|
117
|
-
"""Request where the security policy is applied."""
|
118
|
-
|
119
|
-
def __init__(
|
120
|
-
self, request: Annotated[GenericRequest[TRegistry], Depends(get_request)]
|
121
|
-
):
|
122
|
-
"""
|
123
|
-
Build the security policy.
|
124
|
-
|
125
|
-
When implementing a security policy, multiple parameters can be added
|
126
|
-
to the constructor as FastAPI dependencies, using the `Depends` FastAPI
|
127
|
-
annotation.
|
128
|
-
The security policy is installed has a depenency of the router that hold
|
129
|
-
a route prefix of the application.
|
130
|
-
"""
|
131
|
-
self.request = request
|
132
|
-
self.request.security_policy = self # we do backref to implement has_permission
|
133
|
-
|
134
|
-
@abc.abstractmethod
|
135
|
-
async def identity(self) -> TUser | None:
|
136
|
-
"""
|
137
|
-
Return app-specific user object or raise an HTTPException.
|
138
|
-
"""
|
139
|
-
|
140
|
-
@abc.abstractmethod
|
141
|
-
async def authenticated_userid(self) -> str | UUID | None:
|
142
|
-
"""
|
143
|
-
Return app-specific user object or raise an HTTPException.
|
144
|
-
"""
|
145
|
-
|
146
|
-
@abc.abstractmethod
|
147
|
-
async def has_permission(
|
148
|
-
self, permission: str
|
149
|
-
) -> HasPermission | type[HasPermission]:
|
150
|
-
"""Allow access to everything if signed in."""
|
151
|
-
|
152
|
-
@abc.abstractmethod
|
153
|
-
async def remember(self, user: TUser) -> None:
|
154
|
-
"""Save the user identity in the request session."""
|
155
|
-
|
156
|
-
@abc.abstractmethod
|
157
|
-
async def forget(self) -> None:
|
158
|
-
"""Destroy the request session."""
|
159
|
-
|
160
|
-
|
161
|
-
class InsecurePolicy(AbstractSecurityPolicy[None, Any]):
|
162
|
-
"""
|
163
|
-
An implementation of the security policy made for explicit unsecured access.
|
164
|
-
|
165
|
-
Setting a permission on a view require a security policy, if not set, accessing
|
166
|
-
to a view will raise a RuntimeError. To bypass this error for testing purpose
|
167
|
-
or your own reason, the InsecurePolicy has to be set to the configurator.
|
168
|
-
"""
|
169
|
-
|
170
|
-
async def identity(self) -> None:
|
171
|
-
"""Nobodies is identified."""
|
172
|
-
return None
|
173
|
-
|
174
|
-
async def authenticated_userid(self) -> str | UUID:
|
175
|
-
"""An uuid mades of 0."""
|
176
|
-
return UUID(int=0)
|
177
|
-
|
178
|
-
async def has_permission(
|
179
|
-
self, permission: str
|
180
|
-
) -> HasPermission | type[HasPermission]:
|
181
|
-
"""Access is allways granted."""
|
182
|
-
return Allowed
|
183
|
-
|
184
|
-
async def remember(self, user: None) -> None:
|
185
|
-
"""Do nothing."""
|
186
|
-
|
187
|
-
async def forget(self) -> None:
|
188
|
-
"""Do nothing."""
|
@@ -1,26 +0,0 @@
|
|
1
|
-
"""Find the localization gor the given request."""
|
2
|
-
|
3
|
-
from collections.abc import Callable
|
4
|
-
from typing import TYPE_CHECKING, Any
|
5
|
-
|
6
|
-
from fastlife.config.settings import Settings
|
7
|
-
|
8
|
-
LocaleName = str
|
9
|
-
"""The LocaleName is a locale such as en, fr that will be consume for translations."""
|
10
|
-
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from fastlife.request.request import GenericRequest # coverage: ignore
|
13
|
-
|
14
|
-
LocaleNegociator = Callable[[GenericRequest[Any]], LocaleName] # coverage: ignore
|
15
|
-
"""Interface to implement to negociate a locale""" # coverage: ignore
|
16
|
-
else:
|
17
|
-
LocaleNegociator = Any
|
18
|
-
|
19
|
-
|
20
|
-
def default_negociator(settings: Settings) -> LocaleNegociator:
|
21
|
-
"""The default local negociator return the locale set in the conf."""
|
22
|
-
|
23
|
-
def locale_negociator(request: "GenericRequest[Any]") -> str:
|
24
|
-
return settings.default_locale
|
25
|
-
|
26
|
-
return locale_negociator
|
fastlife/templates/__init__.py
DELETED
fastlife/templates/inline.py
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
"""Inline templates."""
|
2
|
-
|
3
|
-
import inspect
|
4
|
-
from collections.abc import Callable
|
5
|
-
from typing import Any, get_args
|
6
|
-
|
7
|
-
from fastlife.domain.model.template import InlineTemplate
|
8
|
-
from fastlife.shared_utils.infer import is_union
|
9
|
-
|
10
|
-
|
11
|
-
def is_inline_template_returned(endpoint: Callable[..., Any]) -> bool:
|
12
|
-
signature = inspect.signature(endpoint)
|
13
|
-
return_annotation = signature.return_annotation
|
14
|
-
|
15
|
-
if isinstance(return_annotation, type) and issubclass(
|
16
|
-
return_annotation, InlineTemplate
|
17
|
-
):
|
18
|
-
return True
|
19
|
-
|
20
|
-
if is_union(return_annotation):
|
21
|
-
return any(
|
22
|
-
isinstance(arg, type) and issubclass(arg, InlineTemplate)
|
23
|
-
for arg in get_args(return_annotation)
|
24
|
-
)
|
25
|
-
|
26
|
-
return False
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|