function NewUser($uid, $flags, $args) { global $TBBASE, $TBMAIL_APPROVAL, $TBMAIL_AUDIT, $TBMAIL_WWW; global $MIN_UNIX_UID; $isleader = $flags & TBDB_NEWACCOUNT_PROJLEADER ? 1 : 0; $wikionly = $flags & TBDB_NEWACCOUNT_WIKIONLY ? 1 : 0; $webonly = $flags & TBDB_NEWACCOUNT_WEBONLY ? 1 : 0; # # If no uid, we need to generate a unique one for the user. # if (!$uid) { # # Take the first 5 letters of the email to form a root. That gives # us 3 digits to make it unique, since unix uids are limited to 8 # chars, sheesh! # $email = $args["usr_email"]; if (!preg_match('/^([-\\w\\+\\.]+)\\@([-\\w\\.]+)$/', $email, $matches)) { return null; } $token = $matches[1]; # Squeeze out any dots or dashes. $token = preg_replace('/\\./', '', $token); $token = preg_replace('/\\-/', '', $token); # Trim off any trailing numbers or +foo tokens. if (!preg_match('/^([a-zA-Z]+)/', $token, $matches)) { return null; } $token = $matches[1]; # First 5 chars, at most. $token = substr($token, 0, 5); # Grab all root matches from the DB. $query_result = DBQueryFatal("select uid from users " . "where uid like '{$token}%'"); if (!$query_result) { return null; } # Easy; no matches at all! if (!mysql_num_rows($query_result)) { $uid = "{$token}" . "001"; } else { $max = 0; # # Find unused slot. Must be a better way to do this! # while ($row = mysql_fetch_array($query_result)) { $foo = $row[0]; # Split name from number if (!preg_match('/^([a-zA-Z]+)(\\d*)$/', $foo, $matches)) { return null; } $name = $matches[1]; $number = $matches[2]; # Must be exact root if ($name != $token) { continue; } # Backwards compatability; might not have appended number. if (isset($number) && intval($number) > $max) { $max = intval($number); } } $max++; $uid = $token . sprintf("%03d", $max); } } # # The array of inserts is assumed to be safe already. Generate # a list of actual insert clauses to be joined below. # $insert_data = array(); foreach ($args as $name => $value) { $insert_data[] = "{$name}='{$value}'"; } # Every user gets a new unique index. $uid_idx = TBGetUniqueIndex('next_uid'); # Get me an unused unix id. Nice query, eh? Basically, find # unused numbers by looking at existing numbers plus one, and check # to see if that number is taken. $query_result = DBQueryFatal("select u.unix_uid + 1 as start from users as u " . "left outer join users as r on " . " u.unix_uid + 1 = r.unix_uid " . "where u.unix_uid>={$MIN_UNIX_UID} and " . " u.unix_uid<60000 and " . " r.unix_uid is null limit 1"); if (!$query_result || !mysql_num_rows($query_result)) { TBERROR("Could not find an unused unix_uid!", 1); } $row = mysql_fetch_row($query_result); $unix_uid = $row[0]; # Initial mailman_password. $mailman_password = substr(GENHASH(), 0, 10); # And a verification key. $verify_key = md5(uniqid(rand(), 1)); # Now tack on other stuff we need. if ($wikionly) { $insert_data[] = "wikionly='1'"; } if ($webonly) { $insert_data[] = "webonly='1'"; } $insert_data[] = "usr_created=now()"; $insert_data[] = "usr_modified=now()"; $insert_data[] = "pswd_expires=date_add(now(), interval 1 year)"; $insert_data[] = "unix_uid={$unix_uid}"; $insert_data[] = "status='newuser'"; $insert_data[] = "mailman_password='******'"; $insert_data[] = "verify_key='{$verify_key}'"; $insert_data[] = "uid_idx='{$uid_idx}'"; $insert_data[] = "uid='{$uid}'"; # Insert into DB. Should probably lock the table ... if (!DBQueryWarn("insert into users set " . implode(",", $insert_data))) { return null; } if (!DBQueryWarn("insert into user_stats (uid, uid_idx) " . "VALUES ('{$uid}', {$uid_idx})")) { DBQueryFatal("delete from users where uid_idx='{$uid_idx}'"); return null; } $newuser = User::Lookup($uid_idx); if (!$newuser) { return null; } # # See if we are in an initial Emulab setup. # $FirstInitState = TBGetFirstInitState() == "createproject"; if ($FirstInitState) { return $newuser; } # stuff for email message. $key = $newuser->verify_key(); $usr_name = $newuser->name(); $usr_email = $newuser->email(); # Email to user. TBMAIL("{$usr_name} '{$uid}' <{$usr_email}>", "Your New User Key", "\n" . "Dear {$usr_name} ({$uid}):\n\n" . "This is your account verification key: {$key}\n\n" . "Please use this link to verify your user account:\n" . "\n" . " {$TBBASE}/login.php3?vuid={$uid}&key={$key}\n" . "\n" . ($wikionly ? "Once you have verified your account, you will be able to access\n" . "the Wiki. You MUST verify your account first!" : ($webonly ? "Once you have verified your account, Testbed Operations will be\n" . "able to approve you. You MUST verify your account first!" : ($isleader ? "You will then be verified as a user. When you have been both\n" . "verified and approved by Testbed Operations, you will be marked\n" . "as an active user and granted full access to your account.\n" . "You MUST verify your account before your project can be approved!\n" : "Once you have verified your account, the project leader will be\n" . "able to approve you.\n\n" . "You MUST verify your account before the project leader can " . "approve you\n" . "After project approval, you will be marked as an active user, and\n" . "will be granted full access to your user account."))) . "\n\n" . "Thanks,\n" . "Testbed Operations\n", "From: {$TBMAIL_APPROVAL}\n" . "Bcc: {$TBMAIL_AUDIT}\n" . "Errors-To: {$TBMAIL_WWW}"); return $newuser; }
function NewGroup($project, $gid, $leader, $description, $unix_name) { global $TBBASE, $TBMAIL_APPROVAL, $TBMAIL_AUDIT, $TBMAIL_WWW; global $MIN_UNIX_GID; $starting_gid = $MIN_UNIX_GID; $ending_gid = 50000; # # Check that we can guarantee uniqueness of the unix group name. # $query_result = DBQueryFatal("select gid from groups " . "where unix_name='{$unix_name}'"); if (mysql_num_rows($query_result)) { TBERROR("Could not form a unique Unix group name: {$unix_name}!", 1); } # Every group gets a new unique index. $gid_idx = TBGetUniqueIndex('next_gid'); # If project is not defined, then creating initial project group. if (!$project) { $pid = $gid; $pid_idx = $gid_idx; } else { $pid = $project->pid(); $pid_idx = $project->pid_idx(); } $uuid = NewUUID(); # Get me an unused unix id. Nice query, eh? Basically, find # unused numbers by looking at existing numbers plus one, and check # to see if that number is taken. $query_result = DBQueryWarn("select g.unix_gid + 1 as start from groups as g " . "left outer join groups as r on " . " g.unix_gid + 1 = r.unix_gid " . "where g.unix_gid>={$starting_gid} and " . " g.unix_gid<{$ending_gid} and " . " r.unix_gid is null limit 1"); if (!$query_result || !mysql_num_rows($query_result)) { TBERROR("Could not find an unused unix_gid!", 0); return null; } $row = mysql_fetch_row($query_result); $unix_gid = $row[0]; if (!DBQueryWarn("insert into groups set " . " pid='{$pid}', gid='{$gid}', " . " leader='" . $leader->uid() . "'," . " leader_idx='" . $leader->uid_idx() . "'," . " created=now(), " . " description='{$description}', " . " unix_name='{$unix_name}', " . " gid_uuid='{$uuid}', " . " gid_idx={$gid_idx}, " . " pid_idx={$pid_idx}, " . " unix_gid={$unix_gid}")) { return null; } if (!DBQueryWarn("insert into group_stats " . " (pid,gid,gid_idx,pid_idx,gid_uuid) " . "values ('{$pid}', '{$gid}', {$gid_idx}, " . " {$pid_idx}, '{$uuid}')")) { DBQueryFatal("delete from groups where gid_idx='{$gid_idx}'"); return null; } $newgroup = Group::Lookup($gid_idx); if (!$newgroup) { return null; } return $newgroup; }