ethyca-fides 2.70.5b0__py2.py3-none-any.whl → 2.71.0rc0__py2.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.

Potentially problematic release.


This version of ethyca-fides might be problematic. Click here for more details.

Files changed (169) hide show
  1. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/METADATA +3 -1
  2. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/RECORD +160 -150
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/0eef0016cf06_adding_oauth2_config_for_.py +69 -0
  5. fides/api/alembic/migrations/versions/e2cda8d6abc3_add_dismissed_in_activity_view_to_.py +29 -0
  6. fides/api/api/v1/endpoints/connection_endpoints.py +153 -2
  7. fides/api/api/v1/endpoints/privacy_request_endpoints.py +18 -2
  8. fides/api/db/base.py +1 -0
  9. fides/api/models/connection_oauth_credentials.py +57 -0
  10. fides/api/models/connectionconfig.py +7 -0
  11. fides/api/models/detection_discovery/monitor_task.py +2 -1
  12. fides/api/schemas/connection_configuration/connection_oauth_config.py +42 -0
  13. fides/api/schemas/privacy_request.py +1 -0
  14. fides/api/service/connectors/http_connector.py +48 -12
  15. fides/common/api/v1/urn_registry.py +1 -0
  16. fides/ui-build/static/admin/404.html +1 -1
  17. fides/ui-build/static/admin/_next/static/chunks/2962-e92d525bf570a9a3.js +1 -0
  18. fides/ui-build/static/admin/_next/static/chunks/3550-83cb70e80cbe41ba.js +1 -0
  19. fides/ui-build/static/admin/_next/static/chunks/{3700-865408b36fbee782.js → 3700-08e0703b1ef770da.js} +1 -1
  20. fides/ui-build/static/admin/_next/static/chunks/{504-afd3588f1908ac33.js → 504-88caa30c03374e9b.js} +1 -1
  21. fides/ui-build/static/admin/_next/static/chunks/5643-de406832755d9515.js +1 -0
  22. fides/ui-build/static/admin/_next/static/chunks/6419-9b3a86af57c86791.js +1 -0
  23. fides/ui-build/static/admin/_next/static/chunks/7218-e2983b96b95e33b4.js +1 -0
  24. fides/ui-build/static/admin/_next/static/chunks/7725-f2a7be705b75dcc3.js +1 -0
  25. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-a9d053921092de16.js → _app-a77584f9ad3334af.js} +1 -1
  26. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-16ecb33f09224fbb.js → manual-75e99306393938e8.js} +1 -1
  27. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-06a08970907ed3f0.js → [resourceUrn]-2fa4b3a58f75f81d.js} +1 -1
  28. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-4c84d952bb1db690.js → [resourceUrn]-5b31e3d7727b917a.js} +1 -1
  29. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2e1e2b7808d3b21f.js +1 -0
  30. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{[monitorId]-b74dfaf4f4126e57.js → [monitorId]-0d512528b498d75c.js} +1 -1
  31. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-65dc7f5a2ce3eae7.js → [resourceUrn]-5525cf287d4ab493.js} +1 -1
  32. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-4d378516817cf00b.js → discovery-ed4723e1b67d890e.js} +1 -1
  33. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-4a05303416dcb657.js → datamap-15616bea02397ef4.js} +1 -1
  34. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-5119e6602507157f.js → [id]-816e02b6cbe4a684.js} +1 -1
  35. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-cda4e7b5b888e17c.js → new-b6838162200141b3.js} +1 -1
  36. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-9f6c82e14ff2cad2.js → [id]-01e025f878ba806c.js} +1 -1
  37. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-ebc9c90fe99ee68d.js → integrations-14120a529d7dac27.js} +1 -1
  38. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{[id]-f8e3f63bea43db3b.js → [id]-82ebad17eb17c149.js} +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-1eeb320867dbebf4.js → privacy-requests-7af00f72cf694077.js} +1 -1
  40. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-5b423687e227ad4d.js → datamap-f7753e9effae3816.js} +1 -1
  41. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields/[id]-a653c05606c53063.js +1 -0
  42. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields/new-90848e4a15057af1.js +1 -0
  43. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-5edfec10a945ca43.js +1 -0
  44. fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{[key]-8df31428446a6a96.js → [key]-77239269acc2d31a.js} +1 -1
  45. fides/ui-build/static/admin/_next/static/chunks/pages/settings/messaging-providers/{new-af1471bf4571d5d3.js → new-8bf1821722b082e9.js} +1 -1
  46. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-589952aa1a31c33d.js → [id]-547c6ef0ad52b85d.js} +1 -1
  47. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-916238dcc0596957.js → systems-7238e025208078ec.js} +1 -1
  48. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-a8cfa7de4948b374.js +1 -0
  49. fides/ui-build/static/admin/_next/static/css/64fac6fb884435c2.css +1 -0
  50. fides/ui-build/static/admin/_next/static/fY61mOXDNbYtO-3MNEDrx/_buildManifest.js +1 -0
  51. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  52. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  53. fides/ui-build/static/admin/add-systems.html +1 -1
  54. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  55. fides/ui-build/static/admin/consent/configure.html +1 -1
  56. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  57. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  58. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  59. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  60. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  61. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  62. fides/ui-build/static/admin/consent/properties.html +1 -1
  63. fides/ui-build/static/admin/consent/reporting.html +1 -1
  64. fides/ui-build/static/admin/consent.html +1 -1
  65. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  66. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  67. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  68. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  69. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  70. fides/ui-build/static/admin/data-catalog.html +1 -1
  71. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  72. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  73. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  74. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  75. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  76. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  77. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  78. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  79. fides/ui-build/static/admin/datamap.html +1 -1
  80. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  81. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  82. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  83. fides/ui-build/static/admin/dataset/new.html +1 -1
  84. fides/ui-build/static/admin/dataset.html +1 -1
  85. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  86. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  87. fides/ui-build/static/admin/datastore-connection.html +1 -1
  88. fides/ui-build/static/admin/index.html +1 -1
  89. fides/ui-build/static/admin/integrations/[id].html +1 -1
  90. fides/ui-build/static/admin/integrations.html +1 -1
  91. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  92. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  93. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  94. fides/ui-build/static/admin/lib/fides-tcf.js +1 -1
  95. fides/ui-build/static/admin/lib/fides.js +2 -2
  96. fides/ui-build/static/admin/login/[provider].html +1 -1
  97. fides/ui-build/static/admin/login.html +1 -1
  98. fides/ui-build/static/admin/messaging/[id].html +1 -1
  99. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  100. fides/ui-build/static/admin/messaging.html +1 -1
  101. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  102. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  103. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  104. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  105. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  106. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  107. fides/ui-build/static/admin/poc/forms.html +1 -1
  108. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  109. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  110. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  111. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  112. fides/ui-build/static/admin/privacy-requests.html +1 -1
  113. fides/ui-build/static/admin/properties/[id].html +1 -1
  114. fides/ui-build/static/admin/properties/add-property.html +1 -1
  115. fides/ui-build/static/admin/properties.html +1 -1
  116. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  117. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  118. fides/ui-build/static/admin/settings/about.html +1 -1
  119. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  120. fides/ui-build/static/admin/settings/consent.html +1 -1
  121. fides/ui-build/static/admin/settings/custom-fields/[id].html +1 -0
  122. fides/ui-build/static/admin/settings/custom-fields/new.html +1 -0
  123. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  124. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  125. fides/ui-build/static/admin/settings/domains.html +1 -1
  126. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  127. fides/ui-build/static/admin/settings/locations.html +1 -1
  128. fides/ui-build/static/admin/settings/messaging-providers/[key].html +1 -1
  129. fides/ui-build/static/admin/settings/messaging-providers/new.html +1 -1
  130. fides/ui-build/static/admin/settings/messaging-providers.html +1 -1
  131. fides/ui-build/static/admin/settings/organization.html +1 -1
  132. fides/ui-build/static/admin/settings/privacy-requests.html +1 -1
  133. fides/ui-build/static/admin/settings/regulations.html +1 -1
  134. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  135. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  136. fides/ui-build/static/admin/systems.html +1 -1
  137. fides/ui-build/static/admin/taxonomy.html +1 -1
  138. fides/ui-build/static/admin/user-management/new.html +1 -1
  139. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  140. fides/ui-build/static/admin/user-management.html +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/3550-d04125c828d591a1.js +0 -1
  142. fides/ui-build/static/admin/_next/static/chunks/6419-d0c00d661b01f8fa.js +0 -1
  143. fides/ui-build/static/admin/_next/static/chunks/7725-fdc4298dfbea6f80.js +0 -1
  144. fides/ui-build/static/admin/_next/static/chunks/9951-651d521d9a02b6df.js +0 -1
  145. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3d03cd31cd99fa07.js +0 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-c2f1376aca192114.js +0 -1
  147. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-616f5a7cbb99e46d.js +0 -1
  148. fides/ui-build/static/admin/_next/static/css/1866822702989bb3.css +0 -1
  149. fides/ui-build/static/admin/_next/static/uFcubrjoFrTUGQFZXt15O/_buildManifest.js +0 -1
  150. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/WHEEL +0 -0
  151. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/entry_points.txt +0 -0
  152. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/licenses/LICENSE +0 -0
  153. {ethyca_fides-2.70.5b0.dist-info → ethyca_fides-2.71.0rc0.dist-info}/top_level.txt +0 -0
  154. /fides/ui-build/static/admin/_next/static/chunks/{1817-dbde9966025d7970.js → 1817-ca6473f31a67a804.js} +0 -0
  155. /fides/ui-build/static/admin/_next/static/chunks/{3585-451504ea5ed7a1ea.js → 3585-efd5d41f08e180c4.js} +0 -0
  156. /fides/ui-build/static/admin/_next/static/chunks/{3923-a551756b413367ea.js → 3923-98bea73b618292aa.js} +0 -0
  157. /fides/ui-build/static/admin/_next/static/chunks/{5783-8f5713517ebc35f3.js → 5783-d119cb132abd8a91.js} +0 -0
  158. /fides/ui-build/static/admin/_next/static/chunks/{6084-dc473a58c3e2889b.js → 6084-d0943ee628bf4388.js} +0 -0
  159. /fides/ui-build/static/admin/_next/static/chunks/{796-876998c86754da97.js → 796-02086581996a0548.js} +0 -0
  160. /fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-caff552fce501f82.js → add-systems-58920afe2b67f952.js} +0 -0
  161. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-259ad2e10fe6f413.js → configure-fb5017ff5fa54fcc.js} +0 -0
  162. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-7e78616b7b048978.js → privacy-experience-92182be6603c2842.js} +0 -0
  163. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-3ff2fd2570f02f1c.js → privacy-notices-ab54b19609bff325.js} +0 -0
  164. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-910e28bce6a98f3d.js → new-ea198c4a7869f402.js} +0 -0
  165. /fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-108630926347724e.js → dataset-0e3a6ac4797ffbbb.js} +0 -0
  166. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-329333a88f3826eb.js → table-migration-29fb7b39f8962650.js} +0 -0
  167. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-1ae1257f5b388924.js → consent-e5d781b28f8e29c8.js} +0 -0
  168. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-586505df9d853f1f.js → domain-records-744f669431b84f71.js} +0 -0
  169. /fides/ui-build/static/admin/_next/static/{uFcubrjoFrTUGQFZXt15O → fY61mOXDNbYtO-3MNEDrx}/_ssgManifest.js +0 -0
