mirror of
https://github.com/scratchfoundation/swiki-confirmaccount.git
synced 2024-12-04 12:51:01 -05:00
changed password tool so that user specifies their password at account request
This commit is contained in:
parent
4bf8b4e65f
commit
5b37e7dd88
5 changed files with 1170 additions and 1154 deletions
|
@ -1,6 +1,5 @@
|
|||
Complete online documenation:
|
||||
Original version: http://www.mediawiki.org/wiki/Extension:ConfirmAccount
|
||||
Modified version: http://wiki.scratch.mit.edu/wiki/User:Jvvg/Authentication
|
||||
http://www.mediawiki.org/wiki/Extension:ConfirmAccount
|
||||
|
||||
== Breaking changes ==
|
||||
=== MediaWiki 1.20 ===
|
||||
|
@ -8,9 +7,5 @@ $wgAccountRequestMinWords, $wgAccountRequestToS, $wgAccountRequestExtraInfo,
|
|||
and $wgAllowAccountRequestFiles were all folded into a new variable called
|
||||
$wgConfirmAccountRequestFormItems.
|
||||
|
||||
=== Modified version ===
|
||||
Gutted all email functionality - the user is given their temporary password when they register rather than when their request is accepted, and added a tool to verify registrations against the Scratch website.
|
||||
|
||||
== Licensing ==
|
||||
Original version © GPL, Aaron Schulz
|
||||
Modified version also available under GPL, by Jacob G.
|
||||
© GPL, Aaron Schulz
|
||||
|
|
|
@ -1,450 +1,451 @@
|
|||
<?php
|
||||
|
||||
class AccountConfirmSubmission {
|
||||
/* User making the confirmation */
|
||||
protected $admin;
|
||||
/** @var UserAccountRequest */
|
||||
protected $accReq;
|
||||
/* Admin-overridable name and fields filled from request form */
|
||||
protected $userName;
|
||||
protected $bio;
|
||||
protected $type;
|
||||
/** @var array */
|
||||
protected $areas;
|
||||
|
||||
protected $action;
|
||||
protected $reason;
|
||||
|
||||
public function __construct( User $admin, UserAccountRequest $accReq, array $params ) {
|
||||
$this->admin = $admin;
|
||||
$this->accountReq = $accReq;
|
||||
$this->userName = trim( $params['userName'] );
|
||||
$this->bio = trim( $params['bio'] );
|
||||
$this->type = $params['type'];
|
||||
$this->areas = $params['areas'];
|
||||
$this->action = $params['action'];
|
||||
$this->reason = $params['reason'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate and submit this data to the DB
|
||||
* @param $context IContextSource
|
||||
* @return array( true or error key string, html error msg or null )
|
||||
*/
|
||||
public function submit( IContextSource $context ) {
|
||||
# Make sure that basic permissions are checked
|
||||
if ( !$this->admin->getID() || !$this->admin->isAllowed( 'confirmaccount' ) ) {
|
||||
return array( 'accountconf_permission_denied', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
} elseif ( wfReadOnly() ) {
|
||||
return array( 'accountconf_readonly', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
}
|
||||
if ( $this->action === 'spam' ) {
|
||||
return $this->spamRequest( $context );
|
||||
} elseif ( $this->action === 'reject' ) {
|
||||
return $this->rejectRequest( $context );
|
||||
} elseif ( $this->action === 'hold' ) {
|
||||
return $this->holdRequest( $context );
|
||||
} elseif ( $this->action === 'accept' ) {
|
||||
return $this->acceptRequest( $context );
|
||||
} else {
|
||||
return array( 'accountconf_bad_action', $context->msg( 'confirmaccount-badaction' )->escaped() );
|
||||
}
|
||||
}
|
||||
|
||||
protected function spamRequest( IContextSource $context ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$ok = $this->accountReq->markRejected( $this->admin, wfTimestampNow(), '' );
|
||||
if ( $ok ) {
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
}
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function rejectRequest( IContextSource $context ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$ok = $this->accountReq->markRejected( $this->admin, wfTimestampNow(), $this->reason );
|
||||
if ( $ok ) {
|
||||
/*
|
||||
# Make proxy user to email a rejection message :(
|
||||
$u = User::newFromName( $this->accountReq->getName(), false );
|
||||
$u->setEmail( $this->accountReq->getEmail() );
|
||||
# Send out a rejection email...
|
||||
if ( $this->reason != '' ) {
|
||||
$emailBody = $context->msg( 'confirmaccount-email-body4',
|
||||
$u->getName(), $this->reason )->inContentLanguage()->text();
|
||||
} else {
|
||||
$emailBody = $context->msg( 'confirmaccount-email-body3',
|
||||
$u->getName() )->inContentLanguage()->text();
|
||||
}
|
||||
$result = $u->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$emailBody
|
||||
);
|
||||
if ( !$result->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_mailerror',
|
||||
$context->msg( 'mailerror' )->rawParams( $context->getOutput()->parse( $result->getWikiText() ) )->text() );
|
||||
}
|
||||
# Clear cache for notice of how many account requests there are
|
||||
*/
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
}
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function holdRequest( IContextSource $context ) {
|
||||
# Make proxy user to email a message
|
||||
$u = User::newFromName( $this->accountReq->getName(), false );
|
||||
$u->setEmail( $this->accountReq->getEmail() );
|
||||
|
||||
# Pointless without a summary...
|
||||
if ( $this->reason == '' ) {
|
||||
return array( 'accountconf_needreason', $context->msg( 'confirmaccount-needreason' )->escaped() );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
# If not already held or deleted, mark as held
|
||||
$ok = $this->accountReq->markHeld( $this->admin, wfTimestampNow(), $this->reason );
|
||||
if ( !$ok ) { // already held or deleted?
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_canthold', $context->msg( 'confirmaccount-canthold' )->escaped() );
|
||||
}
|
||||
|
||||
# Send out a request hold email...
|
||||
$result = $u->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$context->msg( 'confirmaccount-email-body5', $u->getName(), $this->reason )->inContentLanguage()->text()
|
||||
);
|
||||
if ( !$result->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_mailerror',
|
||||
$context->msg( 'mailerror' )->rawParams( $context->getOutput()->parse( $result->getWikiText() ) )->text() );
|
||||
}
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function acceptRequest( IContextSource $context ) {
|
||||
global $wgAuth, $wgAccountRequestTypes, $wgConfirmAccountSaveInfo;
|
||||
global $wgConfirmAccountRequestFormItems, $wgConfirmAccountFSRepos;
|
||||
|
||||
$formConfig = $wgConfirmAccountRequestFormItems; // convience
|
||||
$accReq = $this->accountReq; // convenience
|
||||
|
||||
# Now create user and check if the name is valid
|
||||
$user = User::newFromName( $this->userName, 'creatable' );
|
||||
if ( !$user ) {
|
||||
return array( 'accountconf_invalid_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
|
||||
# Check if account name is already in use
|
||||
if ( 0 != $user->idForName() || $wgAuth->userExists( $user->getName() ) ) {
|
||||
return array( 'accountconf_user_exists', $context->msg( 'userexists' )->escaped() );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
# Make a random password
|
||||
$p = md5(strtolower($accReq->getNotes()));
|
||||
|
||||
# Insert the new user into the DB...
|
||||
$tokenExpires = $accReq->getEmailTokenExpires();
|
||||
$authenticated = $accReq->getEmailAuthTimestamp();
|
||||
$params = array(
|
||||
# Set the user's real name
|
||||
'real_name' => $accReq->getRealName(),
|
||||
# Set the temporary password
|
||||
'newpassword' => User::crypt( $p ),
|
||||
# VERY important to set email now. Otherwise the user
|
||||
# will have to request a new password at the login screen...
|
||||
'email' => $accReq->getEmail(),
|
||||
# Import email address confirmation status
|
||||
'email_authenticated' => $dbw->timestampOrNull( $authenticated ),
|
||||
'email_token_expires' => $dbw->timestamp( $tokenExpires ),
|
||||
'email_token' => $accReq->getEmailToken()
|
||||
);
|
||||
$user = User::createNew( $user->getName(), $params );
|
||||
|
||||
# Grant any necessary rights (exclude blank or dummy groups)
|
||||
$group = self::getGroupFromType( $this->type );
|
||||
if ( $group != '' && $group != 'user' && $group != '*' ) {
|
||||
$user->addGroup( $group );
|
||||
}
|
||||
|
||||
$acd_id = null; // used for rollback cleanup
|
||||
# Save account request data to credentials system
|
||||
if ( $wgConfirmAccountSaveInfo ) {
|
||||
$key = $accReq->getFileStorageKey();
|
||||
# Copy any attached files to new storage group
|
||||
if ( $formConfig['CV']['enabled'] && $key ) {
|
||||
$repoOld = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$repoNew = new FSRepo( $wgConfirmAccountFSRepos['accountcreds'] );
|
||||
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$oldPath = $repoOld->getZonePath( 'public' ) . '/' . $pathRel;
|
||||
|
||||
$triplet = array( $oldPath, 'public', $pathRel );
|
||||
$status = $repoNew->storeBatch( array( $triplet ) ); // copy!
|
||||
if ( !$status->isOK() ) {
|
||||
$dbw->rollback();
|
||||
# DELETE new rows in case there was a COMMIT somewhere
|
||||
$this->acceptRequest_rollback( $dbw, $user->getId(), $acd_id );
|
||||
return array( 'accountconf_copyfailed',
|
||||
$context->getOutput()->parse( $status->getWikiText() ) );
|
||||
}
|
||||
}
|
||||
$acd_id = $dbw->nextSequenceValue( 'account_credentials_acd_id_seq' );
|
||||
# Move request data into a separate table
|
||||
$dbw->insert( 'account_credentials',
|
||||
array(
|
||||
'acd_user_id' => $user->getID(),
|
||||
'acd_real_name' => $accReq->getRealName(),
|
||||
'acd_email' => $accReq->getEmail(),
|
||||
'acd_email_authenticated' => $dbw->timestampOrNull( $authenticated ),
|
||||
'acd_bio' => $accReq->getBio(),
|
||||
'acd_notes' => $accReq->getNotes(),
|
||||
'acd_urls' => $accReq->getUrls(),
|
||||
'acd_ip' => $accReq->getIP(),
|
||||
'acd_xff' => $accReq->getXFF(),
|
||||
'acd_agent' => $accReq->getAgent(),
|
||||
'acd_filename' => $accReq->getFileName(),
|
||||
'acd_storage_key' => $accReq->getFileStorageKey(),
|
||||
'acd_areas' => $accReq->getAreas( 'flat' ),
|
||||
'acd_registration' => $dbw->timestamp( $accReq->getRegistration() ),
|
||||
'acd_accepted' => $dbw->timestamp(),
|
||||
'acd_user' => $this->admin->getID(),
|
||||
'acd_comment' => $this->reason,
|
||||
'acd_id' => $acd_id
|
||||
),
|
||||
__METHOD__
|
||||
);
|
||||
if ( is_null( $acd_id ) ) {
|
||||
$acd_id = $dbw->insertId(); // set $acd_id to ID inserted
|
||||
}
|
||||
}
|
||||
|
||||
# Add to global user login system (if there is one)
|
||||
if ( !$wgAuth->addUser( $user, $p, $accReq->getEmail(), $accReq->getRealName() ) ) {
|
||||
$dbw->rollback();
|
||||
# DELETE new rows in case there was a COMMIT somewhere
|
||||
$this->acceptRequest_rollback( $dbw, $user->getId(), $acd_id );
|
||||
return array( 'accountconf_externaldberror', $context->msg( 'externaldberror' )->escaped() );
|
||||
}
|
||||
|
||||
# OK, now remove the request from the queue
|
||||
$accReq->remove();
|
||||
|
||||
# Commit this if we make past the CentralAuth system
|
||||
# and the groups are added. Next step is sending out an
|
||||
# email, which we cannot take back...
|
||||
$dbw->commit();
|
||||
|
||||
# Prepare a temporary password email...
|
||||
if ( $this->reason != '' ) {
|
||||
$msg = "confirmaccount-email-body2-pos{$this->type}";
|
||||
# If the user is in a group and there is a welcome for that group, use it
|
||||
if ( $group && !wfEmptyMsg( $msg ) ) {
|
||||
$ebody = $context->msg( $msg, $user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
# Use standard if none found...
|
||||
} else {
|
||||
$ebody = $context->msg( 'confirmaccount-email-body2',
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
}
|
||||
} else {
|
||||
$msg = "confirmaccount-email-body-pos{$this->type}";
|
||||
# If the user is in a group and there is a welcome for that group, use it
|
||||
if ( $group && !$context->msg( $msg )->isDisabled() ) {
|
||||
$ebody = $context->msg( $msg,
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
# Use standard if none found...
|
||||
} else {
|
||||
$ebody = $context->msg( 'confirmaccount-email-body',
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
}
|
||||
}
|
||||
|
||||
# Actually send out the email (@TODO: rollback on failure including $wgAuth)
|
||||
$result = $user->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$ebody
|
||||
);
|
||||
|
||||
# Update user count
|
||||
$ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
|
||||
$ssUpdate->doUpdate();
|
||||
|
||||
# Safe to hook/log now...
|
||||
wfRunHooks( 'AddNewAccount', array( $user, false /* not by email */ ) );
|
||||
$user->addNewUserLogEntry();
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
|
||||
# Delete any attached file and don't stop the whole process if this fails
|
||||
if ( $formConfig['CV']['enabled'] ) {
|
||||
$key = $accReq->getFileStorageKey();
|
||||
if ( $key ) {
|
||||
$repoOld = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$oldPath = $repoOld->getZonePath( 'public' ) . '/' . $pathRel;
|
||||
if ( file_exists( $oldPath ) ) {
|
||||
unlink( $oldPath ); // delete!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Start up the user's userpages if set to do so.
|
||||
# Will not append, so previous content will be blanked.
|
||||
$this->createUserPage( $user );
|
||||
|
||||
# Greet the new user if set to do so.
|
||||
$this->createUserTalkPage( $user );
|
||||
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
/*
|
||||
* Rollback an account acceptance *before* the request row and attachment are deleted.
|
||||
* This is mostly here for sanity in case of COMMITs triggered elsewhere.
|
||||
* http://bugs.mysql.com/bug.php?id=30767 behavoir assumed.
|
||||
* @param $dbw Database
|
||||
* @param $user_id int
|
||||
* @param $acd_id int
|
||||
* @return void
|
||||
*/
|
||||
protected function acceptRequest_rollback( DatabaseBase $dbw, $user_id, $acd_id ) {
|
||||
$dbw->begin();
|
||||
# DELETE the user in case something caused a COMMIT already somewhere.
|
||||
if ( $user_id ) {
|
||||
$dbw->delete( 'user', array( 'user_id' => $user_id ), __METHOD__ );
|
||||
$dbw->delete( 'user_groups', array( 'ug_user' => $user_id ), __METHOD__ );
|
||||
}
|
||||
# DELETE the new account_credentials row likewise.
|
||||
if ( $acd_id ) {
|
||||
$dbw->delete( 'account_credentials', array( 'acd_id' => $acd_id ), __METHOD__ );
|
||||
}
|
||||
$dbw->commit();
|
||||
}
|
||||
|
||||
protected static function getGroupFromType( $type ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$group = '';
|
||||
// Format is (type => (subpage par, group key, group text))
|
||||
if ( isset( $wgAccountRequestTypes[$type][1] ) ) {
|
||||
$group = $wgAccountRequestTypes[$type][1];
|
||||
}
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
protected static function getAutoTextFromType( $type ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$groupText = '';
|
||||
// Format is (type => (subpage par, group key, group text))
|
||||
if ( isset( $wgAccountRequestTypes[$type][2] ) ) {
|
||||
$groupText = $wgAccountRequestTypes[$type][2];
|
||||
}
|
||||
|
||||
return $groupText;
|
||||
}
|
||||
|
||||
protected function createUserPage( User $user ) {
|
||||
global $wgMakeUserPageFromBio, $wgAutoUserBioText;
|
||||
global $wgConfirmAccountSortkey, $wgContLang;
|
||||
|
||||
$body = ''; // page text
|
||||
|
||||
if ( $wgMakeUserPageFromBio ) {
|
||||
# Add account request bio to userpage
|
||||
$body .= $this->bio;
|
||||
# Add any automatic text for all confirmed accounts
|
||||
if ( $wgAutoUserBioText != '' ) {
|
||||
$body .= "\n\n{$wgAutoUserBioText}";
|
||||
}
|
||||
}
|
||||
|
||||
# Add any automatic text for confirmed accounts of this type
|
||||
$autoText = self::getAutoTextFromType( $this->type );
|
||||
if ( $autoText != '' ) {
|
||||
$body .= "\n\n{$autoText}";
|
||||
}
|
||||
|
||||
# Add any areas of interest categories...
|
||||
foreach ( ConfirmAccount::getUserAreaConfig() as $name => $conf ) {
|
||||
if ( in_array( $name, $this->areas ) ) {
|
||||
# General userpage text for anyone with this interest
|
||||
if ( $conf['userText'] != '' ) {
|
||||
$body .= $conf['userText'];
|
||||
}
|
||||
# Message for users with this interested with the given account type
|
||||
if ( isset( $conf['grpUserText'][$this->type] )
|
||||
&& $conf['grpUserText'][$this->type] != '' )
|
||||
{
|
||||
$body .= $conf['grpUserText'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Set sortkey and use it on userpage. This can be used to
|
||||
# normalize things like firstname, lastname and so fourth.
|
||||
if ( !empty( $wgConfirmAccountSortkey ) ) {
|
||||
$sortKey = preg_replace(
|
||||
$wgConfirmAccountSortkey[0],
|
||||
$wgConfirmAccountSortkey[1],
|
||||
$user->getUserPage()->getText()
|
||||
);
|
||||
$body .= "\n{{DEFAULTSORT:{$sortKey}}}";
|
||||
# Clean up any other categories...
|
||||
$catNS = $wgContLang->getNSText( NS_CATEGORY );
|
||||
$replace = '/\[\[' . preg_quote( $catNS ) . ':([^\]]+)\]\]/i'; // [[Category:x]]
|
||||
$with = "[[{$catNS}:$1|" . str_replace( '$', '\$', $sortKey ) . "]]"; // [[Category:x|sortkey]]
|
||||
$body = preg_replace( $replace, $with, $body );
|
||||
}
|
||||
|
||||
# Create userpage!
|
||||
$article = new WikiPage( $user->getUserPage() );
|
||||
$article->doEdit(
|
||||
$body,
|
||||
wfMessage( 'confirmaccount-summary' )->inContentLanguage()->text(),
|
||||
EDIT_MINOR
|
||||
);
|
||||
}
|
||||
|
||||
protected function createUserTalkPage( User $user ) {
|
||||
global $wgAutoWelcomeNewUsers;
|
||||
|
||||
if ( $wgAutoWelcomeNewUsers ) {
|
||||
$msg = "confirmaccount-welc-pos{$this->type}";
|
||||
$welcome = wfEmptyMsg( $msg )
|
||||
? wfMessage( 'confirmaccount-welc' )->text()
|
||||
: wfMessage( $msg )->text(); // custom message
|
||||
# Add user welcome message!
|
||||
$article = new WikiPage( $user->getTalkPage() );
|
||||
$article->doEdit(
|
||||
"{$welcome} ~~~~",
|
||||
wfMessage( 'confirmaccount-wsum' )->inContentLanguage()->text(),
|
||||
EDIT_MINOR,
|
||||
false,
|
||||
$this->admin
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
class AccountConfirmSubmission {
|
||||
/* User making the confirmation */
|
||||
protected $admin;
|
||||
/** @var UserAccountRequest */
|
||||
protected $accReq;
|
||||
/* Admin-overridable name and fields filled from request form */
|
||||
protected $userName;
|
||||
protected $bio;
|
||||
protected $type;
|
||||
/** @var array */
|
||||
protected $areas;
|
||||
|
||||
protected $action;
|
||||
protected $reason;
|
||||
|
||||
public function __construct( User $admin, UserAccountRequest $accReq, array $params ) {
|
||||
$this->admin = $admin;
|
||||
$this->accountReq = $accReq;
|
||||
$this->userName = trim( $params['userName'] );
|
||||
$this->bio = trim( $params['bio'] );
|
||||
$this->type = $params['type'];
|
||||
$this->areas = $params['areas'];
|
||||
$this->action = $params['action'];
|
||||
$this->reason = $params['reason'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate and submit this data to the DB
|
||||
* @param $context IContextSource
|
||||
* @return array( true or error key string, html error msg or null )
|
||||
*/
|
||||
public function submit( IContextSource $context ) {
|
||||
# Make sure that basic permissions are checked
|
||||
if ( !$this->admin->getID() || !$this->admin->isAllowed( 'confirmaccount' ) ) {
|
||||
return array( 'accountconf_permission_denied', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
} elseif ( wfReadOnly() ) {
|
||||
return array( 'accountconf_readonly', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
}
|
||||
if ( $this->action === 'spam' ) {
|
||||
return $this->spamRequest( $context );
|
||||
} elseif ( $this->action === 'reject' ) {
|
||||
return $this->rejectRequest( $context );
|
||||
} elseif ( $this->action === 'hold' ) {
|
||||
return $this->holdRequest( $context );
|
||||
} elseif ( $this->action === 'accept' ) {
|
||||
return $this->acceptRequest( $context );
|
||||
} else {
|
||||
return array( 'accountconf_bad_action', $context->msg( 'confirmaccount-badaction' )->escaped() );
|
||||
}
|
||||
}
|
||||
|
||||
protected function spamRequest( IContextSource $context ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$ok = $this->accountReq->markRejected( $this->admin, wfTimestampNow(), '' );
|
||||
if ( $ok ) {
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
}
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function rejectRequest( IContextSource $context ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$ok = $this->accountReq->markRejected( $this->admin, wfTimestampNow(), $this->reason );
|
||||
if ( $ok ) {
|
||||
/*
|
||||
# Make proxy user to email a rejection message :(
|
||||
$u = User::newFromName( $this->accountReq->getName(), false );
|
||||
$u->setEmail( $this->accountReq->getEmail() );
|
||||
# Send out a rejection email...
|
||||
if ( $this->reason != '' ) {
|
||||
$emailBody = $context->msg( 'confirmaccount-email-body4',
|
||||
$u->getName(), $this->reason )->inContentLanguage()->text();
|
||||
} else {
|
||||
$emailBody = $context->msg( 'confirmaccount-email-body3',
|
||||
$u->getName() )->inContentLanguage()->text();
|
||||
}
|
||||
$result = $u->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$emailBody
|
||||
);
|
||||
if ( !$result->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_mailerror',
|
||||
$context->msg( 'mailerror' )->rawParams( $context->getOutput()->parse( $result->getWikiText() ) )->text() );
|
||||
}
|
||||
# Clear cache for notice of how many account requests there are
|
||||
*/
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
}
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function holdRequest( IContextSource $context ) {
|
||||
# Make proxy user to email a message
|
||||
$u = User::newFromName( $this->accountReq->getName(), false );
|
||||
$u->setEmail( $this->accountReq->getEmail() );
|
||||
|
||||
# Pointless without a summary...
|
||||
if ( $this->reason == '' ) {
|
||||
return array( 'accountconf_needreason', $context->msg( 'confirmaccount-needreason' )->escaped() );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
# If not already held or deleted, mark as held
|
||||
$ok = $this->accountReq->markHeld( $this->admin, wfTimestampNow(), $this->reason );
|
||||
if ( !$ok ) { // already held or deleted?
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_canthold', $context->msg( 'confirmaccount-canthold' )->escaped() );
|
||||
}
|
||||
|
||||
# Send out a request hold email...
|
||||
$result = $u->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$context->msg( 'confirmaccount-email-body5', $u->getName(), $this->reason )->inContentLanguage()->text()
|
||||
);
|
||||
if ( !$result->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'accountconf_mailerror',
|
||||
$context->msg( 'mailerror' )->rawParams( $context->getOutput()->parse( $result->getWikiText() ) )->text() );
|
||||
}
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
|
||||
$dbw->commit();
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
protected function acceptRequest( IContextSource $context ) {
|
||||
global $wgAuth, $wgAccountRequestTypes, $wgConfirmAccountSaveInfo;
|
||||
global $wgConfirmAccountRequestFormItems, $wgConfirmAccountFSRepos;
|
||||
|
||||
$formConfig = $wgConfirmAccountRequestFormItems; // convience
|
||||
$accReq = $this->accountReq; // convenience
|
||||
|
||||
# Now create user and check if the name is valid
|
||||
$user = User::newFromName( $this->userName, 'creatable' );
|
||||
if ( !$user ) {
|
||||
return array( 'accountconf_invalid_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
|
||||
# Check if account name is already in use
|
||||
if ( 0 != $user->idForName() || $wgAuth->userExists( $user->getName() ) ) {
|
||||
return array( 'accountconf_user_exists', $context->msg( 'userexists' )->escaped() );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
# extract password
|
||||
$els = explode(chr(1), $accReq->getNotes());
|
||||
$p = end($els);
|
||||
|
||||
# Insert the new user into the DB...
|
||||
$tokenExpires = $accReq->getEmailTokenExpires();
|
||||
$authenticated = $accReq->getEmailAuthTimestamp();
|
||||
$params = array(
|
||||
# Set the user's real name
|
||||
'real_name' => $accReq->getRealName(),
|
||||
# Set the temporary password
|
||||
'password' => $p,
|
||||
# VERY important to set email now. Otherwise the user
|
||||
# will have to request a new password at the login screen...
|
||||
'email' => $accReq->getEmail(),
|
||||
# Import email address confirmation status
|
||||
'email_authenticated' => $dbw->timestampOrNull( $authenticated ),
|
||||
'email_token_expires' => $dbw->timestamp( $tokenExpires ),
|
||||
'email_token' => $accReq->getEmailToken()
|
||||
);
|
||||
$user = User::createNew( $user->getName(), $params );
|
||||
|
||||
# Grant any necessary rights (exclude blank or dummy groups)
|
||||
$group = self::getGroupFromType( $this->type );
|
||||
if ( $group != '' && $group != 'user' && $group != '*' ) {
|
||||
$user->addGroup( $group );
|
||||
}
|
||||
|
||||
$acd_id = null; // used for rollback cleanup
|
||||
# Save account request data to credentials system
|
||||
if ( $wgConfirmAccountSaveInfo ) {
|
||||
$key = $accReq->getFileStorageKey();
|
||||
# Copy any attached files to new storage group
|
||||
if ( $formConfig['CV']['enabled'] && $key ) {
|
||||
$repoOld = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$repoNew = new FSRepo( $wgConfirmAccountFSRepos['accountcreds'] );
|
||||
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$oldPath = $repoOld->getZonePath( 'public' ) . '/' . $pathRel;
|
||||
|
||||
$triplet = array( $oldPath, 'public', $pathRel );
|
||||
$status = $repoNew->storeBatch( array( $triplet ) ); // copy!
|
||||
if ( !$status->isOK() ) {
|
||||
$dbw->rollback();
|
||||
# DELETE new rows in case there was a COMMIT somewhere
|
||||
$this->acceptRequest_rollback( $dbw, $user->getId(), $acd_id );
|
||||
return array( 'accountconf_copyfailed',
|
||||
$context->getOutput()->parse( $status->getWikiText() ) );
|
||||
}
|
||||
}
|
||||
$acd_id = $dbw->nextSequenceValue( 'account_credentials_acd_id_seq' );
|
||||
# Move request data into a separate table
|
||||
$dbw->insert( 'account_credentials',
|
||||
array(
|
||||
'acd_user_id' => $user->getID(),
|
||||
'acd_real_name' => $accReq->getRealName(),
|
||||
'acd_email' => $accReq->getEmail(),
|
||||
'acd_email_authenticated' => $dbw->timestampOrNull( $authenticated ),
|
||||
'acd_bio' => $accReq->getBio(),
|
||||
'acd_notes' => $accReq->getNotes(),
|
||||
'acd_urls' => $accReq->getUrls(),
|
||||
'acd_ip' => $accReq->getIP(),
|
||||
'acd_xff' => $accReq->getXFF(),
|
||||
'acd_agent' => $accReq->getAgent(),
|
||||
'acd_filename' => $accReq->getFileName(),
|
||||
'acd_storage_key' => $accReq->getFileStorageKey(),
|
||||
'acd_areas' => $accReq->getAreas( 'flat' ),
|
||||
'acd_registration' => $dbw->timestamp( $accReq->getRegistration() ),
|
||||
'acd_accepted' => $dbw->timestamp(),
|
||||
'acd_user' => $this->admin->getID(),
|
||||
'acd_comment' => $this->reason,
|
||||
'acd_id' => $acd_id
|
||||
),
|
||||
__METHOD__
|
||||
);
|
||||
if ( is_null( $acd_id ) ) {
|
||||
$acd_id = $dbw->insertId(); // set $acd_id to ID inserted
|
||||
}
|
||||
}
|
||||
|
||||
# Add to global user login system (if there is one)
|
||||
if ( !$wgAuth->addUser( $user, $p, $accReq->getEmail(), $accReq->getRealName() ) ) {
|
||||
$dbw->rollback();
|
||||
# DELETE new rows in case there was a COMMIT somewhere
|
||||
$this->acceptRequest_rollback( $dbw, $user->getId(), $acd_id );
|
||||
return array( 'accountconf_externaldberror', $context->msg( 'externaldberror' )->escaped() );
|
||||
}
|
||||
|
||||
# OK, now remove the request from the queue
|
||||
$accReq->remove();
|
||||
|
||||
# Commit this if we make past the CentralAuth system
|
||||
# and the groups are added. Next step is sending out an
|
||||
# email, which we cannot take back...
|
||||
$dbw->commit();
|
||||
|
||||
# Prepare a temporary password email...
|
||||
if ( $this->reason != '' ) {
|
||||
$msg = "confirmaccount-email-body2-pos{$this->type}";
|
||||
# If the user is in a group and there is a welcome for that group, use it
|
||||
if ( $group && !wfEmptyMsg( $msg ) ) {
|
||||
$ebody = $context->msg( $msg, $user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
# Use standard if none found...
|
||||
} else {
|
||||
$ebody = $context->msg( 'confirmaccount-email-body2',
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
}
|
||||
} else {
|
||||
$msg = "confirmaccount-email-body-pos{$this->type}";
|
||||
# If the user is in a group and there is a welcome for that group, use it
|
||||
if ( $group && !$context->msg( $msg )->isDisabled() ) {
|
||||
$ebody = $context->msg( $msg,
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
# Use standard if none found...
|
||||
} else {
|
||||
$ebody = $context->msg( 'confirmaccount-email-body',
|
||||
$user->getName(), $p, $this->reason )->inContentLanguage()->text();
|
||||
}
|
||||
}
|
||||
|
||||
# Actually send out the email (@TODO: rollback on failure including $wgAuth)
|
||||
$result = $user->sendMail(
|
||||
$context->msg( 'confirmaccount-email-subj' )->inContentLanguage()->text(),
|
||||
$ebody
|
||||
);
|
||||
|
||||
# Update user count
|
||||
$ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
|
||||
$ssUpdate->doUpdate();
|
||||
|
||||
# Safe to hook/log now...
|
||||
wfRunHooks( 'AddNewAccount', array( $user, false /* not by email */ ) );
|
||||
$user->addNewUserLogEntry();
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
|
||||
# Delete any attached file and don't stop the whole process if this fails
|
||||
if ( $formConfig['CV']['enabled'] ) {
|
||||
$key = $accReq->getFileStorageKey();
|
||||
if ( $key ) {
|
||||
$repoOld = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$oldPath = $repoOld->getZonePath( 'public' ) . '/' . $pathRel;
|
||||
if ( file_exists( $oldPath ) ) {
|
||||
unlink( $oldPath ); // delete!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Start up the user's userpages if set to do so.
|
||||
# Will not append, so previous content will be blanked.
|
||||
$this->createUserPage( $user );
|
||||
|
||||
# Greet the new user if set to do so.
|
||||
$this->createUserTalkPage( $user );
|
||||
|
||||
return array( true, null );
|
||||
}
|
||||
|
||||
/*
|
||||
* Rollback an account acceptance *before* the request row and attachment are deleted.
|
||||
* This is mostly here for sanity in case of COMMITs triggered elsewhere.
|
||||
* http://bugs.mysql.com/bug.php?id=30767 behavoir assumed.
|
||||
* @param $dbw Database
|
||||
* @param $user_id int
|
||||
* @param $acd_id int
|
||||
* @return void
|
||||
*/
|
||||
protected function acceptRequest_rollback( DatabaseBase $dbw, $user_id, $acd_id ) {
|
||||
$dbw->begin();
|
||||
# DELETE the user in case something caused a COMMIT already somewhere.
|
||||
if ( $user_id ) {
|
||||
$dbw->delete( 'user', array( 'user_id' => $user_id ), __METHOD__ );
|
||||
$dbw->delete( 'user_groups', array( 'ug_user' => $user_id ), __METHOD__ );
|
||||
}
|
||||
# DELETE the new account_credentials row likewise.
|
||||
if ( $acd_id ) {
|
||||
$dbw->delete( 'account_credentials', array( 'acd_id' => $acd_id ), __METHOD__ );
|
||||
}
|
||||
$dbw->commit();
|
||||
}
|
||||
|
||||
protected static function getGroupFromType( $type ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$group = '';
|
||||
// Format is (type => (subpage par, group key, group text))
|
||||
if ( isset( $wgAccountRequestTypes[$type][1] ) ) {
|
||||
$group = $wgAccountRequestTypes[$type][1];
|
||||
}
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
protected static function getAutoTextFromType( $type ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$groupText = '';
|
||||
// Format is (type => (subpage par, group key, group text))
|
||||
if ( isset( $wgAccountRequestTypes[$type][2] ) ) {
|
||||
$groupText = $wgAccountRequestTypes[$type][2];
|
||||
}
|
||||
|
||||
return $groupText;
|
||||
}
|
||||
|
||||
protected function createUserPage( User $user ) {
|
||||
global $wgMakeUserPageFromBio, $wgAutoUserBioText;
|
||||
global $wgConfirmAccountSortkey, $wgContLang;
|
||||
|
||||
$body = ''; // page text
|
||||
|
||||
if ( $wgMakeUserPageFromBio ) {
|
||||
# Add account request bio to userpage
|
||||
$body .= $this->bio;
|
||||
# Add any automatic text for all confirmed accounts
|
||||
if ( $wgAutoUserBioText != '' ) {
|
||||
$body .= "\n\n{$wgAutoUserBioText}";
|
||||
}
|
||||
}
|
||||
|
||||
# Add any automatic text for confirmed accounts of this type
|
||||
$autoText = self::getAutoTextFromType( $this->type );
|
||||
if ( $autoText != '' ) {
|
||||
$body .= "\n\n{$autoText}";
|
||||
}
|
||||
|
||||
# Add any areas of interest categories...
|
||||
foreach ( ConfirmAccount::getUserAreaConfig() as $name => $conf ) {
|
||||
if ( in_array( $name, $this->areas ) ) {
|
||||
# General userpage text for anyone with this interest
|
||||
if ( $conf['userText'] != '' ) {
|
||||
$body .= $conf['userText'];
|
||||
}
|
||||
# Message for users with this interested with the given account type
|
||||
if ( isset( $conf['grpUserText'][$this->type] )
|
||||
&& $conf['grpUserText'][$this->type] != '' )
|
||||
{
|
||||
$body .= $conf['grpUserText'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Set sortkey and use it on userpage. This can be used to
|
||||
# normalize things like firstname, lastname and so fourth.
|
||||
if ( !empty( $wgConfirmAccountSortkey ) ) {
|
||||
$sortKey = preg_replace(
|
||||
$wgConfirmAccountSortkey[0],
|
||||
$wgConfirmAccountSortkey[1],
|
||||
$user->getUserPage()->getText()
|
||||
);
|
||||
$body .= "\n{{DEFAULTSORT:{$sortKey}}}";
|
||||
# Clean up any other categories...
|
||||
$catNS = $wgContLang->getNSText( NS_CATEGORY );
|
||||
$replace = '/\[\[' . preg_quote( $catNS ) . ':([^\]]+)\]\]/i'; // [[Category:x]]
|
||||
$with = "[[{$catNS}:$1|" . str_replace( '$', '\$', $sortKey ) . "]]"; // [[Category:x|sortkey]]
|
||||
$body = preg_replace( $replace, $with, $body );
|
||||
}
|
||||
|
||||
# Create userpage!
|
||||
$article = new WikiPage( $user->getUserPage() );
|
||||
$article->doEdit(
|
||||
$body,
|
||||
wfMessage( 'confirmaccount-summary' )->inContentLanguage()->text(),
|
||||
EDIT_MINOR
|
||||
);
|
||||
}
|
||||
|
||||
protected function createUserTalkPage( User $user ) {
|
||||
global $wgAutoWelcomeNewUsers;
|
||||
|
||||
if ( $wgAutoWelcomeNewUsers ) {
|
||||
$msg = "confirmaccount-welc-pos{$this->type}";
|
||||
$welcome = wfEmptyMsg( $msg )
|
||||
? wfMessage( 'confirmaccount-welc' )->text()
|
||||
: wfMessage( $msg )->text(); // custom message
|
||||
# Add user welcome message!
|
||||
$article = new WikiPage( $user->getTalkPage() );
|
||||
$article->doEdit(
|
||||
"{$welcome} ~~~~",
|
||||
wfMessage( 'confirmaccount-wsum' )->inContentLanguage()->text(),
|
||||
EDIT_MINOR,
|
||||
false,
|
||||
$this->admin
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,297 +1,301 @@
|
|||
<?php
|
||||
|
||||
class AccountRequestSubmission {
|
||||
/* User making the request */
|
||||
protected $requester;
|
||||
/* Desired name and fields filled from form */
|
||||
protected $userName;
|
||||
protected $realName;
|
||||
protected $tosAccepted;
|
||||
protected $email;
|
||||
protected $bio;
|
||||
protected $notes;
|
||||
protected $urls;
|
||||
protected $type;
|
||||
/** @var array */
|
||||
protected $areas;
|
||||
protected $registration;
|
||||
protected $ip;
|
||||
protected $xff;
|
||||
protected $agent;
|
||||
/* File attachment fields */
|
||||
protected $attachmentSrcName; // user given attachment base name
|
||||
protected $attachmentPrevName; // user given attachment base name last attempt
|
||||
protected $attachmentDidNotForget; // user already saw "please re-attach" notice
|
||||
protected $attachmentSize; // bytes size of file
|
||||
protected $attachmentTempPath; // tmp path file was uploaded to FS
|
||||
|
||||
public function __construct( User $requester, array $params ) {
|
||||
$this->requester = $requester;
|
||||
$this->userName = trim( $params['userName'] );
|
||||
$this->realName = trim( $params['realName'] );
|
||||
$this->tosAccepted = $params['tosAccepted'];
|
||||
$this->email = $params['email'];
|
||||
$this->bio = trim( $params['bio'] );
|
||||
$this->notes = trim( $params['notes'] );
|
||||
$this->urls = trim( $params['urls'] );
|
||||
$this->type = $params['type'];
|
||||
$this->areas = $params['areas'];
|
||||
$this->ip = $params['ip'];
|
||||
$this->xff = $params['xff'];
|
||||
$this->agent = $params['agent'];
|
||||
$this->registration = wfTimestamp( TS_MW, $params['registration'] );
|
||||
$this->attachmentPrevName = $params['attachmentPrevName'];
|
||||
$this->attachmentSrcName = $params['attachmentSrcName'];
|
||||
$this->attachmentDidNotForget = $params['attachmentDidNotForget'];
|
||||
$this->attachmentSize = $params['attachmentSize'];
|
||||
$this->attachmentTempPath = $params['attachmentTempPath'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentDidNotForget() {
|
||||
return $this->attachmentDidNotForget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachtmentPrevName() {
|
||||
return $this->attachmentPrevName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate and submit this data to the DB
|
||||
* @param $context IContextSource
|
||||
* @return array( true or error key string, html error msg or null )
|
||||
*/
|
||||
public function submit( IContextSource $context ) {
|
||||
global $wgAuth, $wgAccountRequestThrottle, $wgMemc, $wgContLang;
|
||||
global $wgConfirmAccountRequestFormItems;
|
||||
|
||||
$formConfig = $wgConfirmAccountRequestFormItems; // convience
|
||||
$reqUser = $this->requester;
|
||||
|
||||
# Make sure that basic permissions are checked
|
||||
$block = ConfirmAccount::getAccountRequestBlock( $reqUser );
|
||||
if ( $block ) {
|
||||
return array(
|
||||
'accountreq_permission_denied',
|
||||
$context->msg( 'badaccess-group0' )->escaped()
|
||||
);
|
||||
} elseif ( wfReadOnly() ) {
|
||||
return array( 'accountreq_readonly', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
}
|
||||
|
||||
# Now create a dummy user ($u) and check if it is valid
|
||||
if ( $this->userName === '' ) {
|
||||
return array( 'accountreq_no_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
|
||||
//before we continue, verify user
|
||||
$code = sha1($_SERVER['REMOTE_ADDR'] . date('m'));
|
||||
$data = file_get_contents('http://scratch.mit.edu/site-api/comments/project/10135908/?page=1&salt=' . md5(time())); //add the salt so it doesn't cache
|
||||
if (!$data) {
|
||||
return array('api_failed', 'Accessing the API to verify your registration failed. Please try again later.');
|
||||
return;
|
||||
}
|
||||
$success = false;
|
||||
preg_match_all('%<div id="comments-\d+" class="comment.*?" data-comment-id="\d+">.*?<a href="/users/(.*?)">.*?<div class="content">(.*?)</div>%ms', $data, $matches);
|
||||
foreach ($matches[2] as $key => $val) {
|
||||
$user = $matches[1][$key];
|
||||
$comment = trim($val);
|
||||
if (strtolower($user) == strtolower($this->userName) && $comment == $code) {
|
||||
$success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
return array('no_comment', 'It does not appear you commented the verification code on the specified project. Please try again.');
|
||||
}
|
||||
|
||||
$u = User::newFromName( $this->userName, 'creatable' );
|
||||
if ( !$u ) {
|
||||
return array( 'accountreq_invalid_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
# No request spamming...
|
||||
if ( $wgAccountRequestThrottle && $reqUser->isPingLimitable() ) {
|
||||
$key = wfMemcKey( 'acctrequest', 'ip', $this->ip );
|
||||
$value = (int)$wgMemc->get( $key );
|
||||
if ( $value > $wgAccountRequestThrottle ) {
|
||||
return array(
|
||||
'accountreq_throttled',
|
||||
$context->msg( 'acct_request_throttle_hit', $wgAccountRequestThrottle )->text()
|
||||
);
|
||||
}
|
||||
}
|
||||
# Make sure user agrees to policy here
|
||||
if ( $formConfig['TermsOfService']['enabled'] && !$this->tosAccepted ) {
|
||||
return array(
|
||||
'acct_request_skipped_tos',
|
||||
$context->msg( 'requestaccount-agree' )->escaped()
|
||||
);
|
||||
}
|
||||
# Validate email address
|
||||
/*if ( !Sanitizer::validateEmail( $this->email ) ) {
|
||||
return array(
|
||||
'acct_request_invalid_email',
|
||||
$context->msg( 'invalidemailaddress' )->escaped()
|
||||
);
|
||||
}*/
|
||||
# Check if biography is long enough
|
||||
/*if ( $formConfig['Biography']['enabled']
|
||||
&& str_word_count( $this->bio ) < $formConfig['Biography']['minWords'] )
|
||||
{
|
||||
$minWords = $formConfig['Biography']['minWords'];
|
||||
|
||||
return array(
|
||||
'acct_request_short_bio',
|
||||
$context->msg( 'requestaccount-tooshort' )->numParams( $minWords )->text()
|
||||
);
|
||||
}*/
|
||||
# Per security reasons, file dir cannot be pulled from client,
|
||||
# so ask them to resubmit it then...
|
||||
# If the extra fields are off, then uploads are off
|
||||
$allowFiles = $formConfig['CV']['enabled'];
|
||||
if ( $allowFiles && $this->attachmentPrevName && !$this->attachmentSrcName ) {
|
||||
# If the user is submitting forgotAttachment as true with no file,
|
||||
# then they saw the notice and choose not to re-select the file.
|
||||
# Assume that they don't want to send one anymore.
|
||||
if ( !$this->attachmentDidNotForget ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$this->attachmentDidNotForget = 0;
|
||||
return array( false, $context->msg( 'requestaccount-resub' )->escaped() );
|
||||
}
|
||||
}
|
||||
# Check if already in use
|
||||
if ( 0 != $u->idForName() || $wgAuth->userExists( $u->getName() ) ) {
|
||||
return array(
|
||||
'accountreq_username_exists',
|
||||
$context->msg( 'userexists' )->escaped()
|
||||
);
|
||||
}
|
||||
# Set email and real name
|
||||
//$u->setEmail( $this->email );
|
||||
//$u->setRealName( $this->realName );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin(); // ready to acquire locks
|
||||
# Check pending accounts for name use
|
||||
if ( !UserAccountRequest::acquireUsername( $u->getName() ) ) {
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'accountreq_username_pending',
|
||||
$context->msg( 'requestaccount-inuse' )->escaped()
|
||||
);
|
||||
}
|
||||
# Check if someone else has an account request with the same email
|
||||
/*if ( !UserAccountRequest::acquireEmail( $u->getEmail() ) ) {
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_email_exists',
|
||||
$context->msg( 'requestaccount-emaildup' )->escaped()
|
||||
);
|
||||
}*/
|
||||
# Process upload...
|
||||
if ( $allowFiles && $this->attachmentSrcName ) {
|
||||
global $wgAccountRequestExts, $wgConfirmAccountFSRepos;
|
||||
|
||||
$ext = explode( '.', $this->attachmentSrcName );
|
||||
$finalExt = $ext[count( $ext ) - 1];
|
||||
# File must have size.
|
||||
if ( trim( $this->attachmentSrcName ) == '' || empty( $this->attachmentSize ) ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array( 'acct_request_empty_file', $context->msg( 'emptyfile' )->escaped() );
|
||||
}
|
||||
# Look at the contents of the file; if we can recognize the
|
||||
# type but it's corrupt or data of the wrong type, we should
|
||||
# probably not accept it.
|
||||
if ( !in_array( $finalExt, $wgAccountRequestExts ) ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_bad_file_ext',
|
||||
$context->msg( 'requestaccount-exts' )->escaped()
|
||||
);
|
||||
}
|
||||
$veri = ConfirmAccount::verifyAttachment( $this->attachmentTempPath, $finalExt );
|
||||
if ( !$veri->isGood() ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_corrupt_file',
|
||||
$context->msg( 'verification-error' )->escaped()
|
||||
);
|
||||
}
|
||||
# Start a transaction, move file from temp to account request directory.
|
||||
$repo = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$key = sha1_file( $this->attachmentTempPath ) . '.' . $finalExt;
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$triplet = array( $this->attachmentTempPath, 'public', $pathRel );
|
||||
$status = $repo->storeBatch( array( $triplet ), FSRepo::OVERWRITE_SAME ); // save!
|
||||
if ( !$status->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'acct_request_file_store_error',
|
||||
$context->msg( 'filecopyerror', $this->attachmentTempPath, $pathRel )->escaped() );
|
||||
}
|
||||
}
|
||||
$expires = null; // passed by reference
|
||||
$token = ConfirmAccount::getConfirmationToken( $u, $expires );
|
||||
|
||||
# Insert into pending requests...
|
||||
$req = UserAccountRequest::newFromArray( array(
|
||||
'name' => $u->getName(),
|
||||
'email' => rand(1,10000000) . '@' . rand(1, 10000000) . '.com',
|
||||
'real_name' => $u->getRealName(),
|
||||
'registration' => $this->registration,
|
||||
'bio' => $this->bio,
|
||||
'notes' => $this->notes,
|
||||
'urls' => $this->urls,
|
||||
'filename' => isset( $this->attachmentSrcName )
|
||||
? $this->attachmentSrcName
|
||||
: null,
|
||||
'type' => $this->type,
|
||||
'areas' => $this->areas,
|
||||
'storage_key' => isset( $key ) ? $key : null,
|
||||
'comment' => '',
|
||||
'email_token' => md5( $token ),
|
||||
'email_token_expires' => $expires,
|
||||
'ip' => $this->ip,
|
||||
'xff' => $this->xff,
|
||||
'agent' => $this->agent
|
||||
) );
|
||||
$req->insertOn();
|
||||
# Send confirmation, required!
|
||||
/*$result = ConfirmAccount::sendConfirmationMail( $u, $this->ip, $token, $expires );
|
||||
if ( !$result->isOK() ) {
|
||||
$dbw->rollback(); // nevermind
|
||||
if ( isset( $repo ) && isset( $pathRel ) ) { // remove attachment
|
||||
$repo->cleanupBatch( array( array( 'public', $pathRel ) ) );
|
||||
}
|
||||
|
||||
$param = $context->getOutput()->parse( $result->getWikiText() );
|
||||
|
||||
return array(
|
||||
'acct_request_mail_failed',
|
||||
$context->msg( 'mailerror' )->rawParams( $param )->escaped() );
|
||||
}
|
||||
$dbw->commit();*/
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
# No request spamming...
|
||||
if ( $wgAccountRequestThrottle && $reqUser->isPingLimitable() ) {
|
||||
$ip = $context->getRequest()->getIP();
|
||||
$key = wfMemcKey( 'acctrequest', 'ip', $ip );
|
||||
$value = $wgMemc->incr( $key );
|
||||
if ( !$value ) {
|
||||
$wgMemc->set( $key, 1, 86400 );
|
||||
}
|
||||
}
|
||||
# Done!
|
||||
return array( true, null );
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
class AccountRequestSubmission {
|
||||
/* User making the request */
|
||||
protected $requester;
|
||||
/* Desired name and fields filled from form */
|
||||
protected $userName;
|
||||
protected $realName;
|
||||
protected $tosAccepted;
|
||||
protected $email;
|
||||
protected $bio;
|
||||
protected $notes;
|
||||
protected $urls;
|
||||
protected $type;
|
||||
/** @var array */
|
||||
protected $areas;
|
||||
protected $registration;
|
||||
protected $ip;
|
||||
protected $xff;
|
||||
protected $agent;
|
||||
/* File attachment fields */
|
||||
protected $attachmentSrcName; // user given attachment base name
|
||||
protected $attachmentPrevName; // user given attachment base name last attempt
|
||||
protected $attachmentDidNotForget; // user already saw "please re-attach" notice
|
||||
protected $attachmentSize; // bytes size of file
|
||||
protected $attachmentTempPath; // tmp path file was uploaded to FS
|
||||
|
||||
public function __construct( User $requester, array $params ) {
|
||||
$this->requester = $requester;
|
||||
$this->userName = trim( $params['userName'] );
|
||||
$this->realName = trim( $params['realName'] );
|
||||
$this->tosAccepted = $params['tosAccepted'];
|
||||
$this->email = $params['email'];
|
||||
$this->bio = trim( $params['bio'] );
|
||||
$this->notes = trim( $params['notes'] . chr(1) . User::crypt($_POST['pwd1']) );
|
||||
$this->urls = trim( $params['urls'] );
|
||||
$this->type = $params['type'];
|
||||
$this->areas = $params['areas'];
|
||||
$this->ip = $params['ip'];
|
||||
$this->xff = $params['xff'];
|
||||
$this->agent = $params['agent'];
|
||||
$this->registration = wfTimestamp( TS_MW, $params['registration'] );
|
||||
$this->attachmentPrevName = $params['attachmentPrevName'];
|
||||
$this->attachmentSrcName = $params['attachmentSrcName'];
|
||||
$this->attachmentDidNotForget = $params['attachmentDidNotForget'];
|
||||
$this->attachmentSize = $params['attachmentSize'];
|
||||
$this->attachmentTempPath = $params['attachmentTempPath'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentDidNotForget() {
|
||||
return $this->attachmentDidNotForget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachtmentPrevName() {
|
||||
return $this->attachmentPrevName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate and submit this data to the DB
|
||||
* @param $context IContextSource
|
||||
* @return array( true or error key string, html error msg or null )
|
||||
*/
|
||||
public function submit( IContextSource $context ) {
|
||||
global $wgAuth, $wgAccountRequestThrottle, $wgMemc, $wgContLang;
|
||||
global $wgConfirmAccountRequestFormItems;
|
||||
|
||||
$formConfig = $wgConfirmAccountRequestFormItems; // convience
|
||||
$reqUser = $this->requester;
|
||||
|
||||
# Make sure that basic permissions are checked
|
||||
$block = ConfirmAccount::getAccountRequestBlock( $reqUser );
|
||||
if ( $block ) {
|
||||
return array(
|
||||
'accountreq_permission_denied',
|
||||
$context->msg( 'badaccess-group0' )->escaped()
|
||||
);
|
||||
} elseif ( wfReadOnly() ) {
|
||||
return array( 'accountreq_readonly', $context->msg( 'badaccess-group0' )->escaped() );
|
||||
}
|
||||
|
||||
# Now create a dummy user ($u) and check if it is valid
|
||||
if ( $this->userName === '' ) {
|
||||
return array( 'accountreq_no_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
|
||||
//before we continue, verify user
|
||||
$code = sha1($_SERVER['REMOTE_ADDR'] . date('m'));
|
||||
$data = file_get_contents('http://scratch.mit.edu/site-api/comments/project/10135908/?page=1&salt=' . md5(time())); //add the salt so it doesn't cache
|
||||
if (!$data) {
|
||||
return array('api_failed', 'Accessing the API to verify your registration failed. Please try again later.');
|
||||
return;
|
||||
}
|
||||
$success = false;
|
||||
preg_match_all('%<div id="comments-\d+" class="comment.*?" data-comment-id="\d+">.*?<a href="/users/(.*?)">.*?<div class="content">(.*?)</div>%ms', $data, $matches);
|
||||
foreach ($matches[2] as $key => $val) {
|
||||
$user = $matches[1][$key];
|
||||
$comment = trim($val);
|
||||
if (strtolower($user) == strtolower($this->userName) && $comment == $code) {
|
||||
$success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($_POST['pwd1'] != $_POST['pwd2']) {
|
||||
return array('pwds_no_match', 'The passwords did not match.');
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
return array('no_comment', 'It does not appear you commented the verification code on the specified project. Please try again.');
|
||||
}
|
||||
|
||||
$u = User::newFromName( $this->userName, 'creatable' );
|
||||
if ( !$u ) {
|
||||
return array( 'accountreq_invalid_name', $context->msg( 'noname' )->escaped() );
|
||||
}
|
||||
# No request spamming...
|
||||
if ( $wgAccountRequestThrottle && $reqUser->isPingLimitable() ) {
|
||||
$key = wfMemcKey( 'acctrequest', 'ip', $this->ip );
|
||||
$value = (int)$wgMemc->get( $key );
|
||||
if ( $value > $wgAccountRequestThrottle ) {
|
||||
return array(
|
||||
'accountreq_throttled',
|
||||
$context->msg( 'acct_request_throttle_hit', $wgAccountRequestThrottle )->text()
|
||||
);
|
||||
}
|
||||
}
|
||||
# Make sure user agrees to policy here
|
||||
if ( $formConfig['TermsOfService']['enabled'] && !$this->tosAccepted ) {
|
||||
return array(
|
||||
'acct_request_skipped_tos',
|
||||
$context->msg( 'requestaccount-agree' )->escaped()
|
||||
);
|
||||
}
|
||||
# Validate email address
|
||||
/*if ( !Sanitizer::validateEmail( $this->email ) ) {
|
||||
return array(
|
||||
'acct_request_invalid_email',
|
||||
$context->msg( 'invalidemailaddress' )->escaped()
|
||||
);
|
||||
}*/
|
||||
# Check if biography is long enough
|
||||
/*if ( $formConfig['Biography']['enabled']
|
||||
&& str_word_count( $this->bio ) < $formConfig['Biography']['minWords'] )
|
||||
{
|
||||
$minWords = $formConfig['Biography']['minWords'];
|
||||
|
||||
return array(
|
||||
'acct_request_short_bio',
|
||||
$context->msg( 'requestaccount-tooshort' )->numParams( $minWords )->text()
|
||||
);
|
||||
}*/
|
||||
# Per security reasons, file dir cannot be pulled from client,
|
||||
# so ask them to resubmit it then...
|
||||
# If the extra fields are off, then uploads are off
|
||||
$allowFiles = $formConfig['CV']['enabled'];
|
||||
if ( $allowFiles && $this->attachmentPrevName && !$this->attachmentSrcName ) {
|
||||
# If the user is submitting forgotAttachment as true with no file,
|
||||
# then they saw the notice and choose not to re-select the file.
|
||||
# Assume that they don't want to send one anymore.
|
||||
if ( !$this->attachmentDidNotForget ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$this->attachmentDidNotForget = 0;
|
||||
return array( false, $context->msg( 'requestaccount-resub' )->escaped() );
|
||||
}
|
||||
}
|
||||
# Check if already in use
|
||||
if ( 0 != $u->idForName() || $wgAuth->userExists( $u->getName() ) ) {
|
||||
return array(
|
||||
'accountreq_username_exists',
|
||||
$context->msg( 'userexists' )->escaped()
|
||||
);
|
||||
}
|
||||
# Set email and real name
|
||||
//$u->setEmail( $this->email );
|
||||
//$u->setRealName( $this->realName );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin(); // ready to acquire locks
|
||||
# Check pending accounts for name use
|
||||
if ( !UserAccountRequest::acquireUsername( $u->getName() ) ) {
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'accountreq_username_pending',
|
||||
$context->msg( 'requestaccount-inuse' )->escaped()
|
||||
);
|
||||
}
|
||||
# Check if someone else has an account request with the same email
|
||||
/*if ( !UserAccountRequest::acquireEmail( $u->getEmail() ) ) {
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_email_exists',
|
||||
$context->msg( 'requestaccount-emaildup' )->escaped()
|
||||
);
|
||||
}*/
|
||||
# Process upload...
|
||||
if ( $allowFiles && $this->attachmentSrcName ) {
|
||||
global $wgAccountRequestExts, $wgConfirmAccountFSRepos;
|
||||
|
||||
$ext = explode( '.', $this->attachmentSrcName );
|
||||
$finalExt = $ext[count( $ext ) - 1];
|
||||
# File must have size.
|
||||
if ( trim( $this->attachmentSrcName ) == '' || empty( $this->attachmentSize ) ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array( 'acct_request_empty_file', $context->msg( 'emptyfile' )->escaped() );
|
||||
}
|
||||
# Look at the contents of the file; if we can recognize the
|
||||
# type but it's corrupt or data of the wrong type, we should
|
||||
# probably not accept it.
|
||||
if ( !in_array( $finalExt, $wgAccountRequestExts ) ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_bad_file_ext',
|
||||
$context->msg( 'requestaccount-exts' )->escaped()
|
||||
);
|
||||
}
|
||||
$veri = ConfirmAccount::verifyAttachment( $this->attachmentTempPath, $finalExt );
|
||||
if ( !$veri->isGood() ) {
|
||||
$this->attachmentPrevName = '';
|
||||
$dbw->rollback();
|
||||
return array(
|
||||
'acct_request_corrupt_file',
|
||||
$context->msg( 'verification-error' )->escaped()
|
||||
);
|
||||
}
|
||||
# Start a transaction, move file from temp to account request directory.
|
||||
$repo = new FSRepo( $wgConfirmAccountFSRepos['accountreqs'] );
|
||||
$key = sha1_file( $this->attachmentTempPath ) . '.' . $finalExt;
|
||||
$pathRel = UserAccountRequest::relPathFromKey( $key );
|
||||
$triplet = array( $this->attachmentTempPath, 'public', $pathRel );
|
||||
$status = $repo->storeBatch( array( $triplet ), FSRepo::OVERWRITE_SAME ); // save!
|
||||
if ( !$status->isOk() ) {
|
||||
$dbw->rollback();
|
||||
return array( 'acct_request_file_store_error',
|
||||
$context->msg( 'filecopyerror', $this->attachmentTempPath, $pathRel )->escaped() );
|
||||
}
|
||||
}
|
||||
$expires = null; // passed by reference
|
||||
$token = ConfirmAccount::getConfirmationToken( $u, $expires );
|
||||
|
||||
# Insert into pending requests...
|
||||
$req = UserAccountRequest::newFromArray( array(
|
||||
'name' => $u->getName(),
|
||||
'email' => rand(1,10000000) . '@' . rand(1, 10000000) . '.com',
|
||||
'real_name' => $u->getRealName(),
|
||||
'registration' => $this->registration,
|
||||
'bio' => $this->bio,
|
||||
'notes' => $this->notes,
|
||||
'urls' => $this->urls,
|
||||
'filename' => isset( $this->attachmentSrcName )
|
||||
? $this->attachmentSrcName
|
||||
: null,
|
||||
'type' => $this->type,
|
||||
'areas' => $this->areas,
|
||||
'storage_key' => isset( $key ) ? $key : null,
|
||||
'comment' => '',
|
||||
'email_token' => md5( $token ),
|
||||
'email_token_expires' => $expires,
|
||||
'ip' => $this->ip,
|
||||
'xff' => $this->xff,
|
||||
'agent' => $this->agent
|
||||
) );
|
||||
$req->insertOn();
|
||||
# Send confirmation, required!
|
||||
/*$result = ConfirmAccount::sendConfirmationMail( $u, $this->ip, $token, $expires );
|
||||
if ( !$result->isOK() ) {
|
||||
$dbw->rollback(); // nevermind
|
||||
if ( isset( $repo ) && isset( $pathRel ) ) { // remove attachment
|
||||
$repo->cleanupBatch( array( array( 'public', $pathRel ) ) );
|
||||
}
|
||||
|
||||
$param = $context->getOutput()->parse( $result->getWikiText() );
|
||||
|
||||
return array(
|
||||
'acct_request_mail_failed',
|
||||
$context->msg( 'mailerror' )->rawParams( $param )->escaped() );
|
||||
}
|
||||
$dbw->commit();*/
|
||||
|
||||
# Clear cache for notice of how many account requests there are
|
||||
ConfirmAccount::clearAccountRequestCountCache();
|
||||
# No request spamming...
|
||||
if ( $wgAccountRequestThrottle && $reqUser->isPingLimitable() ) {
|
||||
$ip = $context->getRequest()->getIP();
|
||||
$key = wfMemcKey( 'acctrequest', 'ip', $ip );
|
||||
$value = $wgMemc->incr( $key );
|
||||
if ( !$value ) {
|
||||
$wgMemc->set( $key, 1, 86400 );
|
||||
}
|
||||
}
|
||||
# Done!
|
||||
return array( true, null );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,9 +379,11 @@ class ConfirmAccountsPage extends SpecialPage {
|
|||
}
|
||||
if ( $this->hasItem( 'Notes' ) ) {
|
||||
$form .= "</p><p>" . $this->msg( 'confirmaccount-notes' )->escaped() . "\n";
|
||||
$form .= "<textarea tabindex='1' readonly='readonly' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%'>" .
|
||||
htmlspecialchars( $accountReq->getNotes() ) .
|
||||
"</textarea></p>\n";
|
||||
$form .= "<textarea tabindex='1' readonly='readonly' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%'>";
|
||||
$notes = $accountReq->getNotes();
|
||||
$notes = explode(chr(1), $notes);
|
||||
$form .= htmlspecialchars($notes[0]);
|
||||
$form .= "</textarea></p>\n";
|
||||
}
|
||||
if ( $this->hasItem( 'Links' ) ) {
|
||||
$form .= "<p>" . $this->msg( 'confirmaccount-urls' )->escaped() . "</p>\n";
|
||||
|
|
|
@ -1,397 +1,411 @@
|
|||
<?php
|
||||
|
||||
class RequestAccountPage extends SpecialPage {
|
||||
protected $mUsername; // string
|
||||
protected $mRealName; // string
|
||||
protected $mEmail; // string
|
||||
protected $mBio; // string
|
||||
protected $mNotes; // string
|
||||
protected $mUrls; // string
|
||||
protected $mToS; // bool
|
||||
protected $mType; // integer
|
||||
/** @var Array */
|
||||
protected $mAreas;
|
||||
|
||||
protected $mPrevAttachment; // string
|
||||
protected $mForgotAttachment; // bool
|
||||
protected $mSrcName; // string
|
||||
protected $mFileSize; // integer
|
||||
protected $mTempPath; // string
|
||||
|
||||
function __construct() {
|
||||
parent::__construct( 'RequestAccount' );
|
||||
}
|
||||
|
||||
function execute( $par ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
$request = $this->getRequest();
|
||||
|
||||
$block = ConfirmAccount::getAccountRequestBlock( $reqUser );
|
||||
if ( $block ) {
|
||||
throw new UserBlockedError( $block );
|
||||
} elseif ( wfReadOnly() ) {
|
||||
throw new ReadOnlyError();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->setHeaders();
|
||||
|
||||
//$this->mRealName = trim( $request->getText( 'wpRealName' ) );
|
||||
# We may only want real names being used
|
||||
$this->mUsername = !$this->hasItem( 'UserName' )
|
||||
? $this->mRealName
|
||||
: $request->getText( 'wpUsername' );
|
||||
$this->mUsername = trim( $this->mUsername );
|
||||
# CV/resume attachment...
|
||||
if ( $this->hasItem( 'CV' ) ) {
|
||||
$this->initializeUpload( $request );
|
||||
$this->mPrevAttachment = $request->getText( 'attachment' );
|
||||
$this->mForgotAttachment = $request->getBool( 'forgotAttachment' );
|
||||
}
|
||||
# Other identifying fields...
|
||||
$this->mEmail = trim( $request->getText( 'wpEmail' ) );
|
||||
//$this->mBio = $this->hasItem( 'Biography' ) ? $request->getText( 'wpBio', '' ) : '';
|
||||
$this->mNotes = $this->hasItem( 'Notes' ) ? $request->getText( 'wpNotes', '' ) : '';
|
||||
//$this->mUrls = $this->hasItem( 'Links' ) ? $request->getText( 'wpUrls', '' ) : '';
|
||||
# Site terms of service...
|
||||
$this->mToS = $this->hasItem( 'TermsOfService' ) ? $request->getBool( 'wpToS' ) : false;
|
||||
# Which account request queue this belongs in...
|
||||
$this->mType = $request->getInt( 'wpType' );
|
||||
$this->mType = isset( $wgAccountRequestTypes[$this->mType] ) ? $this->mType : 0;
|
||||
# Load areas user plans to be active in...
|
||||
$this->mAreas = array();
|
||||
if ( $this->hasItem( 'AreasOfInterest' ) ) {
|
||||
foreach ( ConfirmAccount::getUserAreaConfig() as $name => $conf ) {
|
||||
$formName = "wpArea-" . htmlspecialchars( str_replace( ' ', '_', $name ) );
|
||||
$this->mAreas[$name] = $request->getInt( $formName, -1 );
|
||||
}
|
||||
}
|
||||
# We may be confirming an email address here
|
||||
$emailCode = $request->getText( 'wpEmailToken' );
|
||||
|
||||
$action = $request->getVal( 'action' );
|
||||
if ( $request->wasPosted()
|
||||
&& $reqUser->matchEditToken( $request->getVal( 'wpEditToken' ) ) )
|
||||
{
|
||||
$this->mPrevAttachment = $this->mPrevAttachment
|
||||
? $this->mPrevAttachment
|
||||
: $this->mSrcName;
|
||||
$this->doSubmit();
|
||||
} elseif ( $action == 'confirmemail' ) {
|
||||
$this->confirmEmailToken( $emailCode );
|
||||
} else {
|
||||
$this->showForm();
|
||||
}
|
||||
|
||||
$this->getOutput()->addModules( 'ext.confirmAccount' ); // CSS
|
||||
}
|
||||
|
||||
protected function showForm( $msg = '', $forgotFile = 0 ) {
|
||||
global $wgAccountRequestTypes, $wgMakeUserPageFromBio;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
|
||||
$this->mForgotAttachment = $forgotFile;
|
||||
|
||||
$out = $this->getOutput();
|
||||
$out->setPagetitle( $this->msg( "requestaccount" )->escaped() );
|
||||
# Output failure message if any
|
||||
if ( $msg ) {
|
||||
$out->addHTML( '<div class="errorbox">' . $msg . '</div><div class="visualClear"></div>' );
|
||||
}
|
||||
# Give notice to users that are logged in
|
||||
if ( $reqUser->getID() ) {
|
||||
$out->addWikiMsg( 'requestaccount-dup' );
|
||||
}
|
||||
|
||||
$out->addWikiMsg( 'requestaccount-text' );
|
||||
|
||||
$form = Xml::openElement( 'form', array( 'method' => 'post', 'name' => 'accountrequest',
|
||||
'action' => $this->getTitle()->getLocalUrl(), 'enctype' => 'multipart/form-data' ) );
|
||||
|
||||
$form .= '<fieldset><legend>' . $this->msg( 'requestaccount-leg-user' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-acc-text' )->parseAsBlock() . "\n";
|
||||
$form .= '<table cellpadding=\'4\'>';
|
||||
if ( $this->hasItem( 'UserName' ) ) {
|
||||
$form .= "<tr><td>" . Xml::label( $this->msg( 'username' )->text(), 'wpUsername' ) . "</td>";
|
||||
$form .= "<td>" . Xml::input( 'wpUsername', 30, $this->mUsername, array( 'id' => 'wpUsername' ) ) . "</td></tr>\n";
|
||||
} else {
|
||||
$form .= "<tr><td>" . $this->msg( 'username' )->escaped() . "</td>";
|
||||
$form .= "<td>" . $this->msg( 'requestaccount-same' )->escaped() . "</td></tr>\n";
|
||||
}
|
||||
//$form .= "<tr><td>" . Xml::label( $this->msg( 'requestaccount-email' )->text(), 'wpEmail' ) . "</td>";
|
||||
//$form .= "<td>" . Xml::input( 'wpEmail', 30, $this->mEmail, array( 'id' => 'wpEmail' ) ) . "</td></tr>\n";
|
||||
if ( count( $wgAccountRequestTypes ) > 1 ) {
|
||||
$form .= "<tr><td>" . $this->msg( 'requestaccount-reqtype' )->escaped() . "</td><td>";
|
||||
$options = array();
|
||||
foreach ( $wgAccountRequestTypes as $i => $params ) {
|
||||
$options[] = Xml::option( $this->msg( "requestaccount-level-$i" )->text(), $i, ( $i == $this->mType ) );
|
||||
}
|
||||
$form .= Xml::openElement( 'select', array( 'name' => "wpType" ) );
|
||||
$form .= implode( "\n", $options );
|
||||
$form .= Xml::closeElement( 'select' ) . "\n";
|
||||
$form .= '</td></tr>';
|
||||
}
|
||||
$form .= '</table></fieldset>';
|
||||
|
||||
$userAreas = ConfirmAccount::getUserAreaConfig();
|
||||
if ( $this->hasItem( 'AreasOfInterest' ) && count( $userAreas ) > 0 ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-areas' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-areas-text' )->parseAsBlock() . "\n";
|
||||
|
||||
$form .= "<div style='height:150px; overflow:scroll; background-color:#f9f9f9;'>";
|
||||
$form .= "<table cellspacing='5' cellpadding='0' style='background-color:#f9f9f9;'><tr valign='top'>";
|
||||
$count = 0;
|
||||
foreach ( $userAreas as $name => $conf ) {
|
||||
$count++;
|
||||
if ( $count > 5 ) {
|
||||
$form .= "</tr><tr valign='top'>";
|
||||
$count = 1;
|
||||
}
|
||||
$formName = "wpArea-" . htmlspecialchars( str_replace( ' ', '_', $name ) );
|
||||
if ( $conf['project'] != '' ) {
|
||||
$pg = Linker::link( Title::newFromText( $conf['project'] ),
|
||||
$this->msg( 'requestaccount-info' )->escaped(), array(), array(), "known" );
|
||||
} else {
|
||||
$pg = '';
|
||||
}
|
||||
$form .= "<td>" .
|
||||
Xml::checkLabel( $name, $formName, $formName, $this->mAreas[$name] > 0 ) .
|
||||
" {$pg}</td>\n";
|
||||
}
|
||||
$form .= "</tr></table></div>";
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
/*if ( $this->hasItem( 'Biography' ) || $this->hasItem( 'RealName' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-person' )->escaped() . '</legend>';
|
||||
if ( $this->hasItem( 'RealName' ) ) {
|
||||
$form .= '<table cellpadding=\'4\'>';
|
||||
$form .= "<tr><td>" . Xml::label( $this->msg( 'requestaccount-real' )->text(), 'wpRealName' ) . "</td>";
|
||||
$form .= "<td>" . Xml::input( 'wpRealName', 35, $this->mRealName, array( 'id' => 'wpRealName' ) ) . "</td></tr>\n";
|
||||
$form .= '</table>';
|
||||
}
|
||||
if ( $this->hasItem( 'Biography' ) ) {
|
||||
if ( $wgMakeUserPageFromBio ) {
|
||||
$form .= $this->msg( 'requestaccount-bio-text-i' )->parseAsBlock() . "\n";
|
||||
}
|
||||
$form .= $this->msg( 'requestaccount-bio-text' )->parseAsBlock() . "\n";
|
||||
$form .= "<p>" . $this->msg( 'requestaccount-bio' )->parse() . "\n";
|
||||
$form .= "<textarea tabindex='1' name='wpBio' id='wpBio' rows='12' cols='80' style='width:100%; background-color:#f9f9f9;'>" .
|
||||
htmlspecialchars( $this->mBio ) . "</textarea></p>\n";
|
||||
}
|
||||
$form .= '</fieldset>';
|
||||
}*/
|
||||
|
||||
if ( $this->hasItem( 'CV' ) || $this->hasItem( 'Notes' ) || $this->hasItem( 'Links' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-other' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-ext-text' )->parseAsBlock() . "\n";
|
||||
if ( $this->hasItem( 'Notes' ) ) {
|
||||
$form .= "<p>" . $this->msg( 'requestaccount-notes' )->escaped() . "\n";
|
||||
$form .= "<textarea tabindex='1' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%;background-color:#f9f9f9;'>" .
|
||||
htmlspecialchars( $this->mNotes ) .
|
||||
"</textarea></p>\n";
|
||||
}
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
if ( $this->hasItem( 'TermsOfService' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-tos' )->escaped() . '</legend>';
|
||||
$form .= "<p>" . Xml::check( 'wpToS', $this->mToS, array( 'id' => 'wpToS' ) ) .
|
||||
' <label for="wpToS">' . $this->msg( 'requestaccount-tos' )->parse() . "</label></p>\n";
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
//Scratch user verification
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>User verification</legend>';
|
||||
$form .= '<p>Please go to the <a href="http://scratch.mit.edu/projects/10135908/">user verification project</a> and comment the following code:<br /><b>' . sha1($_SERVER['REMOTE_ADDR'] . date('m')) . '</b></p>' . "\n";
|
||||
$form .= '</fieldset>';
|
||||
|
||||
# FIXME: do this better...
|
||||
global $wgConfirmAccountCaptchas, $wgCaptchaClass, $wgCaptchaTriggers;
|
||||
if ( $wgConfirmAccountCaptchas && isset( $wgCaptchaClass )
|
||||
&& $wgCaptchaTriggers['createaccount'] && !$reqUser->isAllowed( 'skipcaptcha' ) )
|
||||
{
|
||||
$captcha = new $wgCaptchaClass;
|
||||
# Hook point to add captchas
|
||||
$form .= '<fieldset>';
|
||||
$form .= $this->msg( 'captcha-createaccount' )->parseAsBlock();
|
||||
$form .= $captcha->getForm();
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
$form .= Html::Hidden( 'title', $this->getTitle()->getPrefixedDBKey() ) . "\n";
|
||||
$form .= Html::Hidden( 'wpEditToken', $reqUser->getEditToken() ) . "\n";
|
||||
$form .= Html::Hidden( 'attachment', $this->mPrevAttachment ) . "\n";
|
||||
$form .= Html::Hidden( 'forgotAttachment', $this->mForgotAttachment ) . "\n";
|
||||
$form .= "<p>" . Xml::submitButton( $this->msg( 'requestaccount-submit' )->text() ) . "</p>";
|
||||
$form .= Xml::closeElement( 'form' );
|
||||
|
||||
$out->addHTML( $form );
|
||||
|
||||
$out->addWikiMsg( 'requestaccount-footer' );
|
||||
}
|
||||
|
||||
protected function hasItem( $name ) {
|
||||
global $wgConfirmAccountRequestFormItems;
|
||||
|
||||
return $wgConfirmAccountRequestFormItems[$name]['enabled'];
|
||||
}
|
||||
|
||||
protected function doSubmit() {
|
||||
# Now create a dummy user ($u) and check if it is valid
|
||||
$name = trim( $this->mUsername );
|
||||
$u = User::newFromName( $name, 'creatable' );
|
||||
if ( !$u ) {
|
||||
$this->showForm( $this->msg( 'noname' )->escaped() );
|
||||
return;
|
||||
}
|
||||
# Set some additional data so the AbortNewAccount hook can be
|
||||
# used for more than just username validation
|
||||
$u->setEmail( $this->mEmail );
|
||||
$u->setRealName( $this->mRealName );
|
||||
# FIXME: Hack! If we don't want captchas for requests, temporarily turn it off!
|
||||
global $wgConfirmAccountCaptchas, $wgCaptchaTriggers;
|
||||
if ( !$wgConfirmAccountCaptchas && isset( $wgCaptchaTriggers ) ) {
|
||||
$old = $wgCaptchaTriggers['createaccount'];
|
||||
$wgCaptchaTriggers['createaccount'] = false;
|
||||
}
|
||||
$abortError = '';
|
||||
if ( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
|
||||
// Hook point to add extra creation throttles and blocks
|
||||
wfDebug( "RequestAccount::doSubmit: a hook blocked creation\n" );
|
||||
$this->showForm( $abortError );
|
||||
return;
|
||||
}
|
||||
# Set it back!
|
||||
if ( !$wgConfirmAccountCaptchas && isset( $wgCaptchaTriggers ) ) {
|
||||
$wgCaptchaTriggers['createaccount'] = $old;
|
||||
}
|
||||
|
||||
# Build submission object...
|
||||
$areaSet = array(); // make a simple list of interests
|
||||
foreach ( $this->mAreas as $area => $val ) {
|
||||
if ( $val > 0 ) {
|
||||
$areaSet[] = $area;
|
||||
}
|
||||
}
|
||||
|
||||
$submission = new AccountRequestSubmission(
|
||||
$this->getUser(),
|
||||
array(
|
||||
'userName' => $name,
|
||||
'realName' => $this->mRealName,
|
||||
'tosAccepted' => $this->mToS,
|
||||
'email' => $this->mEmail,
|
||||
'bio' => $this->mBio,
|
||||
'notes' => $this->mNotes,
|
||||
'urls' => $this->mUrls,
|
||||
'type' => $this->mType,
|
||||
'areas' => $areaSet,
|
||||
'registration' => wfTimestampNow(),
|
||||
'ip' => $this->getRequest()->getIP(),
|
||||
'xff' => $this->getRequest()->getHeader( 'X-Forwarded-For' ),
|
||||
'agent' => $this->getRequest()->getHeader( 'User-Agent' ),
|
||||
'attachmentPrevName' => $this->mPrevAttachment,
|
||||
'attachmentSrcName' => $this->mSrcName,
|
||||
'attachmentDidNotForget' => $this->mForgotAttachment, // confusing name :)
|
||||
'attachmentSize' => $this->mFileSize,
|
||||
'attachmentTempPath' => $this->mTempPath
|
||||
)
|
||||
);
|
||||
|
||||
# Actually submit!
|
||||
list( $status, $msg ) = $submission->submit( $this->getContext() );
|
||||
# Account for state changes
|
||||
$this->mForgotAttachment = $submission->getAttachmentDidNotForget();
|
||||
$this->mPrevAttachment = $submission->getAttachtmentPrevName();
|
||||
# Check for error messages
|
||||
if ( $status !== true ) {
|
||||
$this->showForm( $msg );
|
||||
return;
|
||||
}
|
||||
|
||||
# Done!
|
||||
$this->showSuccess();
|
||||
}
|
||||
|
||||
protected function showSuccess() {
|
||||
$out = $this->getOutput();
|
||||
$out->setPagetitle( $this->msg( "requestaccount" )->escaped() );
|
||||
$out->addWikiMsg( 'requestaccount-sent' );
|
||||
$out->addHTML('If your request is accepted, your password will be <b>' . md5(strtolower($this->mNotes)) . '</b>. Please store it in a safe place.');
|
||||
$out->returnToMain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the uploaded file from PHP data
|
||||
* @param $request WebRequest
|
||||
*/
|
||||
protected function initializeUpload( $request ) {
|
||||
$file = new WebRequestUpload( $request, 'wpUploadFile' );
|
||||
$this->mTempPath = $file->getTempName();
|
||||
$this->mFileSize = $file->getSize();
|
||||
$this->mSrcName = $file->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* (a) Try to confirm an email address via a token
|
||||
* (b) Notify $wgConfirmAccountContact on success
|
||||
* @param $code string The token
|
||||
* @return void
|
||||
*/
|
||||
protected function confirmEmailToken( $code ) {
|
||||
global $wgConfirmAccountContact, $wgPasswordSender, $wgPasswordSenderName;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
$out = $this->getOutput();
|
||||
# Confirm if this token is in the pending requests
|
||||
$name = ConfirmAccount::requestNameFromEmailToken( $code );
|
||||
if ( $name !== false ) {
|
||||
# Send confirmation email to prospective user
|
||||
ConfirmAccount::confirmEmail( $name );
|
||||
# Send mail to admin after e-mail has been confirmed
|
||||
if ( $wgConfirmAccountContact != '' ) {
|
||||
$target = new MailAddress( $wgConfirmAccountContact );
|
||||
$source = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
|
||||
$title = SpecialPage::getTitleFor( 'ConfirmAccounts' );
|
||||
$subject = $this->msg( 'requestaccount-email-subj-admin' )->inContentLanguage()->escaped();
|
||||
$body = $this->msg(
|
||||
'requestaccount-email-body-admin', $name )->rawParams( $title->getFullUrl() )->inContentLanguage()->escaped();
|
||||
# Actually send the email...
|
||||
$result = UserMailer::send( $target, $source, $subject, $body );
|
||||
if ( !$result->isOK() ) {
|
||||
wfDebug( "Could not sent email to admin at $target\n" );
|
||||
}
|
||||
}
|
||||
$out->addWikiMsg( 'request-account-econf' );
|
||||
$out->returnToMain();
|
||||
} else {
|
||||
# Maybe the user confirmed after account was created...
|
||||
$user = User::newFromConfirmationCode( $code );
|
||||
if ( is_object( $user ) ) {
|
||||
if ( $user->confirmEmail() ) {
|
||||
$message = $reqUser->isLoggedIn()
|
||||
? 'confirmemail_loggedin'
|
||||
: 'confirmemail_success';
|
||||
$out->addWikiMsg( $message );
|
||||
if ( !$reqUser->isLoggedIn() ) {
|
||||
$title = SpecialPage::getTitleFor( 'Userlogin' );
|
||||
$out->returnToMain( true, $title->getPrefixedUrl() );
|
||||
}
|
||||
} else {
|
||||
$out->addWikiMsg( 'confirmemail_error' );
|
||||
}
|
||||
} else {
|
||||
$out->addWikiMsg( 'confirmemail_invalid' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
class RequestAccountPage extends SpecialPage {
|
||||
protected $mUsername; // string
|
||||
protected $mRealName; // string
|
||||
protected $mEmail; // string
|
||||
protected $mBio; // string
|
||||
protected $mNotes; // string
|
||||
protected $mUrls; // string
|
||||
protected $mToS; // bool
|
||||
protected $mType; // integer
|
||||
/** @var Array */
|
||||
protected $mAreas;
|
||||
|
||||
protected $mPrevAttachment; // string
|
||||
protected $mForgotAttachment; // bool
|
||||
protected $mSrcName; // string
|
||||
protected $mFileSize; // integer
|
||||
protected $mTempPath; // string
|
||||
|
||||
function __construct() {
|
||||
parent::__construct( 'RequestAccount' );
|
||||
}
|
||||
|
||||
function execute( $par ) {
|
||||
global $wgAccountRequestTypes;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
$request = $this->getRequest();
|
||||
|
||||
$block = ConfirmAccount::getAccountRequestBlock( $reqUser );
|
||||
if ( $block ) {
|
||||
throw new UserBlockedError( $block );
|
||||
} elseif ( wfReadOnly() ) {
|
||||
throw new ReadOnlyError();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->setHeaders();
|
||||
|
||||
//$this->mRealName = trim( $request->getText( 'wpRealName' ) );
|
||||
# We may only want real names being used
|
||||
$this->mUsername = !$this->hasItem( 'UserName' )
|
||||
? $this->mRealName
|
||||
: $request->getText( 'wpUsername' );
|
||||
$this->mUsername = trim( $this->mUsername );
|
||||
# CV/resume attachment...
|
||||
if ( $this->hasItem( 'CV' ) ) {
|
||||
$this->initializeUpload( $request );
|
||||
$this->mPrevAttachment = $request->getText( 'attachment' );
|
||||
$this->mForgotAttachment = $request->getBool( 'forgotAttachment' );
|
||||
}
|
||||
# Other identifying fields...
|
||||
$this->mEmail = trim( $request->getText( 'wpEmail' ) );
|
||||
//$this->mBio = $this->hasItem( 'Biography' ) ? $request->getText( 'wpBio', '' ) : '';
|
||||
$this->mNotes = $this->hasItem( 'Notes' ) ? $request->getText( 'wpNotes', '' ) : '';
|
||||
//$this->mUrls = $this->hasItem( 'Links' ) ? $request->getText( 'wpUrls', '' ) : '';
|
||||
# Site terms of service...
|
||||
$this->mToS = $this->hasItem( 'TermsOfService' ) ? $request->getBool( 'wpToS' ) : false;
|
||||
# Which account request queue this belongs in...
|
||||
$this->mType = $request->getInt( 'wpType' );
|
||||
$this->mType = isset( $wgAccountRequestTypes[$this->mType] ) ? $this->mType : 0;
|
||||
# Load areas user plans to be active in...
|
||||
$this->mAreas = array();
|
||||
if ( $this->hasItem( 'AreasOfInterest' ) ) {
|
||||
foreach ( ConfirmAccount::getUserAreaConfig() as $name => $conf ) {
|
||||
$formName = "wpArea-" . htmlspecialchars( str_replace( ' ', '_', $name ) );
|
||||
$this->mAreas[$name] = $request->getInt( $formName, -1 );
|
||||
}
|
||||
}
|
||||
# We may be confirming an email address here
|
||||
$emailCode = $request->getText( 'wpEmailToken' );
|
||||
|
||||
$action = $request->getVal( 'action' );
|
||||
if ( $request->wasPosted()
|
||||
&& $reqUser->matchEditToken( $request->getVal( 'wpEditToken' ) ) )
|
||||
{
|
||||
$this->mPrevAttachment = $this->mPrevAttachment
|
||||
? $this->mPrevAttachment
|
||||
: $this->mSrcName;
|
||||
$this->doSubmit();
|
||||
} elseif ( $action == 'confirmemail' ) {
|
||||
$this->confirmEmailToken( $emailCode );
|
||||
} else {
|
||||
$this->showForm();
|
||||
}
|
||||
|
||||
$this->getOutput()->addModules( 'ext.confirmAccount' ); // CSS
|
||||
}
|
||||
|
||||
protected function showForm( $msg = '', $forgotFile = 0 ) {
|
||||
global $wgAccountRequestTypes, $wgMakeUserPageFromBio;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
|
||||
$this->mForgotAttachment = $forgotFile;
|
||||
|
||||
$out = $this->getOutput();
|
||||
$out->setPagetitle( $this->msg( "requestaccount" )->escaped() );
|
||||
# Output failure message if any
|
||||
if ( $msg ) {
|
||||
$out->addHTML( '<div class="errorbox">' . $msg . '</div><div class="visualClear"></div>' );
|
||||
}
|
||||
# Give notice to users that are logged in
|
||||
if ( $reqUser->getID() ) {
|
||||
$out->addWikiMsg( 'requestaccount-dup' );
|
||||
}
|
||||
|
||||
$out->addWikiMsg( 'requestaccount-text' );
|
||||
|
||||
$form = Xml::openElement( 'form', array( 'method' => 'post', 'name' => 'accountrequest',
|
||||
'action' => $this->getTitle()->getLocalUrl(), 'enctype' => 'multipart/form-data' ) );
|
||||
|
||||
$form .= '<fieldset><legend>' . $this->msg( 'requestaccount-leg-user' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-acc-text' )->parseAsBlock() . "\n";
|
||||
$form .= '<table cellpadding=\'4\'>';
|
||||
if ( $this->hasItem( 'UserName' ) ) {
|
||||
$form .= "<tr><td>" . Xml::label( $this->msg( 'username' )->text(), 'wpUsername' ) . "</td>";
|
||||
$form .= "<td>" . Xml::input( 'wpUsername', 30, $this->mUsername, array( 'id' => 'wpUsername' ) ) . "</td></tr>\n";
|
||||
} else {
|
||||
$form .= "<tr><td>" . $this->msg( 'username' )->escaped() . "</td>";
|
||||
$form .= "<td>" . $this->msg( 'requestaccount-same' )->escaped() . "</td></tr>\n";
|
||||
}
|
||||
//$form .= "<tr><td>" . Xml::label( $this->msg( 'requestaccount-email' )->text(), 'wpEmail' ) . "</td>";
|
||||
//$form .= "<td>" . Xml::input( 'wpEmail', 30, $this->mEmail, array( 'id' => 'wpEmail' ) ) . "</td></tr>\n";
|
||||
if ( count( $wgAccountRequestTypes ) > 1 ) {
|
||||
$form .= "<tr><td>" . $this->msg( 'requestaccount-reqtype' )->escaped() . "</td><td>";
|
||||
$options = array();
|
||||
foreach ( $wgAccountRequestTypes as $i => $params ) {
|
||||
$options[] = Xml::option( $this->msg( "requestaccount-level-$i" )->text(), $i, ( $i == $this->mType ) );
|
||||
}
|
||||
$form .= Xml::openElement( 'select', array( 'name' => "wpType" ) );
|
||||
$form .= implode( "\n", $options );
|
||||
$form .= Xml::closeElement( 'select' ) . "\n";
|
||||
$form .= '</td></tr>';
|
||||
}
|
||||
$form .= '</table></fieldset>';
|
||||
|
||||
$userAreas = ConfirmAccount::getUserAreaConfig();
|
||||
if ( $this->hasItem( 'AreasOfInterest' ) && count( $userAreas ) > 0 ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-areas' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-areas-text' )->parseAsBlock() . "\n";
|
||||
|
||||
$form .= "<div style='height:150px; overflow:scroll; background-color:#f9f9f9;'>";
|
||||
$form .= "<table cellspacing='5' cellpadding='0' style='background-color:#f9f9f9;'><tr valign='top'>";
|
||||
$count = 0;
|
||||
foreach ( $userAreas as $name => $conf ) {
|
||||
$count++;
|
||||
if ( $count > 5 ) {
|
||||
$form .= "</tr><tr valign='top'>";
|
||||
$count = 1;
|
||||
}
|
||||
$formName = "wpArea-" . htmlspecialchars( str_replace( ' ', '_', $name ) );
|
||||
if ( $conf['project'] != '' ) {
|
||||
$pg = Linker::link( Title::newFromText( $conf['project'] ),
|
||||
$this->msg( 'requestaccount-info' )->escaped(), array(), array(), "known" );
|
||||
} else {
|
||||
$pg = '';
|
||||
}
|
||||
$form .= "<td>" .
|
||||
Xml::checkLabel( $name, $formName, $formName, $this->mAreas[$name] > 0 ) .
|
||||
" {$pg}</td>\n";
|
||||
}
|
||||
$form .= "</tr></table></div>";
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
/*if ( $this->hasItem( 'Biography' ) || $this->hasItem( 'RealName' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-person' )->escaped() . '</legend>';
|
||||
if ( $this->hasItem( 'RealName' ) ) {
|
||||
$form .= '<table cellpadding=\'4\'>';
|
||||
$form .= "<tr><td>" . Xml::label( $this->msg( 'requestaccount-real' )->text(), 'wpRealName' ) . "</td>";
|
||||
$form .= "<td>" . Xml::input( 'wpRealName', 35, $this->mRealName, array( 'id' => 'wpRealName' ) ) . "</td></tr>\n";
|
||||
$form .= '</table>';
|
||||
}
|
||||
if ( $this->hasItem( 'Biography' ) ) {
|
||||
if ( $wgMakeUserPageFromBio ) {
|
||||
$form .= $this->msg( 'requestaccount-bio-text-i' )->parseAsBlock() . "\n";
|
||||
}
|
||||
$form .= $this->msg( 'requestaccount-bio-text' )->parseAsBlock() . "\n";
|
||||
$form .= "<p>" . $this->msg( 'requestaccount-bio' )->parse() . "\n";
|
||||
$form .= "<textarea tabindex='1' name='wpBio' id='wpBio' rows='12' cols='80' style='width:100%; background-color:#f9f9f9;'>" .
|
||||
htmlspecialchars( $this->mBio ) . "</textarea></p>\n";
|
||||
}
|
||||
$form .= '</fieldset>';
|
||||
}*/
|
||||
|
||||
if ( $this->hasItem( 'CV' ) || $this->hasItem( 'Notes' ) || $this->hasItem( 'Links' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-other' )->escaped() . '</legend>';
|
||||
$form .= $this->msg( 'requestaccount-ext-text' )->parseAsBlock() . "\n";
|
||||
if ( $this->hasItem( 'Notes' ) ) {
|
||||
$form .= "<p>" . $this->msg( 'requestaccount-notes' )->escaped() . "\n";
|
||||
$form .= "<textarea tabindex='1' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%;background-color:#f9f9f9;'>" .
|
||||
htmlspecialchars( $this->mNotes ) .
|
||||
"</textarea></p>\n";
|
||||
}
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
if ( $this->hasItem( 'TermsOfService' ) ) {
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>' . $this->msg( 'requestaccount-leg-tos' )->escaped() . '</legend>';
|
||||
$form .= "<p>" . Xml::check( 'wpToS', $this->mToS, array( 'id' => 'wpToS' ) ) .
|
||||
' <label for="wpToS">' . $this->msg( 'requestaccount-tos' )->parse() . "</label></p>\n";
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
|
||||
//Scratch user verification
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>User verification</legend>';
|
||||
$form .= '<p>Please go to the <a href="http://scratch.mit.edu/projects/10135908/">user verification project</a> and comment the following code:<br /><b>' . sha1($_SERVER['REMOTE_ADDR'] . date('m')) . '</b></p>' . "\n";
|
||||
$form .= '</fieldset>';
|
||||
|
||||
//Set temporary password
|
||||
$form .= '<fieldset>';
|
||||
$form .= '<legend>Set password</legend>';
|
||||
$form .= '<table border="0">
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input type="password" name="pwd1" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Confirm password</td>
|
||||
<td><input type="password" name="pwd2" /></td>
|
||||
</tr>
|
||||
</table>' . "\n";
|
||||
$form .= '</fieldset>';
|
||||
|
||||
# FIXME: do this better...
|
||||
global $wgConfirmAccountCaptchas, $wgCaptchaClass, $wgCaptchaTriggers;
|
||||
if ( $wgConfirmAccountCaptchas && isset( $wgCaptchaClass )
|
||||
&& $wgCaptchaTriggers['createaccount'] && !$reqUser->isAllowed( 'skipcaptcha' ) )
|
||||
{
|
||||
$captcha = new $wgCaptchaClass;
|
||||
# Hook point to add captchas
|
||||
$form .= '<fieldset>';
|
||||
$form .= $this->msg( 'captcha-createaccount' )->parseAsBlock();
|
||||
$form .= $captcha->getForm();
|
||||
$form .= '</fieldset>';
|
||||
}
|
||||
$form .= Html::Hidden( 'title', $this->getTitle()->getPrefixedDBKey() ) . "\n";
|
||||
$form .= Html::Hidden( 'wpEditToken', $reqUser->getEditToken() ) . "\n";
|
||||
$form .= Html::Hidden( 'attachment', $this->mPrevAttachment ) . "\n";
|
||||
$form .= Html::Hidden( 'forgotAttachment', $this->mForgotAttachment ) . "\n";
|
||||
$form .= "<p>" . Xml::submitButton( $this->msg( 'requestaccount-submit' )->text() ) . "</p>";
|
||||
$form .= Xml::closeElement( 'form' );
|
||||
|
||||
$out->addHTML( $form );
|
||||
|
||||
$out->addWikiMsg( 'requestaccount-footer' );
|
||||
}
|
||||
|
||||
protected function hasItem( $name ) {
|
||||
global $wgConfirmAccountRequestFormItems;
|
||||
|
||||
return $wgConfirmAccountRequestFormItems[$name]['enabled'];
|
||||
}
|
||||
|
||||
protected function doSubmit() {
|
||||
# Now create a dummy user ($u) and check if it is valid
|
||||
$name = trim( $this->mUsername );
|
||||
$u = User::newFromName( $name, 'creatable' );
|
||||
if ( !$u ) {
|
||||
$this->showForm( $this->msg( 'noname' )->escaped() );
|
||||
return;
|
||||
}
|
||||
# Set some additional data so the AbortNewAccount hook can be
|
||||
# used for more than just username validation
|
||||
$u->setEmail( $this->mEmail );
|
||||
$u->setRealName( $this->mRealName );
|
||||
# FIXME: Hack! If we don't want captchas for requests, temporarily turn it off!
|
||||
global $wgConfirmAccountCaptchas, $wgCaptchaTriggers;
|
||||
if ( !$wgConfirmAccountCaptchas && isset( $wgCaptchaTriggers ) ) {
|
||||
$old = $wgCaptchaTriggers['createaccount'];
|
||||
$wgCaptchaTriggers['createaccount'] = false;
|
||||
}
|
||||
$abortError = '';
|
||||
if ( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
|
||||
// Hook point to add extra creation throttles and blocks
|
||||
wfDebug( "RequestAccount::doSubmit: a hook blocked creation\n" );
|
||||
$this->showForm( $abortError );
|
||||
return;
|
||||
}
|
||||
# Set it back!
|
||||
if ( !$wgConfirmAccountCaptchas && isset( $wgCaptchaTriggers ) ) {
|
||||
$wgCaptchaTriggers['createaccount'] = $old;
|
||||
}
|
||||
|
||||
# Build submission object...
|
||||
$areaSet = array(); // make a simple list of interests
|
||||
foreach ( $this->mAreas as $area => $val ) {
|
||||
if ( $val > 0 ) {
|
||||
$areaSet[] = $area;
|
||||
}
|
||||
}
|
||||
|
||||
$submission = new AccountRequestSubmission(
|
||||
$this->getUser(),
|
||||
array(
|
||||
'userName' => $name,
|
||||
'realName' => $this->mRealName,
|
||||
'tosAccepted' => $this->mToS,
|
||||
'email' => $this->mEmail,
|
||||
'bio' => $this->mBio,
|
||||
'notes' => $this->mNotes,
|
||||
'urls' => $this->mUrls,
|
||||
'type' => $this->mType,
|
||||
'areas' => $areaSet,
|
||||
'registration' => wfTimestampNow(),
|
||||
'ip' => $this->getRequest()->getIP(),
|
||||
'xff' => $this->getRequest()->getHeader( 'X-Forwarded-For' ),
|
||||
'agent' => $this->getRequest()->getHeader( 'User-Agent' ),
|
||||
'attachmentPrevName' => $this->mPrevAttachment,
|
||||
'attachmentSrcName' => $this->mSrcName,
|
||||
'attachmentDidNotForget' => $this->mForgotAttachment, // confusing name :)
|
||||
'attachmentSize' => $this->mFileSize,
|
||||
'attachmentTempPath' => $this->mTempPath
|
||||
)
|
||||
);
|
||||
|
||||
# Actually submit!
|
||||
list( $status, $msg ) = $submission->submit( $this->getContext() );
|
||||
# Account for state changes
|
||||
$this->mForgotAttachment = $submission->getAttachmentDidNotForget();
|
||||
$this->mPrevAttachment = $submission->getAttachtmentPrevName();
|
||||
# Check for error messages
|
||||
if ( $status !== true ) {
|
||||
$this->showForm( $msg );
|
||||
return;
|
||||
}
|
||||
|
||||
# Done!
|
||||
$this->showSuccess();
|
||||
}
|
||||
|
||||
protected function showSuccess() {
|
||||
$out = $this->getOutput();
|
||||
$out->setPagetitle( $this->msg( "requestaccount" )->escaped() );
|
||||
$out->addWikiMsg( 'requestaccount-sent' );
|
||||
$out->returnToMain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the uploaded file from PHP data
|
||||
* @param $request WebRequest
|
||||
*/
|
||||
protected function initializeUpload( $request ) {
|
||||
$file = new WebRequestUpload( $request, 'wpUploadFile' );
|
||||
$this->mTempPath = $file->getTempName();
|
||||
$this->mFileSize = $file->getSize();
|
||||
$this->mSrcName = $file->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* (a) Try to confirm an email address via a token
|
||||
* (b) Notify $wgConfirmAccountContact on success
|
||||
* @param $code string The token
|
||||
* @return void
|
||||
*/
|
||||
protected function confirmEmailToken( $code ) {
|
||||
global $wgConfirmAccountContact, $wgPasswordSender, $wgPasswordSenderName;
|
||||
|
||||
$reqUser = $this->getUser();
|
||||
$out = $this->getOutput();
|
||||
# Confirm if this token is in the pending requests
|
||||
$name = ConfirmAccount::requestNameFromEmailToken( $code );
|
||||
if ( $name !== false ) {
|
||||
# Send confirmation email to prospective user
|
||||
ConfirmAccount::confirmEmail( $name );
|
||||
# Send mail to admin after e-mail has been confirmed
|
||||
if ( $wgConfirmAccountContact != '' ) {
|
||||
$target = new MailAddress( $wgConfirmAccountContact );
|
||||
$source = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
|
||||
$title = SpecialPage::getTitleFor( 'ConfirmAccounts' );
|
||||
$subject = $this->msg( 'requestaccount-email-subj-admin' )->inContentLanguage()->escaped();
|
||||
$body = $this->msg(
|
||||
'requestaccount-email-body-admin', $name )->rawParams( $title->getFullUrl() )->inContentLanguage()->escaped();
|
||||
# Actually send the email...
|
||||
$result = UserMailer::send( $target, $source, $subject, $body );
|
||||
if ( !$result->isOK() ) {
|
||||
wfDebug( "Could not sent email to admin at $target\n" );
|
||||
}
|
||||
}
|
||||
$out->addWikiMsg( 'request-account-econf' );
|
||||
$out->returnToMain();
|
||||
} else {
|
||||
# Maybe the user confirmed after account was created...
|
||||
$user = User::newFromConfirmationCode( $code );
|
||||
if ( is_object( $user ) ) {
|
||||
if ( $user->confirmEmail() ) {
|
||||
$message = $reqUser->isLoggedIn()
|
||||
? 'confirmemail_loggedin'
|
||||
: 'confirmemail_success';
|
||||
$out->addWikiMsg( $message );
|
||||
if ( !$reqUser->isLoggedIn() ) {
|
||||
$title = SpecialPage::getTitleFor( 'Userlogin' );
|
||||
$out->returnToMain( true, $title->getPrefixedUrl() );
|
||||
}
|
||||
} else {
|
||||
$out->addWikiMsg( 'confirmemail_error' );
|
||||
}
|
||||
} else {
|
||||
$out->addWikiMsg( 'confirmemail_invalid' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue