added facebook auth

This commit is contained in:
JT Smith 2010-08-27 13:03:58 -05:00
parent 4da8638444
commit 61bd01b5f3
10 changed files with 415 additions and 1 deletions

View file

@ -1,4 +1,5 @@
8.0.0
- Replaced the existing caching mechanism with memcached, which results in a 400% improvement to cache speed. See migration.txt for API changes and gotcha.txt for prereq changes.
- Added "hot sessions" so sessions interact with the database less.
- Added Facebook Auth and FacebookLogin macro.

View file

@ -16,6 +16,7 @@ save you many hours of grief.
* WebGUI now requires the following modules
- Moose
- CHI
- Facebook::Graph
7.9.8
--------------------------------------------------------------------

View file

@ -190,7 +190,7 @@
# List the authentication plug-ins you wish to be available on
# this site.
"authMethods" : [ "LDAP", "WebGUI" ],
"authMethods" : [ "LDAP", "WebGUI", "Twitter", "Facebook"],
# List the merchant gateways you have installed and wish to be
# available on this site.
@ -821,6 +821,7 @@
"EditableToggle" : "EditableToggle",
"e" : "e_companyEmail",
"Extras" : "Extras",
"FacebookLogin" : "FacebookLogin",
"FetchMimeType" : "FetchMimeType",
"FilePump" : "FilePump",
"FileUrl" : "FileUrl",

295
lib/WebGUI/Auth/Facebook.pm Normal file
View file

