register.php 16.8 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
 *
Francois Marier's avatar
Francois Marier committed
7
8
9
10
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
11
 *
Francois Marier's avatar
Francois Marier committed
12
13
14
15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
16
 *
Francois Marier's avatar
Francois Marier committed
17
18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21
 *
 * @package    mahara
 * @subpackage core
22
 * @author     Catalyst IT Ltd
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
28
29
 *
 */

define('INTERNAL', 1);
define('PUBLIC', 1);
30
31
32
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'site');
define('SECTION_PAGE', 'register');
33
require('init.php');
34
require_once('pieforms/pieform.php');
35
require_once('lib/antispam.php');
36
require_once('lib/institution.php');
Martyn Smith's avatar
Martyn Smith committed
37
define('TITLE', get_string('register'));
38
$key = param_alphanum('key', null);
39

40
41
42
43
44
45
46
47
48
49
50
51
/*
 * This page handles three different tasks:
 *   1) Showing a visitor the registration form
 *   2) Telling the visitor to check their e-mail for a message
 *   3) Given a key, display profile information to edit
 *
 * It uses the session to store some state
 */
if (!session_id()) {
    session_start();
}

52
53
// Logged in people can't register. If someone passes a key however, log the 
// user out and see if this key registers someone
Nigel McNie's avatar
Nigel McNie committed
54
if (is_logged_in()) {
55
56
57
58
59
60
    if ($key) {
        $USER->logout();
    }
    else {
        redirect();
    }
61
62
}

63
64
65
66
// Step two of registration (first as it's the easiest): the user has
// registered, show them a screen telling them this.
if (!empty($_SESSION['registered'])) {
    unset($_SESSION['registered']);
67
    die_info(get_string('registeredok', 'auth.internal'));
68
69
}

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
if (!empty($_SESSION['registrationcancelled'])) {
    unset($_SESSION['registrationcancelled']);
    die_info(get_string('registrationcancelledok', 'auth.internal'));
}

// email confirmed, show them a screen telling them this.
if (!empty($_SESSION['emailconfirmed'])) {
    // email institutional administrator(s) of new registration
    if (isset($_SESSION['registrationkey'])) {
        $key = $_SESSION['registrationkey'];
        if ($registration = get_record_select('usr_registration', '"key" = ? AND "pending" = ?', array($key, 1))) {
            $fullname = sprintf("%s %s", trim($registration->firstname), trim($registration->lastname));
            $institution = new Institution($registration->institution);
            $pendingregistrationslink = sprintf("%sadmin/users/pendingregistrations.php", get_config('wwwroot'));

            // list of admins for this institution
            if (count($institution->admins()) > 0) {
                $admins = $institution->admins();
            }
            else {
                // use site admins if the institution doesn't have any
                $admins = get_column('usr', 'id', 'admin', 1, 'deleted', 0);
            }

            // email each admin
            foreach ($admins as $admin) {
                $user = new User();
                $user->find_by_id($admin);
                email_user($user, null,
                    get_string('pendingregistrationadminemailsubject', 'auth.internal', $institution->displayname, get_config('sitename')),
                    get_string('pendingregistrationadminemailtext', 'auth.internal',
                        $user->firstname, $institution->displayname, $pendingregistrationslink,
                        $fullname, $registration->email, $registration->reason, get_config('sitename')),
                    get_string('pendingregistrationadminemailhtml', 'auth.internal',
                        $user->firstname, $institution->displayname, $pendingregistrationslink, $pendingregistrationslink,
                        $fullname, $registration->email, $registration->reason, get_config('sitename'))
                    );
            }
        }

        unset($_SESSION['registrationkey']);
    }

    unset($_SESSION['emailconfirmed']);
    die_info(get_string('emailconfirmedok', 'auth.internal'));
}

