From e0ec61b95c8e3900a14370040ac26d7c1479e9c3 Mon Sep 17 00:00:00 2001
From: Mark Tearle <mtearle@ucc.asn.au>
Date: Sun, 7 Feb 2021 13:55:44 +0800
Subject: [PATCH] Implement register API call

---
 .htaccess             |  4 +++
 quovadis/quovadis.php | 82 ++++++++++++++++++++++++++++++++++---------
 2 files changed, 70 insertions(+), 16 deletions(-)
 create mode 100644 .htaccess

diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..60350af
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,4 @@
+RewriteEngine on
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule ^.*$ /quovadis/index.php [L,QSA]
diff --git a/quovadis/quovadis.php b/quovadis/quovadis.php
index 665a208..39141ac 100644
--- a/quovadis/quovadis.php
+++ b/quovadis/quovadis.php
@@ -8,6 +8,7 @@ require_once('config.php');
 use Ramsey\Uuid\Uuid;
 use RestService\RestService;
 use GuzzleHttp\Client;
+use Leaf\Http\Response;
 
 function check_username($username) {
 	// returns true if we get some info about the username
@@ -29,13 +30,20 @@ function get_desec_txt($config, $name) {
 	$restService = new RestService();
 	$path = "/api/v1/domains/" . $config['QV_DOMAIN'] . "/rrsets/" . $name . "/TXT/";
 	$auth_string = "Token ". $config['QV_DESEC_API'];
-	
-	$response = $restService
-		->setEndpoint('https://desec.io')
-		->setRequestHeaders([
-			'Authorization' => $auth_string
-			])
-		->get($path, [], [], false);
+
+	try {	
+		$response = $restService
+			->setEndpoint('https://desec.io')
+			->setRequestHeaders([
+				'Authorization' => $auth_string
+				])
+			->get($path, [], [], false);
+	} catch (Exception $e) {
+		if( $e->getMessage() == "Not Found" ) {
+			return "";
+		}
+        	throw new Exception($e->getMessage(), $e->getCode());
+        }
 
 	$result = json_decode($response->getBody(), true);
 	if (array_key_exists('records', $result)) {
@@ -45,9 +53,14 @@ function get_desec_txt($config, $name) {
 	}
 }
 
-function check_api_key($api_key) {
+function encrypt_api_key($api_key) {
+	return bin2hex(password_hash($api_key, PASSWORD_DEFAULT));
+}
+
+function check_api_key($config, $username, $api_key) {
 	// API keys need to be alpha numeric
-	return 1;
+        $hash = hex2bin(get_desec_txt($config, $username));
+	return password_verify($api_key, $hash);
 }
 
 function check_challenge($challenge) {
@@ -71,7 +84,6 @@ function check_challenge($challenge) {
 //
 
 function update_desec_txt($config, $name, $txt) {
-	$path = "/api/v1/domains/" . $config['QV_DOMAIN'] . "/rrsets/" . $name . "/TXT/";
 	$auth_string = "Token ". $config['QV_DESEC_API'];
 	$headers = [
 		'Authorization' => $auth_string,
@@ -79,7 +91,13 @@ function update_desec_txt($config, $name, $txt) {
 
 	];
 
-
+	if (get_desec_txt($config, $name) == "") {
+		$method = 'POST';
+		$path = "/api/v1/domains/" . $config['QV_DOMAIN'] . "/rrsets/";
+	} else {
+		$method = 'PUT';
+		$path = "/api/v1/domains/" . $config['QV_DOMAIN'] . "/rrsets/" . $name . "/TXT/";
+	}
 
 	$val =	[
 			'subname' => $name,
@@ -98,7 +116,7 @@ function update_desec_txt($config, $name, $txt) {
 	]);
 
         try {
-	    $response = $client->request('PUT', $path, [ 'headers'=>$headers, 'body'=>$body ]);
+	    $response = $client->request($method, $path, [ 'headers'=>$headers, 'body'=>$body ]);
         } catch (ClientException $e) {
             throw new Exception($e->getResponse()->getReasonPhrase(), $e->getResponse()->getStatusCode());
         } catch (BadResponseException $e) {
@@ -115,16 +133,37 @@ function update_desec_txt($config, $name, $txt) {
 	}
 }
 
+// Send email to user with API key
+
+function email_api_key($username, $api_key) {
+    $headers = array(
+        'From' => 'quovadis@ucc.asn.au',
+        'Reply-To' => 'wheel@ucc.asn.au',
+        'X-Mailer' => 'PHP/' . phpversion()
+    );
+
+    // The message
+    $message = "Quovadis\r\n\r\nUCC DNS Helper\r\nYour API key is: $api_key";
+
+    // In case any of our lines are larger than 70 characters, we should use wordwrap()
+    $message = wordwrap($message, 70, "\r\n");
+
+    // Send
+    mail($username . '@ucc.asn.au', 'Quoavadis API Key', $message, $headers);
+}
+
 // Instantiate Leaf
-$leaf = new Leaf\App;
+$leaf = new Leaf\App();
+#$response = new Leaf\Http\Response();
 
 // Add routes
 $leaf->get('/', function () use($leaf) {
    $config=get_config();
    $s = update_desec_txt($config, "mtearle-test", "test flight");
    $r = get_desec_txt($config, "mtearle-test");
+   $r2 = get_desec_txt($config, "mtearle");
     // since the response object is directly tied to the leaf instance
-   $html = '<h5>My first Leaf app</h5>' . $r . " --- ". $s;
+   $html = '<h5>My first Leaf app</h5>' . $r . " --- ". $s . "----" . $r2;
    $leaf->response()->markup($html);
 });
 
@@ -138,11 +177,20 @@ $leaf->post('/register', function () use($leaf) {
 // * UCC username
 // 
 // Will email to your UCC email address an API key to use with the service
+    $config=get_config();
+
     $username = $leaf->request->get('username');
 
     // Check username is valid
     if ( !check_username($username) ) {
-        $leaf->response->respond(["message" => $username." not valid"]);
+        $leaf->response->json(["message" => $username." not valid"],200);
+	return;
+    }
+
+    // Check there is no existing API key registered for the user
+    $a = get_desec_txt($config, $username);
+    if ( $a <> "" ) {
+        $leaf->response->json(["message" => $username." already registered"],200);
 	return;
     }
 
@@ -150,10 +198,12 @@ $leaf->post('/register', function () use($leaf) {
     $api_key = Uuid::uuid4()->toString();
     
     // Stick API key encrypted into the DNS
+    $u = update_desec_txt($config, $username, encrypt_api_key($api_key));
     
     // Email API key
+    email_api_key($username, $api_key);
     
-    $leaf->response->respond(["message" => $username." has been added and email sent"]);
+    $leaf->response->json(["message" => $username." has been added and email sent"],200);
 });
 
 $leaf->post('/update-api-key', function () use($leaf) {
-- 
GitLab