fastapi-rtk 1.0.0__py3-none-any.whl → 1.0.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.
@@ -206,6 +206,19 @@ class ModelRestApi(BaseApi):
206
206
  """
207
207
  The list of routes to exclude from protection. Defaults to `[]`.
208
208
  """
209
+ expose_params: dict[AVAILABLE_ROUTES, dict[str, Any]] = lazy(lambda: dict())
210
+ """
211
+ Additional parameters to pass to the `expose` decorator for each route. See `expose` decorator for more information.
212
+
213
+ Example:
214
+ ```python
215
+ expose_params = {
216
+ 'image': {
217
+ 'description': 'Custom description for image endpoint',
218
+ },
219
+ }
220
+ ```
221
+ """
209
222
  base_order: Tuple[str, Literal["asc", "desc"]] | None = None
210
223
  """
211
224
  The default order for the list endpoint. Set this to set the default order for the list endpoint.
@@ -1040,12 +1053,15 @@ class ModelRestApi(BaseApi):
1040
1053
  expose(
1041
1054
  "/_image/{filename}",
1042
1055
  methods=["GET"],
1043
- name="Get Image",
1044
- description="Get an image from the application.",
1045
- response_class=FileResponse,
1046
- dependencies=[Depends(has_access_dependency(self, "image"))]
1047
- if "image" in self.protected_routes
1048
- else None,
1056
+ **{
1057
+ "name": "Get Image",
1058
+ "description": f"Get an image associated with an existing {self.datamodel.obj.__name__} item.",
1059
+ "response_class": FileResponse,
1060
+ "dependencies": [Depends(has_access_dependency(self, "image"))]
1061
+ if "image" in self.protected_routes
1062
+ else None,
1063
+ **self.expose_params.get("image", {}),
1064
+ },
1049
1065
  )(self.image_headless)
1050
1066
 
1051
1067
  def file(self):
@@ -1062,12 +1078,15 @@ class ModelRestApi(BaseApi):
1062
1078
  expose(
1063
1079
  "/_file/{filename}",
1064
1080
  methods=["GET"],
1065
- name="Get File",
1066
- description="Get a file from the application.",
1067
- response_class=FileResponse,
1068
- dependencies=[Depends(has_access_dependency(self, "file"))]
1069
- if "file" in self.protected_routes
1070
- else None,
1081
+ **{
1082
+ "name": "Get File",
1083
+ "description": f"Get a file associated with an existing {self.datamodel.obj.__name__} item.",
1084
+ "response_class": FileResponse,
1085
+ "dependencies": [Depends(has_access_dependency(self, "file"))]
1086
+ if "file" in self.protected_routes
1087
+ else None,
1088
+ **self.expose_params.get("file", {}),
1089
+ },
1071
1090
  )(self.file_headless)
1072
1091
 
1073
1092
  def info(self):
@@ -1079,12 +1098,15 @@ class ModelRestApi(BaseApi):
1079
1098
  expose(
1080
1099
  "/_info",
1081
1100
  methods=["GET"],
1082
- name="Get Info",
1083
- description="Get the info for this API's Model.",
1084
- response_model=self.info_return_schema | typing.Any,
1085
- dependencies=[Depends(has_access_dependency(self, "info"))]
1086
- if "info" in self.protected_routes
1087
- else None,
1101
+ **{
1102
+ "name": "Get Info",
1103
+ "description": f"Get metadata information about the model {self.datamodel.obj.__name__}. such as add/edit columns, filter options, titles, and JSONForms schemas.",
1104
+ "response_model": self.info_return_schema | typing.Any,
1105
+ "dependencies": [Depends(has_access_dependency(self, "info"))]
1106
+ if "info" in self.protected_routes
1107
+ else None,
1108
+ **self.expose_params.get("info", {}),
1109
+ },
1088
1110
  )(self.info_headless)
1089
1111
 
1090
1112
  def download(self):
@@ -1096,11 +1118,14 @@ class ModelRestApi(BaseApi):
1096
1118
  expose(
1097
1119
  "/download",
1098
1120
  methods=["GET"],
1099
- name="Download",
1100
- description="Download list of items in CSV format.",
1101
- dependencies=[Depends(has_access_dependency(self, "download"))]
1102
- if "download" in self.protected_routes
1103
- else None,
1121
+ **{
1122
+ "name": "Download",
1123
+ "description": f"Download list of {self.datamodel.obj.__name__} items as a CSV file with support for filtering, ordering, and global search.",
1124
+ "dependencies": [Depends(has_access_dependency(self, "download"))]
1125
+ if "download" in self.protected_routes
1126
+ else None,
1127
+ **self.expose_params.get("download", {}),
1128
+ },
1104
1129
  )(self.download_headless)
1105
1130
 
1106
1131
  #! Disabled until further notice
@@ -1127,11 +1152,14 @@ class ModelRestApi(BaseApi):
1127
1152
  expose(
1128
1153
  "/bulk/{handler}",
1129
1154
  methods=["POST"],
1130
- name="Bulk",
1131
- description="Handle bulk operations.",
1132
- dependencies=[Depends(has_access_dependency(self, "bulk"))]
1133
- if "bulk" in self.protected_routes
1134
- else None,
1155
+ **{
1156
+ "name": "Bulk",
1157
+ "description": f"Handle bulk operations for the model {self.datamodel.obj.__name__} that are set in the API.",
1158
+ "dependencies": [Depends(has_access_dependency(self, "bulk"))]
1159
+ if "bulk" in self.protected_routes
1160
+ else None,
1161
+ **self.expose_params.get("bulk", {}),
1162
+ },
1135
1163
  )(self.bulk_headless)
1136
1164
 
1137
1165
  def get_list(self):
@@ -1143,12 +1171,15 @@ class ModelRestApi(BaseApi):
1143
1171
  expose(
1144
1172
  "/",
1145
1173
  methods=["GET"],
1146
- name="Get items",
1147
- description="Get a list of items.",
1148
- response_model=self.list_return_schema | typing.Any,
1149
- dependencies=[Depends(has_access_dependency(self, "get"))]
1150
- if "get_list" in self.protected_routes
1151
- else None,
1174
+ **{
1175
+ "name": "Get items",
1176
+ "description": f"Get a list of {self.datamodel.obj.__name__} items with support for column selection, filtering, ordering, pagination, and global search.",
1177
+ "response_model": self.list_return_schema | typing.Any,
1178
+ "dependencies": [Depends(has_access_dependency(self, "get"))]
1179
+ if "get_list" in self.protected_routes
1180
+ else None,
1181
+ **self.expose_params.get("get_list", {}),
1182
+ },
1152
1183
  )(self.get_list_headless)
1153
1184
 
1154
1185
  def get(self):
@@ -1160,12 +1191,15 @@ class ModelRestApi(BaseApi):
1160
1191
  expose(
1161
1192
  "/{id}",
1162
1193
  methods=["GET"],
1163
- name="Get item",
1164
- description="Get a single item.",
1165
- response_model=self.show_return_schema | typing.Any,
1166
- dependencies=[Depends(has_access_dependency(self, "get"))]
1167
- if "get" in self.protected_routes
1168
- else None,
1194
+ **{
1195
+ "name": "Get item",
1196
+ "description": f"Get a single {self.datamodel.obj.__name__} item.",
1197
+ "response_model": self.show_return_schema | typing.Any,
1198
+ "dependencies": [Depends(has_access_dependency(self, "get"))]
1199
+ if "get" in self.protected_routes
1200
+ else None,
1201
+ **self.expose_params.get("get", {}),
1202
+ },
1169
1203
  )(self.get_headless)
1170
1204
 
1171
1205
  def post(self):
@@ -1177,12 +1211,15 @@ class ModelRestApi(BaseApi):
1177
1211
  expose(
1178
1212
  "/",
1179
1213
  methods=["POST"],
1180
- name="Add item",
1181
- description="Add a new item.",
1182
- response_model=self.add_return_schema | typing.Any,
1183
- dependencies=[Depends(has_access_dependency(self, "post"))]
1184
- if "post" in self.protected_routes
1185
- else None,
1214
+ **{
1215
+ "name": "Add item",
1216
+ "description": f"Add a new {self.datamodel.obj.__name__} item.",
1217
+ "response_model": self.add_return_schema | typing.Any,
1218
+ "dependencies": [Depends(has_access_dependency(self, "post"))]
1219
+ if "post" in self.protected_routes
1220
+ else None,
1221
+ **self.expose_params.get("post", {}),
1222
+ },
1186
1223
  )(self.post_headless)
1187
1224
 
1188
1225
  def put(self):
@@ -1194,12 +1231,15 @@ class ModelRestApi(BaseApi):
1194
1231
  expose(
1195
1232
  "/{id}",
1196
1233
  methods=["PUT"],
1197
- name="Update item",
1198
- description="Update an item.",
1199
- response_model=self.edit_return_schema | typing.Any,
1200
- dependencies=[Depends(has_access_dependency(self, "put"))]
1201
- if "put" in self.protected_routes
1202
- else None,
1234
+ **{
1235
+ "name": "Update item",
1236
+ "description": f"Update an existing {self.datamodel.obj.__name__} item.",
1237
+ "response_model": self.edit_return_schema | typing.Any,
1238
+ "dependencies": [Depends(has_access_dependency(self, "put"))]
1239
+ if "put" in self.protected_routes
1240
+ else None,
1241
+ **self.expose_params.get("put", {}),
1242
+ },
1203
1243
  )(self.put_headless)
1204
1244
 
1205
1245
  def delete(self):
@@ -1211,12 +1251,15 @@ class ModelRestApi(BaseApi):
1211
1251
  expose(
1212
1252
  "/{id}",
1213
1253
  methods=["DELETE"],
1214
- response_model=GeneralResponse | typing.Any,
1215
- name="Delete item",
1216
- description="Delete an item.",
1217
- dependencies=[Depends(has_access_dependency(self, "delete"))]
1218
- if "delete" in self.protected_routes
1219
- else None,
1254
+ **{
1255
+ "name": "Delete item",
1256
+ "description": f"Delete an existing {self.datamodel.obj.__name__} item.",
1257
+ "response_model": GeneralResponse | typing.Any,
1258
+ "dependencies": [Depends(has_access_dependency(self, "delete"))]
1259
+ if "delete" in self.protected_routes
1260
+ else None,
1261
+ **self.expose_params.get("delete", {}),
1262
+ },
1220
1263
  )(self.delete_headless)
1221
1264
 
1222
1265
  """
fastapi_rtk/manager.py CHANGED
@@ -500,6 +500,7 @@ class UserManager(IDParser, BaseUserManager[User, int]):
500
500
  # Associate account
501
501
  user = await self.get_by_email(account_email)
502
502
  if not associate_by_email:
503
+ await self.on_after_authenticate(user, False)
503
504
  raise exceptions.UserAlreadyExists()
504
505
  user = await self.user_db.add_oauth_account(user, oauth_account_dict)
505
506
  except exceptions.UserNotExists:
@@ -557,6 +558,7 @@ class UserManager(IDParser, BaseUserManager[User, int]):
557
558
  user = await self._handle_role_keys(
558
559
  user, oauth_callback_params["user_dict"].pop("role_keys", None)
559
560
  )
561
+ await self.on_after_authenticate(user)
560
562
  return user
561
563
 
562
564
  @overload
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-rtk
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
5
5
  Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
6
6
  Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
@@ -9,7 +9,7 @@ fastapi_rtk/exceptions.py,sha256=P0qwd4VkeWFotgMVQHgmdT1NphFQaEznKLFIvJzW4Zs,259
9
9
  fastapi_rtk/fastapi_react_toolkit.py,sha256=gDqHq7Bk90LTZm6muOlqBbiFtOMR8xMOxa9edm8ad8w,31891
10
10
  fastapi_rtk/filters.py,sha256=weCH3suCxpGJQYmwhj9D1iAqMPiRnmbRiN7stK0rhoE,181
11
11
  fastapi_rtk/globals.py,sha256=TcoMHCueM7sFwZ8iYorUe4q-3KpVFfV04RAPuMTYFKY,8863
12
- fastapi_rtk/manager.py,sha256=qZmOgVNt8oGQnB36hgUFk4hSo_u685eAvwXUBT9j3Fg,33852
12
+ fastapi_rtk/manager.py,sha256=J86sBByj6E1kZ3CRS0NayI0n5firrfMhAU2d58mz0JM,33965
13
13
  fastapi_rtk/middlewares.py,sha256=ycdaAdLIUaNEZ7KotczTHS6OOqy98Mn1_O7Hpe7Sma8,10325
14
14
  fastapi_rtk/mixins.py,sha256=78RqwrRJFOz6KAxf-GSNOmRdr7R3b-ws7OIENYlzRQQ,238
15
15
  fastapi_rtk/models.py,sha256=lQSqe-r0H7jWBVdqXjEi_bNL1cGQr0YWnyI1ToS_coc,178
@@ -20,7 +20,7 @@ fastapi_rtk/types.py,sha256=-LPnTIbHvqJW81__gab3EWrhjNmznHhptz0BtXkEAHQ,3612
20
20
  fastapi_rtk/version.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
