User Provisioning API example script

For what it’s worth, this is the script I’m using to import users into Nextcloud.
Standard stuff: NO WARRANTIES, NO GAURANTEES
Bugs: fix it and post it.
Changes: do it and post it.

#!/usr/bin/php
<?php
//
// Written by Cameron Smith
// January, 2018
//

$usage            = <<<EOU
usage: addCloudUsers.php filepath

	This script will read a csv file and populate a [next|own]cloud instance
		with new users.

	The path to the csv file is provided as the sole parameter when invoking 
		the script.

	Check the code to see the expected csv format. Change the code for your 
		particular usage case.

	Good Luck!

EOU;

$verbose          = 1; // zero to three
$usersFile        = $argv[1];
if (!$usersFile or $usersFile == '-h' or $usersFile == '--help') {
	echo "$usage";
	exit (1);
}

$protocol         = 'http'; // http or https
$server           = 'example.com'; // required
$baseurl          = "$protocol://$server/ocs/v1.php/cloud/users"; // leave as is
$adminName        = 'adminName'; // required
$adminPass        = 'adminPasword'; // required
$defaultGroup     = 'defaultGroup'; // leave empty if you don't want to assign a group
$defaultPassword  = 'defaultPassword'; // empty string to auto-generate

$skipTo = 2; // set this to 2 if you have a header line in the input file, 
             //   or any other number to skip to that line in the file
             // (First line is line 1)

if (($handle = fopen($usersFile, "r")) !== FALSE) { // open or die
    while (($userData = fgetcsv($handle, 1000, ",")) !== FALSE) { // line-by-line
    	if (++$onLine < $skipTo ) { continue; } // skip to $skipTo
        
		// Change these to suit your usage case and csv file:
		// username is first letter of firstname (field 1) + lastname (field 0) (spaces removed)
		// displayname is firstname (field 1) + space + lastname (field 0)
		// address is fields 4, 5, 6 and 7, with commas
		// phone is field 8
		// email is field 9
        $userName    = strtolower(substr($userData[1], 0, 1) . str_replace(' ', '', $userData[0]));
        $userPass    = $defaultPassword;
        $displayname = $userData[1] . " " . $userData[0];
        $address     = $userData[4] . ", " . $userData[5] . ", " . $userData[6] . ", " . $userData[7];
        $phone       = $userData[8];
        $email       = $userData[9];
        
        if ($verbose > 1 ) {
			echo "$userName \n".
				 "\t$userPass \n".
				 "\t$displayname \n".
				 "\t$address \n".
				 "\t$phone \n".
				 "\t$email \n"
				 ;
        }
        
        //
		//Create a new user
		//
		if ($verbose == 1) { echo "$onLine $userName:$userPass "; }
		if ($verbose > 1)  { echo "Creating user $onLine $userName, pass $userPass\n"; }
		$url       = $baseurl;
		$postfields = http_build_query(array('userid'   => $userName, 
											 'password' => $userPass ));
		$options   = array (CURLOPT_POST       => 1,
							CURLOPT_POSTFIELDS => array('userid'   => $userName, 
														'password' => $userPass )
					 );
		doCurl ($url, $options);

		//
		// Add the new user to the default group
		//
		if ($defaultGroup) {
			if ($verbose == 1) { echo "$userName, group $defaultGroup "; }
			if ($verbose > 1)  { echo "Adding user $userName to group $defaultGroup\n"; }
			$url       = $baseurl . '/' . $userName . '/' . 'groups';
			$options   = array (CURLOPT_POST       => 1,
								CURLOPT_POSTFIELDS => array('groupid' => $defaultGroup
													  )
						 );
			doCurl ($url, $options);
		}

		//
		// Add the other attributes to the user
		//
		if ($verbose > 1) { echo "Adding attributes to user $userName\n"; }
		$url       = $baseurl . '/' . $userName;
		$otherAtts = array('email', 'displayname', 'phone', 'address');
		foreach ($otherAtts as $attribute) {
			if ($$attribute) {
				if ($verbose == 1) { echo "$userName, $attribute: " . $$attribute . " "; }
				if ($verbose > 1)  { echo "Adding attribute $attribute: " . $$attribute . "\n"; }
				$options = array (CURLOPT_CUSTOMREQUEST => "PUT",
// Not doing the http_build_query with PUT doesn't work with the server I'm using.
// 								  CURLOPT_POSTFIELDS => array('key'   => $attribute,
// 															  'value' => $$attribute
// 														)
								  CURLOPT_POSTFIELDS => http_build_query(array('key'   => $attribute,
																			   'value' => $$attribute)
														)
						   );
				doCurl ($url, $options);
			}
		}
//		exit(0); // DEBUG: kill after first line processed

    }
    fclose($handle);
}
else {
	echo "ERROR: Could not open file: $usersFile\n\n$usage\n";
	exit (1);
}

if ($verbose) {echo "*** addCloudUsers finished\n";}
exit (0);


//
// FUNCTION: Do the curl call
//
function doCurl ($url, $options) {
	global $adminName, $adminPass, $verbose, $doe;
	
	$options = $options +
			   array(CURLOPT_RETURNTRANSFER => true,
					 CURLOPT_USERPWD        => $adminName . ":" . $adminPass,
					 CURLOPT_HTTPHEADER     => array('OCS-APIRequest:true'),
			   );

	if ($verbose > 2) {
		$options = $options +
				   array(CURLOPT_VERBOSE => TRUE,
						 CURLOPT_HEADER  => TRUE
				   );
	}

	$ch = curl_init($url);

 	curl_setopt_array( $ch, $options);
	
//  For use with Charles proxy:
// 	curl_setopt($ch, CURLOPT_PROXYPORT, '8888');
// 	curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP');
// 	curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1');

	$response = curl_exec($ch);

	if($response === false) {
		echo 'Curl error: ' . curl_error($ch) . "\n";
		exit(1);
	}
	
	curl_close($ch);
	
	// An error causes an exit
	if (preg_match("~<statuscode>(\d+)</statuscode>~", $response, $matches)) {
		$responseCode = $matches[1]; // what's the status code
		if ($responseCode != '100' ) {
			echo "Error response code; exiting\n$response\n";
			exit(1);
		}
	}
	else { // something is definitely wrong
		echo "No statuscode response; exiting:\n$response\n";
		exit(1);
	}

	// What sort of response do we want to give
//	if ($verbose == 1) { echo "Response code from server: $responseCode\n"; }
	if ($verbose == 1) { echo "\n"; }
	if ($verbose > 1)  { echo "Response from server:\n$response\n\n"; }

	return;
}

?>

Hello,
Nice work.
Can you add some info more about use this script.
Path of the csv file I found, but the structure of the csv I not found.
Thanks

Extremely helpful, thanks. I see a reference to “$doe” in the function - was that accidental or what is it’s purpose.