Django PAM Documentation

Similar documents
django-session-security Documentation

django-ratelimit-backend Documentation

django-sticky-uploads Documentation

django-contact-form Documentation

django-model-report Documentation

django-osm-field Release 0.3.1

django-password-reset Documentation

django-messages Documentation

django-baton Documentation

Easy-select2 Documentation

STWA Documentation. Release Rafał Mirończyk

django-embed-video Documentation

django-embed-video Documentation

kaleo Documentation Release 1.5 Eldarion

django-ajax-form-mixin Documentation

Django MFA Documentation

django-baton Documentation

django-autocomplete-light Documentation

MIT AITI Python Software Development Lab DJ1:

Building a Django Twilio Programmable Chat Application

Django QR Code Documentation

Django File Picker Documentation

django-mama-cas Documentation

django-oscar-paypal Documentation

django-avatar Documentation

django-avatar Documentation

django-embed-video Documentation

Django Extra Views Documentation

ska Documentation Release Artur Barseghyan

django-cas Documentation

Manual Html A Href Onclick Submit Form

django-oauth2-provider Documentation

MapEntity Documentation

DJOAuth2 Documentation

Wifiphisher Documentation

django-dajaxice Documentation

yagmail Documentation

django-autocomplete-light Documentation

SagePay payment gateway package for django-oscar Documentation

django-permission Documentation

Django-Select2 Documentation. Nirupam Biswas

Django urls Django Girls Tutorial

Trunk Player Documentation

django-inplaceedit Documentation

Django-CSP Documentation

micawber Documentation

django-facebook-graph Documentation

django-modern-rpc Documentation

Tangent MicroServices Documentation

Django Part II SPARCS 11 undead. Greatly Inspired by SPARCS 10 hodduc

Django Admin Sortable Documentation

django-sekizai Documentation

I hate money. Release 1.0

cmsplugin-blog Release post 0 Øyvind Saltvik

Bambu API Documentation

Django File Picker Documentation

Django Data Importer Documentation

DBNsim. Giorgio Giuffrè. 0 Abstract How to run it on your machine How to contribute... 2

Django Groups Manager Documentation

Django EL(Endless) Pagination Documentation

django-ad-code Documentation

Configuring Hotspots

Django-frontend-notification Documentation

Nuit Documentation. Release Ben Cardy

The Django Web Framework Part VI

djangotribune Documentation

bottle-rest Release 0.5.0

Django OAuth Toolkit Documentation

kiss.py Documentation

webkitpony Documentation

Djam Documentation. Release Participatory Culture Foundation

django-app-metrics Documentation

wagtailmenus Documentation

wagtailmenus Documentation

django-revproxy Documentation

Biostar Central Documentation. Release latest

AD218 Working with Customers via the IBM Lotus Sametime Links Toolkit. Carl Tyler Instant Technologies

django-allauth-2fa Documentation

GMusicProcurator Documentation

fragapy Documentation

mongodb-tornado-angular Documentation

django-openid Documentation

Django AdminLTE 2 Documentation

django-push Documentation

HOW TO FLASK. And a very short intro to web development and databases

django-telegram-login Documentation

spaste Documentation Release 1.0 Ben Webster

canary Documentation Release 0.1 Branton K. Davis

django-notifier Documentation

alphafilter Documentation

f5-icontrol-rest Documentation

django-teamwork Documentation

Python web frameworks

django-rest-framework-datatables Documentation

django-amp-tools Documentation Release latest

django-registration Documentation

Django Graphos Documentation

TailorDev Contact Documentation

mozilla-django-oidc Documentation

colab Documentation Release 2.0dev Sergio Oliveira

Transcription:

Django PAM Documentation Release 1.4.1 Carl J. Nobile Aug 01, 2018

Contents 1 Contents 3 1.1 Installation................................................ 3 1.2 Configuration............................................... 3 1.3 Overview................................................. 6 1.4 Testing.................................................. 6 1.5 Django PAM............................................... 7 2 Indices and Tables 15 Python Module Index 17 i

ii

This is a simple authentication backend that uses the python-pam package. Django PAM can be used in an SSO (Single Sign On) environment or just with a single box where you want to log into a Django app with your UNIX login. Contents 1

2 Contents

