Revised the documentation.

This commit is contained in:
2022-12-06 21:54:10 +08:00
parent e9a6449505
commit 765822a300
7 changed files with 205 additions and 117 deletions

View File

@ -26,6 +26,13 @@ from hashlib import md5
def make_password_hash(realm: str, username: str, password: str) -> str:
"""Calculates the password hash for the HTTP digest authentication.
Use this function to set the password for the user.
For example:
::
user.password = make_password_hash(realm, username, password)
:param realm: The realm.
:param username: The username.

View File

@ -58,6 +58,16 @@ class DigestAuth:
def login_required(self, view) -> t.Callable:
"""The view decorator for HTTP digest authentication.
For example:
::
@auth.login_required
def admin():
return f"Hello, {g.user.username}!"
The logged-in user can be retrieved at ``g.user``.
:param view: The view.
:return: The login-protected view.
"""
@ -212,7 +222,16 @@ class DigestAuth:
def register_get_password(self, func: t.Callable[[str], t.Optional[str]])\
-> None:
"""Registers the callback to obtain the password hash.
"""The decorator to register the callback to obtain the password hash.
For example:
::
@auth.register_get_password
def get_password_hash(username: str) -> Optional[str]:
user = User.query.filter(User.username == username).first()
return None if user is None else user.password
:param func: The callback that given the username, returns the password
hash, or None if the user does not exist.
@ -235,7 +254,15 @@ class DigestAuth:
def register_get_user(self, func: t.Callable[[str], t.Optional[t.Any]])\
-> None:
"""Registers the callback to obtain the user.
"""The decorator to register the callback to obtain the user.
For example:
::
@auth.register_get_user
def get_user(username: str) -> Optional[User]:
return User.query.filter(User.username == username).first()
:param func: The callback that given the username, returns the user,
or None if the user does not exist.
@ -257,7 +284,15 @@ class DigestAuth:
self.__get_user = UserGetter()
def register_on_login(self, func: t.Callable[[t.Any], None]) -> None:
"""Registers the callback when the user logs in.
"""The decorator to register the callback to run when the user logs in.
For example:
::
@auth.register_on_login
def on_login(user: User) -> None:
user.visits = user.visits + 1
:param func: The callback given the logged-in user.
:return: None.
@ -280,6 +315,15 @@ class DigestAuth:
def init_app(self, app: Flask) -> None:
"""Initializes the Flask application.
For example:
::
app: flask = Flask(__name__)
auth: DigestAuth = DigestAuth()
auth.realm = "My Admin"
auth.init_app(app)
:param app: The Flask application.
:return: None.
"""
@ -335,6 +379,16 @@ class DigestAuth:
This actually causes the next authentication to fail, which forces
the browser to ask the user for the username and password again.
For example:
::
@app.post("/logout")
@auth.login_required
def logout():
auth.logout()
return redirect(request.form.get("next"))
:return: None.
"""
if "user" in session:

View File

@ -29,7 +29,54 @@ from flask_digest_auth.algo import calc_response, make_password_hash
class Client(WerkzeugClient):
"""The test client with HTTP digest authentication enabled."""
"""The test client with HTTP digest authentication enabled.
For unittest example:
::
class MyTestCase(flask_testing.TestCase):
def create_app(self):
app: Flask = create_app({
"SECRET_KEY": token_urlsafe(32),
"TESTING": True
})
app.test_client_class = Client
return app
def test_admin(self):
response = self.client.get("/admin")
self.assertEqual(response.status_code, 401)
response = self.client.get(
"/admin", digest_auth=("my_name", "my_pass"))
self.assertEqual(response.status_code, 200)
For pytest example:
::
@pytest.fixture()
def app():
app: Flask = create_app({
"SECRET_KEY": token_urlsafe(32),
"TESTING": True
})
app.test_client_class = Client
yield app
@pytest.fixture()
def client(app):
return app.test_client()
def test_admin(app: Flask, client: Client):
with app.app_context():
response = self.client.get("/admin")
assert response.status_code == 401
response = self.client.get(
"/admin", digest_auth=("my_name", "my_pass"))
assert response.status_code == 200
"""
def open(self, *args, digest_auth: t.Optional[t.Tuple[str, str]] = None,
**kwargs) -> TestResponse: