diff --git a/docs/_ext/model_field/__init__.py b/docs/_ext/model_field/__init__.py new file mode 100644 index 0000000..4f80d70 --- /dev/null +++ b/docs/_ext/model_field/__init__.py @@ -0,0 +1,17 @@ +from sphinx.application import Sphinx +from sphinx.util.typing import ExtensionMetadata + + +from .roles import ModelFieldRole +from .directives import ModelFieldsDirective + + +def setup(app: Sphinx) -> ExtensionMetadata: + app.add_role("model_field", ModelFieldRole()) + app.add_directive("model_fields", ModelFieldsDirective) + + return { + "version": "0.1", + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/docs/_ext/model_field/directives.py b/docs/_ext/model_field/directives.py new file mode 100644 index 0000000..a778f83 --- /dev/null +++ b/docs/_ext/model_field/directives.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +from docutils import nodes + +from sphinx.util.docutils import SphinxDirective + +from django.utils.module_loading import import_string + +from .utils import get_field_representation + + +class ModelFieldsDirective(SphinxDirective): + """Displays a model's fields with their name, helptext and default in a list""" + + required_arguments = 1 + has_content = True + + def run(self) -> list[nodes.Node]: + + model_path = self.arguments[0] + model = import_string(model_path) + + field_list = [] + + for line in self.content: + field = model._meta.get_field(line) + node = nodes.paragraph("", "", *get_field_representation(field)) + field_list.append(nodes.list_item("", node)) + + bullet_list = nodes.bullet_list("", *field_list) + + return [bullet_list] diff --git a/docs/_ext/model_field/roles.py b/docs/_ext/model_field/roles.py new file mode 100644 index 0000000..0e9e070 --- /dev/null +++ b/docs/_ext/model_field/roles.py @@ -0,0 +1,21 @@ +from sphinx.util.docutils import SphinxRole + +from docutils import nodes +from django.utils.module_loading import import_string + +from .utils import get_field_representation + +class ModelFieldRole(SphinxRole): + """Displays a model field's name, helptext and default inline""" + + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: + + args = self.text.split(" ") + + model_path = args[0] + model = import_string(model_path) + field_name = args[1] + field = model._meta.get_field(field_name) + + field_nodes = get_field_representation(field) + return field_nodes, [] diff --git a/docs/_ext/model_field/utils.py b/docs/_ext/model_field/utils.py new file mode 100644 index 0000000..a1f427c --- /dev/null +++ b/docs/_ext/model_field/utils.py @@ -0,0 +1,17 @@ +from django.db.models.fields import Field +from docutils import nodes + +def get_field_representation(field: Field) -> list[nodes.literal | nodes.Text]: + + name = nodes.literal("", nodes.Text(field.name)) + description = nodes.Text(f": {field.help_text}.") + + field_nodes = [name, description] + + if field.get_default(): + field_nodes.append(nodes.Text(" Defaults to ")) + field_nodes.append(nodes.literal("", nodes.Text(field.get_default()))) + + return field_nodes + + diff --git a/docs/conf.py b/docs/conf.py index ef70081..b0ad50b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -37,9 +37,13 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named "sphinx.ext.*") or your custom # ones. + +sys.path.append(os.path.abspath("./_ext")) + extensions = [ "sphinx.ext.autodoc", "sphinx.ext.todo", + "model_field", ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/setup_configuration.rst b/docs/setup_configuration.rst index e3205d1..c6487e9 100644 --- a/docs/setup_configuration.rst +++ b/docs/setup_configuration.rst @@ -48,45 +48,40 @@ Example: Required Fields: """""""""""""""" +.. model_fields:: mozilla_django_oidc_db.models.OpenIDConnectConfig -* ``oidc_rp_client_id``: OpenID Connect client ID from the OIDC Provider. -* ``oidc_rp_client_secret``: OpenID Connect secret from the OIDC Provider. + oidc_rp_client_id + oidc_rp_client_id + oidc_rp_client_secret The discovery endpoint can be configured to automatically fetch the other endpoints. Otherwise the endpoints must be set individually. -* ``oidc_op_discovery_endpoint``: URL of your OpenID Connect provider discovery endpoint ending with a slash (`.well-known/...` will be added automatically). - - **OR** - -* ``oidc_op_authorization_endpoint``: URL of your OpenID Connect provider authorization endpoint -* ``oidc_op_token_endpoint``: URL of your OpenID Connect provider token endpoint -* ``oidc_op_user_endpoint``: URL of your OpenID Connect provider userinfo endpoint +.. model_fields:: mozilla_django_oidc_db.models.OpenIDConnectConfig + oidc_op_discovery_endpoint + oidc_op_authorization_endpoint + oidc_op_token_endpoint + oidc_op_user_endpoint Optional Fields: """""""""""""""" -* ``oidc_op_jwks_endpoint``: URL of your OpenID Connect provider JSON Web Key Set endpoint. - Required if ``RS256`` is used as signing algorithm. No default value. -* ``claim_mapping``: Mapping from user-model fields to OIDC claims. - Defaults to ``{"email": ["email"], "first_name": ["given_name"], "last_name": ["family_name"]}`` -* ``username_claim``: The name of the OIDC claim that is used as the username. Defaults to ``["sub"]`` -* ``groups_claim``: The name of the OIDC claim that holds the values to map to local user groups. Defaults to ``["roles"]`` -* ``default_groups``: The default groups to which every user logging in with OIDC will be assigned. No default values. -* ``superuser_group_names``: If any of these group names are present in the claims upon login, the user will be marked as a superuser. - If none of these groups are present the user will lose superuser permissions. Defaults to empty list. -* ``make_users_staff``: Users will be flagged as being a staff user automatically. - This allows users to login to the admin interface. Defaults to ``False``. -* ``oidc_use_nonce``: Controls whether the OpenID Connect client uses nonce verification. Defaults to ``True``. -* ``oidc_nonce_size``: Sets the length of the random string used for OpenID Connect nonce verification. Defaults to ``32``. -* ``oidc_state_size``: Sets the length of the random string used for OpenID Connect state verification. Defaults to ``32``. -* ``oidc_rp_idp_sign_key``: Key the Identity Provider uses to sign ID tokens in the case of an RSA sign algorithm. - Should be the signing key in PEM or DER format. No default. -* ``oidc_rp_scopes_list``: OpenID Connect scopes that are requested during login. Defaults to ``["openid", "email", "profile"]``. -* ``oidc_rp_sign_algo``: Algorithm the Identity Provider uses to sign ID tokens. Defaults to ``"HS256"``. -* ``sync_groups``: If checked, local user groups will be created for group names present in the groups claim, - if they do not exist yet locally. Defaults to ``True``. -* ``sync_groups_glob_pattern``: The glob pattern that groups must match to be synchronized to the local database. Defaults to ``"*"``. -* ``userinfo_claims_source``: Indicates the source from which the user information claims should be extracted - (``"userinfo_endpoint"`` or ``"id_token"``). Defaults to ``"userinfo_endpoint"``. +.. model_fields:: mozilla_django_oidc_db.models.OpenIDConnectConfig + + oidc_op_jwks_endpoint + claim_mapping + groups_claim + default_groups + superuser_group_names + make_users_staff + oidc_use_nonce + oidc_nonce_size + oidc_state_size + oidc_rp_idp_sign_key + oidc_rp_scopes_list + oidc_rp_sign_algo + sync_groups + sync_groups_glob_pattern + userinfo_claims_source +