fides/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-09-23T16:10:27-0300",
11
+ "date": "2025-09-24T16:33:32-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "8b238061001b27210142e349894f696a9e163e36",
15
- "version": "2.70.5b0"
14
+ "full-revisionid": "32f4216c8a85464d318fc4088c1f99d8e5e8d86e",
15
+ "version": "2.71.0rc0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,69 @@
1
+ """Adding OAuth2 config for ConnectionConfig
2
+
3
+ Revision ID: 0eef0016cf06
4
+ Revises: 9e0dcbf67b9f
5
+ Create Date: 2025-09-12 01:06:26.838560
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ import sqlalchemy_utils
11
+ from alembic import op
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "0eef0016cf06"
15
+ down_revision = "9e0dcbf67b9f"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade():
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ op.create_table(
23
+ "oauth_config",
24
+ sa.Column("id", sa.String(length=255), nullable=False),
25
+ sa.Column(
26
+ "created_at",
27
+ sa.DateTime(timezone=True),
28
+ server_default=sa.text("now()"),
29
+ nullable=True,
30
+ ),
31
+ sa.Column(
32
+ "updated_at",
33
+ sa.DateTime(timezone=True),
34
+ server_default=sa.text("now()"),
35
+ nullable=True,
36
+ ),
37
+ sa.Column("connection_config_id", sa.String(), nullable=False),
38
+ sa.Column(
39
+ "grant_type",
40
+ sa.Enum(
41
+ "authorization_code",
42
+ "client_credentials",
43
+ "password",
44
+ "implicit",
45
+ name="oauthgranttype",
46
+ ),
47
+ nullable=False,
48
+ ),
49
+ sa.Column("token_url", sa.String(), nullable=False),
50
+ sa.Column("scope", sa.String(), nullable=True),
51
+ sa.Column("client_id", sa.String(), nullable=False),
52
+ sa.Column(
53
+ "client_secret", sqlalchemy_utils.types.StringEncryptedType, nullable=False
54
+ ),
55
+ sa.ForeignKeyConstraint(
56
+ ["connection_config_id"],
57
+ ["connectionconfig.id"],
58
+ ),
59
+ sa.PrimaryKeyConstraint("id"),
60
+ )
61
+ op.create_index(op.f("ix_oauth_config_id"), "oauth_config", ["id"], unique=False)
62
+ # ### end Alembic commands ###
63
+
64
+
65
+ def downgrade():
66
+ # ### commands auto generated by Alembic - please adjust! ###
67
+ op.drop_index(op.f("ix_oauth_config_id"), table_name="oauth_config")
68
+ op.drop_table("oauth_config")
69
+ # ### end Alembic commands ###
@@ -0,0 +1,29 @@
1
+ """add_dismissed_to_monitor_task
2
+
3
+ Revision ID: e2cda8d6abc3
4
+ Revises: 0eef0016cf06
5
+ Create Date: 2025-09-17 23:37:49.678071
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "e2cda8d6abc3"
14
+ down_revision = "0eef0016cf06"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # Add the dismissed column to monitortask table
21
+ op.add_column(
22
+ "monitortask",
23
+ sa.Column("dismissed", sa.Boolean(), nullable=False, server_default="f"),
24
+ )
25
+
26
+
27
+ def downgrade():
28
+ # Remove the dismissed column from monitortask table
29
+ op.drop_column("monitortask", "dismissed")
@@ -2,7 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Annotated, Any, Dict, List, Optional
4
4
 
5
- from fastapi import Depends
5
+ import sqlalchemy
6
+ from fastapi import Depends, HTTPException
6
7
  from fastapi.params import Query, Security
7
8
  from fastapi_pagination import Page, Params
8
9
  from fastapi_pagination.bases import AbstractPage