@ -0,0 +1,295 @@
package WebGUI::Auth::Facebook;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2010 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use base 'WebGUI::Auth';
use Facebook::Graph;
=head1 NAME
WebGUI::Auth::Facebook -- Facebook auth for WebGUI
=head1 DESCRIPTION
Allow Facebook users to authenticate to WebGUI
=head1 METHODS
These methods are available from this class:
=cut
#----------------------------------------------------------------------------
=head2 new ( ... )
Create a new object
=cut
sub new {
my $self = shift->SUPER::new(@_);
return bless $self, __PACKAGE__; # Auth requires rebless
}
#----------------------------------------------------------------------------
=head2 createFacebookUser ( fbuser )
my $user = $self->createFacebookUser( $fb->fetch('me') );
Create a new Facebook::Graph user.
=cut
sub createFacebookUser {
my ( $self, $fbuser ) = @_;
my $user = WebGUI::User->create( $self->session );
$user->username( $fbuser->{name} );
$user->profileField('email', $fbuser->{email});
$user->profileField('firstName', $fbuser->{first_name});
$user->profileField('lastName', $fbuser->{last_name});
$self->saveParams( $user->userId, $self->authMethod, {
"facebookUserId" => $fbuser->{id},
} );
return $user;
}
#----------------------------------------------------------------------------
=head2 editUserSettingsForm ( )
Return the form to edit the settings of this Auth module
=cut
sub editUserSettingsForm {
my $self = shift;
my $session = $self->session;
my ( $setting ) = $session->quick(qw( setting ));
my $i18n = WebGUI::International->new( $session, 'Auth_Facebook' );
my $f = WebGUI::HTMLForm->new( $session );
$f->yesNo(
name => 'facebookAuthEnabled',
value => $setting->get( 'facebookAuthEnabled' ),
label => $i18n->get('enabled'),
hoverHelp => $i18n->get('enabled help'),
);
$f->text(
name => 'facebookAuthAppId',
value => $setting->get( 'facebookAuthAppId' ),
label => $i18n->get('app id'),
hoverHelp => $i18n->get('app id help'),
subtext => $i18n->get('get app id'),
);
$f->text(
name => 'facebookAuthSecret',
value => $setting->get( 'facebookAuthSecret' ),
label => $i18n->get('secret'),
hoverHelp => $i18n->get('secret help'),
);
$f->template(
name => 'facebookAuthTemplateIdChooseUsername',
value => $setting->get( 'facebookAuthTemplateIdChooseUsername' ),
label => $i18n->get('choose username template'),
hoverHelp => $i18n->get('choose username template help'),
namespace => 'Auth/Facebook/ChooseUsername',
);
return $f->printRowsOnly;
}
#----------------------------------------------------------------------------
=head2 editUserSettingsFormSave ( )
Process the form for this Auth module's settings
=cut
sub editUserSettingsFormSave {
my $self = shift;
my $session = $self->session;
my ( $form, $setting ) = $session->quick(qw( form setting ));
my @fields = qw(
facebookAuthEnabled facebookAuthAppId facebookAuthSecret
facebookAuthTemplateIdChooseUsername
);
for my $field ( @fields ) {
$setting->set( $field, $form->get( $field ) );
}
return;
}
#----------------------------------------------------------------------------
=head2 getTemplateChooseUsername ( )
Get the template to choose a username
=cut
sub getTemplateChooseUsername {
my ( $self ) = @_;
my $templateId = $self->session->setting->get('facebookAuthTemplateIdChooseUsername');
return WebGUI::Asset->newById( $self->session, $templateId );
}
#----------------------------------------------------------------------------
=head2 getFacebook ( )
Get the Facebook::Graph object with the appropriate keys
=cut
sub getFacebook {
my ( $self ) = @_;
my ( $url, $scratch, $setting ) = $self->session->quick( qw( url scratch setting ) );
if ( !$self->{_fb} ) {
my $fb = Facebook::Graph->new(
app_id => $setting->get( 'facebookAuthAppId' ),
secret => $setting->get( 'facebookAuthSecret' ),
postback => $url->getSiteURL . $url->page('op=auth&authType=Facebook&method=callback'),
);
if ($scratch->get('facebookAuthAccessToken')) {
$fb->access_token($scratch->get('facebookAuthAccessToken'));
}
$self->{_fb} = $fb;
}
return $self->{_fb};
}
#----------------------------------------------------------------------------
=head2 www_login ( )
Begin the login procedure
=cut
sub www_login {
my ( $self ) = @_;
my $session = $self->session;
my ( $url, $scratch, $setting ) = $session->quick( qw( url scratch setting ) );
my $auth_url = $self->getFacebook
->authorize
->extend_permissions(qw(email))
->uri_as_string;
$session->http->setRedirect($auth_url);
return "redirect";
}
#----------------------------------------------------------------------------
=head2 www_callback ( )
Callback from the Facebook authentication. Try to log the user in, creating a
new user account if necessary.
If the username is taken, allow the user to choose a new one.
=cut
sub www_callback {
my ( $self ) = @_;
my $session = $self->session;
my ( $form, $scratch, $db, $setting ) = $session->quick(qw( form scratch db setting ));
# handle facebook stuff
my $fb = $self->getFacebook;
$fb->request_access_token($form->get('code'));
$scratch->set('facebookAuthAccessToken', $fb->access_token);
my $fbuser = $fb->fetch('me');
### Log the user in
# Find their FB user ID
my $userId = $db->quickScalar(
"SELECT userId FROM authentication WHERE authMethod = ? AND fieldName = ? AND fieldData = ?",
[ "Facebook", "facebookUserId", $fbuser->{id} ],
);
# Returning user
if ( $userId ) {
my $user = WebGUI::User->new( $session, $userId );
$self->user( $user );
return $self->login;
}
# Otherwise see if their screen name exists and create a user
elsif ( !WebGUI::User->newByUsername( $session, $fbuser->{name}) ) {
my $user = $self->createFacebookUser( $fbuser );
$self->user( $user );
return $self->login;
}
# Otherwise ask them for a new username to use
my $i18n = WebGUI::International->new( $session, 'Auth_Facebook' );
my $tmpl = $self->getTemplateChooseUsername;
my $var = {
message => sprintf( $i18n->get("username taken"), $fbuser->{name} ),
};
return $tmpl->process( $var );
}
#----------------------------------------------------------------------------
=head2 www_setUsername ( )
Set the username for a fb user. Only used as part of the initial fb
registration.
=cut
sub www_setUsername {
my ( $self ) = @_;
my $session = $self->session;
my ( $form, $scratch, $db ) = $session->quick(qw( form scratch db ));
my $i18n = WebGUI::International->new( $session, 'Auth_Facebook' );
# Don't allow just anybody to set a username
my $fb = $self->getFacebook;
return if $fb->access_token eq '';
my $fbuser = $fb->fetch('me');
$fbuser->{name} = $form->get('newUsername');
if ( !WebGUI::User->newByUsername( $session, $fbuser->{name} ) ) {
my $user = $self->createFacebookUser( $fbuser );
$self->user( $user );
return $self->login;
}
# Username is again taken! Noooooo!
my $tmpl = $self->getTemplateChooseUsername;
my $var = {
message => sprintf( $i18n->get("username taken"), $fbuser->{name} ),
};
return $tmpl->process( $var );
}
1;

