├── .gitignore ├── COPYING ├── README.rst ├── debug_toolbar_user_panel ├── __init__.py ├── decorators.py ├── forms.py ├── models.py ├── panels.py ├── templates │ └── debug_toolbar_user_panel │ │ ├── content.html │ │ └── panel.html ├── urls.py └── views.py ├── docs ├── Makefile ├── conf.py ├── index.rst ├── playfire.png └── screenshot.png └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | docs/_build 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright © 2010, 2011 UUMC Ltd. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | django-debug-toolbar-user-panel 2 | =============================== 3 | 4 | Documentation: http://code.playfire.com/django-debug-toolbar-user-panel/ 5 | 6 | .. figure:: http://code.playfire.com/django-debug-toolbar-user-panel/_images/screenshot.png 7 | :align: center 8 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playfire/django-debug-toolbar-user-panel/29a163dc985c4b173ead57b09b3cfdd6ca84e76f/debug_toolbar_user_panel/__init__.py -------------------------------------------------------------------------------- /debug_toolbar_user_panel/decorators.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | from django.conf import settings 4 | from django.http import HttpResponseForbidden 5 | 6 | def debug_required(fn): 7 | @functools.wraps(fn) 8 | def wrapper(*args, **kwargs): 9 | if not getattr(settings, 'DEBUG_TOOLBAR_USER_DEBUG', settings.DEBUG): 10 | return HttpResponseForbidden() 11 | return fn(*args, **kwargs) 12 | return wrapper 13 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | 3 | from django import forms 4 | 5 | class UserForm(forms.Form): 6 | val = forms.CharField(label='User.{id,username,email}') 7 | 8 | def get_lookup(self): 9 | val = self.cleaned_data['val'] 10 | 11 | if '@' in val: 12 | return {'email': val} 13 | 14 | try: 15 | return {'pk': int(val)} 16 | except: 17 | return {'username': val} 18 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/models.py: -------------------------------------------------------------------------------- 1 | import debug_toolbar.urls 2 | 3 | try: 4 | from django.conf.urls import patterns, include 5 | except ImportError: 6 | from django.conf.urls.defaults import patterns, include 7 | 8 | from .urls import urlpatterns 9 | 10 | debug_toolbar.urls.urlpatterns += patterns('', 11 | ('', include(urlpatterns)), 12 | ) 13 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/panels.py: -------------------------------------------------------------------------------- 1 | """ 2 | :mod:`django-debug-toolbar-user-panel` 3 | ====================================== 4 | 5 | Panel for the `Django Debug Toolbar `_ 6 | to easily and quickly switch between users. 7 | 8 | * View details on the currently logged in user. 9 | * Login as any user from an arbitrary email address, username or user ID. 10 | * Easily switch between recently logged in users. 11 | 12 | .. figure:: screenshot.png 13 | :align: center 14 | 15 | The panel supports ``django.contrib.auth.models.User`` models that have had 16 | the `username` field removed. 17 | 18 | Installation 19 | ------------ 20 | 21 | Add ``debug_toolbar_user_panel`` to your ``INSTALLED_APPS``:: 22 | 23 | INSTALLED_APPS = ( 24 | ... 25 | 'debug_toolbar_user_panel', 26 | ... 27 | ) 28 | 29 | Add ``debug_toolbar_user_panel.panels.UserPanel`` to ``DEBUG_TOOLBAR_PANELS``:: 30 | 31 | DEBUG_TOOLBAR_PANELS = ( 32 | 'debug_toolbar_user_panel.panels.UserPanel' 33 | 'debug_toolbar.panels.version.VersionDebugPanel', 34 | 'debug_toolbar.panels.timer.TimerDebugPanel', 35 | 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', 36 | 'debug_toolbar.panels.headers.HeaderDebugPanel', 37 | 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', 38 | 'debug_toolbar.panels.sql.SQLDebugPanel', 39 | 'debug_toolbar.panels.template.TemplateDebugPanel', 40 | 'debug_toolbar.panels.signals.SignalDebugPanel', 41 | 'debug_toolbar.panels.logger.LoggingPanel', 42 | ) 43 | 44 | Include ``debug_toolbar_user_panel.urls`` somewhere in your ``urls.py``:: 45 | 46 | urlpatterns = patterns('', 47 | ... 48 | url(r'', include('debug_toolbar_user_panel.urls')), 49 | ... 50 | ) 51 | 52 | Links 53 | ----- 54 | 55 | View/download code 56 | https://github.com/playfire/django-debug-toolbar-user-panel 57 | 58 | File a bug 59 | https://github.com/playfire/django-debug-toolbar-user-panel/issues 60 | """ 61 | 62 | from django.template.loader import render_to_string 63 | from django.utils.translation import ugettext_lazy as _ 64 | 65 | from debug_toolbar.panels import DebugPanel 66 | 67 | class UserPanel(DebugPanel): 68 | """ 69 | Panel that allows you to login as other recently-logged in users. 70 | """ 71 | 72 | name = 'User' 73 | has_content = True 74 | 75 | def nav_title(self): 76 | return _('User') 77 | 78 | def url(self): 79 | return '' 80 | 81 | def title(self): 82 | return _('User') 83 | 84 | def nav_subtitle(self): 85 | return self.request.user.is_authenticated() and self.request.user 86 | 87 | def content(self): 88 | context = self.context.copy() 89 | context.update({ 90 | 'request': self.request, 91 | }) 92 | 93 | return render_to_string('debug_toolbar_user_panel/panel.html', context) 94 | 95 | def process_response(self, request, response): 96 | self.request = request 97 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/templates/debug_toolbar_user_panel/content.html: -------------------------------------------------------------------------------- 1 | {% load url from future %} 2 | 3 |

Current user

4 | 5 | {% if user.is_authenticated %} 6 | 7 | {% for x,y in current %}{% endfor %} 8 | {% for x,y in current %}{% endfor %} 9 |
{{ x }}
{{ y }}
10 | {% else %} 11 |

Not logged in.

12 | {% endif %} 13 | 14 |

Recent users

15 | 16 |
    17 | {% for user in users %} 18 |
  • 19 |
    20 | {% csrf_token %} 21 | {% if next %} 22 | 23 | {% endif %} 24 | 25 |
    26 |
  • 27 | {% endfor %} 28 |
29 | 30 |

Login as any user

31 | 32 |
33 | {{ form.as_p }} 34 | 35 |
36 | 37 |
38 | 39 |
40 | 41 |
42 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/templates/debug_toolbar_user_panel/panel.html: -------------------------------------------------------------------------------- 1 | {% load url from future %} 2 | 3 | 32 | 33 | 52 | 53 |
54 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/urls.py: -------------------------------------------------------------------------------- 1 | try: 2 | from django.conf.urls import patterns, url 3 | except ImportError: 4 | from django.conf.urls.defaults import patterns, url 5 | 6 | from debug_toolbar.urls import _PREFIX 7 | 8 | urlpatterns = patterns('debug_toolbar_user_panel.views', 9 | url(r'^%s/users/$' % _PREFIX, 'content', 10 | name='debug-userpanel'), 11 | url(r'^%s/users/login/$' % _PREFIX, 'login_form', 12 | name='debug-userpanel-login-form'), 13 | url(r'^%s/users/login/(?P-?\d+)$' % _PREFIX, 'login', 14 | name='debug-userpanel-login'), 15 | url(r'^%s/users/logout$' % _PREFIX, 'logout', 16 | name='debug-userpanel-logout'), 17 | ) 18 | -------------------------------------------------------------------------------- /debug_toolbar_user_panel/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponseRedirect, HttpResponseBadRequest 2 | from django.conf import settings 3 | from django.contrib import auth 4 | from django.template import RequestContext 5 | from django.shortcuts import render_to_response, get_object_or_404 6 | from django.contrib.auth import logout as django_logout 7 | from django.contrib.auth.models import User 8 | from django.views.decorators.csrf import csrf_exempt 9 | from django.views.decorators.http import require_POST 10 | 11 | from .forms import UserForm 12 | from .decorators import debug_required 13 | 14 | @debug_required 15 | def content(request): 16 | current = [] 17 | 18 | if request.user.is_authenticated(): 19 | for field in User._meta.fields: 20 | if field.name == 'password': 21 | continue 22 | current.append( 23 | (field.attname, getattr(request.user, field.attname)) 24 | ) 25 | 26 | return render_to_response('debug_toolbar_user_panel/content.html', { 27 | 'form': UserForm(), 28 | 'next': request.GET.get('next'), 29 | 'users': User.objects.order_by('-last_login')[:10], 30 | 'current': current, 31 | }, context_instance=RequestContext(request)) 32 | 33 | @csrf_exempt 34 | @require_POST 35 | @debug_required 36 | def login_form(request): 37 | form = UserForm(request.POST) 38 | 39 | if not form.is_valid(): 40 | return HttpResponseBadRequest() 41 | 42 | return login(request, **form.get_lookup()) 43 | 44 | @csrf_exempt 45 | @require_POST 46 | @debug_required 47 | def login(request, **kwargs): 48 | user = get_object_or_404(User, **kwargs) 49 | 50 | user.backend = settings.AUTHENTICATION_BACKENDS[0] 51 | auth.login(request, user) 52 | 53 | return HttpResponseRedirect(request.POST.get('next', '/')) 54 | 55 | @csrf_exempt 56 | @require_POST 57 | @debug_required 58 | def logout(request): 59 | django_logout(request) 60 | return HttpResponseRedirect(request.POST.get('next', '/')) 61 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " pickle to make pickle files" 22 | @echo " json to make JSON files" 23 | @echo " htmlhelp to make HTML files and a HTML help project" 24 | @echo " qthelp to make HTML files and a qthelp project" 25 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 26 | @echo " changes to make an overview of all changed/added/deprecated items" 27 | @echo " linkcheck to check all external links for integrity" 28 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 29 | 30 | clean: 31 | -rm -rf $(BUILDDIR)/* 32 | 33 | html: 34 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 35 | @echo 36 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 37 | 38 | dirhtml: 39 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 40 | @echo 41 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 42 | 43 | pickle: 44 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 45 | @echo 46 | @echo "Build finished; now you can process the pickle files." 47 | 48 | json: 49 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 50 | @echo 51 | @echo "Build finished; now you can process the JSON files." 52 | 53 | htmlhelp: 54 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 55 | @echo 56 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 57 | ".hhp project file in $(BUILDDIR)/htmlhelp." 58 | 59 | latex: 60 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 61 | @echo 62 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 63 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 64 | "run these through (pdf)latex." 65 | 66 | changes: 67 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 68 | @echo 69 | @echo "The overview file is in $(BUILDDIR)/changes." 70 | 71 | linkcheck: 72 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 73 | @echo 74 | @echo "Link check complete; look for any errors in the above output " \ 75 | "or in $(BUILDDIR)/linkcheck/output.txt." 76 | 77 | doctest: 78 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 79 | @echo "Testing of doctests in the sources finished, look at the " \ 80 | "results in $(BUILDDIR)/doctest/output.txt." 81 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | project = 'django-debug-toolbar-user-panel' 2 | version = '' 3 | release = '' 4 | copyright = '2010, 2011 UUMC Ltd.' 5 | 6 | html_logo = 'playfire.png' 7 | html_theme = 'nature' 8 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] 9 | html_title = "%s documentation" % project 10 | master_doc = 'index' 11 | exclude_trees = ['_build'] 12 | templates_path = ['_templates'] 13 | latex_documents = [ 14 | ('index', '%s.tex' % project, html_title, u'Playfire', 'manual'), 15 | ] 16 | intersphinx_mapping = {'http://docs.python.org/': None} 17 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: debug_toolbar_user_panel.panels 2 | -------------------------------------------------------------------------------- /docs/playfire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playfire/django-debug-toolbar-user-panel/29a163dc985c4b173ead57b09b3cfdd6ca84e76f/docs/playfire.png -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playfire/django-debug-toolbar-user-panel/29a163dc985c4b173ead57b09b3cfdd6ca84e76f/docs/screenshot.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup( 6 | name='django-debug-toolbar-user-panel', 7 | description="Panel for the Django Debug toolbar to quickly switch between " 8 | "users.", 9 | version='0.1', 10 | url='http://code.playfire.com/', 11 | 12 | author='Playfire.com', 13 | author_email='tech@playfire.com', 14 | license='BSD', 15 | 16 | packages=( 17 | 'debug_toolbar_user_panel', 18 | ), 19 | package_data={'': [ 20 | 'templates/debug_toolbar_user_panel/*', 21 | ]}, 22 | ) 23 | --------------------------------------------------------------------------------