From 870c7bc952053263aa2d2a418a3f7b42ad046e57 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Tue, 6 Jan 2015 20:16:48 -0200 Subject: [PATCH 1/6] Various improvements --- .gitignore | 73 +++++++++++++++++++ readme.rst => README.rst | 29 ++++---- django_wordpress_auth/__init__.py | 41 ----------- django_wordpress_auth/middleware.py | 10 --- django_wordpress_auth/router.py | 29 -------- django_wordpress_auth/routers.py | 28 ------- setup.py | 31 ++++++++ wordpress_auth/__init__.py | 7 ++ .../decorators.py | 4 +- wordpress_auth/middleware.py | 8 ++ .../models.py | 19 +++-- wordpress_auth/utils.py | 45 ++++++++++++ .../views.py | 7 +- 13 files changed, 197 insertions(+), 134 deletions(-) create mode 100644 .gitignore rename readme.rst => README.rst (71%) delete mode 100644 django_wordpress_auth/__init__.py delete mode 100644 django_wordpress_auth/middleware.py delete mode 100644 django_wordpress_auth/router.py delete mode 100644 django_wordpress_auth/routers.py create mode 100755 setup.py create mode 100644 wordpress_auth/__init__.py rename {django_wordpress_auth => wordpress_auth}/decorators.py (89%) create mode 100644 wordpress_auth/middleware.py rename {django_wordpress_auth => wordpress_auth}/models.py (86%) create mode 100644 wordpress_auth/utils.py rename {django_wordpress_auth => wordpress_auth}/views.py (69%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc39dbc --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +# Created by https://www.gitignore.io + +### Linux ### +*~ + +# KDE directory preferences +.directory + + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + + +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py + diff --git a/readme.rst b/README.rst similarity index 71% rename from readme.rst rename to README.rst index ff6d798..152048f 100644 --- a/readme.rst +++ b/README.rst @@ -5,7 +5,7 @@ Django Wordpress Auth Introduction ============ -Allows for access in Django to a Wordpress installation for checking for +Allows for access in Django to a WordPress installation for checking for things like login status and roles / capabilities. Requirements @@ -27,14 +27,14 @@ Wordpress Dependencies : Installation ============ -Add your wordpress's auth keys and salts (found in wp-config.php). +Add your WordPress's auth keys and salts (found in wp-config.php) to your settings.py. .. sourcecode:: python - LOGGED_IN_KEY = "rs&^D%jPdu=vk|VVDsdfsdgsdgsdg9sd87f98s7h[Xm$3gT/@1xdasd" - LOGGED_IN_SALT = "3]x^n{d8=su23902iu09jdc09asjd09asjd09jasdV-Lv-OydAQ%?~" + WORDPRESS_LOGGED_IN_KEY = "rs&^D%jPdu=vk|VVDsdfsdgsdgsdg9sd87f98s7h[Xm$3gT/@1xdasd" + WORDPRESS_LOGGED_IN_SALT = "3]x^n{d8=su23902iu09jdc09asjd09asjd09jasdV-Lv-OydAQ%?~" -Add your wordpress database. +Add your WordPress database to DATABASES in settings.py. .. sourcecode:: python @@ -45,15 +45,15 @@ Add your wordpress database. 'wordpress': { # must be named 'wordpress' 'ENGINE': 'django.db.backends.mysql', 'NAME': 'wordpress', - 'USER': 'XXX', - 'PASSWORD': 'XXX', - 'HOST': '', - 'PORT': '', + 'USER': '...', + 'PASSWORD': '...', + 'HOST': '...', + 'PORT': 3306, } } -Add the middleware. Make sure it's placed somewhere after the session -middleware. +Add the middleware to MIDDLEWARE_CLASSES in settings.py. +Make sure it's placed somewhere after the session middleware. .. sourcecode:: python @@ -63,13 +63,13 @@ middleware. 'django_wordpress_auth.middleware.WordpressAuthMiddleware', ) -Finally, add to installed apps. +Finally, add `wordpress_auth` to INSTALLED_APPS. .. sourcecode:: python INSTALLED_APPS = ( # ... - 'django_wordpress_auth', + 'wordpress_auth', ) Usage @@ -96,8 +96,7 @@ You can restrict a view to a capability as well. def my_view(): pass -Finally, the middleware provides access to the wordpress user via -``request.wordpress_user``. +Finally, the middleware provides access to the wordpress user via ``request.wordpress_user``. See ``models.py`` for full reference. Some of the redundant naming conventions in the wordpress database have been made simpler as well. diff --git a/django_wordpress_auth/__init__.py b/django_wordpress_auth/__init__.py deleted file mode 100644 index 6661a47..0000000 --- a/django_wordpress_auth/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -import hmac -import hashlib -import md5 -import urllib2 - -from django.conf import settings -import phpserialize - -from models import WpOptions, WpUsers, WpUsermeta - - -SITE_URL = WpOptions.objects.using('wordpress')\ - .get(option_name='siteurl').option_value -COOKIEHASH = md5.new(SITE_URL).hexdigest() -LOGIN_URL = SITE_URL + "/wp-login.php" - - -def _hmac(salt, data): - return hmac.new(salt, msg=data, digestmod=hashlib.md5).hexdigest() - - -def _generate_auth_cookie(username, password, expires): - expires = str(expires) - wp_salt = settings.LOGGED_IN_KEY + settings.LOGGED_IN_SALT - pass_fragment = password[8:12] - wp_hash = _hmac(wp_salt, username + pass_fragment + "|" + expires) - auth_cookie = _hmac(wp_hash, username + "|" + expires) - return auth_cookie - - -def get_wordpress_user(request): - cookie_key = 'wordpress_logged_in_' + COOKIEHASH - cookie_value = request.COOKIES.get(cookie_key) - if not cookie_value: - return None - username, expires, hmac = urllib2.unquote(cookie_value).split('|') - wp_user = WpUsers.objects.using('wordpress').get(login=username) - if hmac == _generate_auth_cookie(username, wp_user.password, expires): - return wp_user - else: - return None diff --git a/django_wordpress_auth/middleware.py b/django_wordpress_auth/middleware.py deleted file mode 100644 index 34199be..0000000 --- a/django_wordpress_auth/middleware.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.utils.functional import SimpleLazyObject - -from . import get_wordpress_user - - -class WordpressAuthMiddleware(object): - def process_request(self, request): - assert hasattr(request, 'session'), "django-wordpress-auth requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'." - - request.wordpress_user = SimpleLazyObject(lambda: get_wordpress_user(request)) diff --git a/django_wordpress_auth/router.py b/django_wordpress_auth/router.py deleted file mode 100644 index 24eb49e..0000000 --- a/django_wordpress_auth/router.py +++ /dev/null @@ -1,29 +0,0 @@ -# Deprecated, can be removed -import os - -APP_NAME = os.path.basename(os.path.abspath(os.path.join(__file__, os.path.pardir))) - - -class WordpressRouter(object): - - def db_for_read(self, model, **hints): - "Point all operations on wordpress models to 'wordpress'" - if model._meta.app_label == APP_NAME: - return 'wordpress' - return None - - def db_for_write(self, model, **hints): - "Point all operations on wordpress models to 'wordpress'" - if model._meta.app_label == APP_NAME: - return 'wordpress' - return None - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation if a model in wordpress is involved" - if obj1._meta.app_label == APP_NAME or obj2._meta.app_label == APP_NAME: - return True - return None - - def allow_syncdb(self, db, model): - "We don't create the wordpress tables via Django." - return model._meta.app_label != APP_NAME diff --git a/django_wordpress_auth/routers.py b/django_wordpress_auth/routers.py deleted file mode 100644 index 62e5c88..0000000 --- a/django_wordpress_auth/routers.py +++ /dev/null @@ -1,28 +0,0 @@ -import os - -APP_NAME = os.path.basename(os.path.abspath(os.path.join(__file__, os.path.pardir))) - - -class WordpressRouter(object): - - def db_for_read(self, model, **hints): - "Point all operations on wordpress models to 'wordpress'" - if model._meta.app_label == APP_NAME: - return 'wordpress' - return None - - def db_for_write(self, model, **hints): - "Point all operations on wordpress models to 'wordpress'" - if model._meta.app_label == APP_NAME: - return 'wordpress' - return None - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation if a model in wordpress is involved" - if obj1._meta.app_label == APP_NAME or obj2._meta.app_label == APP_NAME: - return True - return None - - def allow_syncdb(self, db, model): - "We don't create the wordpress tables via Django." - return model._meta.app_label != APP_NAME diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..54b4092 --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + +setup( + name='django-wordpress-auth', + version='0.1.0', + description='Django integration with WordPress authentication and roles / capabilities system.', + long_description=open('README.rst').read(), + include_package_data=True, + packages=[ + 'wordpress_auth', + ], + install_requires=[ + 'Django', + 'phpserialize==1.3' + ], + classifiers=[ + 'Environment :: Web Environment', + 'Framework :: Django', + 'Intended Audience :: Developers', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Utilities' + ] +) diff --git a/wordpress_auth/__init__.py b/wordpress_auth/__init__.py new file mode 100644 index 0000000..ae4a369 --- /dev/null +++ b/wordpress_auth/__init__.py @@ -0,0 +1,7 @@ +__version__ = '0.1.0' + +from django.conf import settings + +WORDPRESS_TABLE_PREFIX = getattr(settings, 'WORDPRESS_TABLE_PREFIX', 'wp_') +WORDPRESS_LOGGED_IN_KEY = getattr(settings, 'WORDPRESS_LOGGED_IN_KEY') +WORDPRESS_LOGGED_IN_SALT = getattr(settings, 'WORDPRESS_LOGGED_IN_SALT') diff --git a/django_wordpress_auth/decorators.py b/wordpress_auth/decorators.py similarity index 89% rename from django_wordpress_auth/decorators.py rename to wordpress_auth/decorators.py index 6c5caef..6dd9c1b 100644 --- a/django_wordpress_auth/decorators.py +++ b/wordpress_auth/decorators.py @@ -1,14 +1,14 @@ from django.core.exceptions import PermissionDenied from django.shortcuts import redirect -from . import get_wordpress_user, LOGIN_URL +from wordpress_auth.utils import get_login_url def wordpress_login_required(fn, *args, **kwargs): def wrapped(request, *args, **kwargs): if not request.wordpress_user: redirect_to = request.build_absolute_uri(request.path) - return redirect(LOGIN_URL + "?redirect_to=" + redirect_to) + return redirect(get_login_url() + "?redirect_to=" + redirect_to) else: return fn(request, *args, **kwargs) return wrapped diff --git a/wordpress_auth/middleware.py b/wordpress_auth/middleware.py new file mode 100644 index 0000000..8535420 --- /dev/null +++ b/wordpress_auth/middleware.py @@ -0,0 +1,8 @@ +from django.utils.functional import SimpleLazyObject + +from wordpress_auth.utils import get_wordpress_user + + +class WordPressAuthMiddleware(object): + def process_request(self, request): + request.wordpress_user = SimpleLazyObject(lambda: get_wordpress_user(request)) diff --git a/django_wordpress_auth/models.py b/wordpress_auth/models.py similarity index 86% rename from django_wordpress_auth/models.py rename to wordpress_auth/models.py index a32cde7..3c7c025 100644 --- a/django_wordpress_auth/models.py +++ b/wordpress_auth/models.py @@ -1,6 +1,8 @@ +import phpserialize + from django.db import models -import phpserialize +from wordpress_auth import WORDPRESS_TABLE_PREFIX class WpOptions(models.Model): @@ -10,7 +12,9 @@ class WpOptions(models.Model): autoload = models.CharField(max_length=60) class Meta: - db_table = u'wp_options' + db_table = WORDPRESS_TABLE_PREFIX + 'options' + managed = False + class WpUsermeta(models.Model): umeta_id = models.BigIntegerField(primary_key=True) @@ -19,7 +23,9 @@ class WpUsermeta(models.Model): meta_value = models.TextField(blank=True) class Meta: - db_table = u'wp_usermeta' + db_table = WORDPRESS_TABLE_PREFIX + 'usermeta' + managed = False + class WpUsers(models.Model): # Field name made lowercase. @@ -37,10 +43,11 @@ class WpUsers(models.Model): display_name = models.CharField(max_length=750, db_column='display_name') class Meta: - db_table = u'wp_users' + db_table = WORDPRESS_TABLE_PREFIX + 'users' + managed = False def __str__(self): - return str(self.login) + return self.login @property def roles(self): @@ -54,7 +61,7 @@ def roles(self): def capabilities(self): capabilities = [] roles_data = phpserialize.loads( - WpOptions.objects.using('wordpress')\ + WpOptions.objects.using('wordpress') .get(option_name='wp_user_roles').option_value) for role in self.roles: role_capabilities = roles_data.get(role).get('capabilities') diff --git a/wordpress_auth/utils.py b/wordpress_auth/utils.py new file mode 100644 index 0000000..a672dd8 --- /dev/null +++ b/wordpress_auth/utils.py @@ -0,0 +1,45 @@ +import hmac +import hashlib + +try: + from urllib.parse import urljoin, unquote +except ImportError: + from urlparse import urljoin # Python 2 + from urllib2 import unquote + +from wordpress_auth import WORDPRESS_LOGGED_IN_KEY, WORDPRESS_LOGGED_IN_SALT +from wordpress_auth.models import WpOptions, WpUsers + + +def get_site_url(): + return WpOptions.objects.using('wordpress') \ + .get(option_name='siteurl').option_value + + +def get_login_url(): + return urljoin(get_site_url(), 'wp-login.php') + + +def get_wordpress_user(request): + cookie_hash = hashlib.md5(get_site_url().encode()).hexdigest() + cookie = request.COOKIES.get('wordpress_logged_in_' + cookie_hash) + + if cookie: + username, expires, hmac = unquote(cookie).split('|') + user = WpUsers.objects.using('wordpress').get(login=username) + + if hmac == _generate_auth_cookie(username, user.password, expires): + return user + + +def _hmac(*args, **kwargs): + kwargs['digestmod'] = hashlib.md5 + return hmac.new(*args, **kwargs).hexdigest() + + +def _generate_auth_cookie(username, password, expires): + wp_salt = WORDPRESS_LOGGED_IN_KEY + WORDPRESS_LOGGED_IN_SALT + wp_hash = _hmac(wp_salt, username + password[8:12] + "|" + expires) + cookie = _hmac(wp_hash, username + "|" + expires) + + return cookie diff --git a/django_wordpress_auth/views.py b/wordpress_auth/views.py similarity index 69% rename from django_wordpress_auth/views.py rename to wordpress_auth/views.py index 0ff8dd1..28e7c0a 100644 --- a/django_wordpress_auth/views.py +++ b/wordpress_auth/views.py @@ -1,8 +1,9 @@ from django.http import HttpResponse -from . import get_wordpress_user -from decorators import wordpress_login_required, wordpress_requires_role, \ - wordpress_requires_capability +from wordpress_auth.decorators import ( + wordpress_login_required, wordpress_requires_role, + wordpress_requires_capability +) @wordpress_login_required From 0eb4ed5c35e1f2e44cfe48a3e61624104c47f085 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Tue, 6 Jan 2015 20:29:09 -0200 Subject: [PATCH 2/6] Some adjustments in the README --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 152048f..3da12c0 100644 --- a/README.rst +++ b/README.rst @@ -60,7 +60,7 @@ Make sure it's placed somewhere after the session middleware. MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', # ... - 'django_wordpress_auth.middleware.WordpressAuthMiddleware', + 'wordpress_auth.middleware.WordpressAuthMiddleware', ) Finally, add `wordpress_auth` to INSTALLED_APPS. @@ -96,7 +96,7 @@ You can restrict a view to a capability as well. def my_view(): pass -Finally, the middleware provides access to the wordpress user via ``request.wordpress_user``. +Finally, the middleware provides access to the WordPress user via ``request.wordpress_user``. See ``models.py`` for full reference. Some of the redundant naming conventions -in the wordpress database have been made simpler as well. +in the WordPress database have been made simpler as well. From 97de01650e67b59e217373c3a44014169e482e09 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Tue, 6 Jan 2015 22:01:59 -0200 Subject: [PATCH 3/6] Implementing WordPress untrailingslashit that is applied on the siteurl before calculating the COOKIEHASH --- wordpress_auth/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wordpress_auth/utils.py b/wordpress_auth/utils.py index a672dd8..9ea4f85 100644 --- a/wordpress_auth/utils.py +++ b/wordpress_auth/utils.py @@ -12,9 +12,11 @@ def get_site_url(): - return WpOptions.objects.using('wordpress') \ + url = WpOptions.objects.using('wordpress') \ .get(option_name='siteurl').option_value + return _untrailingslashit(url) + def get_login_url(): return urljoin(get_site_url(), 'wp-login.php') @@ -32,6 +34,10 @@ def get_wordpress_user(request): return user +def _untrailingslashit(str): + return str.rstrip('/\\') + + def _hmac(*args, **kwargs): kwargs['digestmod'] = hashlib.md5 return hmac.new(*args, **kwargs).hexdigest() From bd6a70afe8e0c54392988429e351fde4930a7aa7 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Thu, 8 Jan 2015 20:32:07 -0200 Subject: [PATCH 4/6] Working cookie validation method, yehoo! --- wordpress_auth/models.py | 12 ++++++-- wordpress_auth/utils.py | 60 ++++++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/wordpress_auth/models.py b/wordpress_auth/models.py index 3c7c025..15833fb 100644 --- a/wordpress_auth/models.py +++ b/wordpress_auth/models.py @@ -17,8 +17,9 @@ class Meta: class WpUsermeta(models.Model): - umeta_id = models.BigIntegerField(primary_key=True) - user_id = models.BigIntegerField() + id = models.BigIntegerField(db_column='umeta_id', primary_key=True) + user = models.ForeignKey('wordpress_auth.WpUsers', db_column='user_id', + related_name='meta') meta_key = models.CharField(max_length=765, blank=True) meta_value = models.TextField(blank=True) @@ -69,3 +70,10 @@ def capabilities(self): if enabled: capabilities.append(capability) return set(capabilities) + + def get_session_tokens(self): + """Retrieve all sessions of the user.""" + opt = self.meta.using('wordpress').get(meta_key='session_tokens') \ + .meta_value.encode() + + return phpserialize.loads(opt) diff --git a/wordpress_auth/utils.py b/wordpress_auth/utils.py index 9ea4f85..394f80e 100644 --- a/wordpress_auth/utils.py +++ b/wordpress_auth/utils.py @@ -1,11 +1,11 @@ import hmac import hashlib +from time import time try: - from urllib.parse import urljoin, unquote + from urllib.parse import urljoin except ImportError: from urlparse import urljoin # Python 2 - from urllib2 import unquote from wordpress_auth import WORDPRESS_LOGGED_IN_KEY, WORDPRESS_LOGGED_IN_SALT from wordpress_auth.models import WpOptions, WpUsers @@ -27,25 +27,55 @@ def get_wordpress_user(request): cookie = request.COOKIES.get('wordpress_logged_in_' + cookie_hash) if cookie: - username, expires, hmac = unquote(cookie).split('|') - user = WpUsers.objects.using('wordpress').get(login=username) - - if hmac == _generate_auth_cookie(username, user.password, expires): - return user + return _validate_auth_cookie(cookie) def _untrailingslashit(str): return str.rstrip('/\\') -def _hmac(*args, **kwargs): - kwargs['digestmod'] = hashlib.md5 - return hmac.new(*args, **kwargs).hexdigest() +def _parse_auth_cookie(cookie): + elements = cookie.split('|') + return elements if len(elements) == 4 else None + + +def _validate_auth_cookie(cookie): + cookie_elements = _parse_auth_cookie(cookie) + + if not cookie_elements: + return False + + username, expiration, token, cookie_hmac = cookie_elements + + # Quick check to see if an honest cookie has expired + if float(expiration) < time(): + return False + + # Check if a bad username was entered in the user authentication process + try: + user = WpUsers.objects.using('wordpress').get(login=username) + except WpUsers.DoesNotExist: + return False + + # Check if a bad authentication cookie hash was encountered + pwd_frag = user.password[8:12] + key_salt = WORDPRESS_LOGGED_IN_KEY + WORDPRESS_LOGGED_IN_SALT + key_msg = '{}|{}|{}|{}'.format(username, pwd_frag, expiration, token) + key = hmac.new(key_salt.encode(), key_msg.encode(), digestmod=hashlib.md5) \ + .hexdigest() + + hash_msg = '{}|{}|{}'.format(username, expiration, token) + hash = hmac.new(key.encode(), hash_msg.encode(), digestmod=hashlib.sha256) \ + .hexdigest() + + if hash != cookie_hmac: + return False + # *sigh* we're almost there + # Check if the token is valid for the given user + verifier = hashlib.sha256(token.encode()).hexdigest().encode() -def _generate_auth_cookie(username, password, expires): - wp_salt = WORDPRESS_LOGGED_IN_KEY + WORDPRESS_LOGGED_IN_SALT - wp_hash = _hmac(wp_salt, username + password[8:12] + "|" + expires) - cookie = _hmac(wp_hash, username + "|" + expires) + if verifier not in user.get_session_tokens(): + return False - return cookie + return user From c157aeed68a2078d19717d23dd966e37ae7819a9 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Thu, 8 Jan 2015 20:54:36 -0200 Subject: [PATCH 5/6] Oops, forgot to unquote the cookie value before validation --- wordpress_auth/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wordpress_auth/utils.py b/wordpress_auth/utils.py index 394f80e..57ffaa1 100644 --- a/wordpress_auth/utils.py +++ b/wordpress_auth/utils.py @@ -3,9 +3,10 @@ from time import time try: - from urllib.parse import urljoin + from urllib.parse import urljoin, unquote except ImportError: from urlparse import urljoin # Python 2 + from urllib2 import unquote from wordpress_auth import WORDPRESS_LOGGED_IN_KEY, WORDPRESS_LOGGED_IN_SALT from wordpress_auth.models import WpOptions, WpUsers @@ -27,6 +28,7 @@ def get_wordpress_user(request): cookie = request.COOKIES.get('wordpress_logged_in_' + cookie_hash) if cookie: + cookie = unquote(cookie) return _validate_auth_cookie(cookie) From ed6c0e52eed523881e48ee4201f1535ec9df66e3 Mon Sep 17 00:00:00 2001 From: Rafael Canovas Date: Wed, 14 Jan 2015 16:46:44 -0200 Subject: [PATCH 6/6] Update README.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 3da12c0..38406ed 100644 --- a/README.rst +++ b/README.rst @@ -80,7 +80,7 @@ To restrict a view to a certain role, simply wrap the view in the .. sourcecode:: python - from django_wordpress_auth.decorators import wordpress_requires_role + from wordpress_auth.decorators import wordpress_requires_role @wordpress_requires_role('my_role') def my_view(): @@ -90,7 +90,7 @@ You can restrict a view to a capability as well. .. sourcecode:: python - from django_wordpress_auth.decorators import wordpress_requires_capability + from wordpress_auth.decorators import wordpress_requires_capability @wordpress_requires_capability('my_capability') def my_view():