Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for additional SSO parameters + documentation. #51

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion disqus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import urllib2

from django.core.management.base import CommandError
from django.utils import simplejson as json
try:
import json
except ImportError:
from django.utils import simplejson as json
from django.conf import settings

def call(method, data, post=False):
Expand Down
5 changes: 4 additions & 1 deletion disqus/management/commands/disqus_dumpdata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from optparse import make_option

from django.core.management.base import NoArgsCommand, CommandError
from django.utils import simplejson as json
try:
import json
except ImportError:
from django.utils import simplejson as json

from disqus.api import DisqusClient

Expand Down
1 change: 0 additions & 1 deletion disqus/management/commands/disqus_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from django.contrib import comments
from django.contrib.sites.models import Site
from django.core.management.base import NoArgsCommand
from django.utils import simplejson as json

from disqus.api import DisqusClient

Expand Down
15 changes: 15 additions & 0 deletions disqus/templates/disqus/sso.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script type="text/javascript">
var disqus_config = function() {
this.page.remote_auth_s3 = '{{ message }} {{ hmac }} {{ timestamp }}';
this.page.api_key = '{{ public_api_key }}';

this.sso = {
name: '{{ shortname }}',
button: '{{ button_url }}',
url: '{{ login_url }}',
logout: '{{ logout_url }}',
width: '{{ login_width }}',
height: '{{ login_height }}'
};
}
</script>
84 changes: 53 additions & 31 deletions disqus/templatetags/disqus_tags.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,69 @@
import base64
import hashlib
import hmac
import simplejson
try:
import json
except ImportError:
from django.utils import simplejson as json
import time

from django import template
from django.conf import settings
from django.contrib.sites.models import Site
from django.utils.functional import curry
from django.utils.encoding import force_unicode

register = template.Library()


# Set the disqus_developer variable to 0/1. Default is 0
@register.simple_tag(takes_context=True)
def set_disqus_developer(context, disqus_developer):
context['disqus_developer'] = disqus_developer
return ""


# Set the disqus_identifier variable to some unique value. Defaults to page's URL
@register.simple_tag(takes_context=True)
def set_disqus_identifier(context, *args):
context['disqus_identifier'] = "".join(args)
return ""


# Set the disqus_url variable to some value. Defaults to page's location
@register.simple_tag(takes_context=True)
def set_disqus_url(context, *args):
context['disqus_url'] = "".join(args)
return ""


# Set the disqus_title variable to some value. Defaults to page's title or URL
@register.simple_tag(takes_context=True)
def set_disqus_title(context, disqus_title):
context['disqus_title'] = disqus_title
return ""


# Set the disqus_category_id variable to some value. No default. See
# http://help.disqus.com/customer/portal/articles/472098-javascript-configuration-variables#disqus_category_id
@register.simple_tag(takes_context=True)
def set_disqus_category_id(context, disqus_category_id):
context['disqus_category_id'] = disqus_category_id
return ""


def get_config(context):
"""
return the formatted javascript for any disqus config variables
"""
conf_vars = ['disqus_developer', 'disqus_identifier', 'disqus_url',
'disqus_title', 'disqus_category_id']
'disqus_title', 'disqus_category_id']

output = []
for item in conf_vars:
if item in context:
output.append('\tvar %s = "%s";' % (item, context[item]))
return '\n'.join(output)


@register.simple_tag(takes_context=True)
def disqus_dev(context):
"""
Expand All @@ -69,11 +77,11 @@ def disqus_dev(context):
</script>""" % (Site.objects.get_current().domain, context['request'].path)
return ""

@register.simple_tag(takes_context=True)
def disqus_sso(context):
@register.inclusion_tag('disqus/sso.html', takes_context=True)
def disqus_sso(context, shortname='', login_url=None, logout_url=None, button_url=None, login_width=None, login_height=None):
"""
Return the HTML/js code to enable DISQUS SSO - so logged in users on
your site can be logged in to disqus seemlessly.
your site can be logged in to disqus seamlessly.
"""
# we have to make it str rather than unicode or the HMAC blows up
DISQUS_SECRET_KEY = str(getattr(settings, 'DISQUS_SECRET_KEY', None))
Expand All @@ -82,34 +90,46 @@ def disqus_sso(context):
DISQUS_PUBLIC_KEY = getattr(settings, 'DISQUS_PUBLIC_KEY', None)
if DISQUS_PUBLIC_KEY is None:
return "<p>You need to set DISQUS_PUBLIC_KEY before you can use SSO</p>"

shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)
login_url = login_url if login_url else getattr(settings, 'LOGIN_URL', None)
logout_url = logout_url if logout_url else getattr(settings, 'LOGOUT_URL', None)
button_url = button_url if button_url else getattr(settings, 'DISQUS_LOGIN_BUTTON', None)
login_width = login_width if login_width else getattr(settings, 'DISQUS_LOGIN_WINDOW_WIDTH', None)
login_height = login_height if login_height else getattr(settings, 'DISQUS_LOGIN_WINDOW_HEIGHT', None)

user = context['user']

if user.is_anonymous():
return ""
# create a JSON packet of our data attributes
data = simplejson.dumps({
'id': user.id,
'username': user.username,
'email': user.email,
})
# use empty JSON object as per disqus SSO guide
data = json.dumps({})
else:
# create a JSON packet of our data attributes
data = json.dumps({
'id': user.id,
'username': user.username,
'email': user.email,
})
# encode the data to base64
message = base64.b64encode(data)
# generate a timestamp for signing the message
timestamp = int(time.time())
# generate our hmac signature
sig = hmac.HMAC(DISQUS_SECRET_KEY, '%s %s' % (message, timestamp), hashlib.sha1).hexdigest()

# return a script tag to insert the sso message
return """<script type="text/javascript">
var disqus_config = function() {
this.page.remote_auth_s3 = "%(message)s %(sig)s %(timestamp)s";
this.page.api_key = "%(pub_key)s";
}
</script>""" % dict(
message=message,
timestamp=timestamp,
sig=sig,
pub_key=DISQUS_PUBLIC_KEY,
)

return {
'shortname': shortname,
'config': get_config(context),
'message': message,
'hmac': sig,
'timestamp': timestamp,
'public_api_key': DISQUS_PUBLIC_KEY,
'button_url': button_url,
'login_url': login_url,
'logout_url': logout_url,
'login_width': login_width,
'login_height': login_height,
}

@register.inclusion_tag('disqus/num_replies.html', takes_context=True)
def disqus_num_replies(context, shortname=''):
Expand All @@ -118,20 +138,22 @@ def disqus_num_replies(context, shortname=''):
#disqus_thread anchor into the threads comment count.
"""
shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)

return {
'shortname': shortname,
'config': get_config(context),
}


@register.inclusion_tag('disqus/recent_comments.html', takes_context=True)
def disqus_recent_comments(context, shortname='', num_items=5, excerpt_length=200, hide_avatars=0, avatar_size=32):
def disqus_recent_comments(context, shortname='', num_items=5,
excerpt_length=200, hide_avatars=0, avatar_size=32):
"""
Return the HTML/js code which shows recent comments.

"""
shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)

return {
'shortname': shortname,
'num_items': num_items,
Expand Down
52 changes: 52 additions & 0 deletions docs/templatetags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,58 @@ Result::
- ``shortname``: DISQUS website shortname that should be used. The
``settings.DISQUS_WEBSITE_SHORTNAME`` setting takes precedence
over this parameter. Example: ``{% disqus_show_comments "foobar" %}``

.. _disqus_sso:

disqus_sso
--------------------

Renders the ``disqus/sso.html`` template to render a disqus SSO config block.
Values for ``settings.DISQUS_SECRET_KEY`` and ``settings.DISQUS_PUBLIC_KEY`` must
be defined. See the
`embed code <https://help.disqus.com/customer/portal/articles/236206>`_ for
more information.

Example::

{% load disqus_tags %}
{% disqus_sso %}

Result::

<script type="text/javascript">
var disqus_config = function () {
this.page.remote_auth_s3 = '<message> <hmac> <timestamp>';
this.page.api_key = 'public_api_key';

this.sso = {
name: 'shortname',
button: 'http://example.com/images/samplenews.gif',
icon: 'http://example.com/favicon.png',
url: 'http://example.com/login/',
logout: 'http://example.com/logout/',
width: '800',
height: '400'
};
};
</script>

**Options**:

- ``shortname``: DISQUS website shortname that should be used. The
``settings.DISQUS_WEBSITE_SHORTNAME`` setting takes precedence
over this parameter.
- ``login_url``: Address of the login page. The page will be opened in a new window and it
must close itself after authentication is done. That's how disqus will know it is done and
reload the page. Will default to ``settings.LOGIN_URL`` if not specified.
- ``logout_url``: Address of the logout page. This page must redirect user back to the original
page after logout. Will default to ``settings.LOGOUT_URL`` if not specified.
- ``button_url``: Address of the image that acts as a button. Refer to disqus documentation
for style guide. Will default to ``settings.DISQUS_LOGIN_BUTTON`` if not specified.
- ``login_width``: Width of the login popup window.
Will default to ``settings.DISQUS_LOGIN_WINDOW_WIDTH`` if not specified.
- ``login_height``: Height of the login popup window.
Will default to ``settings.DISQUS_LOGIN_WINDOW_HEIGHT`` if not specified.

.. _disqus_recent_comments:

Expand Down