mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
mlanthaler:OpenID authentication works now. To use it simple create an user account without password and put your *complete* OpenID identifier in the email field, e.g. "http://markus-lanthaler.myopenid.com/".
You can get a free OpenID from http://www.myopenid.com (merged from branches/gsoc) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@41785 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
b0e9e89aad
commit
fbc375a282
@ -7,9 +7,9 @@
|
|||||||
* section of an application.
|
* section of an application.
|
||||||
*
|
*
|
||||||
* On its own, content controller does very little. Its constructor is passed a {@link DataObject}
|
* On its own, content controller does very little. Its constructor is passed a {@link DataObject}
|
||||||
* which is stored in $this->dataRecord. Any unrecognised method calls, for example, Title()
|
* which is stored in $this->dataRecord. Any unrecognised method calls, for example, Title()
|
||||||
* and Content(), will be passed along to the data record,
|
* and Content(), will be passed along to the data record,
|
||||||
*
|
*
|
||||||
* Subclasses of ContentController are generally instantiated by ModelAsController; this will create
|
* Subclasses of ContentController are generally instantiated by ModelAsController; this will create
|
||||||
* a controller based on the URLSegment action variable, by looking in the SiteTree table.
|
* a controller based on the URLSegment action variable, by looking in the SiteTree table.
|
||||||
*/
|
*/
|
||||||
@ -26,7 +26,7 @@ class ContentController extends Controller {
|
|||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Link($action = null) {
|
public function Link($action = null) {
|
||||||
return Director::baseURL() . $this->RelativeLink($action);
|
return Director::baseURL() . $this->RelativeLink($action);
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ class ContentController extends Controller {
|
|||||||
|
|
||||||
if($this->URLSegment){
|
if($this->URLSegment){
|
||||||
if($action == "index") $action = "";
|
if($action == "index") $action = "";
|
||||||
|
|
||||||
// '&' in a URL is apparently naughty
|
// '&' in a URL is apparently naughty
|
||||||
$action = preg_replace('/&/', '&', $action);
|
$action = preg_replace('/&/', '&', $action);
|
||||||
return $this->URLSegment . "/$action";
|
return $this->URLSegment . "/$action";
|
||||||
@ -42,10 +42,10 @@ class ContentController extends Controller {
|
|||||||
user_error("ContentController::RelativeLink() No URLSegment given on a '$this->class' object. Perhaps you should overload it?", E_USER_WARNING);
|
user_error("ContentController::RelativeLink() No URLSegment given on a '$this->class' object. Perhaps you should overload it?", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------------//
|
||||||
// These flexible data methods remove the need for custom code to do simple stuff
|
// These flexible data methods remove the need for custom code to do simple stuff
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the children of the given page.
|
* Return the children of the given page.
|
||||||
* $parentRef can be a page number or a URLSegment
|
* $parentRef can be a page number or a URLSegment
|
||||||
@ -62,12 +62,12 @@ class ContentController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Page($url) {
|
public function Page($url) {
|
||||||
$SQL_url = Convert::raw2sql($url);
|
$SQL_url = Convert::raw2sql($url);
|
||||||
return DataObject::get_one('SiteTree', "URLSegment = '$SQL_url'");
|
return DataObject::get_one('SiteTree', "URLSegment = '$SQL_url'");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init() {
|
public function init() {
|
||||||
parent::init();
|
parent::init();
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ class ContentController extends Controller {
|
|||||||
singleton('SiteTree')->extend('contentcontrollerInit', $this);
|
singleton('SiteTree')->extend('contentcontrollerInit', $this);
|
||||||
|
|
||||||
Director::set_site_mode('site');
|
Director::set_site_mode('site');
|
||||||
|
|
||||||
// Check permissions
|
// Check permissions
|
||||||
if($this->dataRecord && !$this->dataRecord->can('View')) Security::permissionFailure($this);
|
if($this->dataRecord && !$this->dataRecord->can('View')) Security::permissionFailure($this);
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ class ContentController extends Controller {
|
|||||||
Requirements::themedCSS("typography");
|
Requirements::themedCSS("typography");
|
||||||
Requirements::themedCSS("form");
|
Requirements::themedCSS("form");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the project name
|
* Get the project name
|
||||||
*
|
*
|
||||||
@ -109,9 +109,9 @@ class ContentController extends Controller {
|
|||||||
public function data() {
|
public function data() {
|
||||||
return $this->dataRecord;
|
return $this->dataRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a fixed navigation menu of the given level.
|
* Returns a fixed navigation menu of the given level.
|
||||||
*/
|
*/
|
||||||
@ -147,7 +147,7 @@ class ContentController extends Controller {
|
|||||||
* Returns the page in the current page stack of the given level.
|
* Returns the page in the current page stack of the given level.
|
||||||
* Level(1) will return the main menu item that we're currently inside, etc.
|
* Level(1) will return the main menu item that we're currently inside, etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function Level($level) {
|
public function Level($level) {
|
||||||
$parent = $this->data();
|
$parent = $this->data();
|
||||||
$stack = array($parent);
|
$stack = array($parent);
|
||||||
@ -157,25 +157,28 @@ class ContentController extends Controller {
|
|||||||
|
|
||||||
return isset($stack[$level-1]) ? $stack[$level-1] : null;
|
return isset($stack[$level-1]) ? $stack[$level-1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Menu($level) {
|
public function Menu($level) {
|
||||||
return $this->getMenu($level);
|
return $this->getMenu($level);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Section2() {
|
public function Section2() {
|
||||||
return $this->Level(2)->URLSegment;
|
return $this->Level(2)->URLSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default log-in form.
|
* Returns the default log-in form.
|
||||||
*/
|
*
|
||||||
|
* @todo Check if here should be returned just the default log-in form or
|
||||||
|
* all available log-in forms (also OpenID...)
|
||||||
|
*/
|
||||||
public function LoginForm() {
|
public function LoginForm() {
|
||||||
return Object::create('LoginForm', $this, "LoginForm");
|
return MemberAuthenticator::getLoginForm($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SilverStripeNavigator() {
|
public function SilverStripeNavigator() {
|
||||||
$member = Member::currentUser();
|
$member = Member::currentUser();
|
||||||
|
|
||||||
if(Director::isDev() || ($member && $member->isCMSUser())) {
|
if(Director::isDev() || ($member && $member->isCMSUser())) {
|
||||||
Requirements::css('sapphire/css/SilverStripeNavigator.css');
|
Requirements::css('sapphire/css/SilverStripeNavigator.css');
|
||||||
|
|
||||||
@ -188,8 +191,8 @@ class ContentController extends Controller {
|
|||||||
var w = window.open(this.href,windowName(this.target));
|
var w = window.open(this.href,windowName(this.target));
|
||||||
w.focus();
|
w.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function windowName(suffix) {
|
function windowName(suffix) {
|
||||||
@ -213,9 +216,9 @@ JS
|
|||||||
$thisPage = $this->Link();
|
$thisPage = $this->Link();
|
||||||
$cmsLink = '';
|
$cmsLink = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$archiveLink = "";
|
$archiveLink = "";
|
||||||
|
|
||||||
if($date = Versioned::current_archived_date()) {
|
if($date = Versioned::current_archived_date()) {
|
||||||
$dateObj = Object::create('Datetime', $date, null);
|
$dateObj = Object::create('Datetime', $date, null);
|
||||||
// $dateObj->setVal($date);
|
// $dateObj->setVal($date);
|
||||||
@ -224,7 +227,7 @@ JS
|
|||||||
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
||||||
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
||||||
$message = "<div id=\"SilverStripeNavigatorMessage\">Archived site from<br>" . $dateObj->Nice() . "</div>";
|
$message = "<div id=\"SilverStripeNavigatorMessage\">Archived site from<br>" . $dateObj->Nice() . "</div>";
|
||||||
|
|
||||||
} else if(Versioned::current_stage() == 'Stage') {
|
} else if(Versioned::current_stage() == 'Stage') {
|
||||||
$stageLink = "<a class=\"current\">Draft Site</a>";
|
$stageLink = "<a class=\"current\">Draft Site</a>";
|
||||||
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
||||||
@ -235,7 +238,7 @@ JS
|
|||||||
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
||||||
$message = "<div id=\"SilverStripeNavigatorMessage\">PUBLISHED SITE</div>";
|
$message = "<div id=\"SilverStripeNavigatorMessage\">PUBLISHED SITE</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if($member) {
|
if($member) {
|
||||||
$firstname = Convert::raw2xml($member->FirstName);
|
$firstname = Convert::raw2xml($member->FirstName);
|
||||||
$surname = Convert::raw2xml($member->Surame);
|
$surname = Convert::raw2xml($member->Surame);
|
||||||
@ -254,7 +257,7 @@ JS
|
|||||||
<div id="logInStatus">
|
<div id="logInStatus">
|
||||||
$logInMessage
|
$logInMessage
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="switchView" class="bottomTabs">
|
<div id="switchView" class="bottomTabs">
|
||||||
<div class="blank"> View page in: </div>
|
<div class="blank"> View page in: </div>
|
||||||
$cmsLink
|
$cmsLink
|
||||||
@ -291,15 +294,15 @@ HTML;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an error to test the error system
|
* Throw an error to test the error system
|
||||||
*/
|
*/
|
||||||
function throwerror() {
|
function throwerror() {
|
||||||
user_error("This is a test of the error handler - nothing to worry about.", E_USER_ERROR);
|
user_error("This is a test of the error handler - nothing to worry about.", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw a warning to test the error system
|
* Throw a warning to test the error system
|
||||||
*/
|
*/
|
||||||
@ -339,13 +342,13 @@ HTML;
|
|||||||
<div style="margin-left: auto; margin-right: auto; width: 50%;"><p><a href="home/deleteinstallfiles" style="text-align: center;">Click here to delete the install files.</a></p></div></div>
|
<div style="margin-left: auto; margin-right: auto; width: 50%;"><p><a href="home/deleteinstallfiles" style="text-align: center;">Click here to delete the install files.</a></p></div></div>
|
||||||
HTML
|
HTML
|
||||||
);
|
);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
"Title" => $title,
|
"Title" => $title,
|
||||||
"Content" => $content,
|
"Content" => $content,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteinstallfiles() {
|
function deleteinstallfiles() {
|
||||||
$title = new Varchar("Title");
|
$title = new Varchar("Title");
|
||||||
$content = new HTMLText("Content");
|
$content = new HTMLText("Content");
|
||||||
@ -396,7 +399,7 @@ HTML
|
|||||||
HTML
|
HTML
|
||||||
;
|
;
|
||||||
$content->setValue($tempcontent);
|
$content->setValue($tempcontent);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
"Title" => $title,
|
"Title" => $title,
|
||||||
"Content" => $content,
|
"Content" => $content,
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticator base class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for an authentication method
|
* Abstract base class for an authentication method
|
||||||
@ -8,6 +13,8 @@
|
|||||||
* methods like {@link MemberAuthenticator} or {@link OpenIDAuthenticator}.
|
* methods like {@link MemberAuthenticator} or {@link OpenIDAuthenticator}.
|
||||||
*
|
*
|
||||||
* @author Markus Lanthaler <markus@silverstripe.com>
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*
|
||||||
|
* @todo Wouldn't be an interface be the better choice?
|
||||||
*/
|
*/
|
||||||
abstract class Authenticator extends Object
|
abstract class Authenticator extends Object
|
||||||
{
|
{
|
||||||
@ -15,19 +22,24 @@ abstract class Authenticator extends Object
|
|||||||
* Method to authenticate an user
|
* Method to authenticate an user
|
||||||
*
|
*
|
||||||
* @param array $RAW_data Raw data to authenticate the 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()}
|
||||||
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
||||||
* the member object
|
* the member object
|
||||||
*/
|
*/
|
||||||
public abstract function authenticate(array $RAW_data);
|
public abstract function authenticate(array $RAW_data, Form $form = null);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that creates the login form for this authentication method
|
* Method that creates the login form for this authentication method
|
||||||
*
|
*
|
||||||
|
* @param Controller The parent controller, necessary to create the
|
||||||
|
* appropriate form action tag
|
||||||
* @return Form Returns the login form to use with this authentication
|
* @return Form Returns the login form to use with this authentication
|
||||||
* method
|
* method
|
||||||
*/
|
*/
|
||||||
public abstract function getLoginForm();
|
public abstract static function getLoginForm(Controller $controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -6,20 +6,19 @@ class Member extends DataObject {
|
|||||||
'Surname' => "Varchar",
|
'Surname' => "Varchar",
|
||||||
'Email' => "Varchar",
|
'Email' => "Varchar",
|
||||||
'Password' => "Varchar",
|
'Password' => "Varchar",
|
||||||
|
'RememberLoginToken' => "Varchar(50)",
|
||||||
'NumVisit' => "Int",
|
'NumVisit' => "Int",
|
||||||
'LastVisited' => 'Datetime',
|
'LastVisited' => 'Datetime',
|
||||||
'Bounced' => 'Boolean',
|
'Bounced' => 'Boolean',
|
||||||
'AutoLoginHash' => 'Varchar(10)',
|
'AutoLoginHash' => 'Varchar(10)',
|
||||||
'AutoLoginExpired' => 'Datetime',
|
'AutoLoginExpired' => 'Datetime',
|
||||||
'BlacklistedEmail' => 'Boolean',
|
'BlacklistedEmail' => 'Boolean',
|
||||||
);
|
);
|
||||||
static $belongs_many_many = array(
|
static $belongs_many_many = array(
|
||||||
"Groups" => "Group",
|
"Groups" => "Group",
|
||||||
|
|
||||||
);
|
);
|
||||||
static $has_one = array(
|
|
||||||
);
|
|
||||||
|
|
||||||
static $has_many = array(
|
static $has_many = array(
|
||||||
'UnsubscribedRecords' => 'Member_UnsubscribeRecord'
|
'UnsubscribedRecords' => 'Member_UnsubscribeRecord'
|
||||||
);
|
);
|
||||||
@ -30,23 +29,86 @@ class Member extends DataObject {
|
|||||||
'Email' => true,
|
'Email' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs this member in.
|
* Logs this member in
|
||||||
|
*
|
||||||
|
* @param bool $remember If set to TRUE, the member will be logged in
|
||||||
|
* automatically the next time.
|
||||||
*/
|
*/
|
||||||
function logIn() {
|
function logIn($remember = false) {
|
||||||
|
session_regenerate_id(true);
|
||||||
Session::set("loggedInAs", $this->ID);
|
Session::set("loggedInAs", $this->ID);
|
||||||
|
|
||||||
$this->NumVisit++;
|
$this->NumVisit++;
|
||||||
|
|
||||||
|
if($remember) {
|
||||||
|
|
||||||
|
$token = substr(md5(uniqid(rand(), true)), 0, 49 - strlen($this->ID));
|
||||||
|
$this->RememberLoginToken = $token;
|
||||||
|
Cookie::set('alc_enc', $this->ID . ':' . $token);
|
||||||
|
} else {
|
||||||
|
$this->RememberLoginToken = null;
|
||||||
|
Cookie::set('alc_enc', null);
|
||||||
|
Cookie::forceExpiry('alc_enc');
|
||||||
|
}
|
||||||
|
|
||||||
$this->write();
|
$this->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Logs this member in.
|
* Log the user in if the "remember login" cookie is set
|
||||||
|
*
|
||||||
|
* The <i>remember login token</i> will be changed on every successful
|
||||||
|
* auto-login.
|
||||||
*/
|
*/
|
||||||
function logOut(){
|
static function autoLogin() {
|
||||||
Cookie::set('alc_enc',null);
|
if(isset($_COOKIE['alc_enc']) && !Session::get("loggedInAs")) {
|
||||||
Session::clear("loggedInAs");
|
|
||||||
|
list($uid, $token) = explode(':', $_COOKIE['alc_enc'], 2);
|
||||||
|
$uid = Convert::raw2sql($uid);
|
||||||
|
$token = Convert::raw2sql($token);
|
||||||
|
|
||||||
|
$member = DataObject::get_one(
|
||||||
|
"Member", "Member.ID = $uid And RememberLoginToken = '$token'");
|
||||||
|
|
||||||
|
if($member) {
|
||||||
|
session_regenerate_id(true);
|
||||||
|
Session::set("loggedInAs", $member->ID);
|
||||||
|
|
||||||
|
$token = substr(md5(uniqid(rand(), true)),
|
||||||
|
0, 49 - strlen($member->ID));
|
||||||
|
$member->RememberLoginToken = $token;
|
||||||
|
Cookie::set('alc_enc', $member->ID . ':' . $token);
|
||||||
|
|
||||||
|
$member->NumVisit++;
|
||||||
|
$member->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs this member out.
|
||||||
|
*/
|
||||||
|
function logOut() {
|
||||||
|
Session::clear("loggedInAs");
|
||||||
|
session_regenerate_id(true);
|
||||||
|
|
||||||
|
$this->RememberLoginToken = null;
|
||||||
|
Cookie::set('alc_enc', null);
|
||||||
|
Cookie::forceExpiry('alc_enc');
|
||||||
|
|
||||||
|
$this->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an auto login hash
|
||||||
|
*
|
||||||
|
* @todo This is relative insecure, check if we should fix it
|
||||||
|
*/
|
||||||
function generateAutologinHash() {
|
function generateAutologinHash() {
|
||||||
$linkHash = sprintf('%10d', time() );
|
$linkHash = sprintf('%10d', time() );
|
||||||
|
|
||||||
@ -59,31 +121,51 @@ class Member extends DataObject {
|
|||||||
$this->write();
|
$this->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a member in with an auto login hash link
|
* Log a member in with an auto login hash link
|
||||||
*/
|
*/
|
||||||
static function autoLoginHash( $RAW_hash ) {
|
static function autoLoginHash($RAW_hash) {
|
||||||
|
$SQL_hash = Convert::raw2sql($RAW_hash);
|
||||||
$SQL_hash = Convert::raw2sql( $RAW_hash );
|
|
||||||
|
|
||||||
$member = DataObject::get_one('Member',"`AutoLoginHash`='$SQL_hash' AND `AutoLoginExpired` > NOW()");
|
$member = DataObject::get_one('Member',"`AutoLoginHash`='$SQL_hash' AND `AutoLoginExpired` > NOW()");
|
||||||
|
|
||||||
if( $member )
|
if($member)
|
||||||
$member->logIn();
|
$member->logIn();
|
||||||
|
|
||||||
return $member;
|
return $member;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendInfo($type = 'signup'){
|
|
||||||
|
/**
|
||||||
|
* Send signup, change password or forgot password informations to an user
|
||||||
|
*
|
||||||
|
* @param string $type Information type to send ("signup",
|
||||||
|
* "changePassword" or "forgotPassword")
|
||||||
|
*/
|
||||||
|
function sendInfo($type = 'signup') {
|
||||||
switch($type) {
|
switch($type) {
|
||||||
case "signup": $e = new Member_SignupEmail(); break;
|
case "signup":
|
||||||
case "changePassword": $e = new Member_ChangePasswordEmail(); break;
|
$e = new Member_SignupEmail();
|
||||||
case "forgotPassword": $e = new Member_ForgotPasswordEmail(); break;
|
break;
|
||||||
|
case "changePassword":
|
||||||
|
$e = new Member_ChangePasswordEmail();
|
||||||
|
break;
|
||||||
|
case "forgotPassword":
|
||||||
|
$e = new Member_ForgotPasswordEmail();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
$e->populateTemplate($this);
|
$e->populateTemplate($this);
|
||||||
$e->send();
|
$e->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fields for the member form
|
||||||
|
*
|
||||||
|
* @return FieldSet Returns a {@link FieldSet} containing the fields for
|
||||||
|
* the member form.
|
||||||
|
*/
|
||||||
function getMemberFormFields() {
|
function getMemberFormFields() {
|
||||||
return new FieldSet(
|
return new FieldSet(
|
||||||
new TextField("FirstName", "First Name"),
|
new TextField("FirstName", "First Name"),
|
||||||
@ -93,108 +175,84 @@ class Member extends DataObject {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for the member validator
|
||||||
|
*
|
||||||
|
* @return Member_Validator Returns an instance of a
|
||||||
|
* {@link Member_Validator} object.
|
||||||
|
*/
|
||||||
function getValidator() {
|
function getValidator() {
|
||||||
return new Member_Validator();
|
return new Member_Validator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currenly logged in user
|
* Returns the current logged in user
|
||||||
* @todo get_one() is a bit funky.
|
*
|
||||||
|
* @return bool|Member Returns the member object of the current logged in
|
||||||
|
* user or FALSE.
|
||||||
*/
|
*/
|
||||||
static function currentUser() {
|
static function currentUser() {
|
||||||
self::autoLogin();
|
$id = Session::get("loggedInAs");
|
||||||
|
if(!$id) {
|
||||||
|
self::autoLogin();
|
||||||
|
$id = Session::get("loggedInAs");
|
||||||
|
}
|
||||||
|
|
||||||
// Return the details
|
if($id) {
|
||||||
if($id = Session::get("loggedInAs")) {
|
|
||||||
return DataObject::get_one("Member", "Member.ID = $id");
|
return DataObject::get_one("Member", "Member.ID = $id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function autoLogin() {
|
|
||||||
// Auto-login
|
|
||||||
if(isset($_COOKIE['alc_enc']) && !Session::get("loggedInAs")) {
|
|
||||||
// Deliberately obscure...
|
|
||||||
list($data['Email'], $data['Password']) = explode(':',base64_decode($_COOKIE['alc_enc']),2);
|
|
||||||
|
|
||||||
$lf = new LoginForm(null, null, null, null, false);
|
|
||||||
$lf->performLogin($data);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of the current logged in user
|
||||||
|
*
|
||||||
|
* @return int Returns the ID of the current logged in user or 0.
|
||||||
|
*/
|
||||||
static function currentUserID() {
|
static function currentUserID() {
|
||||||
self::autoLogin();
|
|
||||||
|
|
||||||
$id = Session::get("loggedInAs");
|
$id = Session::get("loggedInAs");
|
||||||
|
if(!$id) {
|
||||||
|
self::autoLogin();
|
||||||
|
$id = Session::get("loggedInAs");
|
||||||
|
}
|
||||||
|
|
||||||
return is_numeric($id) ? $id : 0;
|
return is_numeric($id) ? $id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* before the save of this member, the blacklisted email table is updated to ensure no
|
* Add the members email address to the blacklist
|
||||||
* promotional material is sent to the member. (newsletters)
|
*
|
||||||
* standard system messages are still sent such as receipts.
|
* With this method the blacklisted email table is updated to ensure that
|
||||||
|
* no promotional material is sent to the member (newsletters).
|
||||||
|
* Standard system messages are still sent such as receipts.
|
||||||
|
*
|
||||||
|
* @param bool $val Set to TRUE if the address should be added to the
|
||||||
|
* blacklist, otherwise to FALSE.
|
||||||
|
* @return
|
||||||
|
* @todo Check for what the parameter $val is needed! (Markus)
|
||||||
*/
|
*/
|
||||||
function setBlacklistedEmail($val){
|
function setBlacklistedEmail($val) {
|
||||||
if($val && $this->Email){
|
if($val && $this->Email) {
|
||||||
$blacklisting = new Email_BlackList();
|
$blacklisting = new Email_BlackList();
|
||||||
$blacklisting->BlockedEmail = $this->Email;
|
$blacklisting->BlockedEmail = $this->Email;
|
||||||
$blacklisting->MemberID = $this->ID;
|
$blacklisting->MemberID = $this->ID;
|
||||||
$blacklisting->write();
|
$blacklisting->write();
|
||||||
}
|
}
|
||||||
return $this->setField("BlacklistedEmail",$val);
|
|
||||||
|
$this->setField("BlacklistedEmail", $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBeforeWrite() {
|
|
||||||
// If an email's filled out
|
|
||||||
if($this->Email) {
|
|
||||||
// Look for a record with the same email
|
|
||||||
if($this->ID) $idClause = "AND `Member`.ID <> $this->ID";
|
|
||||||
else $idClause = "";
|
|
||||||
|
|
||||||
$existingRecord = DataObject::get_one("Member", "Email = '" . addslashes($this->Email) . "' $idClause");
|
|
||||||
|
|
||||||
// Debug::message("Found an existing member for email $this->Email");
|
|
||||||
|
|
||||||
// If found
|
|
||||||
if($existingRecord) {
|
|
||||||
// Update this record to merge with that member
|
|
||||||
$newID = $existingRecord->ID;
|
|
||||||
if($this->ID) {
|
|
||||||
DB::query("UPDATE Group_Members SET MemberID = $newID WHERE MemberID = $this->ID");
|
|
||||||
}
|
|
||||||
$this->ID = $newID;
|
|
||||||
// Merge existing data into the local record
|
|
||||||
|
|
||||||
foreach($existingRecord->getAllFields() as $k => $v) {
|
|
||||||
if(!isset($this->changed[$k]) || !$this->changed[$k]) $this->record[$k] = $v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::onBeforeWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the member is in one of the given groups
|
|
||||||
*/
|
|
||||||
public function inGroups( $groups ) {
|
|
||||||
foreach( $this->Groups() as $group )
|
|
||||||
$memberGroups[] = $group->Title;
|
|
||||||
|
|
||||||
return count( array_intersect( $memberGroups, $groups ) ) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function inGroup( $groupID ) {
|
|
||||||
foreach( $this->Groups() as $group )
|
|
||||||
if( $groupID == $group->ID )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a random password
|
* Generate a random password
|
||||||
* BDC - added randomiser to kick in if there's no words file on the filesystem.
|
*
|
||||||
|
* BDC - added randomiser to kick in if there's no words file on the
|
||||||
|
* filesystem.
|
||||||
|
*
|
||||||
|
* @return string Returns a random password.
|
||||||
*/
|
*/
|
||||||
static function createNewPassword() {
|
static function createNewPassword() {
|
||||||
if(file_exists('/usr/share/silverstripe/wordlist.txt')) {
|
if(file_exists('/usr/share/silverstripe/wordlist.txt')) {
|
||||||
@ -214,17 +272,105 @@ class Member extends DataObject {
|
|||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler called before writing to the database
|
||||||
|
*
|
||||||
|
* If an email's filled out look for a record with the same email and if
|
||||||
|
* found update this record to merge with that member.
|
||||||
|
*/
|
||||||
|
function onBeforeWrite() {
|
||||||
|
if($this->Email) {
|
||||||
|
if($this->ID) {
|
||||||
|
$idClause = "AND `Member`.ID <> $this->ID";
|
||||||
|
} else {
|
||||||
|
$idClause = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$existingRecord = DataObject::get_one(
|
||||||
|
"Member", "Email = '" . addslashes($this->Email) . "' $idClause");
|
||||||
|
|
||||||
|
// Debug::message("Found an existing member for email $this->Email");
|
||||||
|
|
||||||
|
if($existingRecord) {
|
||||||
|
$newID = $existingRecord->ID;
|
||||||
|
if($this->ID) {
|
||||||
|
DB::query("UPDATE Group_Members SET MemberID = $newID WHERE MemberID = $this->ID");
|
||||||
|
}
|
||||||
|
$this->ID = $newID;
|
||||||
|
// Merge existing data into the local record
|
||||||
|
|
||||||
|
foreach($existingRecord->getAllFields() as $k => $v) {
|
||||||
|
if(!isset($this->changed[$k]) || !$this->changed[$k]) $this->record[$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::onBeforeWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the member is in one of the given groups
|
||||||
|
*
|
||||||
|
* @param array $groups Groups to check
|
||||||
|
* @return bool Returns TRUE if the member is in one of the given groups,
|
||||||
|
* otherwise FALSE.
|
||||||
|
*/
|
||||||
|
public function inGroups(array $groups) {
|
||||||
|
foreach($this->Groups() as $group)
|
||||||
|
$memberGroups[] = $group->Title;
|
||||||
|
|
||||||
|
return count(array_intersect($memberGroups, $groups)) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the member is in the given group
|
||||||
|
*
|
||||||
|
* @param int $groupID ID of the group to check
|
||||||
|
* @return bool Returns TRUE if the member is in the given group,
|
||||||
|
* otherwise FALSE.
|
||||||
|
*/
|
||||||
|
public function inGroup($groupID) {
|
||||||
|
foreach($this->Groups() as $group) {
|
||||||
|
if($groupID == $group->ID)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link inGroup}
|
||||||
|
*
|
||||||
|
* @param int $groupID ID of the group to check
|
||||||
|
* @return bool Returns TRUE if the member is in the given group,
|
||||||
|
* otherwise FALSE.
|
||||||
|
* @see inGroup()
|
||||||
|
*/
|
||||||
|
public function isInGroup($groupID) {
|
||||||
|
return $this->inGroup($groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this user is an administrator.
|
* Returns true if this user is an administrator.
|
||||||
* Administrators have access to everything. The lucky bastards! ;-)
|
* Administrators have access to everything. The lucky bastards! ;-)
|
||||||
*
|
*
|
||||||
|
* @return Returns TRUE if this user is an administrator.
|
||||||
* @todo Should this function really exists? Is not {@link isAdmin()} the
|
* @todo Should this function really exists? Is not {@link isAdmin()} the
|
||||||
* only right name for this?
|
* only right name for this?
|
||||||
* @todo Is {@link Group}::CanCMSAdmin not deprecated?
|
* @todo Is {@link Group}::CanCMSAdmin not deprecated?
|
||||||
*/
|
*/
|
||||||
function _isAdmin() {
|
function _isAdmin() {
|
||||||
if($groups = $this->Groups()) {
|
if($groups = $this->Groups()) {
|
||||||
foreach($groups as $group) if($group->CanCMSAdmin) return true;
|
foreach($groups as $group) {
|
||||||
|
if($group->CanCMSAdmin)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Permission::check('ADMIN');
|
return Permission::check('ADMIN');
|
||||||
@ -245,41 +391,79 @@ class Member extends DataObject {
|
|||||||
}
|
}
|
||||||
function _isCMSUser() {
|
function _isCMSUser() {
|
||||||
if($groups = $this->Groups()) {
|
if($groups = $this->Groups()) {
|
||||||
foreach($groups as $group) if($group->CanCMS) return true;
|
foreach($groups as $group) {
|
||||||
|
if($group->CanCMS)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------//
|
//------------------- HELPER METHODS -----------------------------------//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the complete name of the member
|
||||||
|
*
|
||||||
|
* @return string Returns the first- and surname of the member. If the ID
|
||||||
|
* of the member is equal 0, only the surname is returned.
|
||||||
|
* @todo Check for what this method is used! (Markus)
|
||||||
|
*/
|
||||||
public function getTitle() {
|
public function getTitle() {
|
||||||
if($this->getField('ID') === 0)
|
if($this->getField('ID') === 0)
|
||||||
return $this->getField('Surname');
|
return $this->getField('Surname');
|
||||||
return $this->getField('Surname') . ', ' . $this->getField('FirstName');
|
return $this->getField('Surname') . ', ' . $this->getField('FirstName');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the complete name of the member
|
||||||
|
*
|
||||||
|
* @return string Returns the first- and surname of the member.
|
||||||
|
*/
|
||||||
public function getName() {
|
public function getName() {
|
||||||
return $this->FirstName . ' ' . $this->Surname;
|
return $this->FirstName . ' ' . $this->Surname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName( $name ) {
|
|
||||||
$nameParts = explode( ' ', $name );
|
/**
|
||||||
$this->Surname = array_pop( $nameParts );
|
* Set first- and surname
|
||||||
$this->FirstName = join( ' ', $nameParts );
|
*
|
||||||
|
* This method assumes that the last part of the name is the surname, e.g.
|
||||||
|
* <i>A B C</i> will result in firstname <i>A B</i> and surname <i>C</i>
|
||||||
|
*
|
||||||
|
* @param string $name The name
|
||||||
|
*/
|
||||||
|
public function setName($name) {
|
||||||
|
$nameParts = explode(' ', $name);
|
||||||
|
$this->Surname = array_pop($nameParts);
|
||||||
|
$this->FirstName = join(' ', $nameParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function splitName( $name ) {
|
|
||||||
return $this->setName( $name );
|
/**
|
||||||
|
* Alias for {@link setName}
|
||||||
|
*
|
||||||
|
* @param string $name The name
|
||||||
|
* @see setName()
|
||||||
|
*/
|
||||||
|
public function splitName($name) {
|
||||||
|
return $this->setName($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Figure out what this function does and document it! (Markus)
|
||||||
|
*/
|
||||||
public function Groups() {
|
public function Groups() {
|
||||||
$groups = $this->getManyManyComponents("Groups");
|
$groups = $this->getManyManyComponents("Groups");
|
||||||
|
|
||||||
$unsecure = DataObject::get("Group_Unsecure", "");
|
$unsecure = DataObject::get("Group_Unsecure", "");
|
||||||
if($unsecure) foreach($unsecure as $unsecureItem) {
|
if($unsecure) {
|
||||||
$groups->push($unsecureItem);
|
foreach($unsecure as $unsecureItem) {
|
||||||
|
$groups->push($unsecureItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$groupIDs = $groups->column();
|
$groupIDs = $groups->column();
|
||||||
@ -303,17 +487,13 @@ class Member extends DataObject {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isInGroup($groupID) {
|
|
||||||
$groups = $this->Groups();
|
|
||||||
foreach($groups as $group) {
|
|
||||||
if($group->ID == $groupID) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Figure out what this function does and document it! (Markus)
|
||||||
|
*/
|
||||||
public function map($filter = "", $sort = "", $blank="") {
|
public function map($filter = "", $sort = "", $blank="") {
|
||||||
$ret = new SQLMap(singleton('Member')->extendedSQL($filter, $sort));
|
$ret = new SQLMap(singleton('Member')->extendedSQL($filter, $sort));
|
||||||
if($blank){
|
if($blank) {
|
||||||
$blankMember = new Member();
|
$blankMember = new Member();
|
||||||
$blankMember->Surname = $blank;
|
$blankMember->Surname = $blank;
|
||||||
$blankMember->ID = 0;
|
$blankMember->ID = 0;
|
||||||
@ -324,72 +504,102 @@ class Member extends DataObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function mapInGroups( $groups = null ) {
|
/**
|
||||||
|
* @todo Figure out what this function does and document it! (Markus)
|
||||||
if( !$groups )
|
*/
|
||||||
|
public static function mapInGroups($groups = null) {
|
||||||
|
if(!$groups)
|
||||||
return Member::map();
|
return Member::map();
|
||||||
|
|
||||||
$groupIDList = array();
|
$groupIDList = array();
|
||||||
|
|
||||||
if( is_a( $groups, 'DataObjectSet' ) )
|
if(is_a($groups, 'DataObjectSet')) {
|
||||||
foreach( $groups as $group )
|
foreach( $groups as $group )
|
||||||
$groupIDList[] = $group->ID;
|
$groupIDList[] = $group->ID;
|
||||||
elseif( is_array( $groups ) )
|
} elseif(is_array($groups)) {
|
||||||
$groupIDList = $groups;
|
$groupIDList = $groups;
|
||||||
else
|
} else {
|
||||||
$groupIDList[] = $groups;
|
$groupIDList[] = $groups;
|
||||||
|
}
|
||||||
|
|
||||||
if( empty( $groupIDList ) )
|
if(empty($groupIDList))
|
||||||
return Member::map();
|
return Member::map();
|
||||||
|
|
||||||
return new SQLMap( singleton('Member')->extendedSQL( "`GroupID` IN (" . implode( ',', $groupIDList ) . ")", "Surname, FirstName", "", "INNER JOIN `Group_Members` ON `MemberID`=`Member`.`ID`") );
|
return new SQLMap(singleton('Member')->extendedSQL(
|
||||||
|
"`GroupID` IN (" . implode( ',', $groupIDList ) .
|
||||||
|
")", "Surname, FirstName", "", "INNER JOIN `Group_Members` ON `MemberID`=`Member`.`ID`"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a map of all members in the groups given that have CMS permissions
|
* Get a map of all members in the groups given that have CMS permissions
|
||||||
* Defaults to all groups with CMS permissions
|
*
|
||||||
|
* If no groups are passed, all groups with CMS permissions will be used.
|
||||||
|
*
|
||||||
|
* @param array $groups Groups to consider or NULL to use all groups with
|
||||||
|
* CMS permissions.
|
||||||
|
* @return SQLMap Returns a map of all members in the groups given that
|
||||||
|
* have CMS permissions.
|
||||||
*/
|
*/
|
||||||
public static function mapInCMSGroups( $groups = null ) {
|
public static function mapInCMSGroups($groups = null) {
|
||||||
if( !$groups || $groups->Count() == 0 )
|
if(!$groups || $groups->Count() == 0) {
|
||||||
$groups = DataObject::get('Group',"", "", "INNER JOIN `Permission` ON `Permission`.GroupID = `Group`.ID AND `Permission`.Code IN ('ADMIN', 'CMS_ACCESS_AssetAdmin')");
|
$groups = DataObject::get('Group', "", "",
|
||||||
|
"INNER JOIN `Permission` ON `Permission`.GroupID = `Group`.ID AND `Permission`.Code IN ('ADMIN', 'CMS_ACCESS_AssetAdmin')");
|
||||||
|
}
|
||||||
|
|
||||||
$groupIDList = array();
|
$groupIDList = array();
|
||||||
|
|
||||||
if( is_a( $groups, 'DataObjectSet' ) )
|
if(is_a($groups, 'DataObjectSet')) {
|
||||||
foreach( $groups as $group )
|
foreach($groups as $group)
|
||||||
$groupIDList[] = $group->ID;
|
$groupIDList[] = $group->ID;
|
||||||
elseif( is_array( $groups ) )
|
} elseif(is_array($groups)) {
|
||||||
$groupIDList = $groups;
|
$groupIDList = $groups;
|
||||||
|
}
|
||||||
|
|
||||||
/*if( empty( $groupIDList ) )
|
/*if( empty( $groupIDList ) )
|
||||||
return Member::map(); */
|
return Member::map(); */
|
||||||
|
|
||||||
$filterClause = ($groupIDList) ? "`GroupID` IN (" . implode( ',', $groupIDList ) . ")" : "";
|
$filterClause = ($groupIDList)
|
||||||
|
? "`GroupID` IN (" . implode( ',', $groupIDList ) . ")"
|
||||||
|
: "";
|
||||||
|
|
||||||
return new SQLMap( singleton('Member')->extendedSQL( $filterClause, "Surname, FirstName", "", "INNER JOIN `Group_Members` ON `MemberID`=`Member`.`ID` INNER JOIN `Group` ON `Group`.`ID`=`GroupID`") );
|
return new SQLMap(singleton('Member')->extendedSQL($filterClause,
|
||||||
|
"Surname, FirstName", "",
|
||||||
|
"INNER JOIN `Group_Members` ON `MemberID`=`Member`.`ID` INNER JOIN `Group` ON `Group`.`ID`=`GroupID`"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* When passed an array of groups, and a component set of groups, this function
|
|
||||||
* will return the array of groups the member is NOT in.
|
|
||||||
* @param grouplist an array of group code names.
|
|
||||||
* @param memberGroups a component set of groups ( set to $this->groups() by default )
|
|
||||||
*/
|
|
||||||
public function memberNotInGroups($groupList,$memberGroups = null){
|
|
||||||
if(!$memberGroups) $memberGroups = $this->Groups();
|
|
||||||
|
|
||||||
foreach($memberGroups as $group){
|
/**
|
||||||
if(in_array($group->Code,$groupList)){
|
* Get the groups in which the member is NOT in
|
||||||
$index = array_search($group->Code,$groupList);
|
*
|
||||||
|
* When passed an array of groups, and a component set of groups, this
|
||||||
|
* function will return the array of groups the member is NOT in.
|
||||||
|
*
|
||||||
|
* @param array $groupList An array of group code names.
|
||||||
|
* @param array $memberGroups A component set of groups (if set to NULL,
|
||||||
|
* $this->groups() will be used)
|
||||||
|
* @return array Groups in which the member is NOT in.
|
||||||
|
*/
|
||||||
|
public function memberNotInGroups($groupList, $memberGroups = null){
|
||||||
|
if(!$memberGroups)
|
||||||
|
$memberGroups = $this->Groups();
|
||||||
|
|
||||||
|
foreach($memberGroups as $group) {
|
||||||
|
if(in_array($group->Code, $groupList)) {
|
||||||
|
$index = array_search($group->Code, $groupList);
|
||||||
unset($groupList[$index]);
|
unset($groupList[$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $groupList;
|
return $groupList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a FieldSet of fields that would appropriate for editing this member.
|
* Return a {@link FieldSet} of fields that would appropriate for editing
|
||||||
|
* this member.
|
||||||
|
*
|
||||||
|
* @return FieldSet Return a FieldSet of fields that would appropriate for
|
||||||
|
* editing this member.
|
||||||
*/
|
*/
|
||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
@ -413,12 +623,19 @@ class Member extends DataObject {
|
|||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unsubscribeFromNewsletter( $newsletterType ) {
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from newsletter
|
||||||
|
*
|
||||||
|
* @param NewsletterType $newsletterType Newsletter type to unsubscribe
|
||||||
|
* from
|
||||||
|
*/
|
||||||
|
function unsubscribeFromNewsletter(NewsletterType $newsletterType) {
|
||||||
// record today's date in unsubscriptions
|
// record today's date in unsubscriptions
|
||||||
// this is a little bit redundant
|
// this is a little bit redundant
|
||||||
$unsubscribeRecord = new Member_UnsubscribeRecord();
|
$unsubscribeRecord = new Member_UnsubscribeRecord();
|
||||||
$unsubscribeRecord->unsubscribe( $this, $newsletterType );
|
$unsubscribeRecord->unsubscribe($this, $newsletterType);
|
||||||
$this->Groups()->remove( $newsletterType->GroupID );
|
$this->Groups()->remove($newsletterType->GroupID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function requireDefaultRecords() {
|
function requireDefaultRecords() {
|
||||||
@ -431,161 +648,208 @@ class Member extends DataObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special kind of ComponentSet that has special methods for manipulating a user's membership
|
* Special kind of {@link ComponentSet} that has special methods for
|
||||||
|
* manipulating a user's membership
|
||||||
*/
|
*/
|
||||||
class Member_GroupSet extends ComponentSet {
|
class Member_GroupSet extends ComponentSet {
|
||||||
/**
|
/**
|
||||||
* Control group membership with a number of checkboxes.
|
* Control group membership with a number of checkboxes.
|
||||||
* - If the checkbox fields are present in $data, then the member will be added to the group with the same codename.
|
* - If the checkbox fields are present in $data, then the member will be
|
||||||
* - If the checkbox fields are *NOT* present in $data, then the member willb e removed from the group with the same codename.
|
* added to the group with the same codename.
|
||||||
* @param checkboxes an array list of the checkbox fieldnames (Only values are used.) eg array(0,1,2);
|
* - If the checkbox fields are *NOT* present in $data, then the member
|
||||||
* @param data The form data. usually in the format array(0 => 2) (just pass the checkbox data from your form);
|
* will be removed from the group with the same codename.
|
||||||
|
*
|
||||||
|
* @param array $checkboxes An array list of the checkbox fieldnames (only
|
||||||
|
* values are used). E.g. array(0, 1, 2)
|
||||||
|
* @param array $data The form data. Uually in the format array(0 => 2)
|
||||||
|
* (just pass the checkbox data from your form)
|
||||||
*/
|
*/
|
||||||
function setByCheckboxes($checkboxes, $data) {
|
function setByCheckboxes(array $checkboxes, array $data) {
|
||||||
foreach($checkboxes as $checkbox) {
|
foreach($checkboxes as $checkbox) {
|
||||||
if($data[$checkbox]){
|
if($data[$checkbox]) {
|
||||||
$add[] = $checkbox;
|
$add[] = $checkbox;
|
||||||
}else{
|
} else {
|
||||||
$remove[] = $checkbox;
|
$remove[] = $checkbox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($add)$this->addManyByCodename($add);
|
|
||||||
if($remove) $this->removeManyByCodename($remove);
|
if($add)
|
||||||
|
$this->addManyByCodename($add);
|
||||||
|
|
||||||
|
if($remove)
|
||||||
|
$this->removeManyByCodename($remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows you to set groups based on a checkboxsetfield.
|
* Allows you to set groups based on a CheckboxSetField
|
||||||
* (pass the form element from your post data directly to this method, and it
|
|
||||||
* will update the groups and add and remove the member as appropriate)
|
|
||||||
* @param checkboxsetField - the CheckboxSetField (with data) from your form.
|
|
||||||
*
|
*
|
||||||
* On the form setup
|
* Pass the form element from your post data directly to this method, and
|
||||||
*
|
* it will update the groups and add and remove the member as appropriate.
|
||||||
$fields->push(
|
|
||||||
new CheckboxSetField(
|
|
||||||
"NewsletterSubscriptions",
|
|
||||||
"Receive email notification of events in ",
|
|
||||||
$sourceitems = DataObject::get("NewsletterType")->toDropDownMap("GroupID","Title"),
|
|
||||||
$selectedgroups = $member->Groups()->Map("ID","ID")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
*
|
*
|
||||||
|
* On the form setup:
|
||||||
*
|
*
|
||||||
|
* <code>
|
||||||
|
* $fields->push(
|
||||||
|
* new CheckboxSetField(
|
||||||
|
* "NewsletterSubscriptions",
|
||||||
|
* "Receive email notification of events in ",
|
||||||
|
* $sourceitems = DataObject::get("NewsletterType")->toDropDownMap("GroupID","Title"),
|
||||||
|
* $selectedgroups = $member->Groups()->Map("ID","ID")
|
||||||
|
* )
|
||||||
|
* );
|
||||||
|
* </code>
|
||||||
*
|
*
|
||||||
* On the form handler:
|
* On the form handler:
|
||||||
$groups = $member->Groups();
|
|
||||||
$checkboxfield = $form->Fields()->fieldByName("NewsletterSubscriptions");
|
|
||||||
$groups->setByCheckboxSetField($checkboxfield);
|
|
||||||
*
|
*
|
||||||
|
* <code>
|
||||||
|
* $groups = $member->Groups();
|
||||||
|
* $checkboxfield = $form->Fields()->fieldByName("NewsletterSubscriptions");
|
||||||
|
* $groups->setByCheckboxSetField($checkboxfield);
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @param CheckboxSetField $checkboxsetfield The CheckboxSetField (with
|
||||||
|
* data) from your form.
|
||||||
*/
|
*/
|
||||||
function setByCheckboxSetField($checkboxsetfield){
|
function setByCheckboxSetField(CheckboxSetField $checkboxsetfield) {
|
||||||
|
|
||||||
// Get the values from the formfield.
|
// Get the values from the formfield.
|
||||||
$values = $checkboxsetfield->Value();
|
$values = $checkboxsetfield->Value();
|
||||||
$sourceItems = $checkboxsetfield->getSource();
|
$sourceItems = $checkboxsetfield->getSource();
|
||||||
|
|
||||||
if($sourceItems){
|
if($sourceItems) {
|
||||||
// If (some) values are present, add and remove as necessary.
|
// If (some) values are present, add and remove as necessary.
|
||||||
if($values){
|
if($values) {
|
||||||
// update the groups based on the selections
|
// update the groups based on the selections
|
||||||
foreach($sourceItems as $k => $item){
|
foreach($sourceItems as $k => $item) {
|
||||||
if(in_array($k,$values)){
|
if(in_array($k,$values)) {
|
||||||
$add[] = $k;
|
$add[] = $k;
|
||||||
}else{
|
} else {
|
||||||
$remove[] = $k;
|
$remove[] = $k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// else we should be removing all from the necessary groups.
|
// else we should be removing all from the necessary groups.
|
||||||
}else{
|
} else {
|
||||||
$remove = $sourceItems;
|
$remove = $sourceItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($add)$this->addManyByGroupID($add);
|
if($add)
|
||||||
if($remove) $this->RemoveManyByGroupID($remove);
|
$this->addManyByGroupID($add);
|
||||||
|
|
||||||
}else{
|
if($remove)
|
||||||
USER_ERROR("Member::setByCheckboxSetField() - No source items could be found for checkboxsetfield ". $checkboxsetfield->Name(),E_USER_WARNING);
|
$this->RemoveManyByGroupID($remove);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
USER_ERROR("Member::setByCheckboxSetField() - No source items could be found for checkboxsetfield " .
|
||||||
|
$checkboxsetfield->Name(), E_USER_WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds this member to the groups based on the
|
* Adds this member to the groups based on the group IDs
|
||||||
* groupID.
|
*
|
||||||
|
* @param array $ids Group identifiers.
|
||||||
*/
|
*/
|
||||||
function addManyByGroupID($groupIds){
|
function addManyByGroupID($groupIds){
|
||||||
$groups = $this->getGroupsFromIDs($groupIds);
|
$groups = $this->getGroupsFromIDs($groupIds);
|
||||||
if($groups){
|
if($groups) {
|
||||||
foreach($groups as $group){
|
foreach($groups as $group) {
|
||||||
$this->add($group);
|
$this->add($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the member from many groups based on
|
* Removes the member from many groups based on the group IDs
|
||||||
* the group ID.
|
*
|
||||||
|
* @param array $ids Group identifiers.
|
||||||
*/
|
*/
|
||||||
function removeManyByGroupID($groupIds){
|
function removeManyByGroupID($groupIds) {
|
||||||
$groups = $this->getGroupsFromIDs($groupIds);
|
$groups = $this->getGroupsFromIDs($groupIds);
|
||||||
if($groups){
|
if($groups) {
|
||||||
foreach($groups as $group){
|
foreach($groups as $group) {
|
||||||
$this->remove($group);
|
$this->remove($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the groups from an array of GroupIDs
|
* Returns the groups from an array of group IDs
|
||||||
|
*
|
||||||
|
* @param array $ids Group identifiers.
|
||||||
|
* @return mixed Returns the groups from the array of Group IDs.
|
||||||
*/
|
*/
|
||||||
function getGroupsFromIDs($ids){
|
function getGroupsFromIDs($ids){
|
||||||
if($ids && count($ids) > 1){
|
if($ids && count($ids) > 1) {
|
||||||
return DataObject::get("Group","ID IN (". implode(",",$ids) .")");
|
return DataObject::get("Group", "ID IN (" . implode(",", $ids) . ")");
|
||||||
}else{
|
} else {
|
||||||
return DataObject::get_by_id("Group",$ids[0]);
|
return DataObject::get_by_id("Group", $ids[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds this member to the groups passed.
|
* Adds this member to the groups based on the group codenames
|
||||||
|
*
|
||||||
|
* @param array $codenames Group codenames
|
||||||
*/
|
*/
|
||||||
function addManyByCodename($codenames) {
|
function addManyByCodename($codenames) {
|
||||||
$groups = $this->codenamesToGroups($codenames);
|
$groups = $this->codenamesToGroups($codenames);
|
||||||
if($groups){
|
if($groups) {
|
||||||
foreach($groups as $group){
|
foreach($groups as $group){
|
||||||
$this->add($group);
|
$this->add($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes this member from the groups passed.
|
* Removes this member from the groups based on the group codenames
|
||||||
|
*
|
||||||
|
* @param array $codenames Group codenames
|
||||||
*/
|
*/
|
||||||
function removeManyByCodename($codenames) {
|
function removeManyByCodename($codenames) {
|
||||||
$groups = $this->codenamesToGroups($codenames);
|
$groups = $this->codenamesToGroups($codenames);
|
||||||
if($groups){
|
if($groups) {
|
||||||
foreach($groups as $group){
|
foreach($groups as $group) {
|
||||||
$this->remove($group);
|
$this->remove($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to return the appropriate group via a codename.
|
* Helper function to return the appropriate groups via a codenames
|
||||||
|
*
|
||||||
|
* @param array $codenames Group codenames
|
||||||
|
* @return array Returns the the appropriate groups.
|
||||||
*/
|
*/
|
||||||
protected function codenamesToGroups($codenames) {
|
protected function codenamesToGroups($codenames) {
|
||||||
$list = "'" . implode("', '", $codenames) . "'";
|
$list = "'" . implode("', '", $codenames) . "'";
|
||||||
$output = DataObject::get("Group", "Code IN ($list)");
|
$output = DataObject::get("Group", "Code IN ($list)");
|
||||||
|
|
||||||
// Some are missing - throw warnings
|
// Some are missing - throw warnings
|
||||||
if(!$output || $output->Count() != sizeof($list)) {
|
if(!$output || ($output->Count() != sizeof($list))) {
|
||||||
foreach($codenames as $codename) $missing[$codename] = $codename;
|
foreach($codenames as $codename)
|
||||||
if($output) foreach($output as $record) unset($missing[$record->Code]);
|
$missing[$codename] = $codename;
|
||||||
if($missing) user_error("The following group-codes aren't matched to any groups: " . implode(", ", $missing) . ". You probably need to link up the correct group codes in phpMyAdmin", E_USER_WARNING);
|
|
||||||
|
if($output) {
|
||||||
|
foreach($output as $record)
|
||||||
|
unset($missing[$record->Code]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($missing)
|
||||||
|
user_error("The following group-codes aren't matched to any groups: " .
|
||||||
|
implode(", ", $missing) .
|
||||||
|
". You probably need to link up the correct group codes in phpMyAdmin",
|
||||||
|
E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
@ -594,9 +858,12 @@ class Member_GroupSet extends ComponentSet {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used as template to send an email to new members
|
||||||
|
*/
|
||||||
class Member_SignupEmail extends Email_Template {
|
class Member_SignupEmail extends Email_Template {
|
||||||
protected
|
protected
|
||||||
$from = 'ask@perweek.co.nz',
|
$from = '', // setting a blank from address uses the site's default administrator email
|
||||||
$to = '$Email',
|
$to = '$Email',
|
||||||
$subject = "Thanks for signing up",
|
$subject = "Thanks for signing up",
|
||||||
$body = '
|
$body = '
|
||||||
@ -644,17 +911,19 @@ class Member_SignupEmail extends Email_Template {
|
|||||||
|
|
||||||
function MemberData() {
|
function MemberData() {
|
||||||
return $this->template_data->listOfFields(
|
return $this->template_data->listOfFields(
|
||||||
"FirstName","Surname","Email",
|
"FirstName", "Surname", "Email",
|
||||||
"Phone","Mobile","Street",
|
"Phone", "Mobile", "Street",
|
||||||
"Suburb","City","Postcode","DriversLicense5A","DriversLicense5B"
|
"Suburb", "City", "Postcode", "DriversLicense5A", "DriversLicense5B"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an email saying that the password has been reset.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used as template to send an email saying that the password has been
|
||||||
|
* changed
|
||||||
|
*/
|
||||||
class Member_ChangePasswordEmail extends Email_Template {
|
class Member_ChangePasswordEmail extends Email_Template {
|
||||||
protected $from = ''; // setting a blank from address uses the site's default administrator email
|
protected $from = ''; // setting a blank from address uses the site's default administrator email
|
||||||
protected $subject = "Your password has been changed";
|
protected $subject = "Your password has been changed";
|
||||||
@ -662,31 +931,57 @@ class Member_ChangePasswordEmail extends Email_Template {
|
|||||||
protected $to = '$Email';
|
protected $to = '$Email';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used as template to send the forgot password email
|
||||||
|
*/
|
||||||
class Member_ForgotPasswordEmail extends Email_Template {
|
class Member_ForgotPasswordEmail extends Email_Template {
|
||||||
protected $from = '';
|
protected $from = ''; // setting a blank from address uses the site's default administrator email
|
||||||
protected $subject = "Your password";
|
protected $subject = "Your password";
|
||||||
protected $ss_template = 'ForgotPasswordEmail';
|
protected $ss_template = 'ForgotPasswordEmail';
|
||||||
protected $to = '$Email';
|
protected $to = '$Email';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record to keep track of which records a member has unsubscribed from and when
|
* Record to keep track of which records a member has unsubscribed from and
|
||||||
|
* when
|
||||||
|
*
|
||||||
|
* @todo Check if that email stuff ($from, $to, $subject, $body) is needed
|
||||||
|
* here! (Markus)
|
||||||
*/
|
*/
|
||||||
class Member_UnsubscribeRecord extends DataObject {
|
class Member_UnsubscribeRecord extends DataObject {
|
||||||
|
|
||||||
static $has_one = array(
|
static $has_one = array(
|
||||||
'NewsletterType' => 'NewsletterType',
|
'NewsletterType' => 'NewsletterType',
|
||||||
'Member' => 'Member'
|
'Member' => 'Member'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe the member from a specific newsletter type
|
||||||
|
*
|
||||||
|
* @param int|Member $member Member object or ID
|
||||||
|
* @param int|NewsletterType $newsletterType Newsletter type object or ID
|
||||||
|
*/
|
||||||
|
function unsubscribe($member, $newsletterType) {
|
||||||
|
// $this->UnsubscribeDate()->setVal( 'now' );
|
||||||
|
$this->MemberID = (is_numeric($member))
|
||||||
|
? $member
|
||||||
|
: $member->ID;
|
||||||
|
|
||||||
|
$this->NewsletterTypeID = (is_numeric($newletterType))
|
||||||
|
? $newsletterType
|
||||||
|
: $newsletterType->ID;
|
||||||
|
|
||||||
|
$this->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function unsubscribe( $member, $newsletterType ) {
|
|
||||||
// $this->UnsubscribeDate()->setVal( 'now' );
|
|
||||||
$this->MemberID = ( is_numeric( $member ) ) ? $member : $member->ID;
|
|
||||||
$this->NewsletterTypeID = ( is_numeric( $newletterType ) ) ? $newsletterType : $newsletterType->ID;
|
|
||||||
$this->write();
|
|
||||||
}
|
|
||||||
protected
|
protected
|
||||||
$from = 'ask@perweek.co.nz',
|
$from = '', // setting a blank from address uses the site's default administrator email
|
||||||
$to = '$Email',
|
$to = '$Email',
|
||||||
$subject = "Your password has been changed",
|
$subject = "Your password has been changed",
|
||||||
$body = '
|
$body = '
|
||||||
@ -698,9 +993,19 @@ class Member_UnsubscribeRecord extends DataObject {
|
|||||||
<p>Your password has been changed. Please keep this email, for future reference.</p>';
|
<p>Your password has been changed. Please keep this email, for future reference.</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
class Member_Validator extends RequiredFields {
|
|
||||||
protected $customRequired = array('FirstName', 'Email', 'Password');
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Member Validator
|
||||||
|
*/
|
||||||
|
class Member_Validator extends RequiredFields {
|
||||||
|
|
||||||
|
protected $customRequired = array('FirstName', 'Email'); //, 'Password');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$required = func_get_args();
|
$required = func_get_args();
|
||||||
if(isset($required[0]) && is_array($required[0])) {
|
if(isset($required[0]) && is_array($required[0])) {
|
||||||
@ -708,24 +1013,43 @@ class Member_Validator extends RequiredFields {
|
|||||||
}
|
}
|
||||||
$required = array_merge($required, $this->customRequired);
|
$required = array_merge($required, $this->customRequired);
|
||||||
|
|
||||||
parent::__construct($required);
|
parent::__construct($required);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the submitted member data is valid
|
||||||
|
*
|
||||||
|
* Check if a member with that email doesn't already exist, or if it does
|
||||||
|
* that it is this member.
|
||||||
|
*
|
||||||
|
* @param array $data Submitted data
|
||||||
|
* @return bool Returns TRUE if the submitted data is valid, otherwise
|
||||||
|
* FALSE.
|
||||||
|
*/
|
||||||
function php($data) {
|
function php($data) {
|
||||||
$valid = parent::php($data);
|
$valid = parent::php($data);
|
||||||
|
|
||||||
// Check if a member with that email doesn't already exist, or if it does that it is this member.
|
$member = DataObject::get_one('Member',
|
||||||
$member = DataObject::get_one('Member', "Email = '". Convert::raw2sql($data['Email']) ."'");
|
"Email = '". Convert::raw2sql($data['Email']) ."'");
|
||||||
// if we are in a complex table field popup, use ctf[childID], else use ID
|
|
||||||
$id = (isset($_REQUEST['ctf']['childID'])) ? $_REQUEST['ctf']['childID'] : $_REQUEST['ID'];
|
// if we are in a complex table field popup, use ctf[childID], else use
|
||||||
|
// ID
|
||||||
|
$id = (isset($_REQUEST['ctf']['childID']))
|
||||||
|
? $_REQUEST['ctf']['childID']
|
||||||
|
: $_REQUEST['ID'];
|
||||||
|
|
||||||
if(is_object($member) && $member->ID != $id) {
|
if(is_object($member) && $member->ID != $id) {
|
||||||
$emailField = $this->form->dataFieldByName('Email');
|
$emailField = $this->form->dataFieldByName('Email');
|
||||||
$this->validationError($emailField->id(), "There already exists a member with this email", "required");
|
$this->validationError($emailField->id(),
|
||||||
|
"There already exists a member with this email",
|
||||||
|
"required");
|
||||||
$valid = false;
|
$valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -1,5 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Member authenticator
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticator for the default "member" method
|
* Authenticator for the default "member" method
|
||||||
*
|
*
|
||||||
@ -11,18 +19,25 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
* Method to authenticate an user
|
* Method to authenticate an user
|
||||||
*
|
*
|
||||||
* @param array $RAW_data Raw data to authenticate the 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()}
|
||||||
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
||||||
* the member object
|
* the member object
|
||||||
*/
|
*/
|
||||||
public function authenticate(array $RAW_data) {
|
public function authenticate(array $RAW_data, Form $form = null) {
|
||||||
$SQL_user = Convert::raw2sql($RAW_data['Email']);
|
$SQL_user = Convert::raw2sql($RAW_data['Email']);
|
||||||
$SQL_password = Convert::raw2sql($RAW_data['Password']);
|
$SQL_password = Convert::raw2sql($RAW_data['Password']);
|
||||||
|
|
||||||
$member = DataObject::get_one(
|
$member = DataObject::get_one(
|
||||||
"Member", "Email = '$SQL_user' And Password = '$SQL_password'");
|
"Member", "Email = '$SQL_user' AND Password = '$SQL_password'");
|
||||||
|
|
||||||
if($member) {
|
if($member) {
|
||||||
Session::clear("BackURL");
|
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.",
|
||||||
|
"bad");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $member;
|
return $member;
|
||||||
@ -32,11 +47,13 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
/**
|
/**
|
||||||
* Method that creates the login form for this authentication method
|
* Method that creates the login form for this authentication method
|
||||||
*
|
*
|
||||||
|
* @param Controller The parent controller, necessary to create the
|
||||||
|
* appropriate form action tag
|
||||||
* @return Form Returns the login form to use with this authentication
|
* @return Form Returns the login form to use with this authentication
|
||||||
* method
|
* method
|
||||||
*/
|
*/
|
||||||
public function getLoginForm() {
|
public static function getLoginForm(Controller $controller) {
|
||||||
return Object::create("MemberLoginForm", $this, "LoginForm");
|
return Object::create("MemberLoginForm", $controller, "LoginForm");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log-in form for the "member" authentication method
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log-in form for the "member" authentication method
|
* Log-in form for the "member" authentication method
|
||||||
*/
|
*/
|
||||||
@ -7,13 +14,22 @@ class MemberLoginForm extends Form {
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param $controller
|
* @param Controller $controller The parent controller, necessary to
|
||||||
* @param $name
|
* create the appropriate form action tag.
|
||||||
* @param $fields
|
* @param string $name The method on the controller that will return this
|
||||||
* @param $actions
|
* form object.
|
||||||
* @param $checkCurrentUser
|
* @param FieldSet|FormField $fields All of the fields in the form - a
|
||||||
|
* {@link FieldSet} of {@link FormField}
|
||||||
|
* objects.
|
||||||
|
* @param FieldSet|FormAction $actions All of the action buttons in the
|
||||||
|
* form - a {@link FieldSet} of
|
||||||
|
* {@link FormAction} objects
|
||||||
|
* @param bool $checkCurrentUser If set to TRUE, it will be checked if a
|
||||||
|
* the user is currently logged in, and if
|
||||||
|
* so, only a logout button will be rendered
|
||||||
*/
|
*/
|
||||||
function __construct($controller, $name, $fields = null, $actions = null, $checkCurrentUser = true) {
|
function __construct($controller, $name, $fields = null, $actions = null,
|
||||||
|
$checkCurrentUser = true) {
|
||||||
|
|
||||||
$customCSS = project() . '/css/member_login.css';
|
$customCSS = project() . '/css/member_login.css';
|
||||||
if(Director::fileExists($customCSS)) {
|
if(Director::fileExists($customCSS)) {
|
||||||
@ -24,19 +40,21 @@ class MemberLoginForm extends Form {
|
|||||||
$backURL = $_REQUEST['BackURL'];
|
$backURL = $_REQUEST['BackURL'];
|
||||||
} else {
|
} else {
|
||||||
$backURL = Session::get('BackURL');
|
$backURL = Session::get('BackURL');
|
||||||
//Session::clear("BackURL"); don't clear the back URL here! Should be used until the right password is entered!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($checkCurrentUser && Member::currentUserID()) {
|
if($checkCurrentUser && Member::currentUserID()) {
|
||||||
$fields = new FieldSet();
|
$fields = new FieldSet();
|
||||||
$actions = new FieldSet(new FormAction("logout", "Log in as someone else"));
|
$actions = new FieldSet(new FormAction("logout",
|
||||||
|
"Log in as someone else"));
|
||||||
} else {
|
} else {
|
||||||
if(!$fields) {
|
if(!$fields) {
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
new HiddenField("AuthenticationMethod", null, "Member"),
|
new HiddenField("AuthenticationMethod", null, "Member"),
|
||||||
new TextField("Email", "Email address", Session::get('SessionForms.MemberLoginForm.Email')),
|
new TextField("Email", "Email address",
|
||||||
|
Session::get('SessionForms.MemberLoginForm.Email')),
|
||||||
new EncryptField("Password", "Password"),
|
new EncryptField("Password", "Password"),
|
||||||
new CheckboxField("Remember", "Remember me next time?",true)
|
new CheckboxField("Remember", "Remember me next time?",
|
||||||
|
Session::get('SessionForms.MemberLoginForm.Remember'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(!$actions) {
|
if(!$actions) {
|
||||||
@ -60,7 +78,8 @@ class MemberLoginForm extends Form {
|
|||||||
*/
|
*/
|
||||||
protected function getMessageFromSession() {
|
protected function getMessageFromSession() {
|
||||||
parent::getMessageFromSession();
|
parent::getMessageFromSession();
|
||||||
if(($member = Member::currentUser()) && !Session::get('MemberLoginForm.force_message')) {
|
if(($member = Member::currentUser()) &&
|
||||||
|
!Session::get('MemberLoginForm.force_message')) {
|
||||||
$this->message = "You're logged in as $member->FirstName.";
|
$this->message = "You're logged in as $member->FirstName.";
|
||||||
}
|
}
|
||||||
Session::set('MemberLoginForm.force_message', false);
|
Session::set('MemberLoginForm.force_message', false);
|
||||||
@ -75,18 +94,21 @@ class MemberLoginForm extends Form {
|
|||||||
* @param array $data Submitted data
|
* @param array $data Submitted data
|
||||||
*/
|
*/
|
||||||
public function dologin($data) {
|
public function dologin($data) {
|
||||||
if($this->performLogin($data)){
|
if($this->performLogin($data)) {
|
||||||
|
Session::clear('SessionForms.MemberLoginForm.Email');
|
||||||
|
Session::clear('SessionForms.MemberLoginForm.Remember');
|
||||||
|
|
||||||
if($backURL = $_REQUEST['BackURL']) {
|
if($backURL = $_REQUEST['BackURL']) {
|
||||||
Session::clear("BackURL");
|
Session::clear("BackURL");
|
||||||
Session::clear('SessionForms.MemberLoginForm.Email');
|
|
||||||
Director::redirect($backURL);
|
Director::redirect($backURL);
|
||||||
} else
|
} else
|
||||||
Director::redirectBack();
|
Director::redirectBack();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Session::set('SessionForms.MemberLoginForm.Email', $data['Email']);
|
Session::set('SessionForms.MemberLoginForm.Email', $data['Email']);
|
||||||
if($badLoginURL = Session::get("BadLoginURL")){
|
Session::set('SessionForms.MemberLoginForm.Remember',
|
||||||
|
isset($data['Remember']));
|
||||||
|
if($badLoginURL = Session::get("BadLoginURL")) {
|
||||||
Director::redirect($badLoginURL);
|
Director::redirect($badLoginURL);
|
||||||
} else {
|
} else {
|
||||||
Director::redirectBack();
|
Director::redirectBack();
|
||||||
@ -96,13 +118,16 @@ class MemberLoginForm extends Form {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log out
|
* Log out form handler method
|
||||||
*
|
*
|
||||||
* @todo Figure out for what this method is used! Is it really used at all?
|
* This method is called when the user clicks on "logout" on the form
|
||||||
|
* created when the parameter <i>$checkCurrentUser</i> of the
|
||||||
|
* {@link __construct constructor} was set to TRUE and the user was
|
||||||
|
* currently logged in.
|
||||||
*/
|
*/
|
||||||
public function logout(){
|
public function logout() {
|
||||||
$s = new Security();
|
$s = new Security();
|
||||||
return $s->logout();
|
$s->logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -113,20 +138,16 @@ class MemberLoginForm extends Form {
|
|||||||
* @return Member Returns the member object on successful authentication
|
* @return Member Returns the member object on successful authentication
|
||||||
* or NULL on failure.
|
* or NULL on failure.
|
||||||
*/
|
*/
|
||||||
public function performLogin($data){
|
public function performLogin($data) {
|
||||||
if($member = MemberAuthenticator::authenticate($data)) {
|
if($member = MemberAuthenticator::authenticate($data, $this)) {
|
||||||
$firstname = Convert::raw2xml($member->FirstName);
|
$firstname = Convert::raw2xml($member->FirstName);
|
||||||
$this->sessionMessage("Welcome Back, {$firstname}", "good");
|
Session::set("Security.Message.message", "Welcome Back, {$firstname}");
|
||||||
$member->LogIn();
|
Session::set("Security.Message.type", "good");
|
||||||
|
|
||||||
if(isset($data['Remember'])) {
|
$member->LogIn(isset($data['Remember']));
|
||||||
// Deliberately obscure...
|
|
||||||
Cookie::set('alc_enc',base64_encode("$data[Email]:$data[Password]"));
|
|
||||||
}
|
|
||||||
return $member;
|
return $member;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->sessionMessage("That doesn't seem to be the right email address or password. Please try again.", "bad");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,13 +156,15 @@ class MemberLoginForm extends Form {
|
|||||||
/**
|
/**
|
||||||
* Forgot password form handler method
|
* Forgot password form handler method
|
||||||
*
|
*
|
||||||
* This method is called when the user clicks on "Log in"
|
* This method is called when the user clicks on "I've lost my password"
|
||||||
*
|
*
|
||||||
* @param array $data Submitted data
|
* @param array $data Submitted data
|
||||||
*/
|
*/
|
||||||
function forgotPassword($data) {
|
function forgotPassword($data) {
|
||||||
$SQL_data = Convert::raw2sql($data);
|
$SQL_data = Convert::raw2sql($data);
|
||||||
if($data['Email'] && $member = DataObject::get_one("Member", "Member.Email = '$SQL_data[Email]'")) {
|
|
||||||
|
if($data['Email'] && $member = DataObject::get_one("Member",
|
||||||
|
"Member.Email = '$SQL_data[Email]'")) {
|
||||||
if(!$member->Password) {
|
if(!$member->Password) {
|
||||||
$member->createNewPassword();
|
$member->createNewPassword();
|
||||||
$member->write();
|
$member->write();
|
||||||
@ -151,7 +174,9 @@ class MemberLoginForm extends Form {
|
|||||||
Director::redirect('Security/passwordsent/' . urlencode($data['Email']));
|
Director::redirect('Security/passwordsent/' . urlencode($data['Email']));
|
||||||
|
|
||||||
} else if($data['Email']) {
|
} 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?", "bad");
|
$this->sessionMessage(
|
||||||
|
"Sorry, but I don't recognise the email address. Maybe you need to sign up, or perhaps you used another email address?",
|
||||||
|
"bad");
|
||||||
Director::redirectBack();
|
Director::redirectBack();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenID authenticator and controller
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Require the OpenID consumer code.
|
* Require the OpenID consumer code.
|
||||||
*/
|
*/
|
||||||
@ -29,10 +37,13 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
* Method to authenticate an user
|
* Method to authenticate an user
|
||||||
*
|
*
|
||||||
* @param array $RAW_data Raw data to authenticate the 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()}
|
||||||
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
||||||
* the member object
|
* the member object
|
||||||
*/
|
*/
|
||||||
public function authenticate(array $RAW_data) {
|
public function authenticate(array $RAW_data, Form $form = null) {
|
||||||
$openid = $RAW_data['OpenIDURL'];
|
$openid = $RAW_data['OpenIDURL'];
|
||||||
|
|
||||||
$trust_root = Director::absoluteBaseURL();
|
$trust_root = Director::absoluteBaseURL();
|
||||||
@ -59,9 +70,27 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
|
|
||||||
// No auth request means we can't begin OpenID.
|
// No auth request means we can't begin OpenID.
|
||||||
if(!$auth_request) {
|
if(!$auth_request) {
|
||||||
displayError("Authentication error; not a valid OpenID.");
|
if(!is_null($form)) {
|
||||||
|
$form->sessionMessage("That doesn't seem to be a valid OpenID " .
|
||||||
|
"or i-name identifier. Please try again.",
|
||||||
|
"bad");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$SQL_user = Convert::raw2sql($auth_request->endpoint->claimed_id);
|
||||||
|
if(!($member = DataObject::get_one("Member", "Email = '$SQL_user'"))) {
|
||||||
|
if(!is_null($form)) {
|
||||||
|
$form->sessionMessage("Either your account is not enabled for " .
|
||||||
|
"OpenID/i-name authentication " .
|
||||||
|
"or the entered identifier is wrong. " .
|
||||||
|
"Please try again.",
|
||||||
|
"bad");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Check if the POST request should be send directly (without rendering a form)
|
* @todo Check if the POST request should be send directly (without rendering a form)
|
||||||
@ -97,6 +126,7 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
"</title></head>",
|
"</title></head>",
|
||||||
"<body onload='document.getElementById(\"".$form_id."\").submit()'>",
|
"<body onload='document.getElementById(\"".$form_id."\").submit()'>",
|
||||||
$form_html,
|
$form_html,
|
||||||
|
"<p>Click "Continue" to login. You are only seeing this because you appear to have JavaScript disabled.</p>",
|
||||||
"</body></html>");
|
"</body></html>");
|
||||||
|
|
||||||
print implode("\n", $page_contents);
|
print implode("\n", $page_contents);
|
||||||
@ -109,11 +139,13 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
/**
|
/**
|
||||||
* Method that creates the login form for this authentication method
|
* Method that creates the login form for this authentication method
|
||||||
*
|
*
|
||||||
|
* @param Controller The parent controller, necessary to create the
|
||||||
|
* appropriate form action tag
|
||||||
* @return Form Returns the login form to use with this authentication
|
* @return Form Returns the login form to use with this authentication
|
||||||
* method
|
* method
|
||||||
*/
|
*/
|
||||||
public function getLoginForm() {
|
public static function getLoginForm(Controller $controller) {
|
||||||
return Object::create("OpenIDLoginForm", $this, "LoginForm");
|
return Object::create("OpenIDLoginForm", $controller, "LoginForm");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +167,96 @@ class OpenIDAuthenticator_Controller extends Controller {
|
|||||||
function run($requestParams) {
|
function run($requestParams) {
|
||||||
parent::init();
|
parent::init();
|
||||||
|
|
||||||
if(isset($_GET['debug_profile'])) Profiler::mark("OpenIDAuthenticator_Controller");
|
if(isset($_GET['debug_profile']))
|
||||||
|
Profiler::mark("OpenIDAuthenticator_Controller");
|
||||||
|
|
||||||
die("Not implemented yet!");
|
|
||||||
|
|
||||||
if(isset($_GET['debug_profile'])) Profiler::unmark("OpenIDAuthenticator_Controller");
|
/**
|
||||||
|
* This is where the example will store its OpenID information.
|
||||||
|
* You should change this path if you want the example store to be
|
||||||
|
* created elsewhere. After you're done playing with the example
|
||||||
|
* script, you'll have to remove this directory manually.
|
||||||
|
*/
|
||||||
|
$store_path = TEMP_FOLDER;
|
||||||
|
|
||||||
|
if(!file_exists($store_path) && !mkdir($store_path)) {
|
||||||
|
print "Could not create the FileStore directory '$store_path'. ".
|
||||||
|
" Please check the effective permissions.";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
$store = new Auth_OpenID_FileStore($store_path);
|
||||||
|
|
||||||
|
$consumer = new Auth_OpenID_Consumer($store, new SessionWrapper());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Complete the authentication process using the server's response.
|
||||||
|
$response = $consumer->complete();
|
||||||
|
|
||||||
|
if($response->status == Auth_OpenID_CANCEL) {
|
||||||
|
Session::set("Security.Message.message",
|
||||||
|
"The verification was cancelled. Please try again.");
|
||||||
|
Session::set("Security.Message.type", "bad");
|
||||||
|
|
||||||
|
if(isset($_GET['debug_profile']))
|
||||||
|
Profiler::unmark("OpenIDAuthenticator_Controller");
|
||||||
|
|
||||||
|
Director::redirect("Security/login");
|
||||||
|
|
||||||
|
} else if($response->status == Auth_OpenID_FAILURE) {
|
||||||
|
Session::set("Security.Message.message", // use $response->message ??
|
||||||
|
"The OpenID/i-name authentication failed.");
|
||||||
|
Session::set("Security.Message.type", "bad");
|
||||||
|
|
||||||
|
if(isset($_GET['debug_profile']))
|
||||||
|
Profiler::unmark("OpenIDAuthenticator_Controller");
|
||||||
|
|
||||||
|
Director::redirect("Security/login");
|
||||||
|
|
||||||
|
} else if($response->status == Auth_OpenID_SUCCESS) {
|
||||||
|
$openid = $response->identity_url;
|
||||||
|
$user = $openid;
|
||||||
|
|
||||||
|
if($response->endpoint->canonicalID) {
|
||||||
|
$user = $response->endpoint->canonicalID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(isset($_GET['debug_profile']))
|
||||||
|
Profiler::unmark("OpenIDAuthenticator_Controller");
|
||||||
|
|
||||||
|
|
||||||
|
$SQL_user = Convert::raw2sql($user);
|
||||||
|
if($member = DataObject::get_one("Member", "Email = '$SQL_user'")) {
|
||||||
|
$firstname = Convert::raw2xml($member->FirstName);
|
||||||
|
Session::set("Security.Message.message", "Welcome Back, {$firstname}");
|
||||||
|
Session::set("Security.Message.type", "good");
|
||||||
|
|
||||||
|
$member->LogIn(
|
||||||
|
Session::get('SessionForms.OpenIDLoginForm.Remember'));
|
||||||
|
|
||||||
|
Session::clear('SessionForms.OpenIDLoginForm.OpenIDURL');
|
||||||
|
Session::clear('SessionForms.OpenIDLoginForm.Remember');
|
||||||
|
|
||||||
|
if($backURL = Session::get("BackURL")) {
|
||||||
|
Session::clear("BackURL");
|
||||||
|
Director::redirect($backURL);
|
||||||
|
} else {
|
||||||
|
Director::redirectBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Session::set("Security.Message.message",
|
||||||
|
"Login failed. Please try again.");
|
||||||
|
Session::set("Security.Message.type", "bad");
|
||||||
|
|
||||||
|
if($badLoginURL = Session::get("BadLoginURL")) {
|
||||||
|
Director::redirect($badLoginURL);
|
||||||
|
} else {
|
||||||
|
Director::redirectBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -166,7 +283,7 @@ class OpenIDAuthenticator_Controller extends Controller {
|
|||||||
*
|
*
|
||||||
* @author Markus Lanthaler <markus@silverstripe.com>
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
*/
|
*/
|
||||||
class SessionWrapper {
|
class SessionWrapper extends Auth_Yadis_PHPSession {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a session key/value pair.
|
* Set a session key/value pair.
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenID log-in form
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenID log-in form
|
* OpenID log-in form
|
||||||
@ -11,11 +18,19 @@ class OpenIDLoginForm extends Form {
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param $controller
|
* @param Controller $controller The parent controller, necessary to
|
||||||
* @param $name
|
* create the appropriate form action tag.
|
||||||
* @param $fields
|
* @param string $name The method on the controller that will return this
|
||||||
* @param $actions
|
* form object.
|
||||||
* @param $checkCurrentUser
|
* @param FieldSet|FormField $fields All of the fields in the form - a
|
||||||
|
* {@link FieldSet} of {@link FormField}
|
||||||
|
* objects.
|
||||||
|
* @param FieldSet|FormAction $actions All of the action buttons in the
|
||||||
|
* form - a {@link FieldSet} of
|
||||||
|
* {@link FormAction} objects
|
||||||
|
* @param bool $checkCurrentUser If set to TRUE, it will be checked if a
|
||||||
|
* the user is currently logged in, and if
|
||||||
|
* so, only a logout button will be rendered
|
||||||
*/
|
*/
|
||||||
function __construct($controller, $name, $fields = null, $actions = null,
|
function __construct($controller, $name, $fields = null, $actions = null,
|
||||||
$checkCurrentUser = true) {
|
$checkCurrentUser = true) {
|
||||||
@ -28,19 +43,20 @@ class OpenIDLoginForm extends Form {
|
|||||||
$backURL = $_REQUEST['BackURL'];
|
$backURL = $_REQUEST['BackURL'];
|
||||||
} else {
|
} else {
|
||||||
$backURL = Session::get('BackURL');
|
$backURL = Session::get('BackURL');
|
||||||
//Session::clear("BackURL"); don't clear the back URL here! Should be used until the right password is entered!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($checkCurrentUser && Member::currentUserID()) {
|
if($checkCurrentUser && Member::currentUserID()) {
|
||||||
$fields = new FieldSet();
|
$fields = new FieldSet();
|
||||||
$actions = new FieldSet(new FormAction("logout", "Log in as someone else"));
|
$actions = new FieldSet(new FormAction("logout",
|
||||||
|
"Log in as someone else"));
|
||||||
} else {
|
} else {
|
||||||
if(!$fields) {
|
if(!$fields) {
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
new HiddenField("AuthenticationMethod", null, "OpenID"),
|
new HiddenField("AuthenticationMethod", null, "OpenID"),
|
||||||
new TextField("OpenIDURL", "OpenID URL",
|
new TextField("OpenIDURL", "OpenID URL",
|
||||||
Session::get('SessionForms.OpenIDLoginForm.OpenIDURL')),
|
Session::get('SessionForms.OpenIDLoginForm.OpenIDURL')),
|
||||||
new CheckboxField("Remember", "Remember me next time?", true)
|
new CheckboxField("Remember", "Remember me next time?",
|
||||||
|
Session::get('SessionForms.OpenIDLoginForm.Remember'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(!$actions) {
|
if(!$actions) {
|
||||||
@ -79,60 +95,34 @@ class OpenIDLoginForm extends Form {
|
|||||||
* @param array $data Submitted data
|
* @param array $data Submitted data
|
||||||
*/
|
*/
|
||||||
public function dologin($data) {
|
public function dologin($data) {
|
||||||
if($this->performLogin($data)){
|
Session::set('SessionForms.OpenIDLoginForm.Remember',
|
||||||
|
isset($data['Remember']));
|
||||||
|
|
||||||
if($backURL = $_REQUEST['BackURL']) {
|
OpenIDAuthenticator::authenticate($data, $this);
|
||||||
Session::clear("BackURL");
|
|
||||||
Session::clear('SessionForms.OpenIDLoginForm.OpenIDURL');
|
|
||||||
Director::redirect($backURL);
|
|
||||||
} else
|
|
||||||
Director::redirectBack();
|
|
||||||
|
|
||||||
|
// If the OpenID authenticator returns, an error occured!
|
||||||
|
Session::set('SessionForms.OpenIDLoginForm.OpenIDURL',
|
||||||
|
$data['OpenIDURL']);
|
||||||
|
|
||||||
|
if($badLoginURL = Session::get("BadLoginURL")){
|
||||||
|
Director::redirect($badLoginURL);
|
||||||
} else {
|
} else {
|
||||||
Session::set('SessionForms.OpenIDLoginForm.OpenIDURL', $data['OpenIDURL']);
|
Director::redirectBack();
|
||||||
if($badLoginURL = Session::get("BadLoginURL")){
|
|
||||||
Director::redirect($badLoginURL);
|
|
||||||
} else {
|
|
||||||
Director::redirectBack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log out
|
* Log out form handler method
|
||||||
*
|
*
|
||||||
* @todo Figure out for what this method is used! Is it really used at all?
|
* This method is called when the user clicks on "logout" on the form
|
||||||
|
* created when the parameter <i>$checkCurrentUser</i> of the
|
||||||
|
* {@link __construct constructor} was set to TRUE and the user was
|
||||||
|
* currently logged in.
|
||||||
*/
|
*/
|
||||||
public function logout() {
|
public function logout() {
|
||||||
$s = new Security();
|
$s = new Security();
|
||||||
return $s->logout();
|
$s->logout();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to authenticate the user
|
|
||||||
*
|
|
||||||
* @param array Submitted data
|
|
||||||
* @return Member Returns the member object on successful authentication
|
|
||||||
* or NULL on failure.
|
|
||||||
*/
|
|
||||||
public function performLogin(array $data) {
|
|
||||||
if($member = OpenIDAuthenticator::authenticate($data)) {
|
|
||||||
$firstname = Convert::raw2xml($member->FirstName);
|
|
||||||
$this->sessionMessage("Welcome Back, {$firstname}", "good");
|
|
||||||
$member->LogIn();
|
|
||||||
|
|
||||||
if(isset($data['Remember'])) {
|
|
||||||
// Deliberately obscure...
|
|
||||||
Cookie::set('alc_enc',base64_encode("$data[OpenIDURL]"));
|
|
||||||
}
|
|
||||||
return $member;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$this->sessionMessage("Login failed. Please try again.", "bad");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,20 +18,30 @@ class Security extends Controller {
|
|||||||
protected static $strictPathChecking = false;
|
protected static $strictPathChecking = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register that we've had a permission failure trying to view the given page.
|
* Register that we've had a permission failure trying to view the given page
|
||||||
|
*
|
||||||
* This will redirect to a login page.
|
* This will redirect to a login page.
|
||||||
* @param page The controller that you were on to cause the permission failure.
|
|
||||||
* @param messageSet The message to show to the user. This can be a string, or a map of different
|
|
||||||
* messages for different contexts. If you pass an array, you can use the following keys:
|
|
||||||
* - default: The default message
|
|
||||||
* - logInAgain: The message to show if the user has just logged out and the
|
|
||||||
* - alreadyLoggedIn: The message to show if the user is already logged in and lacks the permission to access the item.
|
|
||||||
* If you don't provide a messageSet, a default will be used.
|
* If you don't provide a messageSet, a default will be used.
|
||||||
|
*
|
||||||
|
* @param $page The controller that you were on to cause the permission
|
||||||
|
* failure.
|
||||||
|
* @param string|array $messageSet The message to show to the user. This
|
||||||
|
* can be a string, or a map of different
|
||||||
|
* messages for different contexts.
|
||||||
|
* If you pass an array, you can use the
|
||||||
|
* following keys:
|
||||||
|
* - default: The default message
|
||||||
|
* - logInAgain: The message to show
|
||||||
|
* if the user has just
|
||||||
|
* logged out and the
|
||||||
|
* - alreadyLoggedIn: The message to
|
||||||
|
* show if the user
|
||||||
|
* is already logged
|
||||||
|
* in and lacks the
|
||||||
|
* permission to
|
||||||
|
* access the item.
|
||||||
*/
|
*/
|
||||||
static function permissionFailure($page = null, $messageSet = null) {
|
static function permissionFailure($page, $messageSet = null) {
|
||||||
// $loginForm = singleton('Security')->LoginForm();
|
|
||||||
|
|
||||||
//user_error('debug', E_USER_ERROR);
|
|
||||||
// Prepare the messageSet provided
|
// Prepare the messageSet provided
|
||||||
if(!$messageSet) {
|
if(!$messageSet) {
|
||||||
$messageSet = array(
|
$messageSet = array(
|
||||||
@ -47,24 +57,24 @@ class Security extends Controller {
|
|||||||
if(Member::currentUserID()) {
|
if(Member::currentUserID()) {
|
||||||
// user_error( 'PermFailure with member', E_USER_ERROR );
|
// user_error( 'PermFailure with member', E_USER_ERROR );
|
||||||
|
|
||||||
$message = $messageSet['alreadyLoggedIn'] ? $messageSet['alreadyLoggedIn'] : $messageSet['default'];
|
$message = $messageSet['alreadyLoggedIn']
|
||||||
//$_SESSION['LoginForm']['force_form'] = true;
|
? $messageSet['alreadyLoggedIn']
|
||||||
//$_SESSION['LoginForm']['type'] = 'warning';
|
: $messageSet['default'];
|
||||||
|
|
||||||
Member::logout();
|
Member::logout();
|
||||||
|
|
||||||
} else if(substr(Director::history(),0,15) == 'Security/logout') {
|
} else if(substr(Director::history(),0,15) == 'Security/logout') {
|
||||||
$message = $messageSet['logInAgain'] ? $messageSet['logInAgain'] : $messageSet['default'];
|
$message = $messageSet['logInAgain']
|
||||||
|
? $messageSet['logInAgain']
|
||||||
|
: $messageSet['default'];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$message = $messageSet['default'];
|
$message = $messageSet['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* $loginForm->sessionMessage($message, 'warning');
|
Session::set("Security.Message.message", $message);
|
||||||
Session::set("SecurityMessage.Error.message", $message);
|
Session::set("Security.Message.type", 'warning');
|
||||||
Session::set("SecurityMessage.Error.type", $type);*/
|
|
||||||
|
|
||||||
// $_SESSION['LoginForm']['message'] = $message;
|
|
||||||
Session::set("BackURL", $_SERVER['REQUEST_URI']);
|
Session::set("BackURL", $_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
if(Director::is_ajax()) {
|
if(Director::is_ajax()) {
|
||||||
@ -85,10 +95,10 @@ class Security extends Controller {
|
|||||||
switch($_REQUEST['AuthenticationMethod'])
|
switch($_REQUEST['AuthenticationMethod'])
|
||||||
{
|
{
|
||||||
case 'Member':
|
case 'Member':
|
||||||
return MemberAuthenticator::GetLoginForm();
|
return MemberAuthenticator::GetLoginForm($this);
|
||||||
break;
|
break;
|
||||||
case 'OpenID':
|
case 'OpenID':
|
||||||
return OpenIDAuthenticator::GetLoginForm();
|
return OpenIDAuthenticator::GetLoginForm($this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,13 +109,16 @@ class Security extends Controller {
|
|||||||
/**
|
/**
|
||||||
* Get the login forms for all available authentication methods
|
* Get the login forms for all available authentication methods
|
||||||
*
|
*
|
||||||
|
* @return array Returns an array of available login forms (array of Form
|
||||||
|
* objects).
|
||||||
|
*
|
||||||
* @todo Check how to activate/deactivate authentication methods
|
* @todo Check how to activate/deactivate authentication methods
|
||||||
*/
|
*/
|
||||||
function GetLoginForms()
|
function GetLoginForms()
|
||||||
{
|
{
|
||||||
$forms = array();
|
$forms = array();
|
||||||
array_push($forms, MemberAuthenticator::GetLoginForm());
|
array_push($forms, MemberAuthenticator::GetLoginForm($this));
|
||||||
array_push($forms, OpenIDAuthenticator::GetLoginForm());
|
array_push($forms, OpenIDAuthenticator::GetLoginForm($this));
|
||||||
|
|
||||||
return $forms;
|
return $forms;
|
||||||
}
|
}
|
||||||
@ -115,6 +128,7 @@ class Security extends Controller {
|
|||||||
* Get a link to a security action
|
* Get a link to a security action
|
||||||
*
|
*
|
||||||
* @param string $action Name of the action
|
* @param string $action Name of the action
|
||||||
|
* @return string Returns the link to the given action
|
||||||
*/
|
*/
|
||||||
function Link($action = null) {
|
function Link($action = null) {
|
||||||
return "Security/$action";
|
return "Security/$action";
|
||||||
@ -130,15 +144,18 @@ class Security extends Controller {
|
|||||||
* they should go.
|
* they should go.
|
||||||
*/
|
*/
|
||||||
function logout($redirect = true) {
|
function logout($redirect = true) {
|
||||||
Cookie::set('alc_enc',null);
|
if($member = Member::currentUser())
|
||||||
Cookie::forceExpiry('alc_enc');
|
$member->logOut();
|
||||||
Session::clear("loggedInAs");
|
|
||||||
if($redirect) Director::redirectBack();
|
if($redirect)
|
||||||
|
Director::redirectBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Show the "login" page
|
||||||
*
|
*
|
||||||
|
* @return string Returns the "login" page as HTML code.
|
||||||
*/
|
*/
|
||||||
function login() {
|
function login() {
|
||||||
Requirements::javascript("jsparty/behaviour.js");
|
Requirements::javascript("jsparty/behaviour.js");
|
||||||
@ -164,9 +181,23 @@ class Security extends Controller {
|
|||||||
foreach($forms as $form)
|
foreach($forms as $form)
|
||||||
$content .= $form->forTemplate();
|
$content .= $form->forTemplate();
|
||||||
|
|
||||||
$customisedController = $controller->customise(array(
|
if(strlen($message = Session::get('Security.Message.message')) > 0) {
|
||||||
"Content" => $content
|
$message_type = Session::get('Security.Message.type');
|
||||||
));
|
if($message_type == 'bad') {
|
||||||
|
$message = "<p class=\"message $message_type\">$message</p>";
|
||||||
|
} else {
|
||||||
|
$message = "<p>$message</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$customisedController = $controller->customise(array(
|
||||||
|
"Content" => $message,
|
||||||
|
"Form" => $content
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
$customisedController = $controller->customise(array(
|
||||||
|
"Content" => $content
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return $customisedController->renderWith("Page");
|
return $customisedController->renderWith("Page");
|
||||||
}
|
}
|
||||||
@ -174,7 +205,9 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Show the "lost password" page
|
||||||
*
|
*
|
||||||
|
* @return string Returns the "lost password " page as HTML code.
|
||||||
*/
|
*/
|
||||||
function lostpassword() {
|
function lostpassword() {
|
||||||
Requirements::javascript("jsparty/prototype.js");
|
Requirements::javascript("jsparty/prototype.js");
|
||||||
@ -189,7 +222,8 @@ class Security extends Controller {
|
|||||||
$controller = new Page_Controller($tmpPage);
|
$controller = new Page_Controller($tmpPage);
|
||||||
|
|
||||||
$customisedController = $controller->customise(array(
|
$customisedController = $controller->customise(array(
|
||||||
"Content" => "<p>Enter your e-mail address and we will send you a password</p>",
|
"Content" =>
|
||||||
|
"<p>Enter your e-mail address and we will send you a password</p>",
|
||||||
"Form" => $this->LostPasswordForm(),
|
"Form" => $this->LostPasswordForm(),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -199,7 +233,9 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Show the "password sent" page
|
||||||
*
|
*
|
||||||
|
* @return string Returns the "password sent" page as HTML code.
|
||||||
*/
|
*/
|
||||||
function passwordsent() {
|
function passwordsent() {
|
||||||
Requirements::javascript("jsparty/behaviour.js");
|
Requirements::javascript("jsparty/behaviour.js");
|
||||||
@ -216,7 +252,8 @@ class Security extends Controller {
|
|||||||
$email = $this->urlParams['ID'];
|
$email = $this->urlParams['ID'];
|
||||||
$customisedController = $controller->customise(array(
|
$customisedController = $controller->customise(array(
|
||||||
"Title" => "Password sent to '$email'",
|
"Title" => "Password sent to '$email'",
|
||||||
"Content" => "<p>Thank you, your password has been sent to '$email'.</p>",
|
"Content" =>
|
||||||
|
"<p>Thank you, your password has been sent to '$email'.</p>",
|
||||||
));
|
));
|
||||||
|
|
||||||
//Controller::$currentController = $controller;
|
//Controller::$currentController = $controller;
|
||||||
@ -225,7 +262,9 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Factory method for the lost password form
|
||||||
*
|
*
|
||||||
|
* @return Form Returns the lost password form
|
||||||
*/
|
*/
|
||||||
function LostPasswordForm() {
|
function LostPasswordForm() {
|
||||||
return new MemberLoginForm($this, "LostPasswordForm", new FieldSet(
|
return new MemberLoginForm($this, "LostPasswordForm", new FieldSet(
|
||||||
@ -238,17 +277,23 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate using the given email and password, returning the appropriate member object if
|
* Authenticate using the given email and password, returning the
|
||||||
|
* appropriate member object if
|
||||||
|
*
|
||||||
|
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
||||||
|
* the member object
|
||||||
*/
|
*/
|
||||||
static function authenticate($RAW_email, $RAW_password) {
|
static function authenticate($RAW_email, $RAW_password) {
|
||||||
$SQL_email = Convert::raw2sql($RAW_email);
|
$SQL_email = Convert::raw2sql($RAW_email);
|
||||||
$SQL_password = Convert::raw2sql($RAW_password);
|
$SQL_password = Convert::raw2sql($RAW_password);
|
||||||
|
|
||||||
// Default login (see {@setDetaultAdmin()})
|
// Default login (see {@setDetaultAdmin()})
|
||||||
if( $RAW_email == self::$username && $RAW_password == self::$password && !empty( self::$username ) && !empty( self::$password ) ) {
|
if(($RAW_email == self::$username) && ($RAW_password == self::$password)
|
||||||
|
&& !empty(self::$username) && !empty(self::$password)) {
|
||||||
$member = self::findAnAdministrator();
|
$member = self::findAnAdministrator();
|
||||||
} else {
|
} else {
|
||||||
$member = DataObject::get_one("Member", "Email = '$SQL_email' And Password = '$SQL_password'");
|
$member = DataObject::get_one("Member",
|
||||||
|
"Email = '$SQL_email' And Password = '$SQL_password'");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $member;
|
return $member;
|
||||||
@ -257,8 +302,12 @@ class Security extends Controller {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a member with administrator privileges
|
* Return a member with administrator privileges
|
||||||
|
*
|
||||||
|
* @return Member Returns a member object that has administrator
|
||||||
|
* privileges.
|
||||||
*/
|
*/
|
||||||
static function findAnAdministrator($username = 'admin', $password = 'password') {
|
static function findAnAdministrator($username = 'admin',
|
||||||
|
$password = 'password') {
|
||||||
$permission = DataObject::get_one("Permission", "`Code` = 'ADMIN'");
|
$permission = DataObject::get_one("Permission", "`Code` = 'ADMIN'");
|
||||||
|
|
||||||
$adminGroup = null;
|
$adminGroup = null;
|
||||||
@ -292,10 +341,10 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will set a static default-admin (e.g. "td") which is not existing as
|
* This will set a static default-admin (e.g. "td") which is not existing
|
||||||
* a database-record. By this workaround we can test pages in dev-mode with
|
* as a database-record. By this workaround we can test pages in dev-mode
|
||||||
* a unified login. Submitted login-credentials are first checked against
|
* with a unified login. Submitted login-credentials are first checked
|
||||||
* this static information in {@authenticate()}.
|
* against this static information in {@authenticate()}.
|
||||||
*
|
*
|
||||||
* @param $username String
|
* @param $username String
|
||||||
* @param $password String (Cleartext)
|
* @param $password String (Cleartext)
|
||||||
@ -310,10 +359,12 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set strict path checking. This prevents sharing of the session
|
* Set strict path checking
|
||||||
* across several sites in the domain.
|
|
||||||
*
|
*
|
||||||
* @param strictPathChecking boolean to enable or disable strict patch checking.
|
* This prevents sharing of the session across several sites in the domain.
|
||||||
|
*
|
||||||
|
* @param boolean $strictPathChecking To enable or disable strict patch
|
||||||
|
* checking.
|
||||||
*/
|
*/
|
||||||
static function setStrictPathChecking($strictPathChecking) {
|
static function setStrictPathChecking($strictPathChecking) {
|
||||||
self::$strictPathChecking = $strictPathChecking;
|
self::$strictPathChecking = $strictPathChecking;
|
||||||
@ -321,7 +372,9 @@ class Security extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get strict path checking
|
||||||
*
|
*
|
||||||
|
* @return boolean Status of strict path checking
|
||||||
*/
|
*/
|
||||||
static function getStrictPathChecking() {
|
static function getStrictPathChecking() {
|
||||||
return self::$strictPathChecking;
|
return self::$strictPathChecking;
|
||||||
|
Loading…
Reference in New Issue
Block a user