Skip to content

Commit

Permalink
Facebook auth working nicely
Browse files Browse the repository at this point in the history
TODO:
-> Allow to log out
-> Create custom login page
-> Be a man
  • Loading branch information
siemanko committed Jan 25, 2013
1 parent cb44cc3 commit 0530c77
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CodeStreak/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@
)

AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile'
#FACEBOOK_REGISTRATION_BACKEND = 'registration.backends.default.DefaultBackend'


CACHES = {
'default': {
Expand Down
13 changes: 13 additions & 0 deletions CodeStreak/static/base/css/cs-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,16 @@ body {
text-shadow: 0 1px 0 #fff;
padding: 10px 10px;
}

.navbar-text img {
max-height:30px;
width:auto;
vertical-align:middle;
border: 1px solid black;
border-radius: 4px;
-moz-border-radius: 4px;
-khtml-border-radius: 4px;
-webkit-border-radius: 4px;
margin-left:5px;
margin-right:5px;
}
48 changes: 48 additions & 0 deletions CodeStreak/static/base/css/facebook.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#facebook_shade {
position : fixed;
height : 100%;
width : 100%;
top : 0px;
left : 0px;
background-color : #222;
opacity : 0.8;
filter : alpha(opacity=80);
-moz-opacity : 0.8;
z-index : 1000;
}

#facebook_lightbox {
position : relative;
width : 300px;
background-color : #fff;
margin : 200px auto;
text-align : center;
padding : 30px 20px;
-moz-box-shadow : 0px 0px 8px #000;
-webkit-box-shadow : 0px 0px 8px #000;
box-shadow : 0px 0px 8px #000;
moz-border-radius : 2px;
border-radius : 2px;
z-index : 1001;
}

#facebook_wrapper {
position : absolute;
top : 0px;
width : 100%;
z-index : 1001;
}

#facebook_loading {
margin-top : 15px;
}

#facebook_close {
position : absolute;
right : 10px;
top : 10px;
width : 16px;
height : 16px;
background : url('../images/facebook_close.png');
cursor : pointer;
}
17 changes: 17 additions & 0 deletions CodeStreak/static/base/js/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
$(document).ready(function(){
$('#facebook-button').button();

$('#facebook-button').click(function() {
$(this).button('loading');
});
});

facebookAppId = '377224379022058';
facebookDefaultScope = ["email", "user_about_me", "user_birthday", "user_website"];
staticUrl = '/static/';
function facebookJSLoaded(){
FB.init({appId: facebookAppId, status: true, cookie: true, xfbml: true, oauth: true});
}
window.fbAsyncInit = facebookJSLoaded;
F = new facebookClass(facebookAppId);
F.load();
158 changes: 158 additions & 0 deletions CodeStreak/static/base/js/facebook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@

/* Ugly as fuck */
facebookDefaultScope = ["email", "user_about_me", "user_birthday", "user_website"]

/*
Maps locale from django to Facebook
scraped like this from FB:
curl https://www.facebook.com/translations/FacebookLocales.xml -s | grep "<representation>" FacebookLocales.xml | sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'
* */
fbLocales = ["af_ZA", "ar_AR", "az_AZ", "be_BY", "bg_BG", "bn_IN", "bs_BA",
"ca_ES", "cs_CZ", "cy_GB", "da_DK", "de_DE", "el_GR", "en_GB", "en_PI",
"en_UD", "en_US", "eo_EO", "es_ES", "es_LA", "et_EE", "eu_ES", "fa_IR",
"fb_LT", "fi_FI", "fo_FO", "fr_CA", "fr_FR", "fy_NL", "ga_IE", "gl_ES",
"he_IL", "hi_IN", "hr_HR", "hu_HU", "hy_AM", "id_ID", "is_IS", "it_IT",
"ja_JP", "ka_GE", "ko_KR", "ku_TR", "la_VA", "lt_LT", "lv_LV", "mk_MK",
"ml_IN", "ms_MY", "nb_NO", "ne_NP", "nl_NL", "nn_NO", "pa_IN", "pl_PL",
"ps_AF", "pt_BR", "pt_PT", "ro_RO", "ru_RU", "sk_SK", "sl_SI", "sq_AL",
"sr_RS", "sv_SE", "sw_KE", "ta_IN", "te_IN", "th_TH", "tl_PH", "tr_TR",
"uk_UA", "vi_VN", "zh_CN", "zh_HK", "zh_TW"];

