8894c6bb08439c365dc235fd4de90701fd737de6
[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 // Site tags for sites to include on registration page
225 $adm->GetSiteTags(array("tagname" => "include_site_register"));
226
227 list($sites, $roles, $include_tags) = $adm->commit();
228
229 if ($include_tags) {
230     // If there are any include tags, then filter the list of sites to only
231     // those with include tags.
232     //
233     // If there were no include tags, then we include them all.
234
235     $include_ids = array();
236     foreach ($include_tags as $tag) {
237         if ($tag['value']) {
238             $include_ids [$tag['site_id']] = $tag;
239         }
240     }
241     $new_sites = array();
242     foreach ($sites as $site) {
243         if ($include_ids[$site['site_id']]) {
244             $new_sites []= $site;
245         }
246     }
247     $sites = $new_sites;
248 }
249
250 // Prepend invalid site to beginning of list to force user to select a site
251 $sites = array_merge(array(array('site_id' => -1, 'name' => 'Select a site', 'enabled' => TRUE)), $sites);
252
253 // Drop down selection box for each site
254 function site_option($site) {
255   global $person;
256
257   $site_id = $site['site_id'];
258
259   if (!empty($person['site_ids']) && in_array($site_id, $person['site_ids'])) {
260     $selected = 'selected="selected"';
261   } else {
262     $selected = "";
263   }
264
265   $option = "<option value='$site_id' $selected";
266   if ( ! $site['enabled'] )
267     $option .= " disabled='disabled'";
268   $option .= ">";
269   $option .= htmlspecialchars($site['name']);
270   # Safari/IE do not implement disabled correctly
271   if ( ! $site['enabled'] )
272     $option .= " (disabled, or pending registration)";
273   $option .= "</option>";
274   return $option;
275 }
276 $site_options = implode("\n", array_map('site_option', $sites));
277
278 // Do not tempt users to register for the admin role. Administrators
279 // should register normally, then be granted the admin role by another
280 // admin. Also, all accounts should have the user role (see above).
281 foreach ($roles as $i => $role) {
282   if ($role['name'] == 'admin' || $role['name'] == 'user') {
283     unset($roles[$i]);
284   }
285 }
286
287 // Standard roles
288 global $standard_roles;
289 $standard_roles = array('user' => 'User',
290                         'pi' => 'Principal Investigator',
291                         'tech' => 'Technical Contact',
292                         'admin' => 'Administrator');
293
294 // Drop down selection box for each role
295 function role_option($role) {
296   global $standard_roles, $selected_roles;
297
298   $name = $role['name'];
299
300   if (!empty($person['roles']) && in_array($name, $person['roles'])) {
301     $selected = 'selected="selected"';
302   } else {
303     $selected = "";
304   }
305
306   $display = array_key_exists($name, $standard_roles) ? $standard_roles[$name] : $name;
307
308   $option = "<option value=\"$name\" $selected>";
309   $option .= htmlspecialchars($display);
310   $option .= "</option>";
311   return $option;
312 }
313 $role_options = implode("\n", array_map('role_option', $roles));
314
315
316 $nifty=new PlekitNifty ('register','person-register','medium');
317 $nifty->start();
318
319 print <<< EOF
320 <div style="max-width: 800px;">
321 <p>The ViCCI testbed is affiliated with <a href="http://www.planet-lab.org/">PlanetLab</a>.
322 If you already have a PlanetLab account, you can use it on ViCCI.
323 You do not need to register for a new ViCCI account.
324 In other words, a PlanetLab account gives you access to both PlanetLab and ViCCI.</p>
325
326 <p>If you do not already have a PlanetLab account, you have two options.
327 One is to first long into <a href="http://www.planet-lab.org/">PlanetLab</a> and create an account there.
328 You account will be approved if (a) you belong to an site that is a member of
329 the PlanetLab Consortium, and (b) the Principle Investigator (PI) for your site
330 approves your request. Since PlanetLab primarily supports network research,
331 and PIs are typically Computer Scientists that approve accounts for researchers
332 doing network and distributed systems research, this may or may not be appropriate
333 for you. If not, the second option is to create a ViCCI-only account by filling
334 out the following web form.</p>
335
336 <p>Note that having a user account is not sufficient for gaining access to ViCCI.
337 You also need to create a slice (project), which will also require PI approval.
338 Once the slice has been created, you will be able to allocate ViCCI resources
339 (some number of VMs) to it. As with user accounts, PlanetLab slices also have
340 access to ViCCI, while ViCCI slices are limited to only ViCCI.</p></div>
341 EOF;
342
343 $details = new PlekitDetails(TRUE);
344 $details -> start();
345 $details->form_start(l_person_register(),array());
346
347 // Do not allow resubmits
348 $register_button="<input type='submit' name='op' value='Register'  class='form-submit' />";
349 if (empty($person['person_id'])) {
350   $details->tr($register_button,'center');
351   $details->space();
352 }
353
354 foreach ($person_form as $name => $item) {
355
356   if ( ! empty($item['comment'])) {
357     $details->space();
358     $details->tr($item['comment'] . ":");
359   }
360
361   $title = $item['title'];
362   $required = $item['required'] ? '<span class="form-required" title="This field is required.">*</span>' : "";
363   $class = $item['required'] ? "required" : "";
364   if ($item['required'] && !empty($person) && empty($person[$name])) {
365     $class .= " error";
366   }
367
368   // Label part
369   $left_part = "<label class='$class' for='edit-$name'>$title: $required</label>";
370
371   // input part
372   switch ($name) {
373
374   case 'site_ids':
375     $right_part= "<select name='site_ids[]' id='edit-site_ids' class='form-select $class'> $site_options </select>";
376     break;
377
378   case 'roles':
379     $right_part="";
380     if (0) { /* Not letting users select PI or Tech any more.  Its only lead to confusion and abuse. */
381       $right_part = "<select name='roles[]' multiple='multiple' id='edit-roles' class='form-select $class'> $role_options </select>";
382     }
383     break;
384
385   default:
386     $maxlength = $item['maxlength'];
387     $size = $item['size'];
388     $value = !empty($person[$name]) ? $person[$name] : "";
389     $type = $name == 'password' ? "password" : "text";
390     $right_part = "<input type='$type' maxlength='$maxlength' name='$name' id='edit-$name' size='$size' value='$value' class='form-text $class'>";
391     break;
392   }
393
394   $details->th_td($left_part,$right_part);
395 }
396
397 // Do not allow resubmits
398 if (empty($person['person_id'])) {
399   $details->space();
400   $details->tr($register_button,'center');
401 }
402
403 $details->form_end();
404 $details->end();
405 $nifty->end();
406
407 include 'plc_footer.php';
408
409 ?>