117
// Step three of registration - given a key register the user
118
if (isset($key)) {
119

120
121
122
123
124
    // Begin the registration form buliding
    if (!$registration = get_record_select('usr_registration', '"key" = ? AND expiry >= ?', array($key, db_format_timestamp(time())))) {
        die_info(get_string('registrationnosuchkey', 'auth.internal'));
    }

125
126
127
128
129
130
    // In case a new session has started, reset the session language
    // to the one selected during registration
    if (!empty($registration->lang)) {
        $SESSION->set('lang', $registration->lang);
    }

131
132
133
134
135
136
137
138
139
140
141
142
143
144
    // check if institution requires admin approval for registration
    // if so and !$registration->pending page hit was email confirmation
    // update registration details + redirect to notify user
    $confirm = get_field('institution', 'registerconfirm', 'name', $registration->institution);
    if ($confirm && $registration->pending == 0) {
        $values['key']   = get_random_key();
        $values['pending'] = 1;
        $values['expiry'] = db_format_timestamp(time() + (86400 * 7)); // now + 1 week
        update_record('usr_registration', $values, array('email' => $registration->email));
        $SESSION->set('emailconfirmed', true);
        $SESSION->set('registrationkey', $values['key']);
        redirect('/register.php');
    }

145
    function create_registered_user($profilefields=array()) {
146
        global $registration, $SESSION, $USER, $confirm;
147
        require_once(get_config('libroot') . 'user.php');
148

149
        db_begin();
150
151
152
153

        // Move the user record to the usr table from the registration table
        $registrationid = $registration->id;
        unset($registration->id);
154
        unset($registration->expiry);
155
        if ($expirytime = get_config('defaultaccountlifetime')) {
156
157
            $registration->expiry = db_format_timestamp(time() + $expirytime);
        }
158
        $registration->lastlogin = db_format_timestamp(time());
159
160
161

        $authinstance = get_record('auth_instance', 'institution', $registration->institution, 'authname', 'internal');
        if (false == $authinstance) {
162
            throw new ConfigException('No internal auth instance for institution');
163
164
165
166
167
168
169
        }

        $user = new User();
        $user->active           = 1;
        $user->authinstance     = $authinstance->id;
        $user->firstname        = $registration->firstname;
        $user->lastname         = $registration->lastname;
170
        $user->email            = $registration->email;
171
172
        $user->username         = get_new_username($user->firstname . $user->lastname);
        $user->passwordchange   = 1;
173

174
        create_user($user, $profilefields);
175

176
177
178
179
180
181
182
183
184
185
        // If the institution is 'mahara' then don't do anything
        if ($registration->institution != 'mahara') {
            $institutions = get_records_select_array('institution', "name != 'mahara'");

            // If there is only one available, join it without requiring approval
            if (count($institutions) == 1) {
                $user->join_institution($registration->institution);
            }
            // Else, since there are multiple, request to join
            else {
186
187
188
189
190
191
                if ($confirm && $registration->pending == 2) {
                    $user->join_institution($registration->institution);
                }
                else {
                    $user->add_institution_request($registration->institution);
                }
192
193
194
            }
        }

195

196
197
198
        if (!empty($registration->lang) && $registration->lang != 'default') {
            set_account_preference($user->id, 'lang', $registration->lang);
        }
199
200

        // Delete the old registration record
201
202
        delete_records('usr_registration', 'id', $registrationid);

203
204
        db_commit();

205
        // Log the user in and send them to the homepage
206
207
        $USER = new LiveUser();
        $USER->reanimate($user->id, $authinstance->id);
Nigel McNie's avatar
Nigel McNie committed
208

209
        $SESSION->add_ok_msg(get_string('registrationcomplete', 'mahara', get_config('sitename')));
210
        $SESSION->set('resetusername', true);
211
        redirect();
212
    }
213
    create_registered_user();
214
215
}

216
217
218

// Default page - show the registration form

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
$elements = array(
    'firstname' => array(
        'type' => 'text',
        'title' => get_string('firstname'),
        'rules' => array(
            'required' => true
        )
    ),
    'lastname' => array(
        'type' => 'text',
        'title' => get_string('lastname'),
        'rules' => array(
            'required' => true
        )
    ),
    'email' => array(
        'type' => 'text',
        'title' => get_string('emailaddress'),
        'rules' => array(
            'required' => true,
            'email' => true
        )
    )
);
243
244
245
$sql = 'SELECT
            i.*
        FROM
246
247
            {institution} i,
            {auth_instance} ai