View file

@ -0,0 +1,37 @@
package WebGUI::Macro::FacebookLogin;
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2010 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use strict;
=head1 NAME
Package WebGUI::Macro::FacebookLogin
=head1 DESCRIPTION
Works with the Facebook Auth plugin to allow users to log in using facebook.
=cut
#-------------------------------------------------------------------
sub process {
my $session = shift;
my $url = $session->url;
return sprintf '<a href="%s"><img src="%s" alt="login with Facebook" /></a>',
$url->page('op=auth;authType=Facebook;method=login'),
$url->extras('macro/FacebookLogin/login-button.png');
}
1;
#vim:ft=perl

View file

@ -0,0 +1,74 @@
package WebGUI::i18n::English::Auth_Facebook;
use strict;
our $I18N = {
'enabled' => {
message => q{Enabled},
lastUpdated => 0,
context => q{Label for auth setting field},
},
'enabled help' => {
message => q{Enabled Facebook-based login},
lastUpdated => 0,
context => q{Hover help for auth setting field},
},
'get app id' => {
message => q{Get a Facebook App Id from <a href="http://apps.facebook.com/developer">http://apps.facebook.com/developer</a>},
lastUpdated => 0,
context => q{Link to get a Facebook App Id},
},
'app id' => {
message => q{Application Id},
lastUpdated => 0,
context => q{Label for auth setting field},
},
'app id help' => {
message => q{The Application ID from your Facebook application settings},
lastUpdated => 0,
context => q{Hover help for auth setting field},
},
'secret' => {
message => q{Application Secret},
lastUpdated => 0,
context => q{Label for auth setting field},
},
'secret help' => {
message => q{The Facebook Application Secret from your application settings},
lastUpdated => 0,
context => q{Hover help for auth setting field},
},
'choose username title' => {
message => q{Choose a Username},
lastUpdated => 0,
context => q{Title for screen to choose a username},
},
'username taken' => {
message => q{That username "%s" is taken. Please choose a new username.},
lastUpdated => 0,
context => q{An error message for the choose a username screen},
},
'choose username template' => {
message => q{Choose Username Template},
lastUpdated => 0,
context => q{Label for auth setting field},
},
'choose username template help' => {
message => q{The template to choose a username if the user's screen name already exists},
lastUpdated => 0,
context => q{Hover help for auth setting field},
},
};
1;
#vim:ft=perl

View file

@ -157,6 +157,7 @@ checkModule('HTTP::Exception', );
checkModule('Net::Twitter', "3.13006" );
checkModule('Number::Format', );
checkModule('Email::Valid', );
checkModule('Facebook::Graph', '0.0505' );
failAndExit("Required modules are missing, running no more checks.") if $missingModule;

View file

@ -0,0 +1,4 @@
insert into settings values ('facebookAuthEnabled',0);
insert into settings values ('facebookAuthAppId','');
insert into settings values ('facebookAuthSecret','');
insert into settings values ('facebookAuthTemplateIdChooseUsername','anlFXped9lqXPThZTdFX0A');

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB