From 0db7a0aff021d82d7a1dd02901837a66a6b75c32 Mon Sep 17 00:00:00 2001
From: Sibidharan Nandhakumar <hello@sibidharan.me>
Date: Fri, 14 May 2021 21:39:14 +0530
Subject: [PATCH] Login API and documentation

---
 .htaccess                |  2 ++
 api/apis/auth/login.php  | 29 ++++++++++++++++++++
 api/apis/auth/signup.php |  6 +---
 api/index.php            |  2 ++
 api/lib/Auth.class.php   | 59 ++++++++++++++++++++++++++++++++++++++++
 api/lib/User.class.php   | 38 ++++++++++++++++++++++++++
 hash.php                 |  9 ++++++
 sg.php                   | 17 ++++++------
 8 files changed, 149 insertions(+), 13 deletions(-)
 create mode 100644 api/apis/auth/login.php
 create mode 100644 api/lib/User.class.php
 create mode 100644 hash.php

diff --git a/.htaccess b/.htaccess
index bde068d..623837e 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,3 +1,5 @@
+Header add Access-Control-Allow-Origin: *
+
 RewriteEngine On
 RewriteBase /
 
diff --git a/api/apis/auth/login.php b/api/apis/auth/login.php
new file mode 100644
index 0000000..a772c9d
--- /dev/null
+++ b/api/apis/auth/login.php
@@ -0,0 +1,29 @@
+<?php
+
+${basename(__FILE__, '.php')} = function(){
+    if($this->get_request_method() == "POST" and isset($this->_request['username']) and isset($this->_request['password'])){
+        $username = $this->_request['username'];
+        $password = $this->_request['password'];
+        try {
+            $auth = new Auth($username, $password);
+            $data = [
+                "message" => "Login success",
+                "token" => $auth->getAuthToken()
+            ];
+            $data = $this->json($data);
+            $this->response($data, 200);
+        } catch(Exception $e){
+            $data = [
+                "error" => $e->getMessage()
+            ];
+            $data = $this->json($data);
+            $this->response($data, 406);
+        }
+    } else {
+        $data = [
+            "error" => "Bad request"
+        ];
+        $data = $this->json($data);
+        $this->response($data, 400);
+    }
+};
\ No newline at end of file
diff --git a/api/apis/auth/signup.php b/api/apis/auth/signup.php
index fbfe8f5..99117d7 100644
--- a/api/apis/auth/signup.php
+++ b/api/apis/auth/signup.php
@@ -22,11 +22,7 @@ ${basename(__FILE__, '.php')} = function(){
          
     } else {
         $data = [
-            "error" => "Bad request",
-            "method" => $this->get_request_method(),
-            "server" => $_SERVER,
-            "post" => $_POST,
-            "get" => $_GET
+            "error" => "Bad request"
         ];
         $data = $this->json($data);
         $this->response($data, 400);
diff --git a/api/index.php b/api/index.php
index a9b03c7..124689a 100644
--- a/api/index.php
+++ b/api/index.php
@@ -3,6 +3,8 @@ error_reporting(E_ALL ^ E_DEPRECATED);
 require_once($_SERVER['DOCUMENT_ROOT']."/api/REST.api.php");
 require_once($_SERVER['DOCUMENT_ROOT']."/api/lib/Database.class.php");
 require_once($_SERVER['DOCUMENT_ROOT']."/api/lib/Signup.class.php");
+require_once($_SERVER['DOCUMENT_ROOT']."/api/lib/User.class.php");
+require_once($_SERVER['DOCUMENT_ROOT']."/api/lib/Auth.class.php");
 
 class API extends REST {
     
diff --git a/api/lib/Auth.class.php b/api/lib/Auth.class.php
index a4abe2d..c9e5018 100644
--- a/api/lib/Auth.class.php
+++ b/api/lib/Auth.class.php
@@ -1,2 +1,61 @@
 <?php
 
+require_once($_SERVER['DOCUMENT_ROOT'].'/api/lib/Database.class.php');
+require_once($_SERVER['DOCUMENT_ROOT'].'/api/lib/User.class.php');
+require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
+
+class Auth {
+
+    private $db;
+    private $isTokenAuth = false;
+    private $loginToken = null;
+
+    public function __construct($username, $password = NULL){
+        $this->db = Database::getConnection();
+        if($password == NULL){
+            //token based auth
+            $this->token = $username;
+            $this->isTokenAuth = true;
+            //we have to validate the token
+        } else {
+            $this->username = $username; //it might be username or email.
+            $this->password = $password;
+        }
+
+        if($this->isTokenAuth){
+            throw new Exception("Not Implemented");
+        } else {
+            $user = new User($this->username);
+            $hash = $user->getPasswordHash();
+            $this->username = $user->getUsername();
+            if(password_verify($this->password, $hash)){
+                if(!$user->isActive()){
+                    throw new Exception("Please check your email and activate your account.");
+                }
+                $this->loginToken = $this->addSession();
+            } else {
+                throw new Exception("Password Mismatch");
+            }
+        }
+    }
+
+    public function getAuthToken(){
+        return $this->loginToken;
+    }
+
+    private function addSession(){
+        $token = Auth::generateRandomHash(32);
+        $query = "INSERT INTO `apis`.`session` (`username`, `token`) VALUES ('$this->username', '$token');";
+        if(mysqli_query($this->db, $query)){
+            return $token;
+        } else {
+            throw new Exception(mysqli_error($this->db));
+        }
+        
+    }
+
+    public static function generateRandomHash($len){
+        $bytes = openssl_random_pseudo_bytes($len, $cstrong);
+        return bin2hex($bytes);
+    }
+}
\ No newline at end of file
diff --git a/api/lib/User.class.php b/api/lib/User.class.php
new file mode 100644
index 0000000..01be1f2
--- /dev/null
+++ b/api/lib/User.class.php
@@ -0,0 +1,38 @@
+<?php
+
+require_once($_SERVER['DOCUMENT_ROOT'].'/api/lib/Database.class.php');
+require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
+
+class User {
+    private $db;
+    private $user;
+
+    public function __construct($username){
+        $this->username = $username;
+        $this->db = Database::getConnection();
+        $query = "SELECT * FROM auth WHERE username='$this->username' OR email='$this->username'";
+        //echo $query;
+        $result = mysqli_query($this->db, $query);
+        if(mysqli_num_rows($result) == 1){
+            $this->user = mysqli_fetch_assoc($result);
+        } else {
+            throw new Exception("User not found");
+        }
+    }
+
+    public function getUsername(){
+        return $this->user['username'];
+    }
+
+    public function getPasswordHash(){
+        return $this->user['password'];
+    }
+
+    public function getEmail(){
+        return $this->user['email'];
+    }
+
+    public function isActive(){
+        return $this->user['active'];
+    }
+}
\ No newline at end of file
diff --git a/hash.php b/hash.php
new file mode 100644
index 0000000..fc8cb10
--- /dev/null
+++ b/hash.php
@@ -0,0 +1,9 @@
+<?php
+
+    $bytes = openssl_random_pseudo_bytes(32, $cstrong);
+    $hex   = bin2hex($bytes);
+    echo "Lengths: Bytes: $i and Hex: " . strlen($hex) . PHP_EOL;
+    var_dump($hex);
+    var_dump($cstrong);
+    echo PHP_EOL;
+?>
\ No newline at end of file
diff --git a/sg.php b/sg.php
index 5a6a525..de13316 100644
--- a/sg.php
+++ b/sg.php
@@ -1,14 +1,15 @@
 <pre>
 <?php
+require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
+require_once($_SERVER['DOCUMENT_ROOT'].'/api/lib/User.class.php');
+
+try{
+    $user = new User('sibidharan@icloud.com');
+    echo $user->getUsername();
+} catch(Exception $e){
+    echo $e->getMessage();
+}
 
-print_r($GLOBALS);
-print_r($_SERVER);
-print_r($_REQUEST);
-print_r($_POST);
-print_r($_GET);
-print_r($_FILES);
-print_r($_ENV);
-print_r($_COOKIE);
 
 ?>
 </pre>
\ No newline at end of file
-- 
GitLab