Skip to content

Commit

Permalink
Add auth info to auth page
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbaldwin44 committed Oct 31, 2024
1 parent bfd1aac commit 2821c89
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
4 changes: 3 additions & 1 deletion docs/extending-locust.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ to the ``login_manager``. The ``user_loader`` should return ``None`` to deny aut
authentication to the app should be granted.

To display errors on the login page, such as an incorrect username / password combination, you may store the ``auth_error``
on the session object: ``session["auth_error"] = "Incorrect username or password"``.
on the session object: ``session["auth_error"] = "Incorrect username or password"``. If you have non-erroneous information
you would like to display to the user, you can opt instead to set ``auth_info`` on the session object:
``session["auth_info"] = "Successfully created new user!"``

A full example can be seen `in the auth example <https://github.com/locustio/locust/tree/master/examples/web_ui_auth/basic.py>`_.

Expand Down
34 changes: 32 additions & 2 deletions locust/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from itertools import chain
from json import dumps
from time import time
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, TypedDict

import gevent
from flask import (
Expand Down Expand Up @@ -53,6 +53,34 @@
DEFAULT_CACHE_TIME = 2.0


class InputField(TypedDict):
label: str
name: str
default_value: bool | None
choices: list[str] | None
is_secret: bool | None


class CustomForm(TypedDict):
inputs: list[InputField] | None
callback_url: str
submit_button_text: str | None


class AuthProvider(TypedDict):
label: str | None
callback_url: str
icon_url: str | None


class AuthArgs(TypedDict, total=False):
custom_form: CustomForm
auth_providers: AuthProvider
username_password_callback: str
error: str
info: str


class WebUI:
"""
Sets up and runs a Flask web app that can start and stop load tests using the
Expand Down Expand Up @@ -84,7 +112,7 @@ def my_custom_route():
"""Arguments used to render index.html for the web UI. Must be used with custom templates
extending index.html."""

auth_args: dict[str, Any]
auth_args: AuthArgs
"""Arguments used to render auth.html for the web UI auth page. Must be used when configuring auth"""

def __init__(
Expand Down Expand Up @@ -506,6 +534,7 @@ def login():
return redirect(url_for("index"))

self.auth_args["error"] = session.get("auth_error", None)
self.auth_args["info"] = session.get("auth_info", None)

return render_template_from(
"auth.html",
Expand Down Expand Up @@ -577,6 +606,7 @@ def wrapper(*args, **kwargs):
if self.web_login:
try:
session["auth_error"] = None
session["auth_info"] = None
return login_required(view_func)(*args, **kwargs)
except Exception as e:
return f"Locust auth exception: {e} See https://docs.locust.io/en/stable/extending-locust.html#adding-authentication-to-the-web-ui for configuring authentication."
Expand Down
4 changes: 4 additions & 0 deletions locust/webui/src/pages/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default function Auth({
authProviders,
customForm,
error,
info,
usernamePasswordCallback,
}: IAuthArgs) {
const theme = useCreateTheme();
Expand All @@ -36,6 +37,7 @@ export default function Auth({
rowGap: 4,
boxShadow: 24,
borderRadius: 4,
width: 400,
border: '3px solid black',
p: 4,
}}
Expand All @@ -48,6 +50,7 @@ export default function Auth({
<Box sx={{ display: 'flex', flexDirection: 'column', rowGap: 2 }}>
<TextField label='Username' name='username' />
<PasswordField />
{info && <Alert severity='info'>{info}</Alert>}
{error && <Alert severity='error'>{error}</Alert>}
<Button size='large' type='submit' variant='contained'>
Login
Expand All @@ -61,6 +64,7 @@ export default function Auth({
{customForm.inputs.map((inputProps, index) => (
<CustomInput key={`custom-form-input-${index}`} {...inputProps} />
))}
{info && <Alert severity='info'>{info}</Alert>}
{error && <Alert severity='error'>{error}</Alert>}
<Button size='large' type='submit' variant='contained'>
{customForm.submitButtonText || 'Login'}
Expand Down
1 change: 1 addition & 0 deletions locust/webui/src/types/auth.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface IAuthProviders {
export interface IAuthArgs {
usernamePasswordCallback?: string;
error?: string;
info?: string;
authProviders?: IAuthProviders[];
customForm?: {
inputs: ICustomInput[];
Expand Down

0 comments on commit 2821c89

Please sign in to comment.