mlanthaler: Implemented OpenIDAuthenticatedRole so that the OpenID credentials are now stored in a specific column (gsoc ticket #4). In that way member system is will remain extensible (no restriction due to not support multiple-inheritance).

The role is applied automatically when the OpenIDAuthenticator is registered. 
(merged from branches/gsoc)


git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@41911 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2007-09-15 20:00:00 +00:00
parent 6b378430f4
commit d6ddbf2cff
6 changed files with 234 additions and 32 deletions

View File

@ -76,8 +76,13 @@ abstract class Authenticator extends Object
if(is_subclass_of($authenticator, 'Authenticator') == false)
return false;
if(in_array($authenticator, self::$authenticators) == false)
array_push(self::$authenticators, $authenticator);
if(in_array($authenticator, self::$authenticators) == false) {
if(call_user_func(array($authenticator, 'onRegister')) === true) {
array_push(self::$authenticators, $authenticator);
} else {
return false;
}
}
return true;
}
@ -92,6 +97,23 @@ abstract class Authenticator extends Object
public static function getAuthenticators() {
return self::$authenticators;
}
/**
* Callback function that is called when the authenticator is registered
*
* Use this method for initialization of a newly registered authenticator.
* Just overload this method and it will be called when the authenticator
* is registered.
* <b>If the method returns FALSE, the authenticator won't be
* registered!</b>
*
* @return bool Returns TRUE on success, FALSE otherwise.
*/
protected static function onRegister() {
return true;
}
}
?>

View File

@ -36,7 +36,7 @@ class MemberAuthenticator extends Authenticator {
Session::clear("BackURL");
} else if(!is_null($form)) {
$form->sessionMessage(
"That doesn't seem to be the right email address or password. Please try again.",
"That doesn't seem to be the right e-mail address or password. Please try again.",
"bad");
}
@ -63,7 +63,7 @@ class MemberAuthenticator extends Authenticator {
* @return string Returns the name of the authentication method.
*/
public static function getName() {
return "Email &amp; Password";
return "E-mail &amp; Password";
}
}

View File

@ -53,7 +53,7 @@ class MemberLoginForm extends LoginForm {
$fields = new FieldSet(
new HiddenField("AuthenticationMethod", null,
$this->authenticator_class, $this),
new TextField("Email", "Email address",
new TextField("Email", "E-mail address",
Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
new EncryptField("Password", "Password", null, $this),
new CheckboxField("Remember", "Remember me next time?",
@ -114,7 +114,9 @@ class MemberLoginForm extends LoginForm {
if($badLoginURL = Session::get("BadLoginURL")) {
Director::redirect($badLoginURL);
} else {
Director::redirectBack();
// Show the right tab on failed login
Director::redirect(Director::absoluteURL(Security::Link("login")) .
'#' . $this->FormName() .'_tab');
}
}
}
@ -178,7 +180,7 @@ class MemberLoginForm extends LoginForm {
} else if($data['Email']) {
$this->sessionMessage(
"Sorry, but I don't recognise the email address. Maybe you need to sign up, or perhaps you used another email address?",
"Sorry, but I don't recognise the e-mail address. Maybe you need to sign up, or perhaps you used another e-mail address?",
"bad");
Director::redirectBack();

View File

@ -0,0 +1,143 @@
<?php
/**
* OpenID authentication decorator
*
* @author Markus Lanthaler <markus@silverstripe.com>
*/
/**
* Decorator for the member class to support OpenID authentication
*
* This class adds the needed fields to the default member class to support
* authentication via OpenID.
*
* @author Markus Lanthaler <markus@silverstripe.com
*/
class OpenIDAuthenticatedRole extends DataObjectDecorator{
/**
* Edit the given query object to support queries for this extension
*/
function augmentSQL(SQLQuery &$query) {
}
/**
* Update the database schema as required by this extension
*/
function augmentDatabase() {
/* if(Permission::check('ADMIN')) {
$exist = DB::query( "SHOW TABLES LIKE 'ForumMember'" )->numRecords();
if($exist > 0) {
DB::query( "UPDATE `Member`, `ForumMember` " .
"SET `Member`.`ClassName` = 'Member'," . "`Member`.`ForumRank` =
`ForumMember`.`ForumRank`," . "`Member`.`Occupation` =
`ForumMember`.`Occupation`," . "`Member`.`Country` =
`ForumMember`.`Country`," . "`Member`.`Nickname` =
`ForumMember`.`Nickname`," . "`Member`.`FirstNamePublic` =
`ForumMember`.`FirstNamePublic`," . "`Member`.`SurnamePublic` =
`ForumMember`.`SurnamePublic`," . "`Member`.`OccupationPublic` =
`ForumMember`.`OccupationPublic`," . "`Member`.`CountryPublic` =
`ForumMember`.`CountryPublic`," . "`Member`.`EmailPublic` =
`ForumMember`.`EmailPublic`," . "`Member`.`AvatarID` =
`ForumMember`.`AvatarID`," . "`Member`.`LastViewed` =
`ForumMember`.`LastViewed`" . "WHERE `Member`.`ID` =
`ForumMember`.`ID`"
);
echo( "<div style=\"padding:5px; color:white;
background-color:blue;\">The data transfer has succeeded. However,
to complete it, you must delete the ForumMember table. To do this,
execute the query \"DROP TABLE 'ForumMember'\".</div>" );
}
}*/
}
/**
* Define extra database fields
*
* Returns a map where the keys are db, has_one, etc, and the values are
* additional fields/relations to be defined
*
* @return array Returns a map where the keys are db, has_one, etc, and
* the values are additional fields/relations to be defined
*/
function extraDBFields() {
return array(
'db' => array('IdentityURL' => 'Varchar(255)'),
'has_one' => array(),
'defaults' => array('IdentityURL' => null),
'indexes' => array('IdentityURL', 'unique (IdentityURL)')
);
}
/**
* Change the member dialog in the CMS
*
* This method updates the form in the member dialog to make it possible
* to edit the new database fields.
*/
function updateCMSFields(FieldSet &$fields) {
//if(Permission::checkMember($this->owner->ID, "ACCESS_FORUM")) {
$fields->push(new HeaderField("OpenID/i-name credentials"), "OpenIDHeader");
$fields->push(new LiteralField("OpenIDDescription",
"<p>Make sure you enter your normalized OpenID/i-name credentials here, i.e. with protocol and trailing slash for OpenID (e.g. http://openid.silverstripe.com/).</p>"));
$fields->push(new TextField("IdentityURL", "OpenID URL/i-name"), "IdentityURL");
/*
$fields->push(new PasswordField("ConfirmPassword", "Confirm Password"));
$fields->push(new ImageField("Avatar", "Upload avatar"));
$fields->push(new DropdownField("ForumRank", "User rating",
array("Community Member" => "Community Member",
"Administrator" => "Administrator",
"Moderator" => "Moderator",
"SilverStripe User" => "SilverStripe User",
"SilverStripe Developer" => "SilverStripe Developer",
"Core Development Team" => "Core Development Team",
"Google Summer of Code Hacker" => "Google Summer of Code Hacker",
"Lead Developer" => "Lead Developer")
)
);
}*/
}
/**
* Can the current user edit the given member?
*
* Only the user itself or an administrator can edit an user account.
*
* @return bool Returns TRUE if this member can be edited, FALSE otherwise
*/
function canEdit() {
if($this->owner->ID == Member::currentUserID())
return true;
$member = Member::currentUser();
if($member)
return $member->isAdmin();
return false;
}
/**
* Factory method for the member validator
*
* @return Member_Validator Returns an instance of a
* {@link Member_Validator} object.
*/
function getValidator() {
die('<p style="color: red;">Called getValidator()</p>');
return new Member_Validator();
}
}
?>

View File

@ -39,13 +39,30 @@ require_once "Auth/OpenID/SReg.php";
*/
class OpenIDAuthenticator extends Authenticator {
/**
* Callback function that is called when the authenticator is registered
*
* Use this method for initialization of a newly registered authenticator.
* Just overload this method and it will be called when the authenticator
* is registered.
* <b>If the method returns FALSE, the authenticator won't be
* registered!</b>
*
* @return bool Returns TRUE on success, FALSE otherwise.
*/
protected static function onRegister() {
Member::addRole('OpenIDAuthenticatedRole');
return true;
}
/**
* Method to authenticate an user
*
* @param array $RAW_data Raw data to authenticate the user
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @return bool Returns FALSE if authentication fails, otherwise the
* method will not return at all because the browser will be
* redirected to some other server.
@ -54,7 +71,16 @@ class OpenIDAuthenticator extends Authenticator {
* (without rendering a form and using javascript)
*/
public function authenticate(array $RAW_data, Form $form = null) {
$openid = $RAW_data['OpenIDURL'];
$openid = trim($RAW_data['OpenIDURL']);
if(strlen($openid) == 0) {
if(!is_null($form)) {
$form->sessionMessage("Please enter your OpenID URL or your i-name.",
"bad");
}
return false;
}
$trust_root = Director::absoluteBaseURL();
$return_to_url = $trust_root . 'OpenIDAuthenticator_Controller';
@ -74,8 +100,9 @@ class OpenIDAuthenticator extends Authenticator {
return false;
}
$SQL_user = Convert::raw2sql($auth_request->endpoint->claimed_id);
if(!($member = DataObject::get_one("Member", "Email = '$SQL_user'"))) {
$SQL_identity = Convert::raw2sql($auth_request->endpoint->claimed_id);
if(!($member = DataObject::get_one("Member",
"Member.IdentityURL = '$SQL_identity'"))) {
if(!is_null($form)) {
$form->sessionMessage("Either your account is not enabled for " .
"OpenID/i-name authentication " .
@ -89,10 +116,12 @@ class OpenIDAuthenticator extends Authenticator {
if($auth_request->shouldSendRedirect()) {
// For OpenID 1, send a redirect.
$redirect_url = $auth_request->redirectURL($trust_root, $return_to_url);
$redirect_url = $auth_request->redirectURL($trust_root,
$return_to_url);
if(Auth_OpenID::isFailure($redirect_url)) {
displayError("Could not redirect to server: " . $redirect_url->message);
displayError("Could not redirect to server: " .
$redirect_url->message);
} else {
Director::redirect($redirect_url);
}
@ -102,16 +131,19 @@ class OpenIDAuthenticator extends Authenticator {
// server.
$form_id = 'openid_message';
$form_html = $auth_request->formMarkup($trust_root, $return_to_url,
false, array('id' => $form_id));
false,
array('id' => $form_id));
if(Auth_OpenID::isFailure($form_html)) {
displayError("Could not redirect to server: " . $form_html->message);
displayError("Could not redirect to server: " .
$form_html->message);
} else {
$page_contents = array(
"<html><head><title>",
"OpenID transaction in progress",
"</title></head>",
"<body onload='document.getElementById(\"".$form_id."\").submit()'>",
"<body onload='document.getElementById(\"". $form_id .
"\").submit()'>",
$form_html,
"<p>Click &quot;Continue&quot; to login. You are only seeing " .
"this because you appear to have JavaScript disabled.</p>",
@ -129,8 +161,8 @@ class OpenIDAuthenticator extends Authenticator {
/**
* Method that creates the login form for this authentication method
*
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @return Form Returns the login form to use with this authentication
* method
*/
@ -139,12 +171,12 @@ class OpenIDAuthenticator extends Authenticator {
}
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
public static function getName() {
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
public static function getName() {
return "OpenID/i-name";
}
}
@ -202,10 +234,9 @@ class OpenIDAuthenticator_Controller extends Controller {
} else if($response->status == Auth_OpenID_SUCCESS) {
$openid = $response->identity_url;
$user = $openid;
if($response->endpoint->canonicalID) {
$user = $response->endpoint->canonicalID;
$openid = $response->endpoint->canonicalID;
}
@ -213,10 +244,12 @@ class OpenIDAuthenticator_Controller extends Controller {
Profiler::unmark("OpenIDAuthenticator_Controller");
$SQL_user = Convert::raw2sql($user);
if($member = DataObject::get_one("Member", "Email = '$SQL_user'")) {
$SQL_identity = Convert::raw2sql($openid);
if($member = DataObject::get_one("Member",
"Member.IdentityURL = '$SQL_identity'")) {
$firstname = Convert::raw2xml($member->FirstName);
Session::set("Security.Message.message", "Welcome Back, {$firstname}");
Session::set("Security.Message.message",
"Welcome Back, {$firstname}");
Session::set("Security.Message.type", "good");
$member->LogIn(

View File

@ -111,7 +111,9 @@ class OpenIDLoginForm extends LoginForm {
if($badLoginURL = Session::get("BadLoginURL")){
Director::redirect($badLoginURL);
} else {
Director::redirectBack();
// Show the right tab on failed login
Director::redirect(Director::absoluteURL(Security::Link("login")) .
'#' . $this->FormName() .'_tab');
}
}