@@ -13,9 +14,15 @@ from pydantic import Field
13
14
  from sqlalchemy import null, or_
14
15
  from sqlalchemy.orm import Session
15
16
  from sqlalchemy_utils import escape_like
16
- from starlette.status import HTTP_200_OK, HTTP_204_NO_CONTENT
17
+ from starlette.status import (
18
+ HTTP_200_OK,
19
+ HTTP_204_NO_CONTENT,
20
+ HTTP_404_NOT_FOUND,
21
+ HTTP_422_UNPROCESSABLE_ENTITY,
22
+ )
17
23
 
18
24
  from fides.api.api import deps
25
+ from fides.api.models.connection_oauth_credentials import OAuthConfig
19
26
  from fides.api.models.connectionconfig import ConnectionConfig, ConnectionType
20
27
  from fides.api.oauth.utils import verify_oauth_client
21
28
  from fides.api.schemas.connection_configuration import connection_secrets_schemas
@@ -25,6 +32,9 @@ from fides.api.schemas.connection_configuration.connection_config import (
25
32
  ConnectionConfigurationResponseWithSystemKey,
26
33
  CreateConnectionConfigurationWithSecrets,
27
34
  )
35
+ from fides.api.schemas.connection_configuration.connection_oauth_config import (
36
+ OAuthConfigSchema,
37
+ )
28
38
  from fides.api.schemas.connection_configuration.connection_secrets import (
29
39
  TestStatusMessage,
30
40
  )
@@ -45,6 +55,7 @@ from fides.common.api.scope_registry import (
45
55
  )
