copy over register.php from plewww
[plewww-sso.git] / planetlab / persons / register.php
1 <?php
2 // $Id$
3 //
4 // Account registration and verification form. This form can be called
5 // in one of two ways:
6 //
7 // 1. ?first_name=FIRST_NAME&last_name=LAST_NAME&email=EMAIL...
8 //
9 // Called by the form at the bottom of the page to register a new
10 // account. If any required fields are missing, AddPerson() will fault
11 // and the specified fields will be highlighted. Otherwise, the
12 // account is registered (but not enabled), and VerifyPerson() sends
13 // the user a link back to this page.
14 //
15 // 2. ?id=PERSON_ID&key=VERIFICATION_KEY...
16 //
17 // Sent to the specified user by VerifyPerson(). If the user receives
18 // the message, then the registered e-mail address is considered
19 // valid, and registration can continue. VerifyPerson() is called
20 // again, and sends the current PI(s) (and support if the user is
21 // requesting a PI role) a link to the user's Account Details page to
22 // enable the account.
23 //
24 // Mark Huang <mlhuang@cs.princeton.edu>
25 // Copyright (C) 2007 The Trustees of Princeton University
26 //
27 // $Id$ $
28 //
29
30 // Get session and API handles
31 require_once 'plc_session.php';
32 global $plc, $api, $adm;
33
34 // Print header
35 require_once 'plc_drupal.php';
36 include 'plc_header.php';
37
38 require_once 'plc_functions.php';
39 require_once 'nifty.php';
40 require_once 'details.php';
41
42 drupal_set_title('Account Registration');
43
44 // Drupalish, but does not use Drupal itself to generate the form
45 global $person_form;
46
47 $person_form = array();
48 $person_form['first_name'] = array('title' => 'First name', 'required' => TRUE,
49                             'maxlength' => 60, 'size' => 15);
50 $person_form['last_name'] = array('title' => 'Last name', 'required' => TRUE,
51                             'maxlength' => 60, 'size' => 15);
52 $person_form['title'] = array('title' => 'Title', 'required' => FALSE,
53                        'maxlength' => 60, 'size' => 5);
54 $person_form['phone'] = array('title' => 'Telephone', 'required' => FALSE,
55                        'maxlength' => 60, 'size' => 20);
56 $person_form['email'] = array('title' => 'E-mail', 'required' => TRUE,
57                        'maxlength' => 60, 'size' => 30);
58 $person_form['password'] = array('title' => 'Password', 'required' => TRUE,
59                        'maxlength' => 60, 'size' => 20);
60 $person_form['site_ids'] = array('title' => 'Site', 'required' => TRUE);
61 if (0)
62   $person_form['roles'] = array('title' => 'Additional Roles', 'required' => FALSE);
63
64 //////////////////// additional messages
65 $person_form['email']['comment'] = <<< EOF
66 Your <b>E-mail</b> address must be able to receive e-mail and will be
67 used as your $PLC_NAME username
68 EOF;
69
70 $person_form['site_ids']['comment'] = <<< EOF
71 Select the site where you belong 
72 EOF;
73
74 if (0)
75   $person_form['roles']['comment'] = <<< EOF
76 Do not select the <b>Principal Investigator</b> or <b>Technical
77 Contact</b> roles unless you have spoken with the current PI of your
78 site, and you intend to assume either or both of these roles.
79 <br> Use Command-Clic to unselect or for multiple selection
80 EOF;
81
82 //////////////////// parse form values and store in $person
83 global $person;
84 $person = array();
85 foreach ($person_form as $name => $item) {
86   if (!empty($_REQUEST[$name])) {
87     $person[$name] = $_REQUEST[$name];
88   }
89 }
90
91 // Filter out "Select a site"
92 if (!empty($person['site_ids'])) {
93   $person['site_ids'] = array_filter($person['site_ids'],
94                                      create_function('$site_id', 'return intval($site_id) > 0;'));
95 }
96
97 //////////////////// minimal checking
98 function check_form ($person) {
99   global $person_form;
100   global $adm;
101   
102   // Look for missing/blank entries
103   $missing = array();
104   foreach ($person_form as $name => $item) {
105     if ($item['required'] && empty($person[$name])) {
106       $missing[] = $item['title'];
107     }
108   }
109
110   // missing fields
111   if (!empty($missing)) {
112     $warnings=array();
113     foreach ($missing as $field) $warnings []= "$field field is required.";
114     print html_div(plc_itemize($warnings),"messages error");
115     return FALSE;
116   } 
117
118   // check that the email address is not already used on this peer
119   $email=$person['email'];
120   $already = $adm->GetPersons ( array('email'=>$person['email'],'peer_id'=>NULL) );
121   if ( ! empty ($already) ) {
122     print html_div(plc_itemize(array("Email $email already used !")),"messages error");
123     return FALSE;
124   }
125
126   return TRUE;
127 }
128
129 //////////////////// perform api calls
130 function register_person ($person) {
131
132   global $adm;
133
134   $errors = errors_init ();
135
136   // N.B.: site_ids and roles are ignored by AddPerson()
137   $person_id = $adm->AddPerson($person);
138   $errors = errors_record ($adm,$errors);
139
140   if (empty($errors)) {
141     $adm->begin();
142
143     // Add person to requested sites
144     foreach ($person['site_ids'] as $site_id) {
145       $adm->AddPersonToSite($person_id, intval($site_id));
146       $adm->SetPersonPrimarySite($person_id, intval($site_id));
147     }
148
149     // Add requested roles. Always add the user role. 
150     $adm->AddRoleToPerson('user', $person_id);
151     if (!empty($person['roles'])) {
152       foreach ($person['roles'] as $role) {
153         $adm->AddRoleToPerson($role, $person_id);
154       }
155     }
156
157     // Send an e-mail containing a link back to this page, which will
158     // verify the given e-mail address as valid. PIs can still create
159     // and enable accounts on behalf of their users, they just have to
160     // find and enable the accounts manually after registering them.
161     $adm->VerifyPerson($person_id);
162
163     // Disable submit button
164     $person['person_id'] = $person_id;
165
166     $adm->commit();
167     $errors = errors_record ($adm,$errors);
168   }
169
170   if (!empty($errors)) {
171     errors_display($errors);
172   } else {
173     $email=$person['email'];
174     $text="Your registration request has been received. An e-mail has been sent to $email with further instructions.";
175     print html_div($text,"messages status");
176   }
177 }
178
179 ////////////////////
180 if (!empty($person) && check_form ($person))
181   register_person($person);
182
183 $PLC_NAME = htmlspecialchars(PLC_NAME);
184
185 // E-mail address verified, go ahead and notify the PI (and possibly
186 // support if a PI role was requested) that a registration request was
187 // received.
188 if (!empty($_REQUEST['id']) && !empty($_REQUEST['key'])) {
189   $person_id = intval($_REQUEST['id']);
190   if ($adm->VerifyPerson($person_id, $_REQUEST['key']) != 1) {
191     plc_error($adm->error());
192   } else {
193     $persons = $adm->GetPersons(array($person_id));
194     $person = $persons[0];
195
196     // Remove the password field from the form so that it is not
197     // highlighted as missing.
198     unset($person_form['password']);
199
200     $messages = array();
201     $messages []= 'Your e-mail address has been verified. ';
202     $messages []= 'The PI(s) at your site have been notified of your account registration ';
203
204     if (! in_array('pi', $person['roles'])) {
205       $messages []= 'They are responsible for enabling your account.';
206     } else {
207       $support = PLC_MAIL_SUPPORT_ADDRESS;
208       $messages []= "They should contact <a href=\"mailto:$support\">$PLC_NAME Support <$support></a>. ";
209       $messages []= "$PLC_NAME Support will enable your account once authorized by your PI(s).";
210     }
211
212     plc_itemize($messages,"messages status");
213   }
214 }
215
216 $adm->begin();
217
218 // All defined sites
219 // cannot register with foreign site
220 $adm->GetSites(array('is_public' => TRUE, 'peer_id' => NULL,'-SORT'=>'name'), 
221                array('site_id', 'name','enabled','peer_id'));
222 // All defined roles
223 $adm->GetRoles();
224
225 list($sites, $roles) = $adm->commit();
226
227 // Prepend invalid site to beginning of list to force user to select a site
228 $sites = array_merge(array(array('site_id' => -1, 'name' => 'Select a site', 'enabled' => TRUE)), $sites);
229
230 // Drop down selection box for each site
231 function site_option($site) {
232   global $person;
233
234   $site_id = $site['site_id'];
235
236   if (!empty($person['site_ids']) && in_array($site_id, $person['site_ids'])) {
237     $selected = 'selected="selected"';
238   } else {
239     $selected = "";
240   }
241
242   $option = "<option value='$site_id' $selected";
243   if ( ! $site['enabled'] )
244     $option .= " disabled='disabled'";
245   $option .= ">";
246   $option .= htmlspecialchars($site['name']);
247   # Safari/IE do not implement disabled correctly
248   if ( ! $site['enabled'] )
249     $option .= " (disabled, or pending registration)";
250   $option .= "</option>";
251   return $option;
252 }
253 $site_options = implode("\n", array_map('site_option', $sites));
254
255 // Do not tempt users to register for the admin role. Administrators
256 // should register normally, then be granted the admin role by another
257 // admin. Also, all accounts should have the user role (see above).
258 foreach ($roles as $i => $role) {
259   if ($role['name'] == 'admin' || $role['name'] == 'user') {
260     unset($roles[$i]);
261   }
262 }
263
264 // Standard roles
265 global $standard_roles;
266 $standard_roles = array('user' => 'User',
267                         'pi' => 'Principal Investigator',
268                         'tech' => 'Technical Contact',
269                         'admin' => 'Administrator');
270
271 // Drop down selection box for each role
272 function role_option($role) {
273   global $standard_roles, $selected_roles;
274
275   $name = $role['name'];
276
277   if (!empty($person['roles']) && in_array($name, $person['roles'])) {
278     $selected = 'selected="selected"';
279   } else {
280     $selected = "";
281   }
282
283   $display = array_key_exists($name, $standard_roles) ? $standard_roles[$name] : $name;
284
285   $option = "<option value=\"$name\" $selected>";
286   $option .= htmlspecialchars($display);
287   $option .= "</option>";
288   return $option;
289 }
290 $role_options = implode("\n", array_map('role_option', $roles));
291
292
293 $nifty=new PlekitNifty ('register','person-register','medium');
294 $nifty->start();
295 $details = new PlekitDetails(TRUE);
296 $details -> start();
297 $details->form_start(l_person_register(),array());
298
299 // Do not allow resubmits
300 $register_button="<input type='submit' name='op' value='Register'  class='form-submit' />";
301 if (empty($person['person_id'])) {
302   $details->tr($register_button,'center');
303   $details->space();
304 }
305
306 foreach ($person_form as $name => $item) {
307
308   if ( ! empty($item['comment'])) {
309     $details->space();
310     $details->tr($item['comment'] . ":");
311   }
312
313   $title = $item['title'];
314   $required = $item['required'] ? '<span class="form-required" title="This field is required.">*</span>' : "";
315   $class = $item['required'] ? "required" : "";
316   if ($item['required'] && !empty($person) && empty($person[$name])) {
317     $class .= " error";
318   }
319
320   // Label part
321   $left_part = "<label class='$class' for='edit-$name'>$title: $required</label>";
322
323   // input part
324   switch ($name) {
325
326   case 'site_ids':
327     $right_part= "<select name='site_ids[]' id='edit-site_ids' class='form-select $class'> $site_options </select>";
328     break;
329
330   case 'roles':
331     $right_part="";
332     if (0) { /* Not letting users select PI or Tech any more.  Its only lead to confusion and abuse. */
333       $right_part = "<select name='roles[]' multiple='multiple' id='edit-roles' class='form-select $class'> $role_options </select>";
334     }
335     break;
336
337   default:
338     $maxlength = $item['maxlength'];
339     $size = $item['size'];
340     $value = !empty($person[$name]) ? $person[$name] : "";
341     $type = $name == 'password' ? "password" : "text";
342     $right_part = "<input type='$type' maxlength='$maxlength' name='$name' id='edit-$name' size='$size' value='$value' class='form-text $class'>";
343     break;
344   }
345
346   $details->th_td($left_part,$right_part);
347 }
348
349 // Do not allow resubmits
350 if (empty($person['person_id'])) {
351   $details->space();
352   $details->tr($register_button,'center');
353 }
354
355 $details->form_end();
356 $details->end();
357 $nifty->end();
358
359 include 'plc_footer.php';
360
361 ?>