fbLocaleMapping = {};
for (var i=0; i<fbLocales.length;i++){
var k = fbLocales[i].split("_")[0];
fbLocaleMapping[k] = fbLocales[i];
fbLocaleMapping[fbLocales[i]] = fbLocales[i];
}

/* Define dummy gettext if Django's javascrip_catalog is not being used */
if (typeof gettext != 'function') {
window.gettext = function(text) {
return text;
};
}

facebookClass = function() { this.initialize.apply(this, arguments); };
facebookClass.prototype = {
initialize: function (appId) {
this.appId = appId;

var scope = this;
function javascriptLoaded() {
scope.javascriptLoaded.call(scope);
}

var iphone = navigator.userAgent.match(/iPhone/i)
var ipod = navigator.userAgent.match(/iPod/i);
var ipad = navigator.userAgent.match(/iPad/i);
var ithing = iphone || ipod || ipad;
this.ithing = ithing;
},

getDefaultScope : function() {
var defaultScope;
if (typeof(facebookDefaultScope) != 'undefined') {
defaultScope = facebookDefaultScope;
} else {
defaultScope = ['email', 'user_about_me', 'user_birthday', 'user_website'];
}
return defaultScope;
},

connect: function (formElement, requiredPerms) {
if (this.ithing) {
return formElement.submit();
}
requiredPerms = requiredPerms || this.getDefaultScope();
this.connectLoading(gettext('A Facebook pop-up has opened, please follow the instructions to sign in.'));
var scope = this;
FB.login(function(response) {
if (response.status == 'unknown') {
var errorMessage = gettext('Sorry, we couldn\'t log you in. Please try again.');
scope.connectLoading(errorMessage, true, true);
} else {
//showloading
scope.connectLoading(gettext('Now loading your profile...'));
//submit the form
formElement.submit();
}
},
{scope: requiredPerms.join(',')}
);
},

connectLoading: function (message, closeable, hideLoading) {
/*
* Show a loading lightbox to clarify what's happening to the user
*/
var facebookMessage = document.getElementById('facebook_message');
var facebookContainer = document.getElementById('facebook_container');
if (!facebookMessage) {
var container = document.createElement('div');
container.id = 'facebook_container';
var html = '<div id="facebook_shade"></div>\
<div id="facebook_wrapper">\
<div id="facebook_lightbox">\
<div id="facebook_message" />{{ message }}</div>\
<img id="facebook_loading" src="' + staticUrl + 'images/facebook_loading.gif" alt="..."/>\
<div id="facebook_close" style="display: none" onclick="document.getElementById(\'facebook_container\').style.display=\'none\';"></div>\
</div>\
</div>';
html = html.replace('{{ message }}', message);
container.innerHTML = html;
document.body.appendChild(container);
facebookMessage = document.getElementById('facebook_message');
facebookContainer = document.getElementById('facebook_container');
}
facebookMessage.innerHTML = message;
facebookContainer.style.display = message ? 'block' : 'none';
document.getElementById('facebook_close').style.display = closeable ? 'block' : 'none';
document.getElementById('facebook_loading').style.display = hideLoading ? 'none' : 'inline';

//set the correct top
var requiredTop = this.getViewportScrollY();
document.getElementById('facebook_lightbox').style.top = requiredTop + 'px';
},


load: function () {
var facebookScript = document.getElementById('facebook_js');
if (!facebookScript) {
var e = document.createElement('script');
e.type = 'text/javascript';
// gets the locale, tries to get the facebook synonym and
// the checks if it is a valid FB locale
var fbLocale = "en_US";
if(typeof(locale) != 'undefined') {
if (locale in fbLocaleMapping) {
fbLocale = fbLocaleMapping[locale];
}
}
var fbLocation = '//connect.facebook.net/' + fbLocale + '/all.js';
e.src = document.location.protocol + fbLocation;
e.async = true;
e.id = 'facebook_js';
document.getElementById('fb-root').appendChild(e);
}
},

getViewportScrollY: function() {
var scrollY = 0;
if( document.documentElement && document.documentElement.scrollTop ) {
scrollY = document.documentElement.scrollTop;
}
else if( document.body && document.body.scrollTop ) {
scrollY = document.body.scrollTop;
}
else if( window.pageYOffset ) {
scrollY = window.pageYOffset;
}
else if( window.scrollY ) {
scrollY = window.scrollY;
}
return scrollY;
}
};