248
249
        WHERE
            ai.authname = \'internal\' AND
250
251
            ai.institution = i.name AND
            i.registerallowed = 1';
252
253
$institutions = get_records_sql_array($sql, array());

254
255
256
257
258
if (count($institutions) > 1) {
    $options = array();
    foreach ($institutions as $institution) {
        $options[$institution->name] = $institution->displayname;
    }
259
    natcasesort($options);
260
    array_unshift($options, get_string('chooseinstitution', 'mahara'));
261
262
263
    $elements['institution'] = array(
        'type' => 'select',
        'title' => get_string('institution'),
264
265
266
267
        'options' => $options,
        'rules' => array(
            'required' => true
        )
268
269
    );
}
270
271
272
273
else if ($institutions) { // Only one option - probably mahara ('No Institution') but that's not certain

    $institution = array_shift($institutions);

274
275
    $elements['institution'] = array(
        'type' => 'hidden',
276
        'value' => $institution->name
277
278
    );
}
279
280
281
else {
    die_info(get_string('registeringdisallowed'));
}
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
$registerterms = get_config('registerterms');
if ($registerterms) {
    $elements['tandc'] = array(
        'type' => 'radio',
        'title' => get_string('iagreetothetermsandconditions', 'auth.internal'),
        'options' => array(
            'yes' => get_string('yes'),
            'no'  => get_string('no')
        ),
        'defaultvalue' => 'no',
        'rules' => array(
            'required' => true
        ),
        'separator' => ' &nbsp; '
    );
}
299

300
$elements['submit'] = array(
301
302
    'type' => 'submit',
    'value' => get_string('register'),
303
304
);

305
306
// swap the name and email fields at random
if (rand(0,1)) {
307
308
309
    $emailelement = $elements['email'];
    unset($elements['email']);
    $elements = array('email' => $emailelement) + $elements;
310
311
}

312
313
314
$form = array(
    'name' => 'register',
    'method' => 'post',
315
316
    'plugintype' => 'core',
    'pluginname' => 'register',
317
    'action' => '',
318
    'showdescriptiononerror' => false,
319
    'renderer' => 'table',
320
321
322
323
324
325
    'elements' => $elements,
    'spam' => array(
        'secret'       => get_config('formsecret'),
        'mintime'      => 5,
        'hash'         => array('firstname', 'lastname', 'email', 'institution', 'tandc', 'submit'),
    ),
326
327
);

328
329
330
331
332
333
/**
 * @todo add note: because the form select thing will eventually enforce
 * that the result for $values['institution'] was in the original lot,
 * and because that only allows authmethods that use 'internal' auth, we
 * can guarantee that the auth method is internal
 */
