diff options
-rwxr-xr-x | django_authopenid/urls.py | 2 | ||||
-rwxr-xr-x | fbconnect/__init__.py | 0 | ||||
-rwxr-xr-x | fbconnect/fb.py | 70 | ||||
-rwxr-xr-x | fbconnect/forms.py | 8 | ||||
-rwxr-xr-x | fbconnect/models.py | 6 | ||||
-rwxr-xr-x | fbconnect/tests.py | 23 | ||||
-rwxr-xr-x | fbconnect/urls.py | 11 | ||||
-rwxr-xr-x | fbconnect/views.py | 63 | ||||
-rw-r--r-- | forum/urls.py | 1 | ||||
-rw-r--r-- | settings.py | 143 | ||||
-rw-r--r-- | settings_local.py.dist | 1 | ||||
-rw-r--r-- | templates/authopenid/complete.html | 8 | ||||
-rwxr-xr-x | templates/authopenid/signin.html | 2 | ||||
-rwxr-xr-x | templates/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 |