5 changes: 5 additions & 0 deletions CodeStreak/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.conf.urls import patterns, include, url

from django.contrib import admin
Expand Down Expand Up @@ -28,5 +29,9 @@
'CodeStreak.contests.views.contest_ranking',
name='contest-ranking'),

url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),

url(r'^pula', 'CodeStreak.contests.views.pula'),
)
40 changes: 37 additions & 3 deletions CodeStreak/xhpy/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from django.conf import settings
from django.contrib import messages
from django.template import Context, loader
from django.template.context import RequestContext
from django_facebook.models import FacebookProfile

from CodeStreak.xhpy.lib import *

Expand All @@ -16,12 +19,14 @@ def render(self):
settings.STATIC_URL + 'css/bootstrap.min.css',
settings.STATIC_URL + 'css/bootstrap-responsive.min.css',
settings.STATIC_URL + 'css/cs-base.css',
settings.STATIC_URL + 'css/facebook.css',
]
js_files = [
settings.STATIC_URL + 'js/jquery-1.9.0.min.js',
settings.STATIC_URL + 'js/bootstrap.min.js',
]

settings.STATIC_URL + 'js/facebook.js',
settings.STATIC_URL + 'js/base.js',
]
# Compose head of page
head = \
<head>
Expand Down Expand Up @@ -49,6 +54,8 @@ def render(self):
{content}
{footer}
</div>
<div id="fb-root">
</div>
</body>

# Add CSS files to header
Expand All @@ -72,15 +79,28 @@ def render(self):


class :cs:header(:x:element):
attribute float end_timestamp
attribute float end_timestamp,
object user
children :cs:header-link*, :cs:header-separator*

def __init__(self, *args, **kwargs):
super(:cs:header, self).__init__(*args, **kwargs)
self.prepended_children = <x:frag />

def render(self):
user = self.getAttribute('user')
end_timestamp = self.getAttribute('end_timestamp')
fb_image = None
user_displayname = None
if user.is_authenticated():
if user.first_name and user.last_name:
user_displayname = user.first_name + ' ' + user.last_name
else:
user_displayname = user.username
fb_user = FacebookProfile.objects.filter(user_id = user.id)
if len(fb_user) > 0 and fb_user[0].image:
fb_image = fb_user[0].image.url

return \
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
Expand All @@ -92,6 +112,20 @@ def render(self):
{self.prepended_children}
{self.getChildren()}
</ul>
{ <div class="navbar-text pull-right">
{user_displayname}
{<img src={fb_image} />
if fb_image else <x:frag />}
</div>
if user.is_authenticated() else
<form action="/facebook/connect/?facebook_login=1" method="post">
<input type="hidden" value="" name="next" />
<button id="facebook-button" type="button" class="btn \
btn-primary pull-right" data-loading-text="Loading..." \
onclick="F.connect(this.parentNode); return false;">
Connect with Facebook
</button>
</form>}
{<div class="navbar-text pull-right">Time left:{' '}
<span id="timeLeft" class={end_timestamp}>
00:00:00
Expand Down

0 comments on commit 0530c77

Please sign in to comment.