21
21
  fastapi_rtk/api/__init__.py,sha256=MwFR7HHppnhbjZGg3sOdQ6nqy9uxnHHXvicpswNFMNA,245
22
22
  fastapi_rtk/api/base_api.py,sha256=42I9v3b25lqxNAMDGEtajA5-btIDSyUWF0xMDgGkA8c,8078
23
- fastapi_rtk/api/model_rest_api.py,sha256=y-X1VTuTQXc5sQUx6xdiUL2iqAnEcOHzMHtJyprh5Qg,102871
23
+ fastapi_rtk/api/model_rest_api.py,sha256=Hp6ws1CjLG-2e-yHxniIudUUmnKff9js2VVZ4Q5JMoo,105111
24
24
  fastapi_rtk/auth/__init__.py,sha256=iX7O41NivBYDfdomEaqm4lUx9KD17wI4g3EFLF6kUTw,336
25
25
  fastapi_rtk/auth/auth.py,sha256=MZmuueioiMbSHjd_F3frKEqCA3yjtanRWyKOy6CnOd0,20994
26
26
  fastapi_rtk/auth/hashers/__init__.py,sha256=uBThFj2VPPSMSioxYTktNiM4-mVgtDAjTpKA3ZzWxxs,110
@@ -122,8 +122,8 @@ fastapi_rtk/utils/timezone.py,sha256=62S0pPWuDFFXxV1YTFCsc4uKiSP_Ba36Fv7S3gYjfhs
122
122
  fastapi_rtk/utils/update_signature.py,sha256=PIzZgNpGEwvDNgQ3G51Zi-QhVV3mbxvUvSwDwf_-yYs,2209
123
123
  fastapi_rtk/utils/use_default_when_none.py,sha256=H2HqhKy_8eYk3i1xijEjuaKak0oWkMIkrdz6T7DK9QU,469
124
124
  fastapi_rtk/utils/werkzeug.py,sha256=1Gv-oyqSmhVGrmNbB9fDqpqJzPpANOzWf4zMMrhW9UA,3245
125
- fastapi_rtk-1.0.0.dist-info/METADATA,sha256=grC-hA6CC_63TNYgS07mx9YlGdOow1jirtraHPFz30A,1270
126
- fastapi_rtk-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
- fastapi_rtk-1.0.0.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
128
- fastapi_rtk-1.0.0.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
129
- fastapi_rtk-1.0.0.dist-info/RECORD,,
125
+ fastapi_rtk-1.0.1.dist-info/METADATA,sha256=Nar7z0i7UfidWgYcijllpGWUaKUxYAhFbIy0l0hCvyA,1270
126
+ fastapi_rtk-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
+ fastapi_rtk-1.0.1.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
128
+ fastapi_rtk-1.0.1.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
129
+ fastapi_rtk-1.0.1.dist-info/RECORD,,