334
function register_validate(Pieform $form, $values) {
335
    global $SESSION, $registerterms;
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

    $spamtrap = new_spam_trap(array(
        array(
            'type' => 'name',
            'value' => $values['firstname'],
        ),
        array(
            'type' => 'name',
            'value' => $values['lastname'],
        ),
        array(
            'type' => 'email',
            'value' => $values['email'],
        ),
    ));

    if ($form->spam_error() || $spamtrap->is_spam()) {
353
354
355
356
357
        $msg = get_string('formerror');
        $emailcontact = get_config('emailcontact');
        if (!empty($emailcontact)) {
            $msg .= ' ' . get_string('formerroremail', 'mahara', $emailcontact, $emailcontact);
        }
358
359
        $form->set_error(null, $msg);
        return;
360
    }
361
362

    $institution = $values['institution'];
363
    safe_require('auth', 'internal');
364
365
366

    // First name and last name must contain at least one non whitespace
    // character, so that there's something to read
367
368
    if (!$form->get_error('firstname') && !preg_match('/\S/', $values['firstname'])) {
        $form->set_error('firstname', $form->i18n('required'));
369
370
    }

371
372
    if (!$form->get_error('lastname') && !preg_match('/\S/', $values['lastname'])) {
        $form->set_error('lastname', $form->i18n('required'));
373
374
375
    }

    // The e-mail address cannot already be in the system
376
377
378
379
    if (!$form->get_error('email')
        && (record_exists('usr', 'email', $values['email'])
        || record_exists('artefact_internal_profile_email', 'email', $values['email']))) {
        $form->set_error('email', get_string('emailalreadytaken', 'auth.internal'));
380
381
382
    }
    
    // If the user hasn't agreed to the terms and conditions, don't bother
383
    if ($registerterms && $values['tandc'] != 'yes') {
384
        $form->set_error('tandc', get_string('youmaynotregisterwithouttandc', 'auth.internal'));
385
    }
386

387
    $institution = get_record_sql('
388
        SELECT 
389
            i.name, i.maxuseraccounts, i.registerallowed, COUNT(u.id)
390
391
392
393
394
395
        FROM {institution} i
            LEFT OUTER JOIN {usr_institution} ui ON ui.institution = i.name
            LEFT OUTER JOIN {usr} u ON (ui.usr = u.id AND u.deleted = 0)
        WHERE
            i.name = ?
        GROUP BY
396
            i.name, i.maxuseraccounts, i.registerallowed', array($institution));
397

398
    if (!empty($institution->maxuseraccounts) && $institution->count >= $institution->maxuseraccounts) {
399
        $form->set_error($hashed['institution'], get_string('institutionfull'));
400
401
    }

402
    if (!$institution || !$institution->registerallowed) {
403
        $form->set_error('institution', get_string('registrationnotallowed'));
404
405
    }

406
407
}

408
function register_submit(Pieform $form, $values) {
409
    global $SESSION;
410
411
412
413

    // store password encrypted
    // don't die_info, since reloading the page shows the login form.
    // instead, redirect to some other page that says this
414
    safe_require('auth', 'internal');
415
    $values['key']   = get_random_key();
416
    // @todo the expiry date should be configurable
417
418
    $values['expiry'] = db_format_timestamp(time() + 86400);
    $values['lang'] = $SESSION->get('lang');
419
    try {
420
421
422
423
424
425
        if (!record_exists('usr_registration', 'email', $values['email'])) {
            insert_record('usr_registration', $values);
        }
        else {
            update_record('usr_registration', $values, array('email' => $values['email']));
        }
426

427
428
429
430
431
432
433
434
        // if the institution requires a registration workflow
        // redirect to get more details
        $confirm = get_field('institution', 'registerconfirm', 'name', $values['institution']);
        if ($confirm) {
            $id = get_field('usr_registration', 'id', 'email', $values['email']);
            redirect('/register/reason.php?r='.$id);
        }

435
        $user =(object) $values;
436
        $user->admin = 0;
437
        $user->staff = 0;
438
        email_user($user, null,
439
            get_string('registeredemailsubject', 'auth.internal', get_config('sitename')),
440
441
            get_string('registeredemailmessagetext', 'auth.internal', $values['firstname'], get_config('sitename'), get_config('wwwroot'), $values['key'], get_config('sitename')),
            get_string('registeredemailmessagehtml', 'auth.internal', $values['firstname'], get_config('sitename'), get_config('wwwroot'), $values['key'], get_config('wwwroot'), $values['key'], get_config('sitename')));
442
443
    }
    catch (EmailException $e) {
444
        log_warn($e);
445
        die_info(get_string('registrationunsuccessful', 'auth.internal'));
446
447
    }
    catch (SQLException $e) {
448
        log_warn($e);
449
        die_info(get_string('registrationunsuccessful', 'auth.internal'));
450
451
452
453
454
    }

    // Add a marker in the session to say that the user has registered
    $_SESSION['registered'] = true;

455
    redirect('/register.php');
456
457
}

458
459
460
461
462
463
$registerdescription = get_string('registerwelcome');
if ($registerterms) {
    $registerdescription .= ' ' . get_string('registeragreeterms');
}
$registerdescription .= ' ' . get_string('registerprivacy');

464
$smarty = smarty();
465
$smarty->assign('register_form', pieform($form));
466
467
468
469
$smarty->assign('registerdescription', $registerdescription);
if ($registerterms) {
    $smarty->assign('termsandconditions', get_site_page_content('termsandconditions'));
}
470
$smarty->assign('PAGEHEADING', TITLE);
471
$smarty->display('register.tpl');