46
56
  from fides.common.api.v1.urn_registry import (
47
57
  CONNECTION_BY_KEY,
58
+ CONNECTION_OAUTH,
48
59
  CONNECTION_SECRETS,
49
60
  CONNECTION_TEST,
50
61
  CONNECTIONS,
@@ -312,3 +323,143 @@ def test_connection_config_secrets(
312
323
  connection_config = get_connection_config_or_error(db, connection_key)
313
324
  msg = f"Test completed for ConnectionConfig with key: {connection_key}."
314
325
  return connection_status(connection_config, msg, db)
326
+
327
+
328
+ @router.put(
329
+ CONNECTION_OAUTH,
330
+ dependencies=[Security(verify_oauth_client, scopes=[CONNECTION_CREATE_OR_UPDATE])],
331
+ status_code=HTTP_200_OK,
332
+ )
333
+ def put_connection_oauth_config(
334
+ connection_key: FidesKey,
335
+ *,
336
+ oauth_config: OAuthConfigSchema,
337
+ db: Session = Depends(deps.get_db),
338
+ verify: Optional[bool] = True,
339
+ ) -> TestStatusMessage:
340
+ """
341
+ Create or update the OAuth2 configuration for a given connection.
342
+ """
343
+ connection_config = get_connection_config_or_error(db, connection_key)
344
+
345
+ if connection_config.connection_type != ConnectionType.https:
346
+ raise HTTPException(
347
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
348
+ detail="OAuth2 configuration can only be set for HTTPS connections.",
349
+ )
350
+
351
+ logger.info("Updating OAuth2 config for '{}'", connection_key)
352
+ connection_config.oauth_config = OAuthConfig(
353
+ **oauth_config.model_dump(mode="json") # type: ignore[arg-type]
354
+ )
355
+ connection_config.save(db=db)
356
+
357
+ msg = (
358
+ f"OAuth2 configuration updated for ConnectionConfig with key: {connection_key}."
359
+ )
360
+
361
+ if verify:
362
+ return connection_status(connection_config, msg, db)
363
+
364
+ return TestStatusMessage(msg=msg, test_status=None)
365
+
366
+
367
+ @router.delete(
368
+ CONNECTION_OAUTH,
369
+ dependencies=[Security(verify_oauth_client, scopes=[CONNECTION_CREATE_OR_UPDATE])],
370
+ status_code=HTTP_204_NO_CONTENT,
371
+ response_model=None,
372
+ )
373
+ def delete_connection_oauth_config(
374
+ connection_key: FidesKey,
375
+ *,
376
+ db: Session = Depends(deps.get_db),
377
+ ) -> None:
378
+ """
379
+ Delete the OAuth2 configuration for a given connection.
380
+ """
381
+ connection_config = get_connection_config_or_error(db, connection_key)
382
+
383
+ if connection_config.connection_type != ConnectionType.https:
384
+ raise HTTPException(
385
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
386
+ detail="OAuth2 configuration can only be deleted for HTTPS connections",
387
+ )
388
+
389
+ if not connection_config.oauth_config:
390
+ raise HTTPException(
391
+ status_code=HTTP_404_NOT_FOUND,
392
+ detail="No OAuth2 configuration found to delete.",
393
+ )
394
+
395
+ logger.info("Deleting OAuth2 config for '{}'", connection_key)
396
+ connection_config.oauth_config = None
397
+ connection_config.save(db=db)
398
+
399
+
400
+ @router.patch(
401
+ CONNECTION_OAUTH,
402
+ dependencies=[Security(verify_oauth_client, scopes=[CONNECTION_CREATE_OR_UPDATE])],
403
+ status_code=HTTP_200_OK,
404
+ )
405
+ def patch_connection_oauth_config(
406
+ connection_key: FidesKey,
407
+ *,
408
+ oauth_config: OAuthConfigSchema,
409
+ db: Session = Depends(deps.get_db),
410
+ verify: Optional[bool] = True,
411
+ ) -> TestStatusMessage:
412
+ """
413
+ Partially update the OAuth2 configuration for a given connection.
414
+ """
415
+ connection_config = get_connection_config_or_error(db, connection_key)
416
+
417
+ if connection_config.connection_type != ConnectionType.https:
418
+ raise HTTPException(
419
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
420
+ detail="OAuth2 configuration can only be set for HTTPS connections.",
421
+ )
422
+
423
+ existing_oauth_config: Optional[Dict[str, Any]] = (
424
+ {
425
+ "grant_type": connection_config.oauth_config.grant_type.value,
426
+ "token_url": connection_config.oauth_config.token_url,
427
+ "scope": connection_config.oauth_config.scope,
428
+ "client_id": connection_config.oauth_config.client_id,
429
+ "client_secret": connection_config.oauth_config.client_secret,
430
+ }
431
+ if connection_config.oauth_config
432
+ else None
433
+ )
434
+
435
+ # Combine the existing config with the new config overlaid
436
+ patched_oauth_config = {}
437
+ if existing_oauth_config:
438
+ patched_oauth_config = {**existing_oauth_config}
439
+
440
+ patched_oauth_config = {
441
+ **patched_oauth_config,
442
+ **{k: v for (k, v) in oauth_config.model_dump(mode="json").items() if v is not None}, # type: ignore[dict-item]
443
+ }
444
+
445
+ logger.info("Patching OAuth2 config for '{}'", connection_key)
446
+ validated_config = OAuthConfigSchema.model_validate(patched_oauth_config)
447
+ try:
448
+ connection_config.oauth_config = OAuthConfig(
449
+ **validated_config.model_dump(mode="json")
450
+ )
451
+ connection_config.save(db=db)
452
+ except sqlalchemy.exc.IntegrityError as exc:
453
+ raise HTTPException(
454
+ status_code=HTTP_422_UNPROCESSABLE_ENTITY,
455
+ detail="Invalid OAuth2 configuration.",
456
+ ) from exc
457
+
458
+ msg = (
459
+ f"OAuth2 configuration updated for ConnectionConfig with key: {connection_key}."
460
+ )
461
+
462
+ if verify:
463
+ return connection_status(connection_config, msg, db)
464
+
465
+ return TestStatusMessage(msg=msg, test_status=None)
@@ -4,7 +4,7 @@ import csv
4
4
  import io
5
5
  import json
6
6
  from collections import defaultdict
7
- from datetime import datetime, timezone
7
+ from datetime import datetime, timedelta, timezone
8
8
  from typing import (
9
9
  Annotated,
10
10
  Any,
@@ -285,15 +285,19 @@ def privacy_request_csv_download(
285
285
  "Status",
286
286
  "Request Type",
287
287
  "Time Received",
288
+ "Deadline",
288
289
  "Reviewed By",
289
290
  "Request ID",
290
291
  "Time Approved/Denied",
291
292
  "Denial Reason",
293
+ "Last Updated",
294
+ "Completed On",
292
295
  ]
293
296
  + identity_columns
294
297
  + with_prefix("Custom Field", list(custom_field_columns.values()))
295
298
  )
296
299
 
300
+ pr: PrivacyRequest
297
301
  for pr in privacy_request_query:
298
302
  denial_reason = (
299
303
  denial_audit_logs[pr.id]
@@ -301,14 +305,26 @@ def privacy_request_csv_download(
301
305
  else None
302
306
  )
303
307
 
308
+ action_types: List[str] = []
309
+ if pr and pr.policy:
310
+ for rule in pr.policy.rules or []: # type: ignore
311
+ action_types.append(rule.action_type)
312
+
313
+ deadline: Optional[datetime] = None
314
+ if pr.days_left and pr.created_at:
315
+ deadline = pr.created_at + timedelta(days=pr.days_left)
316
+
304
317
  static_cells = [
305
318
  pr.status.value if pr.status else None,
306
- pr.policy.rules[0].action_type if len(pr.policy.rules) > 0 else None,
319
+ ("+".join(action_types)),
307
320
  pr.created_at,
321
+ deadline,
308
322
  pr.reviewed_by,
309
323
  pr.id,
310
324
  pr.reviewed_at,
311
325
  denial_reason,
326
+ pr.updated_at,
327
+ pr.finalized_at,
312
328
  ]
313
329
 
314
330
  identity_cells = extract_identity_cells(identity_columns, pr)
fides/api/db/base.py CHANGED
@@ -9,6 +9,7 @@ from fides.api.models.audit_log import AuditLog
9
9
  from fides.api.models.authentication_request import AuthenticationRequest
10
10
  from fides.api.models.client import ClientDetail
11
11
  from fides.api.models.comment import Comment, CommentReference
12
+ from fides.api.models.connection_oauth_credentials import OAuthConfig
12
13
  from fides.api.models.connectionconfig import ConnectionConfig
13
14
  from fides.api.models.consent_automation import ConsentAutomation
14
15
  from fides.api.models.custom_asset import CustomAsset
@@ -0,0 +1,57 @@
1
+ import enum
2
+
3
+ from sqlalchemy import Column, Enum, ForeignKey, String
4
+ from sqlalchemy.ext.declarative import declared_attr
5
+ from sqlalchemy.orm import relationship
6
+ from sqlalchemy_utils.types.encrypted.encrypted_type import (
7
+ AesGcmEngine,
8
+ StringEncryptedType,
9
+ )
10
+
11
+ from fides.api.db.base_class import Base
12
+ from fides.api.models.connectionconfig import ConnectionConfig
13
+
14
+ # pylint: disable=unused-import
15
+ from fides.api.models.sql_models import System # type: ignore[attr-defined]
16
+ from fides.config import CONFIG
17
+
18
+
19
+ class OAuthGrantType(enum.Enum):
20
+ authorization_code = "authorization_code"
21
+ client_credentials = "client_credentials"
22
+ password = "password"
23
+ implicit = "implicit"
24
+
25
+
26
+ class OAuthConfig(Base):
27
+ """
28
+ Stores credentials to connect fidesops to anything that uses OAuth2 for authentication.
29
+ """
30
+
31
+ @declared_attr
32
+ def __tablename__(cls) -> str:
33
+ """Overriding base class method to set the table name."""
34
+ return "oauth_config"
35
+
36
+ connection_config_id = Column(
37
+ String, ForeignKey(ConnectionConfig.id_field_path), nullable=False
38
+ )
39
+
40
+ grant_type = Column(Enum(OAuthGrantType), nullable=False)
41
+ token_url = Column(String, nullable=False)
42
+ scope = Column(String, nullable=True)
43
+ client_id = Column(String, nullable=False)
44
+ client_secret = Column(
45
+ StringEncryptedType(
46
+ String,
47
+ CONFIG.security.app_encryption_key,
48
+ AesGcmEngine,
49
+ "pkcs5",
50
+ ),
51
+ nullable=False,
52
+ )
53
+
54
+ connection_config = relationship(
55
+ "ConnectionConfig",
56
+ back_populates="oauth_config",
57
+ )
@@ -261,6 +261,13 @@ class ConnectionConfig(Base):
261
261
  ARRAY(Enum(ActionType, native_enum=False)), unique=False, nullable=True
262
262
  )
263
263
 
264
+ oauth_config = relationship( # type: ignore[misc]
265
+ "OAuthConfig",
266
+ back_populates="connection_config",
267
+ cascade="all, delete-orphan",
268
+ uselist=False,
269
+ )
270
+
264
271
  @property
265
272
  def system_key(self) -> Optional[str]:
266
273
  """Property for caching a system identifier for systems (or connector names as a fallback) for consent reporting"""
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from enum import Enum
4
4
  from typing import List, Optional
5
5
 
6
- from sqlalchemy import ARRAY, Column
6
+ from sqlalchemy import ARRAY, Boolean, Column
7
7
  from sqlalchemy import Enum as SQLAlchemyEnum
8
8
  from sqlalchemy import ForeignKey, String
9
9
  from sqlalchemy.dialects.postgresql import JSONB
@@ -51,6 +51,7 @@ class MonitorTask(WorkerTask, Base):
51
51
  )
52
52
  staged_resource_urns = Column(ARRAY(String), nullable=True)
53
53
  child_resource_urns = Column(ARRAY(String), nullable=True)
54
+ dismissed = Column(Boolean, nullable=False, default=False)
54
55
 
55
56
  monitor_config = relationship(MonitorConfig, cascade="all, delete")
56
57
  execution_logs = relationship(
@@ -0,0 +1,42 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+ from fides.api.schemas.base_class import NoValidationSchema
7
+
8
+
9
+ class OAuthGrantType(str, Enum):
10
+ """OAuth2 grant types supported by the system"""
11
+
12
+ client_credentials = "client_credentials"
13
+
14
+
15
+ class OAuthConfigSchema(BaseModel):
16
+ """Schema for OAuth2 configuration used in API requests"""
17
+
18
+ grant_type: Optional[OAuthGrantType] = None
19
+ token_url: Optional[str] = None
20
+ scope: Optional[str] = None
21
+ client_id: Optional[str] = None
22
+ client_secret: Optional[str] = Field(json_schema_extra={"sensitive": True})
23
+
24
+ model_config = ConfigDict(
25
+ from_attributes=True, use_enum_values=True, extra="forbid"
26
+ )
27
+
28
+
29
+ class OAuthConfigResponse(BaseModel):
30
+ """Schema for OAuth2 configuration used in API responses with masked sensitive fields"""
31
+
32
+ grant_type: OAuthGrantType
33
+ token_url: str
34
+ scope: Optional[str] = None
35
+ client_id: str
36
+ client_secret: str = "**********" # Always masked in responses
37
+
38
+ model_config = ConfigDict(from_attributes=True, use_enum_values=True)
39
+
40
+
41
+ class OAuthConfigDocsSchema(OAuthConfigSchema, NoValidationSchema):
42
+ """OAuth2 Config Schema for API Docs"""
@@ -342,6 +342,7 @@ class PrivacyRequestResponse(FidesSchema):
342
342
  deleted_by: Optional[str] = None
343
343
  finalized_at: Optional[datetime] = None
344
344
  finalized_by: Optional[str] = None
345
+
345
346
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
346
347
 
347
348
 
@@ -3,6 +3,9 @@ from typing import Any, Dict, List, Optional
3
3
 
4
4
  import requests
5
5
  from loguru import logger
6
+ from oauthlib.oauth2 import BackendApplicationClient
7
+ from requests.auth import HTTPBasicAuth
8
+ from requests_oauthlib import OAuth2Session
6
9
  from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
7
10
 
8
11
  from fides.api.common_exceptions import ClientUnsuccessfulException
@@ -41,25 +44,58 @@ class HTTPSConnector(BaseConnector[None]):
41
44
  ) -> Optional[Dict[str, Any]]:
42
45
  """Calls a client-defined endpoint and returns the data that it responds with"""
43
46
  config = HttpsSchema(**self.configuration.secrets or {})
44
- headers = self.build_authorization_header()
45
- headers.update(additional_headers)
47
+
48
+ def _request_with_oauth() -> requests.Response:
49
+ """Helper function to make a request with OAuth2 authentication"""
50
+ client_id = oauth_config.client_id
51
+ client_secret = oauth_config.client_secret
52
+ scopes = oauth_config.scope.split(" ") or []
53
+ auth = HTTPBasicAuth(client_id, client_secret)
54
+ client = BackendApplicationClient(client_id=client_id)
55
+ session_client = OAuth2Session(client=client, scope=scopes)
56
+ try:
57
+ # Fetch the access token from the token URL
58
+ session_client.fetch_token(token_url=oauth_config.token_url, auth=auth)
59
+ except Exception as e:
60
+ logger.error(f"Error fetching OAuth2 token: {e}")
61
+ raise ClientUnsuccessfulException(
62
+ status_code=HTTP_500_INTERNAL_SERVER_ERROR
63
+ )
64
+
65
+ return session_client.post(
66
+ url=config.url, headers=additional_headers, json=request_body
67
+ )
68
+
69
+ def _request_without_oauth() -> requests.Response:
70
+ """Helper function to make a request without OAuth2 authentication"""
71
+ headers = self.build_authorization_header()
72
+ headers.update(additional_headers)
73
+ return requests.post(url=config.url, headers=headers, json=request_body)
74
+
75
+ oauth_config = self.configuration.oauth_config
46
76
 
47
77
  try:
48
- response = requests.post(url=config.url, headers=headers, json=request_body)
78
+ response = (
79
+ _request_with_oauth()
80
+ if oauth_config is not None
81
+ else _request_without_oauth()
82
+ )
83
+
84
+ if not response_expected:
85
+ return {}
86
+
87
+ if not response.ok:
88
+ logger.error("Invalid response received from webhook.")
89
+ raise ClientUnsuccessfulException(status_code=response.status_code)
90
+
91
+ return json.loads(response.text)
92
+
49
93
  except requests.ConnectionError:
50
- logger.info("Requests connection error received.")
94
+ logger.error("HTTPS client received a connection error.")
51
95
  raise ClientUnsuccessfulException(
52
96
  status_code=HTTP_500_INTERNAL_SERVER_ERROR
53
97
  )
54
98
 
55
- if not response_expected:
56
- return {}
57
-
58
- if not response.ok:
59
- logger.error("Invalid response received from webhook.")
60
- raise ClientUnsuccessfulException(status_code=response.status_code)
61
- return json.loads(response.text)
62
-
63
99
  def test_connection(self) -> Optional[ConnectionTestStatus]:
64
100
  """
65
101
  Override to skip connection test
@@ -158,6 +158,7 @@ CONNECTION_TYPE_SECRETS = "/connection_type/{connection_type}/secret"
158
158
  CONNECTIONS = "/connection"
159
159
  CONNECTION_BY_KEY = "/connection/{connection_key}"
160
160
  CONNECTION_SECRETS = "/connection/{connection_key}/secret"
161
+ CONNECTION_OAUTH = "/connection/{connection_key}/oauth"
161
162
  CONNECTION_TEST = "/connection/{connection_key}/test"
162
163
  AUTHORIZE = "/connection/{connection_key}/authorize"
163
164
 
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/1866822702989bb3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/1866822702989bb3.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-2766492c5dbceb0a.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-a9d053921092de16.js" defer=""></script><script src="/_next/static/chunks/pages/404-2eb8aed4939f1142.js" defer=""></script><script src="/_next/static/uFcubrjoFrTUGQFZXt15O/_buildManifest.js" defer=""></script><script src="/_next/static/uFcubrjoFrTUGQFZXt15O/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"uFcubrjoFrTUGQFZXt15O","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/64fac6fb884435c2.css" as="style"/><link rel="stylesheet" href="/_next/static/css/64fac6fb884435c2.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-2766492c5dbceb0a.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-a77584f9ad3334af.js" defer=""></script><script src="/_next/static/chunks/pages/404-2eb8aed4939f1142.js" defer=""></script><script src="/_next/static/fY61mOXDNbYtO-3MNEDrx/_buildManifest.js" defer=""></script><script src="/_next/static/fY61mOXDNbYtO-3MNEDrx/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"fY61mOXDNbYtO-3MNEDrx","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2962],{96586:function(t,r,e){var n=e(57753),o=e(82452),i=e(22115),a=e(38256),u=e(67426);function c(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}c.prototype.clear=n,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=u,t.exports=c},36301:function(t,r,e){var n=e(69417),o=e(72470),i=e(66165),a=e(71873),u=e(52556);function c(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}c.prototype.clear=n,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=u,t.exports=c},44538:function(t,r,e){var n=e(81822)(e(77400),"Map");t.exports=n},74554:function(t,r,e){var n=e(39448),o=e(7738),i=e(66575),a=e(7238),u=e(38738);function c(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}c.prototype.clear=n,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=u,t.exports=c},46151:function(t,r,e){var n=e(81822)(e(77400),"Set");t.exports=n},52485:function(t,r,e){var n=e(74554),o=e(38639),i=e(88379);function a(t){var r=-1,e=null==t?0:t.length;for(this.__data__=new n;++r<e;)this.add(t[r])}a.prototype.add=a.prototype.push=o,a.prototype.has=i,t.exports=a},90756:function(t){t.exports=function(t,r){for(var e=-1,n=null==t?0:t.length;++e<n;)if(r(t[e],e,t))return!0;return!1}},93382:function(t,r,e){var n=e(85638);t.exports=function(t,r){for(var e=t.length;e--;)if(n(t[e][0],r))return e;return -1}},32866:function(t,r,e){var n=e(12772),o=e(92360);t.exports=function t(r,e,i,a,u){return r===e||(null!=r&&null!=e&&(o(r)||o(e))?n(r,e,i,a,t,u):r!=r&&e!=e)}},12772:function(t,r,e){var n=e(23694),o=e(27042),i=e(370),a=e(39584),u=e(3533),c=e(19785),s=e(43854),f=e(48519),p="[object Arguments]",_="[object Array]",v="[object Object]",h=Object.prototype.hasOwnProperty;t.exports=function(t,r,e,l,y,d){var b=c(t),x=c(r),g=b?_:u(t),j=x?_:u(r);g=g==p?v:g,j=j==p?v:j;var w=g==v,O=j==v,z=g==j;if(z&&s(t)){if(!s(r))return!1;b=!0,w=!1}if(z&&!w)return d||(d=new n),b||f(t)?o(t,r,e,l,y,d):i(t,r,g,e,l,y,d);if(!(1&e)){var k=w&&h.call(t,"__wrapped__"),m=O&&h.call(r,"__wrapped__");if(k||m){var E=k?t.value():t,P=m?r.value():r;return d||(d=new n),y(E,P,e,l,d)}}return!!z&&(d||(d=new n),a(t,r,e,l,y,d))}},46729:function(t,r,e){var n=e(28338),o=e(99678),i=e(11611),a=e(76532),u=/^\[object .+?Constructor\]$/,c=Object.prototype,s=Function.prototype.toString,f=c.hasOwnProperty,p=RegExp("^"+s.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!i(t)||o(t))&&(n(t)?p:u).test(a(t))}},65581:function(t){t.exports=function(t,r){return t.has(r)}},64937:function(t,r,e){var n=e(77400)["__core-js_shared__"];t.exports=n},27042:function(t,r,e){var n=e(52485),o=e(90756),i=e(65581);t.exports=function(t,r,e,a,u,c){var s=1&e,f=t.length,p=r.length;if(f!=p&&!(s&&p>f))return!1;var _=c.get(t),v=c.get(r);if(_&&v)return _==r&&v==t;var h=-1,l=!0,y=2&e?new n:void 0;for(c.set(t,r),c.set(r,t);++h<f;){var d=t[h],b=r[h];if(a)var x=s?a(b,d,h,r,t,c):a(d,b,h,t,r,c);if(void 0!==x){if(x)continue;l=!1;break}if(y){if(!o(r,function(t,r){if(!i(y,r)&&(d===t||u(d,t,e,a,c)))return y.push(r)})){l=!1;break}}else if(!(d===b||u(d,b,e,a,c))){l=!1;break}}return c.delete(t),c.delete(r),l}},370:function(t,r,e){var n=e(96539),o=e(59942),i=e(85638),a=e(27042),u=e(19383),c=e(43735),s=n?n.prototype:void 0,f=s?s.valueOf:void 0;t.exports=function(t,r,e,n,s,p,_){switch(e){case"[object DataView]":if(t.byteLength!=r.byteLength||t.byteOffset!=r.byteOffset)break;t=t.buffer,r=r.buffer;case"[object ArrayBuffer]":if(t.byteLength!=r.byteLength||!p(new o(t),new o(r)))break;return!0;case"[object Boolean]":case"[object Date]":case"[object Number]":return i(+t,+r);case"[object Error]":return t.name==r.name&&t.message==r.message;case"[object RegExp]":case"[object String]":return t==r+"";case"[object Map]":var v=u;case"[object Set]":var h=1&n;if(v||(v=c),t.size!=r.size&&!h)break;var l=_.get(t);if(l)return l==r;n|=2,_.set(t,r);var y=a(v(t),v(r),n,s,p,_);return _.delete(t),y;case"[object Symbol]":if(f)return f.call(t)==f.call(r)}return!1}},39584:function(t,r,e){var n=e(51385),o=Object.prototype.hasOwnProperty;t.exports=function(t,r,e,i,a,u){var c=1&e,s=n(t),f=s.length;if(f!=n(r).length&&!c)return!1;for(var p=f;p--;){var _=s[p];if(!(c?_ in r:o.call(r,_)))return!1}var v=u.get(t),h=u.get(r);if(v&&h)return v==r&&h==t;var l=!0;u.set(t,r),u.set(r,t);for(var y=c;++p<f;){var d=t[_=s[p]],b=r[_];if(i)var x=c?i(b,d,_,r,t,u):i(d,b,_,t,r,u);if(!(void 0===x?d===b||a(d,b,e,i,u):x)){l=!1;break}y||(y="constructor"==_)}if(l&&!y){var g=t.constructor,j=r.constructor;g!=j&&"constructor"in t&&"constructor"in r&&!("function"==typeof g&&g instanceof g&&"function"==typeof j&&j instanceof j)&&(l=!1)}return u.delete(t),u.delete(r),l}},95899:function(t,r,e){var n=e(54479);t.exports=function(t,r){var e=t.__data__;return n(r)?e["string"==typeof r?"string":"hash"]:e.map}},81822:function(t,r,e){var n=e(46729),o=e(15371);t.exports=function(t,r){var e=o(t,r);return n(e)?e:void 0}},15371:function(t){t.exports=function(t,r){return null==t?void 0:t[r]}},57753:function(t,r,e){var n=e(35718);t.exports=function(){this.__data__=n?n(null):{},this.size=0}},82452:function(t){t.exports=function(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r}},22115:function(t,r,e){var n=e(35718),o=Object.prototype.hasOwnProperty;t.exports=function(t){var r=this.__data__;if(n){var e=r[t];return"__lodash_hash_undefined__"===e?void 0:e}return o.call(r,t)?r[t]:void 0}},38256:function(t,r,e){var n=e(35718),o=Object.prototype.hasOwnProperty;t.exports=function(t){var r=this.__data__;return n?void 0!==r[t]:o.call(r,t)}},67426:function(t,r,e){var n=e(35718);t.exports=function(t,r){var e=this.__data__;return this.size+=this.has(t)?0:1,e[t]=n&&void 0===r?"__lodash_hash_undefined__":r,this}},54479:function(t){t.exports=function(t){var r=typeof t;return"string"==r||"number"==r||"symbol"==r||"boolean"==r?"__proto__"!==t:null===t}},99678:function(t,r,e){var n,o=e(64937),i=(n=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"";t.exports=function(t){return!!i&&i in t}},69417:function(t){t.exports=function(){this.__data__=[],this.size=0}},72470:function(t,r,e){var n=e(93382),o=Array.prototype.splice;t.exports=function(t){var r=this.__data__,e=n(r,t);return!(e<0)&&(e==r.length-1?r.pop():o.call(r,e,1),--this.size,!0)}},66165:function(t,r,e){var n=e(93382);t.exports=function(t){var r=this.__data__,e=n(r,t);return e<0?void 0:r[e][1]}},71873:function(t,r,e){var n=e(93382);t.exports=function(t){return n(this.__data__,t)>-1}},52556:function(t,r,e){var n=e(93382);t.exports=function(t,r){var e=this.__data__,o=n(e,t);return o<0?(++this.size,e.push([t,r])):e[o][1]=r,this}},39448:function(t,r,e){var n=e(96586),o=e(36301),i=e(44538);t.exports=function(){this.size=0,this.__data__={hash:new n,map:new(i||o),string:new n}}},7738:function(t,r,e){var n=e(95899);t.exports=function(t){var r=n(this,t).delete(t);return this.size-=r?1:0,r}},66575:function(t,r,e){var n=e(95899);t.exports=function(t){return n(this,t).get(t)}},7238:function(t,r,e){var n=e(95899);t.exports=function(t){return n(this,t).has(t)}},38738:function(t,r,e){var n=e(95899);t.exports=function(t,r){var e=n(this,t),o=e.size;return e.set(t,r),this.size+=e.size==o?0:1,this}},19383:function(t){t.exports=function(t){var r=-1,e=Array(t.size);return t.forEach(function(t,n){e[++r]=[n,t]}),e}},35718:function(t,r,e){var n=e(81822)(Object,"create");t.exports=n},38639:function(t){t.exports=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this}},88379:function(t){t.exports=function(t){return this.__data__.has(t)}},43735:function(t){t.exports=function(t){var r=-1,e=Array(t.size);return t.forEach(function(t){e[++r]=t}),e}},76532:function(t){var r=Function.prototype.toString;t.exports=function(t){if(null!=t){try{return r.call(t)}catch(t){}try{return t+""}catch(t){}}return""}},85638:function(t){t.exports=function(t,r){return t===r||t!=t&&r!=r}},56141:function(t,r,e){var n=e(32866);t.exports=function(t,r){return n(t,r)}},28338:function(t,r,e){var n=e(99736),o=e(11611);t.exports=function(t){if(!o(t))return!1;var r=n(t);return"[object Function]"==r||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}},11611:function(t){t.exports=function(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}}}]);
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3550,2962],{96586:function(t,e,r){var n=r(57753),o=r(82452),a=r(22115),i=r(38256),u=r(67426);function s(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}s.prototype.clear=n,s.prototype.delete=o,s.prototype.get=a,s.prototype.has=i,s.prototype.set=u,t.exports=s},36301:function(t,e,r){var n=r(69417),o=r(72470),a=r(66165),i=r(71873),u=r(52556);function s(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}s.prototype.clear=n,s.prototype.delete=o,s.prototype.get=a,s.prototype.has=i,s.prototype.set=u,t.exports=s},44538:function(t,e,r){var n=r(81822)(r(77400),"Map");t.exports=n},74554:function(t,e,r){var n=r(39448),o=r(7738),a=r(66575),i=r(7238),u=r(38738);function s(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}s.prototype.clear=n,s.prototype.delete=o,s.prototype.get=a,s.prototype.has=i,s.prototype.set=u,t.exports=s},46151:function(t,e,r){var n=r(81822)(r(77400),"Set");t.exports=n},52485:function(t,e,r){var n=r(74554),o=r(38639),a=r(88379);function i(t){var e=-1,r=null==t?0:t.length;for(this.__data__=new n;++e<r;)this.add(t[e])}i.prototype.add=i.prototype.push=o,i.prototype.has=a,t.exports=i},90756:function(t){t.exports=function(t,e){for(var r=-1,n=null==t?0:t.length;++r<n;)if(e(t[r],r,t))return!0;return!1}},93382:function(t,e,r){var n=r(85638);t.exports=function(t,e){for(var r=t.length;r--;)if(n(t[r][0],e))return r;return -1}},32866:function(t,e,r){var n=r(12772),o=r(92360);t.exports=function t(e,r,a,i,u){return e===r||(null!=e&&null!=r&&(o(e)||o(r))?n(e,r,a,i,t,u):e!=e&&r!=r)}},12772:function(t,e,r){var n=r(23694),o=r(27042),a=r(370),i=r(39584),u=r(3533),s=r(19785),l=r(43854),c=r(48519),f="[object Arguments]",p="[object Array]",d="[object Object]",_=Object.prototype.hasOwnProperty;t.exports=function(t,e,r,h,v,y){var b=s(t),g=s(e),m=b?p:u(t),x=g?p:u(e);m=m==f?d:m,x=x==f?d:x;var j=m==d,w=x==d,O=m==x;if(O&&l(t)){if(!l(e))return!1;b=!0,j=!1}if(O&&!j)return y||(y=new n),b||c(t)?o(t,e,r,h,v,y):a(t,e,m,r,h,v,y);if(!(1&r)){var k=j&&_.call(t,"__wrapped__"),P=w&&_.call(e,"__wrapped__");if(k||P){var E=k?t.value():t,z=P?e.value():e;return y||(y=new n),v(E,z,r,h,y)}}return!!O&&(y||(y=new n),i(t,e,r,h,v,y))}},46729:function(t,e,r){var n=r(28338),o=r(99678),a=r(11611),i=r(76532),u=/^\[object .+?Constructor\]$/,s=Object.prototype,l=Function.prototype.toString,c=s.hasOwnProperty,f=RegExp("^"+l.call(c).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!a(t)||o(t))&&(n(t)?f:u).test(i(t))}},65581:function(t){t.exports=function(t,e){return t.has(e)}},64937:function(t,e,r){var n=r(77400)["__core-js_shared__"];t.exports=n},27042:function(t,e,r){var n=r(52485),o=r(90756),a=r(65581);t.exports=function(t,e,r,i,u,s){var l=1&r,c=t.length,f=e.length;if(c!=f&&!(l&&f>c))return!1;var p=s.get(t),d=s.get(e);if(p&&d)return p==e&&d==t;var _=-1,h=!0,v=2&r?new n:void 0;for(s.set(t,e),s.set(e,t);++_<c;){var y=t[_],b=e[_];if(i)var g=l?i(b,y,_,e,t,s):i(y,b,_,t,e,s);if(void 0!==g){if(g)continue;h=!1;break}if(v){if(!o(e,function(t,e){if(!a(v,e)&&(y===t||u(y,t,r,i,s)))return v.push(e)})){h=!1;break}}else if(!(y===b||u(y,b,r,i,s))){h=!1;break}}return s.delete(t),s.delete(e),h}},370:function(t,e,r){var n=r(96539),o=r(59942),a=r(85638),i=r(27042),u=r(19383),s=r(43735),l=n?n.prototype:void 0,c=l?l.valueOf:void 0;t.exports=function(t,e,r,n,l,f,p){switch(r){case"[object DataView]":if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)break;t=t.buffer,e=e.buffer;case"[object ArrayBuffer]":if(t.byteLength!=e.byteLength||!f(new o(t),new o(e)))break;return!0;case"[object Boolean]":case"[object Date]":case"[object Number]":return a(+t,+e);case"[object Error]":return t.name==e.name&&t.message==e.message;case"[object RegExp]":case"[object String]":return t==e+"";case"[object Map]":var d=u;case"[object Set]":var _=1&n;if(d||(d=s),t.size!=e.size&&!_)break;var h=p.get(t);if(h)return h==e;n|=2,p.set(t,e);var v=i(d(t),d(e),n,l,f,p);return p.delete(t),v;case"[object Symbol]":if(c)return c.call(t)==c.call(e)}return!1}},39584:function(t,e,r){var n=r(51385),o=Object.prototype.hasOwnProperty;t.exports=function(t,e,r,a,i,u){var s=1&r,l=n(t),c=l.length;if(c!=n(e).length&&!s)return!1;for(var f=c;f--;){var p=l[f];if(!(s?p in e:o.call(e,p)))return!1}var d=u.get(t),_=u.get(e);if(d&&_)return d==e&&_==t;var h=!0;u.set(t,e),u.set(e,t);for(var v=s;++f<c;){var y=t[p=l[f]],b=e[p];if(a)var g=s?a(b,y,p,e,t,u):a(y,b,p,t,e,u);if(!(void 0===g?y===b||i(y,b,r,a,u):g)){h=!1;break}v||(v="constructor"==p)}if(h&&!v){var m=t.constructor,x=e.constructor;m!=x&&"constructor"in t&&"constructor"in e&&!("function"==typeof m&&m instanceof m&&"function"==typeof x&&x instanceof x)&&(h=!1)}return u.delete(t),u.delete(e),h}},95899:function(t,e,r){var n=r(54479);t.exports=function(t,e){var r=t.__data__;return n(e)?r["string"==typeof e?"string":"hash"]:r.map}},81822:function(t,e,r){var n=r(46729),o=r(15371);t.exports=function(t,e){var r=o(t,e);return n(r)?r:void 0}},15371:function(t){t.exports=function(t,e){return null==t?void 0:t[e]}},57753:function(t,e,r){var n=r(35718);t.exports=function(){this.__data__=n?n(null):{},this.size=0}},82452:function(t){t.exports=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}},22115:function(t,e,r){var n=r(35718),o=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;if(n){var r=e[t];return"__lodash_hash_undefined__"===r?void 0:r}return o.call(e,t)?e[t]:void 0}},38256:function(t,e,r){var n=r(35718),o=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;return n?void 0!==e[t]:o.call(e,t)}},67426:function(t,e,r){var n=r(35718);t.exports=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=n&&void 0===e?"__lodash_hash_undefined__":e,this}},54479:function(t){t.exports=function(t){var e=typeof t;return"string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t}},99678:function(t,e,r){var n,o=r(64937),a=(n=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"";t.exports=function(t){return!!a&&a in t}},69417:function(t){t.exports=function(){this.__data__=[],this.size=0}},72470:function(t,e,r){var n=r(93382),o=Array.prototype.splice;t.exports=function(t){var e=this.__data__,r=n(e,t);return!(r<0)&&(r==e.length-1?e.pop():o.call(e,r,1),--this.size,!0)}},66165:function(t,e,r){var n=r(93382);t.exports=function(t){var e=this.__data__,r=n(e,t);return r<0?void 0:e[r][1]}},71873:function(t,e,r){var n=r(93382);t.exports=function(t){return n(this.__data__,t)>-1}},52556:function(t,e,r){var n=r(93382);t.exports=function(t,e){var r=this.__data__,o=n(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}},39448:function(t,e,r){var n=r(96586),o=r(36301),a=r(44538);t.exports=function(){this.size=0,this.__data__={hash:new n,map:new(a||o),string:new n}}},7738:function(t,e,r){var n=r(95899);t.exports=function(t){var e=n(this,t).delete(t);return this.size-=e?1:0,e}},66575:function(t,e,r){var n=r(95899);t.exports=function(t){return n(this,t).get(t)}},7238:function(t,e,r){var n=r(95899);t.exports=function(t){return n(this,t).has(t)}},38738:function(t,e,r){var n=r(95899);t.exports=function(t,e){var r=n(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}},19383:function(t){t.exports=function(t){var e=-1,r=Array(t.size);return t.forEach(function(t,n){r[++e]=[n,t]}),r}},35718:function(t,e,r){var n=r(81822)(Object,"create");t.exports=n},38639:function(t){t.exports=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this}},88379:function(t){t.exports=function(t){return this.__data__.has(t)}},43735:function(t){t.exports=function(t){var e=-1,r=Array(t.size);return t.forEach(function(t){r[++e]=t}),r}},76532:function(t){var e=Function.prototype.toString;t.exports=function(t){if(null!=t){try{return e.call(t)}catch(t){}try{return t+""}catch(t){}}return""}},85638:function(t){t.exports=function(t,e){return t===e||t!=t&&e!=e}},56141:function(t,e,r){var n=r(32866);t.exports=function(t,e){return n(t,e)}},28338:function(t,e,r){var n=r(99736),o=r(11611);t.exports=function(t){if(!o(t))return!1;var e=n(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}},11611:function(t){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},76737:function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t,e){for(var r in e)Object.defineProperty(t,r,{enumerable:!0,get:e[r]})}(e,{default:function(){return u},noSSR:function(){return i}});let n=r(51538);r(24246),r(27378);let o=n._(r(21887));function a(t){return{default:(null==t?void 0:t.default)||t}}function i(t,e){return delete e.webpack,delete e.modules,t(e)}function u(t,e){let r=o.default,n={loading:t=>{let{error:e,isLoading:r,pastDelay:n}=t;return null}};t instanceof Promise?n.loader=()=>t:"function"==typeof t?n.loader=t:"object"==typeof t&&(n={...n,...t});let u=(n={...n,...e}).loader;return(n.loadableGenerated&&(n={...n,...n.loadableGenerated},delete n.loadableGenerated),"boolean"!=typeof n.ssr||n.ssr)?r({...n,loader:()=>null!=u?u().then(a):Promise.resolve(a(()=>null))}):(delete n.webpack,delete n.modules,i(r,n))}("function"==typeof e.default||"object"==typeof e.default&&null!==e.default)&&void 0===e.default.__esModule&&(Object.defineProperty(e.default,"__esModule",{value:!0}),Object.assign(e.default,e),t.exports=e.default)},28438:function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"LoadableContext",{enumerable:!0,get:function(){return n}});let n=r(51538)._(r(27378)).default.createContext(null)},21887:function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return p}});let n=r(51538)._(r(27378)),o=r(28438),a=[],i=[],u=!1;function s(t){let e=t(),r={loading:!0,loaded:null,error:null};return r.promise=e.then(t=>(r.loading=!1,r.loaded=t,t)).catch(t=>{throw r.loading=!1,r.error=t,t}),r}class l{promise(){return this._res.promise}retry(){this._clearTimeouts(),this._res=this._loadFn(this._opts.loader),this._state={pastDelay:!1,timedOut:!1};let{_res:t,_opts:e}=this;t.loading&&("number"==typeof e.delay&&(0===e.delay?this._state.pastDelay=!0:this._delay=setTimeout(()=>{this._update({pastDelay:!0})},e.delay)),"number"==typeof e.timeout&&(this._timeout=setTimeout(()=>{this._update({timedOut:!0})},e.timeout))),this._res.promise.then(()=>{this._update({}),this._clearTimeouts()}).catch(t=>{this._update({}),this._clearTimeouts()}),this._update({})}_update(t){this._state={...this._state,error:this._res.error,loaded:this._res.loaded,loading:this._res.loading,...t},this._callbacks.forEach(t=>t())}_clearTimeouts(){clearTimeout(this._delay),clearTimeout(this._timeout)}getCurrentValue(){return this._state}subscribe(t){return this._callbacks.add(t),()=>{this._callbacks.delete(t)}}constructor(t,e){this._loadFn=t,this._opts=e,this._callbacks=new Set,this._delay=null,this._timeout=null,this.retry()}}function c(t){return function(t,e){let r=Object.assign({loader:null,loading:null,delay:200,timeout:null,webpack:null,modules:null},e),a=null;function s(){if(!a){let e=new l(t,r);a={getCurrentValue:e.getCurrentValue.bind(e),subscribe:e.subscribe.bind(e),retry:e.retry.bind(e),promise:e.promise.bind(e)}}return a.promise()}if(!u){let t=r.webpack?r.webpack():r.modules;t&&i.push(e=>{for(let r of t)if(e.includes(r))return s()})}function c(t,e){!function(){s();let t=n.default.useContext(o.LoadableContext);t&&Array.isArray(r.modules)&&r.modules.forEach(e=>{t(e)})}();let i=n.default.useSyncExternalStore(a.subscribe,a.getCurrentValue,a.getCurrentValue);return n.default.useImperativeHandle(e,()=>({retry:a.retry}),[]),n.default.useMemo(()=>{var e;return i.loading||i.error?n.default.createElement(r.loading,{isLoading:i.loading,pastDelay:i.pastDelay,timedOut:i.timedOut,error:i.error,retry:a.retry}):i.loaded?n.default.createElement((e=i.loaded)&&e.default?e.default:e,t):null},[t,i])}return c.preload=()=>s(),c.displayName="LoadableComponent",n.default.forwardRef(c)}(s,t)}function f(t,e){let r=[];for(;t.length;){let n=t.pop();r.push(n(e))}return Promise.all(r).then(()=>{if(t.length)return f(t,e)})}c.preloadAll=()=>new Promise((t,e)=>{f(a).then(t,e)}),c.preloadReady=t=>(void 0===t&&(t=[]),new Promise(e=>{let r=()=>(u=!0,e());f(i,t).then(r,r)})),window.__NEXT_PRELOADREADY=c.preloadReady;let p=c},65218:function(t,e,r){t.exports=r(76737)}}]);