CHAPTER 1 Contents 1.1 Installation The easiest way to install the Django PAM package is with pip: $ pip install django-pam You can also install with GitHub. This is useful if you need to see Django PAM running in a real environment: $ git clone https://github.com/cnobile2012/django-pam.git Note: Be aware that the pip requirements in the GitHub repository are not frozen. This may cause Django PAM to break if dependencies are used that are much newer than what I used. If this happens, please put an issue in my GitHub account to let me know. 1.2 Configuration 1.2.1 Installing the Backend Authenticator You will need to add Django PAM to your INSTALLED_APPS: INSTALLED_APPS = [... 'django_pam', ] Next you will need to add the Django PAM backend to the AUTHENTICATION_BACKENDS: 3

AUTHENTICATION_BACKENDS = [ 'django_pam.auth.backends.pambackend', 'django.contrib.auth.backends.modelbackend', ] Note: 1. The user that runs the application needs to be a member of the /etc/shadow file group, this is usually the web server user. This is necessary so the web server can authenticate other users. To do this run the command below with the proper user. $ sudo usermod -a -G shadow <user> 2. If you use your UNIX account username you will be logged in through the PAMBackend backend. If you use the Django username you will be logged in through the ModelBackend, assuming both usernames and passwords are not the same. 1.2.2 Using the Django PAM Login and Logout Templates Use as is with Django PAM CSS Add the statement below to urlpatterns in your urls.py file: re_path(r'^django-pam/', include('django_pam.urls')), Then put the HTML below in your template: {% load staticfiles %} <a href="{% url 'django-pam:login' %}">Login</a> <a href="{% url 'django-pam:logout' %}?next={{ next }}">Logout</a> Use Modified CSS Add the statements below to urlpatterns in your urls.py file: re_path(r'^login/$', LoginView.as_view(template_name='<your template dir>/login.html '), name='login'), re_path(r"^logout/(?p<next>[\w\-\:/]+)?$", LogoutView.as_view( template_name='<your template dir>/logout.html'), name='logout'), Create login.html and logout.html templates. Login: {% extends "your_base.html" %} {% load staticfiles %} {% block script %} {{ form.media }} <link rel="stylesheet" href="{% static '<your css file>' %}"> {% endblock %} {% block content %}{% include "django_pam/accounts/_login.html" %}{% endblock %} The stanza above includes the Django PAM CSS and JavaScript code through the form. Then your overriding CSS is included. The JavaScript code, that s included from the form, is not dependent on any toolkit. 4 Chapter 1. Contents

Logout: {% extends "your_base.html" %} {% load staticfiles %} {% block script %} <link rel="stylesheet" href="{% static 'django_pam/css/auth.css' %}"> <link rel="stylesheet" href="{% static '<your css file>' %}"> {% endblock %} {% block content %}{% include "django_pam/accounts/_logout.html" %}{% endblock %} There is no form for logout so the CSS from Django PAM and your overriding CSS need to be included the normal way. Then use something like the HTML below in your HTML template: {% load staticfiles %} <a href="{% url 'login' %}">Login</a> <a href="{% url 'logout' %}?next={{ next }}">Logout</a> 1.2.3 Using the Django PAM Login and Logout Modals Using the modals require a little more work, but it s still not to difficult. In your base.html head include: <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css" media="all" rel="stylesheet" /> <link href="{% static 'django_pam/css/modal.css' %}" type="text/css" media="all" rel="stylesheet" /> <script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1nt4dteyoj7br+vtu7+t8vp13humzfbjniyoejo=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></ script> <script src="{% static 'django_pam/js/js.cookie-2.0.4.min.js' %}"></script> <script src="{% static 'django_pam/js/inheritance.js' %}"></script> <script src="{% static 'django_pam/js/modal.js' %}"></script> At the bottom of your base.html template include this line just before the </html> tag: {% block modals %}{% endblock %} Then in the template that has your login html add at the bottom of the template: {% block modals %} <div id="modals"> {% include "django_pam/modals/login.html" %} {% include "django_pam/modals/logout.html" %} </div> <!-- div#modals --> {% endblock %} Note: The JavaScript for the modals is written in ES6 which is supported in most of the newer browsers. See: ECMAScript 6. Use Babel or Traceur if you wish to Transpile my JavaScript code. 1.2. Configuration 5

