summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xdjango_authopenid/urls.py2
-rwxr-xr-xfbconnect/__init__.py0
-rwxr-xr-xfbconnect/fb.py70
-rwxr-xr-xfbconnect/forms.py8
-rwxr-xr-xfbconnect/models.py6
-rwxr-xr-xfbconnect/tests.py23
-rwxr-xr-xfbconnect/urls.py11
-rwxr-xr-xfbconnect/views.py63
-rw-r--r--forum/urls.py1
-rw-r--r--settings.py143
-rw-r--r--settings_local.py.dist1
-rw-r--r--templates/authopenid/complete.html8
-rwxr-xr-xtemplates/authopenid/signin.html2
-rwxr-xr-xtemplates/fbconnect/xd_receiver.html (renamed from templates/xd_receiver.html)0
14 files changed, 263 insertions, 75 deletions
diff --git a/django_authopenid/urls.py b/django_authopenid/urls.py
index 6a4e9b0f..9ed621bc 100755
--- a/django_authopenid/urls.py
+++ b/django_authopenid/urls.py
@@ -1,14 +1,12 @@
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import patterns, url
from django.utils.translation import ugettext as _
-from django.views.generic.simple import direct_to_template
urlpatterns = patterns('django_authopenid.views',
# yadis rdf
url(r'^yadis.xrdf$', 'xrdf', name='yadis_xrdf'),
# manage account registration
url(r'^%s$' % _('signin/'), 'signin', name='user_signin'),
- url(r'^xd_receiver$', direct_to_template, {'template': 'xd_receiver.html'}, name='xd_receiver'),
url(r'^%s%s$' % (_('signin/'),_('newquestion/')), 'signin', kwargs = {'newquestion':True}, name='user_signin_new_question'),
url(r'^%s%s$' % (_('signin/'),_('newanswer/')), 'signin', kwargs = {'newanswer':True}, name='user_signin_new_answer'),
url(r'^%s$' % _('signout/'), 'signout', name='user_signout'),
diff --git a/fbconnect/__init__.py b/fbconnect/__init__.py
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/fbconnect/__init__.py
diff --git a/fbconnect/fb.py b/fbconnect/fb.py
new file mode 100755
index 00000000..7aeda131
--- /dev/null
+++ b/fbconnect/fb.py
@@ -0,0 +1,70 @@
+from django.conf import settings
+from time import time
+from datetime import datetime
+from urllib import urlopen, urlencode
+from json import load as load_json
+import md5
+import logging
+
+REST_SERVER = 'http://api.facebook.com/restserver.php'
+
+def generate_sig(values):
+ keys = []
+
+ for key in sorted(values.keys()):
+ keys.append(key)
+
+ signature = ''.join(['%s=%s' % (key, values[key]) for key in keys]) + settings.FB_SECRET
+ return md5.new(signature).hexdigest()
+
+def check_cookies_signature(cookies):
+ API_KEY = settings.FB_API_KEY
+
+ values = {}
+
+ for key in cookies.keys():
+ if (key.startswith(API_KEY + '_')):
+ values[key.replace(API_KEY + '_', '')] = cookies[key]
+
+ return generate_sig(values) == cookies[API_KEY]
+
+def get_user_data(cookies):
+ request_data = {
+ 'method': 'Users.getInfo',
+ 'api_key': settings.FB_API_KEY,
+ 'call_id': time(),
+ 'v': '1.0',
+ 'uids': cookies[settings.FB_API_KEY + '_user'],
+ 'fields': 'name,first_name,last_name',
+ 'format': 'json',
+ }
+
+ request_data['sig'] = generate_sig(request_data)
+ fb_response = load_json(urlopen(REST_SERVER, urlencode(request_data)))
+ return fb_response[0]
+
+
+def delete_cookies():
+ API_KEY = settings.FB_API_KEY
+
+ response.delete_cookie(API_KEY + '_user')
+ response.delete_cookie(API_KEY + '_session_key')
+ response.delete_cookie(API_KEY + '_expires')
+ response.delete_cookie(API_KEY + '_ss')
+ response.delete_cookie(API_KEY)
+ response.delete_cookie('fbsetting_' + API_KEY)
+
+def check_session_expiry(cookies):
+ return datetime.fromtimestamp(float(cookies[settings.FB_API_KEY+'_expires'])) > datetime.now()
+
+STATES = {
+ 'FIRSTTIMER': 1,
+ 'SESSIONEXPIRED': 2,
+}
+
+def get_user_state(request):
+ if settings.FB_API_KEY in request.COOKIES:
+ if check_cookies_signature(request.COOKIES):
+ if check_session_expiry(request.COOKIES):
+ return STATES['FIRSTTIMER']
+
diff --git a/fbconnect/forms.py b/fbconnect/forms.py
new file mode 100755
index 00000000..94f86816
--- /dev/null
+++ b/fbconnect/forms.py
@@ -0,0 +1,8 @@
+from django_authopenid.forms import NextUrlField, UserNameField, UserEmailField
+
+from django import forms
+
+class FBConnectRegisterForm(forms.Form):
+ next = NextUrlField()
+ username = UserNameField()
+ email = UserEmailField()
diff --git a/fbconnect/models.py b/fbconnect/models.py
new file mode 100755
index 00000000..33a723e8
--- /dev/null
+++ b/fbconnect/models.py
@@ -0,0 +1,6 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+class FBAssociation(models.Model):
+ user = models.ForeignKey(User)
+ fbuid = models.TextField(max_length=12)
diff --git a/fbconnect/tests.py b/fbconnect/tests.py
new file mode 100755
index 00000000..a6f218a9
--- /dev/null
+++ b/fbconnect/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/fbconnect/urls.py b/fbconnect/urls.py
new file mode 100755
index 00000000..e4048151
--- /dev/null
+++ b/fbconnect/urls.py
@@ -0,0 +1,11 @@
+from django.conf.urls.defaults import *
+from django.utils.translation import ugettext as _
+from django.views.generic.simple import direct_to_template
+from views import signin, register
+
+urlpatterns = patterns('',
+ url(r'^xd_receiver$', direct_to_template, {'template': 'fbconnect/xd_receiver.html'}, name='xd_receiver'),
+ url(r'^%s' % _('signin/'), signin, name="fb_signin"),
+ url(r'^%s' % _('register/'), register, name="fb_user_register"),
+
+)
diff --git a/fbconnect/views.py b/fbconnect/views.py
new file mode 100755
index 00000000..2acb1dc0
--- /dev/null
+++ b/fbconnect/views.py
@@ -0,0 +1,63 @@
+from django.shortcuts import render_to_response as render
+from django.template import RequestContext
+from django.http import HttpResponseRedirect
+from django.utils.safestring import mark_safe
+from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
+from django.contrib.auth import login
+from models import FBAssociation
+from forum.forms import EditUserEmailFeedsForm
+from django.conf import settings
+
+import fb
+import forms
+
+import logging
+
+def signin(request):
+ user_state = fb.get_user_state(request)
+
+ if user_state == fb.STATES['FIRSTTIMER']:
+ return HttpResponseRedirect(reverse('fb_user_register'))
+
+ return HttpResponseRedirect('/')
+
+def register(request):
+ if fb.get_user_state(request) == fb.STATES['FIRSTTIMER']:
+ user_data = fb.get_user_data(request.COOKIES)
+
+ if 'bnewaccount' in request.POST.keys():
+ form1 = forms.FBConnectRegisterForm(request.POST)
+ email_feeds_form = EditUserEmailFeedsForm(request.POST)
+
+ if (form1.is_valid() and email_feeds_form.is_valid()):
+ tmp_pwd = User.objects.make_random_password()
+ user_ = User.objects.create_user(form1.cleaned_data['username'],
+ form1.cleaned_data['email'], tmp_pwd)
+
+ user_.set_unusable_password()
+
+ uassoc = FBAssociation(user=user_, fbuid=user_data['uid'])
+ uassoc.save()
+
+ user_.backend = "django.contrib.auth.backends.ModelBackend"
+ login(request, user_)
+ email_feeds_form.save(user_)
+
+ return HttpResponseRedirect('/')
+ else:
+ form1 = forms.FBConnectRegisterForm(initial={
+ 'next': '/',
+ 'username': user_data['name'],
+ 'email': '',
+ })
+
+ email_feeds_form = EditUserEmailFeedsForm()
+
+ return render('authopenid/complete.html', {
+ 'form1': form1,
+ 'email_feeds_form': email_feeds_form,
+ 'provider':mark_safe('facebook'),
+ 'login_type':'facebook',
+ 'gravatar_faq_url':reverse('faq') + '#gravatar',
+ }, context_instance=RequestContext(request))
diff --git a/forum/urls.py b/forum/urls.py
index 62e70161..f7d6eba5 100644
--- a/forum/urls.py
+++ b/forum/urls.py
@@ -86,6 +86,7 @@ urlpatterns = patterns('',
url(r'^%s(?P<short_name>[^/]+)/$' % _('books/'), app.book, name='book'),
url(r'^%s$' % _('search/'), app.search, name='search'),
url(r'^%s$' % _('feedback/'), app.feedback, name='feedback'),
+ (r'^%sfb/' % _('account/'), include('fbconnect.urls')),
(r'^%s' % _('account/'), include('django_authopenid.urls')),
(r'^i18n/', include('django.conf.urls.i18n')),
)
diff --git a/settings.py b/settings.py
index 5cc06b78..e2e97cb1 100644
--- a/settings.py
+++ b/settings.py
@@ -1,71 +1,72 @@
-# encoding:utf-8
-# Django settings for lanai project.
-import os.path
-import sys
-
-SITE_ID = 1
-
-ADMIN_MEDIA_PREFIX = '/forum/admin/media/'
-SECRET_KEY = '$oo^&_m&qwbib=(_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm'
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.load_template_source',
- 'django.template.loaders.app_directories.load_template_source',
-# 'django.template.loaders.eggs.load_template_source',
-)
-
-MIDDLEWARE_CLASSES = (
- 'django.middleware.gzip.GZipMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- #'django.middleware.locale.LocaleMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.middleware.transaction.TransactionMiddleware',
- #'django.middleware.sqlprint.SqlPrintingMiddleware',
- 'middleware.anon_user.ConnectToSessionMessagesMiddleware',
- 'middleware.pagesize.QuestionsPageSizeMiddleware',
- 'middleware.cancel.CancelActionMiddleware',
- 'debug_toolbar.middleware.DebugToolbarMiddleware',
-)
-
-TEMPLATE_CONTEXT_PROCESSORS = (
- 'django.core.context_processors.request',
- 'context.application_settings',
- #'django.core.context_processors.i18n',
- 'user_messages.context_processors.user_messages',#must be before auth
- 'django.core.context_processors.auth', #this is required for admin
-)
-
-ROOT_URLCONF = 'urls'
-
-TEMPLATE_DIRS = (
- os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
-)
-
-#UPLOAD SETTINGS
-FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/')
-FILE_UPLOAD_HANDLERS = ("django.core.files.uploadhandler.MemoryFileUploadHandler",
- "django.core.files.uploadhandler.TemporaryFileUploadHandler",)
-DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
-# for user upload
-ALLOW_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
-# unit byte
-ALLOW_MAX_FILE_SIZE = 1024 * 1024
-
-INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- 'django.contrib.admin',
- 'django.contrib.humanize',
- 'django.contrib.sitemaps',
- 'forum',
- 'django_authopenid',
- #'djangosphinx',
- 'debug_toolbar' ,
- 'user_messages',
-)
-
-# User settings
-from settings_local import *
+# encoding:utf-8
+# Django settings for lanai project.
+import os.path
+import sys
+
+SITE_ID = 1
+
+ADMIN_MEDIA_PREFIX = '/forum/admin/media/'
+SECRET_KEY = '$oo^&_m&qwbib=(_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm'
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.gzip.GZipMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ #'django.middleware.locale.LocaleMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.middleware.transaction.TransactionMiddleware',
+ #'django.middleware.sqlprint.SqlPrintingMiddleware',
+ 'middleware.anon_user.ConnectToSessionMessagesMiddleware',
+ 'middleware.pagesize.QuestionsPageSizeMiddleware',
+ 'middleware.cancel.CancelActionMiddleware',
+ 'debug_toolbar.middleware.DebugToolbarMiddleware',
+)
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+ 'django.core.context_processors.request',
+ 'context.application_settings',
+ #'django.core.context_processors.i18n',
+ 'user_messages.context_processors.user_messages',#must be before auth
+ 'django.core.context_processors.auth', #this is required for admin
+)
+
+ROOT_URLCONF = 'urls'
+
+TEMPLATE_DIRS = (
+ os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
+)
+
+#UPLOAD SETTINGS
+FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/')
+FILE_UPLOAD_HANDLERS = ("django.core.files.uploadhandler.MemoryFileUploadHandler",
+ "django.core.files.uploadhandler.TemporaryFileUploadHandler",)
+DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
+# for user upload
+ALLOW_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
+# unit byte
+ALLOW_MAX_FILE_SIZE = 1024 * 1024
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.admin',
+ 'django.contrib.humanize',
+ 'django.contrib.sitemaps',
+ 'forum',
+ 'django_authopenid',
+ #'djangosphinx',
+ 'debug_toolbar' ,
+ 'user_messages',
+ 'fbconnect',
+)
+
+# User settings
+from settings_local import *
diff --git a/settings_local.py.dist b/settings_local.py.dist
index 8d645025..55028ba2 100644
--- a/settings_local.py.dist
+++ b/settings_local.py.dist
@@ -89,3 +89,4 @@ SPHINX_PORT=3312
#Facebook settings
FB_API_KEY='' #your api key from facebook
+FB_SECRET='' #your application secret
diff --git a/templates/authopenid/complete.html b/templates/authopenid/complete.html
index ce5fb7fe..efed74c7 100644
--- a/templates/authopenid/complete.html
+++ b/templates/authopenid/complete.html
@@ -34,6 +34,8 @@ parameters:
{% else %}
{% blocktrans %}register new external {{provider}} account info, see {{gravatar_faq_url}}{% endblocktrans %}
{% endif %}
+ {% else %}
+ {% blocktrans %}register new Facebook connect account info, see {{gravatar_faq_url}}{% endblocktrans %}
{% endifequal %}
{% endifequal %}
</div>
@@ -69,7 +71,11 @@ parameters:
{% ifequal login_type 'openid' %}
<form name="fregister" action="{% url user_register %}" method="POST">
{% else %}
- <form name="fregister" action="{% url user_signin %}" method="POST">
+ {% ifequal login_type 'facebook' %}
+ <form name="fregister" action="{% url fb_user_register %}" method="POST">
+ {% else %}
+ <form name="fregister" action="{% url user_signin %}" method="POST">
+ {% endifequal %}
{% endifequal %}
{{ form1.next }}
<div class="form-row-vertical">
diff --git a/templates/authopenid/signin.html b/templates/authopenid/signin.html
index 3a12f1c6..da1e5491 100755
--- a/templates/authopenid/signin.html
+++ b/templates/authopenid/signin.html
@@ -64,7 +64,7 @@
</div>
</li>
<li title="Facebook Connect">
- <fb:login-button onlogin="window.location.reload(true)"></fb:login-button>
+ <fb:login-button onlogin="window.location = '{% url fb_signin %}'"></fb:login-button>
</li>
</ul>
<ul class="providers">
diff --git a/templates/xd_receiver.html b/templates/fbconnect/xd_receiver.html
index c67c57b7..c67c57b7 100755
--- a/templates/xd_receiver.html
+++ b/templates/fbconnect/xd_receiver.html