Skip to content

Commit 5682000

Browse files
authored
feat: JWT auth dialog (#38)
1 parent cc9b55b commit 5682000

3 files changed

Lines changed: 88 additions & 48 deletions

File tree

fastapi_forge/frontend/panels/model_editor_panel.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def _toggle_auth_model(self) -> None:
8787
state.render_model_editor_fn()
8888

8989
if state.render_content_fn:
90-
state.render_content_fn()
90+
state.render_content_fn.refresh()
91+
9192
self._render_action_group.refresh()
9293

9394
if model.metadata.is_auth_model:

fastapi_forge/frontend/panels/project_config_panel.py

Lines changed: 80 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -157,59 +157,92 @@ def _update_taskiq_state(self, *_) -> None:
157157
self.use_taskiq.value = False
158158
state.use_taskiq = False
159159

160-
def _handle_builtin_auth_change(self, event: ValueChangeEventArguments) -> None:
160+
async def _create_auth_model_dialog(self) -> bool:
161+
dialog = ui.dialog()
162+
with dialog, ui.card().classes("w-full max-w-md p-6 text-center"):
163+
ui.icon("check_circle", color="green-500").classes("text-4xl self-center")
164+
ui.markdown(
165+
"JWT Auth needs a model with 'email' and 'password' fields. "
166+
"Select any model as auth model later, or create one now (optional)."
167+
).classes("text-center")
168+
169+
create_model_checkbox = ui.checkbox(
170+
"Create default 'auth_user' model", value=True
171+
).classes("w-full mt-4")
172+
173+
with ui.row().classes("w-full justify-center gap-4 mt-4"):
174+
ui.button("Cancel", color="negative", on_click=dialog.close)
175+
ui.button(
176+
"Enable JWT Auth",
177+
color="primary",
178+
on_click=lambda: dialog.submit(create_model_checkbox.value),
179+
)
180+
181+
return await dialog
182+
183+
async def _handle_builtin_auth_change(
184+
self, event: ValueChangeEventArguments
185+
) -> None:
161186
"""Handle JWT Auth checkbox changes"""
162187
enabled = event.value
163188
state.use_builtin_auth = enabled
164189

165-
if enabled:
166-
if any(model.name == "auth_user" for model in state.models):
167-
ui.notify("The 'auth_user' model already exists.", type="negative")
168-
self.use_builtin_auth.value = False
169-
state.use_builtin_auth = False
190+
if not enabled:
191+
auth_model = state.get_auth_model()
192+
if not auth_model:
170193
return
194+
auth_model.metadata.is_auth_model = False
195+
if state.render_content_fn:
196+
state.render_content_fn.refresh()
197+
if state.render_actions_fn:
198+
state.render_actions_fn.refresh()
199+
return
171200

172-
try:
173-
auth_user_model = Model(
174-
name="auth_user",
175-
metadata=ModelMetadata(is_auth_model=True),
176-
fields=[
177-
ModelField(
178-
name="id",
179-
type=FieldDataTypeEnum.UUID,
180-
primary_key=True,
181-
unique=True,
182-
index=True,
183-
),
184-
*DEFAULT_AUTH_USER_FIELDS,
185-
ModelField(
186-
name="created_at",
187-
type=FieldDataTypeEnum.DATETIME,
188-
default_value="datetime.now(timezone.utc)",
189-
metadata=ModelFieldMetadata(is_created_at_timestamp=True),
190-
),
191-
ModelField(
192-
name="updated_at",
193-
type=FieldDataTypeEnum.DATETIME,
194-
default_value="datetime.now(timezone.utc)",
195-
extra_kwargs={"onupdate": "datetime.now(timezone.utc)"},
196-
metadata=ModelFieldMetadata(is_updated_at_timestamp=True),
197-
),
198-
],
199-
)
200-
state.models.append(auth_user_model)
201-
if state.render_models_fn:
202-
state.render_models_fn()
203-
ui.notify("The 'auth_user' model has been created.", type="positive")
204-
except ValidationError as exc:
205-
notify_validation_error(exc)
206-
else:
207-
state.models = [
208-
model for model in state.models if model.name != "auth_user"
209-
]
210-
if state.render_models_fn:
211-
state.render_models_fn()
212-
ui.notify("The 'auth_user' model has been deleted.", type="positive")
201+
create_model_dialog = await self._create_auth_model_dialog()
202+
203+
if not create_model_dialog:
204+
return
205+
206+
if any(model.name == "auth_user" for model in state.models):
207+
ui.notify("The 'auth_user' model already exists.", type="negative")
208+
self.use_builtin_auth.value = False
209+
state.use_builtin_auth = False
210+
return
211+
212+
try:
213+
auth_user_model = Model(
214+
name="auth_user",
215+
metadata=ModelMetadata(is_auth_model=True),
216+
fields=[
217+
ModelField(
218+
name="id",
219+
type=FieldDataTypeEnum.UUID,
220+
primary_key=True,
221+
unique=True,
222+
index=True,
223+
),
224+
*DEFAULT_AUTH_USER_FIELDS,
225+
ModelField(
226+
name="created_at",
227+
type=FieldDataTypeEnum.DATETIME,
228+
default_value="datetime.now(timezone.utc)",
229+
metadata=ModelFieldMetadata(is_created_at_timestamp=True),
230+
),
231+
ModelField(
232+
name="updated_at",
233+
type=FieldDataTypeEnum.DATETIME,
234+
default_value="datetime.now(timezone.utc)",
235+
extra_kwargs={"onupdate": "datetime.now(timezone.utc)"},
236+
metadata=ModelFieldMetadata(is_updated_at_timestamp=True),
237+
),
238+
],
239+
)
240+
state.models.append(auth_user_model)
241+
if state.render_content_fn:
242+
state.render_content_fn.refresh()
243+
ui.notify("The 'auth_user' model has been created.", type="positive")
244+
except ValidationError as exc:
245+
notify_validation_error(exc)
213246

214247
async def _warn_overwrite(self) -> bool:
215248
"""Show a confirmation dialog if the project already exists."""

fastapi_forge/frontend/state.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,5 +258,11 @@ def _trigger_ui_refresh(self) -> None:
258258
if self.render_actions_fn:
259259
self.render_actions_fn.refresh()
260260

261+
def get_auth_model(self) -> Model | None:
262+
return next(
263+
(model for model in self.models if model.metadata.is_auth_model),
264+
None,
265+
)
266+
261267

262268
state: ProjectState = ProjectState()

0 commit comments

Comments
 (0)