1.3 Overview 1.3.1 Backend Authenticator PAMBackend.authenticate Authentication method 1 This method has two keyword arguments one for the username and the other for the password, both are manditory. There is a third argument used to pass in a dict of additional arguments that you may want stored in the database on the first login of the user. In order to use the additional arguments both the django.contrib.auth.authenticate function and either the django.contrib.auth.forms.authenticationform or the Django PAM django_pam.accounts.forms.authenticationform would need to be overridden, depending on which one you use. PAMBackend.get_user Returns the authenticated user 2 There is one positional argument that can be the pk, username, or email. The email would be used only if the email is used instead of the username to identify the user. 1.3.2 Login and Logout Views LoginView 3 Usage: re_path(r'^login/$', LoginView.as_view( form_class=myauthenticationform, success_url='/my/success/url/', redirect_field_name='my-redirect-field-name', template_name='your_template.html' ), name='login'), This view is written to work with either a template POST or a XMLHttpRequest POST request. LogoutView 4 Usage: re_path(r'^logout/$', LogoutView.as_view( template_name='my_template.html', success_url='/my/success/url/), redirect_field_name='my-redirect-field-name' ), name='logout') This view is written to work with either a template POST or a XMLHttpRequest POST request. 1.4 Testing Since the user of the server that runs an application, that uses the backend provided by this package, needs to be a member of the UNIX shadow group, testing is a bit complicated. Because of this, this project is not able to run on 1 See source docs django_pam.auth.backends.pambackend.authenticate() 2 See source docs django_pam.auth.backends.pambackend.get_user() 3 See source docs django_pam.accounts.views.loginview 4 See source docs django_pam.accounts.views.logoutview 6 Chapter 1. Contents

Travis CI. However, setting up tests to run locally can be done by following the few steps. 1.4.1 Give Your User Account Shadow Privileges This assumes that it is your user account that the runserver is running in. If not, then use the account that is running the runserver. $ sudo usermod -a -G shadow <username> 1.4.2 Create a guest User $ sudo useradd guest -m -s /bin/bash -d /home/guest $ sudo passwd guest You will need to logout of your account then log back in again, this means out of any GUI that you may be in. After logged back in tests will run correctly, however, you will need to enter the username and password multiple times. This will get old fast. 1.4.3 Creating a.django_pam File Create a.django_pam file in the same directory as manage.py. On separate lines put guest (the username), the password you chose for it, and then a fake email address. With this file in-place the test will no longer prompt for the username and password and will run all the tests with no prompts. 1.5 Django PAM 1.5.1 django_pam package django_pam.accounts package django_pam.accounts.tests package django_pam.accounts.tests.test_accounts_forms module class django_pam.accounts.tests.test_accounts_forms.testauthenticationform(name) Bases: django_pam.auth.tests.base_test.basedjangopam setup() Hook method for setting up the test fixture before exercising it. test_invalid_credentials() Test for invalid credentials. test_missing_credentials() Test for missing credentials. 1.5. Django PAM 7

test_user_created() Test that the form created a user. Form constructor signature: init (self, request=none, *args, **kwargs) django_pam.accounts.tests.test_accounts_views module class django_pam.accounts.tests.test_accounts_views.testloginview(name) Bases: django_pam.auth.tests.base_test.basedjangopam setup() Hook method for setting up the test fixture before exercising it. test_get_login_screen() Test that the login screen returns properly. test_post_login_ajax_invalid() Test that an invalid AJAX login returns a redirect properly. test_post_login_ajax_valid() Test that a valid AJAX login returns a redirect properly. test_post_login_form_invalid() Test that an invalid form login returns a redirect properly. test_post_login_form_invalid_redirection() Test that redirection will not take you off site. test_post_login_form_valid() Test that a valid form login returns a redirect properly. class django_pam.accounts.tests.test_accounts_views.testlogoutview(name) Bases: django_pam.auth.tests.base_test.basedjangopam setup() Hook method for setting up the test fixture before exercising it. test_get_logout_screen() Test that the logout screen returns properly. test_post_logout_ajax() Test that a valid ajax logout returns properly. test_post_logout_form() Test that a valid form logout returns a redirect properly. test_post_logout_form_invalid() Test that if the success_url is not set an exception is raised. django_pam.accounts.forms module Django PAM forms. class django_pam.accounts.forms.authenticationform(request=none, *args, **kwargs) Bases: django.contrib.auth.forms.authenticationform Authentication form 8 Chapter 1. Contents

class Media Bases: object css = {'all': ('django_pam/css/auth.css',)} js = ('django_pam/js/auth.js',) base_fields = {'email': clean() Does the authentication and saves the email if exists. declared_fields = {'email': media <django.forms.fields.emailfield object at 0x7fa490a90470>, 'pa <django.forms.fields.emailfield object at 0x7fa490a90470>, django_pam.accounts.urls module Django PAM accounta/urls.py django_pam.accounts.view_mixins module Dynamic Column view mixins. class django_pam.accounts.view_mixins.ajaxableresponsemixin Bases: object Mixin to add AJAX support to a form. Must be used with an object-based FormView (e.g. CreateView) form_invalid(form) Renders the invalid form error description. See Django s form_invalid. If the request is an AJAX request return this data as a JSON string. Parameters form (Django's form object.) The Django form object. Return type Result from Django s form_valid or a JSON string. form_valid(form) Renders the valid data. See Django s form_valid. If the request is an AJAX request return this data as a JSON string. Parameters form (Django's form object.) The Django form object. Return type Result from Django s form_valid or a JSON string. get_data(**context) Returns an object that will be serialized as JSON by json.dumps(). Parameters context (dict) Context added to the JSON response. Return type dict Updated context class django_pam.accounts.view_mixins.jsonresponsemixin Bases: object A mixin that can be used to render a JSON response. get_data(**context) Returns an object that will be serialized as JSON by json.dumps(). Parameters context (dict) Context added to the JSON response. Return type dict Updated context 1.5. Django PAM 9

render_to_json_response(context, **response_kwargs) Returns a JSON response, transforming context to make the payload. Parameters context (See Django Context.) The template rendering context. response_kwargs Response keywords arguments. Return type See Django response_class. django_pam.accounts.views module Django PAM views.py class django_pam.accounts.views.loginview(**kwargs) Bases: django_pam.accounts.view_mixins.ajaxableresponsemixin, django.views. generic.edit.formview A class version of django.contrib.auth.views.login. Usage: re_path(r'^login/$', LoginView.as_view( form_class=myauthenticationform, success_url='/my/success/url/', redirect_field_name='my-redirect-field-name', template_name='your_template.html' ), name='login'), dispatch(request, *args, **kwargs) Dispatches the request to the correct HTTP handler method. Parameters request The Django request object. args Positional arguments. kwargs Keyword arguments. Return type The proper handler. form_class alias of django_pam.accounts.forms.authenticationform form_valid(form) The user has provided valid credentials (this was checked in the form s is_valid() method). Parameters form (Django Form) A Django form object. Return type Result of AjaxableResponseMixin.form_valid. get_context_data(**context) Get any extra context for GET methods. Parameters context (dict) Context for GET methods. Return type dict get_data(**context) Add to the JSON context. Parameters context (dict) A json response context. 10 Chapter 1. Contents

Return type dict get_form_kwargs() Incoming AJAX data structure from an HTML <form> tag: [{'name': 'username', 'value': '<username>'}, {'name': 'password', 'value': '<password>'}, {'name': 'next', 'value': '<redirect URI>'} ] Return type dict get_success_url() Returns a url used for redirection. Return type str redirect_field_name = 'next' success_url = '' template_name = 'django_pam/accounts/login.html' class django_pam.accounts.views.logoutview(**kwargs) Bases: django_pam.accounts.view_mixins.jsonresponsemixin, django.views. generic.base.templateview A class version of django.contrib.auth.views.logout. Usage: re_path(r'^logout/$', LogoutView.as_view( template_name='my_template.html', success_url='/my/success/url/), redirect_field_name='my-redirect-field-name' ), name='logout') get(request, *args, **kwargs) A GET method handler. Parameters request The Django request object. args Positional arguments. kwargs (dict) Keyword arguments. Return type A response object. get_context_data(**kwargs) Add to the template context. Parameters kwargs (dict) Keyword arguments. Return type dict get_data(**context) Add to the JSON context. Parameters context (dict) A json response context. Return type dict 1.5. Django PAM 11

get_success_url() Returns the supplied success URL. Return type str post(request, *args, **kwargs) A POST method handler. Note: Incoming AJAX data structure from an HTML <form> tag: [{'name': 'next', 'value': '<redirect URI>'}] Parameters request The Django request object. args Positional arguments. kwargs (dict) Keyword arguments. Return type A response object. redirect_field_name = 'next' success_url = '/accounts/login/' template_name = 'django_pam/accounts/logout.html' django_pam.auth package django_pam.auth.tests package django_pam.auth.tests.base_test module class django_pam.auth.tests.base_test.basedjangopam(name) Bases: django.test.testcases.testcase django_pam.auth.tests.test_auth_backends module class django_pam.auth.tests.test_auth_backends.testpambackend(name) Bases: django_pam.auth.tests.base_test.basedjangopam setup() Hook method for setting up the test fixture before exercising it. test_authenticate_fail() Test that authenticate fails with invalid credentials. test_authenticate_pass() Test that authenticate method works properly. test_get_user_invalid() Test that an invalid user returns a None object. test_get_user_valid() Test that the PAMBackend.authenticate() method works properly. 12 Chapter 1. Contents

django_pam.auth.backends module Django PAM backend. class django_pam.auth.backends.pambackend Bases: django.contrib.auth.backends.modelbackend An implementation of a PAM backend authentication module. authenticate(username=none, password=none, **extra_fields) Authenticate using PAM then get the account if it exists else create a new account. Parameters username (str) The users username. This is a manditory field. password (str) The users password. This is a manditory field. extra_fields (dict) Additonal keyword options of any editable field in the user model or arguments in the PAM authenticate method. Return type The Django user object. get_user(user_data) Get the user by either the username, email, or the pk. Parameters user_data The username, email or pk. Return type A Django user object. django_pam.urls module Django PAM urls.py 1.5. Django PAM 13

14 Chapter 1. Contents

CHAPTER 2 Indices and Tables genindex modindex search 15

16 Chapter 2. Indices and Tables

Python Module Index d django_pam, 13 django_pam.accounts, 12 django_pam.accounts.forms, 8 django_pam.accounts.tests, 8 django_pam.accounts.tests.test_accounts_forms, 7 django_pam.accounts.tests.test_accounts_views, 8 django_pam.accounts.urls, 9 django_pam.accounts.view_mixins, 9 django_pam.accounts.views, 10 django_pam.auth, 13 django_pam.auth.backends, 13 django_pam.auth.tests, 12 django_pam.auth.tests.base_test, 12 django_pam.auth.tests.test_auth_backends, 12 django_pam.urls, 13 17

18 Python Module Index

Index A AjaxableResponseMixin (class in django_pam.accounts.view_mixins), 9 authenticate() (django_pam.auth.backends.pambackend method), 13 AuthenticationForm (class in django_pam.accounts.forms), 8 AuthenticationForm.Media (class in django_pam.accounts.forms), 8 C clean() (django_pam.accounts.forms.authenticationform method), 9 css (django_pam.accounts.forms.authenticationform.media D attribute), 9 get_data() (django_pam.accounts.view_mixins.ajaxableresponsemixin declared_fields (django_pam.accounts.forms.authenticationform method), 9 attribute), 9 get_data() (django_pam.accounts.view_mixins.jsonresponsemixin dispatch() (django_pam.accounts.views.loginview method), 9 method), 10 get_data() (django_pam.accounts.views.loginview django_pam (module), 13 method), 10 django_pam.accounts (module), 12 get_data() (django_pam.accounts.views.logoutview django_pam.accounts.forms (module), 8 django_pam.accounts.tests (module), 8 django_pam.accounts.tests.test_accounts_forms (mod- (mod- ule), 7 django_pam.accounts.tests.test_accounts_views ule), 8 django_pam.accounts.urls (module), 9 django_pam.accounts.view_mixins (module), 9 django_pam.accounts.views (module), 10 django_pam.auth (module), 13 django_pam.auth.backends (module), 13 django_pam.auth.tests (module), 12 django_pam.auth.tests.base_test (module), 12 django_pam.auth.tests.test_auth_backends (module), 12 django_pam.urls (module), 13 F form_class (django_pam.accounts.views.loginview attribute), 10 form_invalid() (django_pam.accounts.view_mixins.ajaxableresponsemixin B method), 9 base_fields (django_pam.accounts.forms.authenticationformform_valid() (django_pam.accounts.view_mixins.ajaxableresponsemixin attribute), 9 method), 9 BaseDjangoPAM (class in form_valid() (django_pam.accounts.views.loginview django_pam.auth.tests.base_test), 12 method), 10 G get() (django_pam.accounts.views.logoutview method), 11 get_context_data() (django_pam.accounts.views.loginview method), 10 get_context_data() (django_pam.accounts.views.logoutview method), 11 method), 11 get_form_kwargs() (django_pam.accounts.views.loginview method), 11 get_success_url() (django_pam.accounts.views.loginview method), 11 get_success_url() (django_pam.accounts.views.logoutview method), 11 get_user() (django_pam.auth.backends.pambackend method), 13 19

J js (django_pam.accounts.forms.authenticationform.media attribute), 9 JSONResponseMixin (class in django_pam.accounts.view_mixins), 9 L LoginView (class in django_pam.accounts.views), 10 LogoutView (class in django_pam.accounts.views), 11 M media (django_pam.accounts.forms.authenticationform attribute), 9 P PAMBackend (class in django_pam.auth.backends), 13 post() (django_pam.accounts.views.logoutview method), 12 R method), 8 redirect_field_name (django_pam.accounts.views.loginviewtest_post_login_form_invalid_redirection() attribute), 11 redirect_field_name (django_pam.accounts.views.logoutview attribute), 12 test_post_login_form_valid() render_to_json_response() (django_pam.accounts.view_mixins.jsonresponsemixin method), 9 S test_post_logout_form() (django_pam.accounts.tests.test_accounts_views.te setup() (django_pam.accounts.tests.test_accounts_forms.testauthenticationform method), 8 method), 7 test_post_logout_form_invalid() setup() (django_pam.accounts.tests.test_accounts_views.testloginview (django_pam.accounts.tests.test_accounts_views.testlogoutview method), 8 method), 8 setup() (django_pam.accounts.tests.test_accounts_views.testlogoutview test_user_created() (django_pam.accounts.tests.test_accounts_forms.testau method), 8 method), 7 setup() (django_pam.auth.tests.test_auth_backends.testpambackend TestAuthenticationForm method), 12 success_url (django_pam.accounts.views.loginview attribute), 11 success_url (django_pam.accounts.views.logoutview attribute), 12 (class in T template_name (django_pam.accounts.views.loginview attribute), 11 template_name (django_pam.accounts.views.logoutview attribute), 12 test_authenticate_fail() (django_pam.auth.tests.test_auth_backends.testpambackend method), 12 test_authenticate_pass() (django_pam.auth.tests.test_auth_backends.testpambackend method), 12 test_get_login_screen() (django_pam.accounts.tests.test_accounts_views.testloginview method), 8 test_get_logout_screen() (django_pam.accounts.tests.test_accounts_views.t method), 8 test_get_user_invalid() (django_pam.auth.tests.test_auth_backends.testpam method), 12 test_get_user_valid() (django_pam.auth.tests.test_auth_backends.testpamb method), 12 test_invalid_credentials() (django_pam.accounts.tests.test_accounts_forms.testauthenticati method), 7 test_missing_credentials() (django_pam.accounts.tests.test_accounts_forms.testauthenticati method), 7 test_post_login_ajax_invalid() (django_pam.accounts.tests.test_accounts_views.testloginview method), 8 test_post_login_ajax_valid() (django_pam.accounts.tests.test_accounts_views.testloginview method), 8 test_post_login_form_invalid() (django_pam.accounts.tests.test_accounts_views.testloginview (django_pam.accounts.tests.test_accounts_views.testloginview method), 8 (django_pam.accounts.tests.test_accounts_views.testloginview method), 8 test_post_logout_ajax() (django_pam.accounts.tests.test_accounts_views.te method), 8 django_pam.accounts.tests.test_accounts_forms), 7 TestLoginView (class in django_pam.accounts.tests.test_accounts_views), 8 TestLogoutView (class in django_pam.accounts.tests.test_accounts_views), 8 TestPAMBackend (class in django_pam.auth.tests.test_auth_backends), 12 20 Index