Search what you want

Showing posts with label RESTAPI. Show all posts
Showing posts with label RESTAPI. Show all posts

Thursday, September 29, 2016

Instalasi REST API mneggunakan SLIM Framework (php)

Proses Instalasi SLIM:
1. instalasi composer terlebih dahulu. kunjungi halaman https://getcomposer.org/.
    - download composer.phar
$ curl -sS https://getcomposer.org/installer | php
atau kunjungi
https://getcomposer.org/composer.phar
    - install composer
$ php composer.phar install
2. install slim-skeleton (bundle)
$ php composer.phar create-project slim/slim-skeleton [my-app-name]
$ php composer.phar create-project slim/slim-skeleton mySlim
atau
$ composer create-project slim/slim-skeleton mySlim
tunggu hingga proses instalasi selesai

3. setelah selesai SLIM Framework telah dapat digunakan dengan mengeksekusi command
$ composer start
buka web dengan address localhost:8080

Proses hello word untuk routing pertama:
1. open file projek dan buka /publik/index.php, tambahkan kode berikut sebelum $app->run():
$app->get('/hello/{name}', function (Request $request, Response $response) {
    $name = $request->getAttribute('name');
    $response->getBody()->write("Hello, $name");

    return $response;
});
2. save
3. akses link pada browser localhost:8000/hello/ardhi
__________________________________________________
___________________________________________________

Proses Koneksi ke database Mysql:
1. buat database pada mysql dengan nama "restapi"
2. buat tabel dengan nama "tasks"
--
-- Table structure for `tasks`
--
CREATE TABLE IF NOT EXISTS `tasks` (
  `id` int(11) NOT NULL,
  `task` varchar(200) NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
ALTER TABLE `tasks` ADD PRIMARY KEY (`id`);
ALTER TABLE `tasks` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
3. tambahkan data pada tabel tersebut
INSERT INTO `tasks` (`id`, `task`, `status`, `created_at`) VALUES
(1, 'Find bugs', 1, '2016-04-10 23:50:40'),
(2, 'Review code', 1, '2016-04-10 23:50:40'),
(3, 'Fix bugs', 1, '2016-04-10 23:50:40'),
(4, 'Refactor Code', 1, '2016-04-10 23:50:40'),
(5, 'Push to prod', 1, '2016-04-10 23:50:50');
3. buka file settings.php di /src/settings.php
4. tambahkan kode berikut
<?php
return [
    'settings' => [
        'displayErrorDetails' => true, // set to false in production
        'addContentLengthHeader' => false, // Allow the web server to send the content-length header
         'determineRouteBeforeAppMiddleware' => true,

        // Renderer settings
        'renderer' => [
            'template_path' => __DIR__ . '/../templates/',
        ],

        // Monolog settings
        'logger' => [
            'name' => 'slim-app',
            'path' => __DIR__ . '/../logs/app.log',
            'level' => \Monolog\Logger::DEBUG,
        ],
        "db" => [
            "host" => "localhost",
            "dbname" => "restapi",
            "user" => "user",
            "pass" => "password",
        ],
    ],
];
5. buka file dependencies.php di /src/dependencies.php
<?php
// DIC configuration

$container = $app->getContainer();

// view renderer
$container['renderer'] = function ($c) {
    $settings = $c->get('settings')['renderer'];
    return new Slim\Views\PhpRenderer($settings['template_path']);
};

// monolog
$container['logger'] = function ($c) {
    $settings = $c->get('settings')['logger'];
    $logger = new Monolog\Logger($settings['name']);
    $logger->pushProcessor(new Monolog\Processor\UidProcessor());
    $logger->pushHandler(new Monolog\Handler\StreamHandler($settings['path'], $settings['level']));
    return $logger;
};

$container['db'] = function ($c) {
    $settings = $c->get('settings')['db'];
    $pdo = new PDO("mysql:host=" . $settings['host'] . ";dbname=" . $settings['dbname'],
        $settings['user'], $settings['pass']);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    return $pdo;
};
4. sekarang kamu dapat mengakses database dengan syntax $this->db
5. akses data. buka /publik/index.php, tambahkan kode berikut sebelum $app->run():
$app->group('/api/v1', function () use ($app) {
 
    // get all todos
    $app->get('/todos', function ($request, $response, $args) {
         $sth = $this->db->prepare("SELECT * FROM tasks ORDER BY task");
        $sth->execute();
        $todos = $sth->fetchAll();
        return $this->response->withJson($todos);
    });
 
    // Retrieve todo with id
    $app->get('/todo/[{id}]', function ($request, $response, $args) {
         $sth = $this->db->prepare("SELECT * FROM tasks WHERE id=:id");
        $sth->bindParam("id", $args['id']);
        $sth->execute();
        $todos = $sth->fetchObject();
        return $this->response->withJson($todos);
    });
 
 
    // Search for todo with given search teram in their name
    $app->get('/todos/search/[{query}]', function ($request, $response, $args) {
         $sth = $this->db->prepare("SELECT * FROM tasks WHERE UPPER(task) LIKE :query ORDER BY task");
        $query = "%".$args['query']."%";
        $sth->bindParam("query", $query);
        $sth->execute();
        $todos = $sth->fetchAll();
        return $this->response->withJson($todos);
    });
 
    // Add a new todo
    $app->post('/todo', function ($request, $response) {
        $input = $request->getParsedBody();
        $sql = "INSERT INTO tasks (task) VALUES (:task)";
         $sth = $this->db->prepare($sql);
        $sth->bindParam("task", $input['task']);
        $sth->execute();
        $input['id'] = $this->db->lastInsertId();
        return $this->response->withJson($input);
    });
        
 
    // DELETE a todo with given id
    $app->delete('/todo/[{id}]', function ($request, $response, $args) {
         $sth = $this->db->prepare("DELETE FROM tasks WHERE id=:id");
        $sth->bindParam("id", $args['id']);
        $sth->execute();
        $todos = $sth->fetchAll();
        return $this->response->withJson($todos);
    });
 
    // Update todo with given id
    $app->put('/todo/[{id}]', function ($request, $response, $args) {
        $input = $request->getParsedBody();
        $sql = "UPDATE tasks SET task=:task WHERE id=:id";
         $sth = $this->db->prepare($sql);
        $sth->bindParam("id", $args['id']);
        $sth->bindParam("task", $input['task']);
        $sth->execute();
        $input['id'] = $args['id'];
        return $this->response->withJson($input);
    });
 
});
6. sekarang kita dapat mengakses data yang ada di data base dengan mengakses


Proses filter akses yang diizinkan:
1.




ref:
http://www.slimframework.com
http://www.slimframework.com/docs/tutorial/first-app.html
https://arjunphp.com/creating-restful-api-slim-framework/

Tuesday, September 27, 2016

Install Loopback [NodeJS]

uninstall seluruh instalasi node dan npm yang pernah dilakukan.
sudo apt-get purge nodejs
sudo apt-get autoremove

Proses instalasi NodeJS:
1. masuk sebagai super user (linux/ubuntu)
$ su
2. Masukan password root yang berada di computer
3. masukan repository nodejs 6
4. instalasi Node
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
$ sudo apt-get install -y nodejs
5. setelah proses instalasi selesai, cek version dari node dan npm
$ node -v
akan tampil versi dari node -> v6.6.0

$ npm -v
akan tampil versi dari npm -> 3.10.3

jika node masih dalam versi "v0.10.32" maka ulangi proses instalasi node. pastikan anda dalam akses sebagai super user (ubuntu)

jika npm masih dalam versi dibawah 2.1.8 maka coba install kembali npm nya

$ npm install npm -g

Proses Instalasi Loopback:
1. install loopback

$ npm install -g strongloop
tunggu hingga proses instalasi selesai

2. masuk ke directory dimana projek akan ditempatkan

$ slc loopback
3. masukan nama directory projek yang akan dibuat

[?] What's the name of your application? namaFolder
tunggu hingga proses instalasi selesai

4. Change directory to your app
 $ cd namaFolder
5. Create a model in your app
$ slc loopback:model
6. Compose your API, run, deploy, profile, and monitor it with Arc
$ slc arc
7. Run the app
$ node .

Proses koneksi ke database MySql:
1. Masuk ke derectory projek 
$ cd <go-to-your-directory>
2. jalankan GUI
$ slc arc
 akan langsung diarahkan ke address yang diizinkan

3. register akun yang akan di buat
klik link untuk register

4. isikan alamat email yang akan digunakan untuk login

5. masuk ke dashboard email, akan dikirimkan email verifikasi ke alamat email anda, klik link tersebut.

6. lengkapi data diri anda anda untuk akun anda.

7. setelah selesai, kembali ke halaman login dan login dengan akun yang telah di buat
8. buat koneksi ke database yang di inginkan, saya memilih MySql
kemudian "test connection".

9. jika terjadi kesalahan dalam koneksi "Connector "mysql" is not installed."  install terlebih dahulu koneksi ke databasenya

9.1. masuk ke directory projek
9.2. install koneksi ke mysql
$ npm install loopback-connector-mysql --save
10. jika koneksi telah dibuat, tidak akan ada lagi pesan kesalahan

11. import all attribut in mysql database to loopback


12. jika berhasil, jalankan servernya

GUI untuk loopback


uji coba menggunakna rest client



~Sekian dan semoga berguna~


ref:
http://askubuntu.com/questions/786015/how-to-remove-nodejs-from-ubuntu-16-04

https://nodejs.org/en/download/package-manager/

http://loopback.io/getting-started/

https://strongloop.com/get-started/

https://docs.strongloop.com/display/public/LB/Connecting+models+to+data+sources

Monday, March 7, 2016

Creating RestAPI with PHP+Slim Framework

Bismillah..
Hai, apa kabar kalian? (kalian siapa?) kaya ada yang baca aja nih blog. haha... gpp sih, emang niatnya blog ini untuk jadi tempat menulis apa yang sudah pernah saya lakukan, dan biar kalau mau mengulangi lagi terkait suatu materi biar gampang aja, tinggal ngeliat catetan di internet. dari pada cuman di tulis di buku dan akhirnya termakan usia dan akhirnya ilang? wkwk...

Pada kesempatan kali ini saya akan mencoba untuk membuat RESTAPI. hmmmm.. kalian pastinya udah pada tau kan ya apa itu RESTAPI? kalau belum tau gapapa sih, saya juga baru memahaminya 2-3 minggu belakangan ini, karena tuntutan juga sih. :). oke berikut saya akan membuat RESTAPI dengan PHP dan ada satu framework yang telah dibuat terkait REST dengan bahasa PHP. framework SLIM ini digunakan untuk mempermudah proses pembuatan sistem secara keseluruhan. :) mau tau lebih jauh tentang RESTAPI? baca ajalah ya prinsip dari REST itu.

Apa aja yang dibutuhkan untuk membuat RESTAPI ini?
1. Kemauan untuk bisa
2. Pemahaman tentang bahasa PHP
3. Pemahaman tentang JSON
5. IDE untuk menuliskan code, saya lebih senang menggunakan NETBEANS (8.0.2)
6. komputer yang bisa menjalankan php server, mysql database. jika kalian menggunakan OS windows, kalian bisa menggunakan XAMPP. (Saya meggunakan OS Ubuntu)
7. REST Client, untuk nyoba-nyoba kalau udah jadi

saya akan menjelaskan sedikit deh gmna nanti REST ini akan digunakan. Misalkan jika kita punya akun di facebook, kita dapat melakukan pengubahan data kita ketika kita sudah login dengan akun yang kita miliki, kita dapat metihan postingan teman2 kita, membuat postingan, melakukan editing terhadap profile yang kita miliki, dan menghapus postingan kita. kalau misalkan kita belom login berarti kita tidak misa melakukan aktifitas itu semua.

tetapi dengan RESTAPI ini, kita tidak diharuskan login ketika kita ingin mmelakukan aktifitas/ operasi database tersebut. kita nantinya akan diberikan sebuah/beberapa token untuk digunakan untuk operasi database tersebut. jadi setiap kita melakukan CRUD kita tidak diharuskan melakukan login, tetapi kita hanya diminta untuk memberikan token yang ada. okeh gitu aja yang saya tau. hehe

langsung saja kemasalah teknis, berikut kode yang akan jelaskan, kode ini saya ambil dari blognya Ravi Tamada. cukup mudah untuk dimengerti bagi kita yang sudah pernah berkecimpung di bahasa PHP. saya membuat service ini untuk men-store data dari alat (IoT).

1. Buat folder Root (dengan nama apapun), kalau saya menamakannya folder "skripsian"
2. Buat sub folder lainnya. "include"(untuk meletakkan file2 yang berhubungan dgn database), "libs" (untuk meletakkan folder SLIM), dan "v1" (tempat meletakkan folder index untuk routing alamat)
3. Download SLIM Framework dan letakkan di folder libs.
4. Buat configurasi untuk database
define('DB_USERNAME', 'root');
define('DB_PASSWORD', '03011995');
define('DB_HOST', 'localhost');
define('DB_NAME', 'restapi');

define('USER_CREATED_SUCCESSFULLY', 0);
define('USER_CREATE_FAILED', 1);
define('USER_ALREADY_EXISTED', 2);
ket:
root -> nama user di database mysql
03011995 -> password user di database mysql, biasanya di kosongkan
localhost -> alamat server databasenya
restapi -> nama database yang digunakan

5. buat database di mysql, ini unutk meletakkan data yang kita miliki


SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE DATABASE restapi;
 
USE restapi;

CREATE TABLE IF NOT EXISTS `tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sensor1` float NOT NULL COMMENT 'pH',
  `sensor2` float NOT NULL COMMENT 'Suhu',
  `sensor3` float NOT NULL COMMENT 'Do',
  `output` float NOT NULL,
  `status` int(1) NOT NULL DEFAULT '0',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(250) DEFAULT NULL,
  `email` varchar(255) NOT NULL,
  `password_hash` text NOT NULL,
  `api_key` varchar(32) NOT NULL,
  `status` int(1) NOT NULL DEFAULT '1',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;

CREATE TABLE IF NOT EXISTS `user_tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `task_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `task_id` (`task_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;


ALTER TABLE `user_tasks`
  ADD CONSTRAINT `user_tasks_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `user_tasks_ibfk_2` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
6. setelah konfigurasi database sudah jadi, kita akan membuat file untuk melakukan koneksi ke database. file ini di panggil setiap kita ingin melakukka operasi ke database.
-DBConnect.php-
<?php

class DbConnect {

    private $conn;

    function __construct() {        
    }

    /**
     * Establishing database connection
     * @return database connection handler
     */
    function connect() {
        include_once dirname(__FILE__) . '/Config.php';

        // Connecting to mysql database
        $this->conn = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);

        // Check for database connection error
        if (mysqli_connect_errno()) {
            echo "Failed to connect to MySQL: " . mysqli_connect_error();
        }

        // returing connection resource
        return $this->conn;
    }

}

?>
7. buat file untuk melakukan operasi ke database.
-DBHandler.php-

method (users table):
 - createUser = untuk membuat user baru
 - checkLogin = untuk login user
 - isUserExists = untuk mengecek apakah user terdaftar
 - getUserByEmail = untuk mendapatkan nama user dari email yang diberikan
 - getApiKeyById = untuk mendapatkkan kode untuk operasi API untuk user tertentu
 - getUserId = untuk mendapatkan id user
 - isValidApiKey = untuk mengecek apakah token/kode yang digunakan valid unutk operaasi API
 - generateApiKey = untuk membuat token/kode ketika user pertamakali membuat akun

method (tasks table):
 - createTask = untuk menstore data ke database
 - getTask = untuk mendapatkan data dengan id tertentu
 - getAllUserTasks = untuk mendapatkan seluruh data yang dimiliki seorang user
 - updateTask = untuk mengubah data yang telah dimiliki
 - deleteTask = untuk menghapus data yang ada

method (user_task)
 - createUserTask = unutk membuat hubungan antara user dengan data yang dibuat
<?php

/**
 * Class to handle all db operations
 * This class will have CRUD methods for database tables
 *
 * @author Ravi Tamada
 * @link URL Tutorial link
 */
class DbHandler {

    private $conn;

    function __construct() {
        require_once dirname(__FILE__) . '/DbConnect.php';
        // opening db connection
        $db = new DbConnect();
        $this->conn = $db->connect();
    }

    /* ------------- `users` table method ------------------ */

    /**
     * Creating new user
     * @param String $name User full name
     * @param String $email User login email id
     * @param String $password User login password
     */
    public function createUser($name, $email, $password) {
        require_once 'PassHash.php';
        $response = array();

        // First check if user already existed in db
        if (!$this->isUserExists($email)) {
            // Generating password hash
            $password_hash = PassHash::hash($password);

            // Generating API key
            $api_key = $this->generateApiKey();

            // insert query
            $stmt = $this->conn->prepare("INSERT INTO users(name, email, password_hash, api_key, status) values(?, ?, ?, ?, 1)");
            $stmt->bind_param("ssss", $name, $email, $password_hash, $api_key);

            $result = $stmt->execute();

            $stmt->close();

            // Check for successful insertion
            if ($result) {
                // User successfully inserted
                return USER_CREATED_SUCCESSFULLY;
            } else {
                // Failed to create user
                return USER_CREATE_FAILED;
            }
        } else {
            // User with same email already existed in the db
            return USER_ALREADY_EXISTED;
        }

        return $response;
    }

    /**
     * Checking user login
     * @param String $email User login email id
     * @param String $password User login password
     * @return boolean User login status success/fail
     */
    public function checkLogin($email, $password) {
        // fetching user by email
        $stmt = $this->conn->prepare("SELECT password_hash FROM users WHERE email = ?");

        $stmt->bind_param("s", $email);

        $stmt->execute();

        $stmt->bind_result($password_hash);

        $stmt->store_result();

        if ($stmt->num_rows > 0) {
            // Found user with the email
            // Now verify the password

            $stmt->fetch();

            $stmt->close();

            if (PassHash::check_password($password_hash, $password)) {
                // User password is correct
                return TRUE;
            } else {
                // user password is incorrect
                return FALSE;
            }
        } else {
            $stmt->close();

            // user not existed with the email
            return FALSE;
        }
    }

    /**
     * Checking for duplicate user by email address
     * @param String $email email to check in db
     * @return boolean
     */
    private function isUserExists($email) {
        $stmt = $this->conn->prepare("SELECT id from users WHERE email = ?");
        $stmt->bind_param("s", $email);
        $stmt->execute();
        $stmt->store_result();
        $num_rows = $stmt->num_rows;
        $stmt->close();
        return $num_rows > 0;
    }

    /**
     * Fetching user by email
     * @param String $email User email id
     */
    public function getUserByEmail($email) {
        $stmt = $this->conn->prepare("SELECT name, email, api_key, status, created_at FROM users WHERE email = ?");
        $stmt->bind_param("s", $email);
        if ($stmt->execute()) {
            // $user = $stmt->get_result()->fetch_assoc();
            $stmt->bind_result($name, $email, $api_key, $status, $created_at);
            $stmt->fetch();
            $user = array();
            $user["name"] = $name;
            $user["email"] = $email;
            $user["api_key"] = $api_key;
            $user["status"] = $status;
            $user["created_at"] = $created_at;
            $stmt->close();
            return $user;
        } else {
            return NULL;
        }
    }

    /**
     * Fetching user api key
     * @param String $user_id user id primary key in user table
     */
    public function getApiKeyById($user_id) {
        $stmt = $this->conn->prepare("SELECT api_key FROM users WHERE id = ?");
        $stmt->bind_param("i", $user_id);
        if ($stmt->execute()) {
            // $api_key = $stmt->get_result()->fetch_assoc();
            // TODO
            $stmt->bind_result($api_key);
            $stmt->close();
            return $api_key;
        } else {
            return NULL;
        }
    }

    /**
     * Fetching user id by api key
     * @param String $api_key user api key
     */
    public function getUserId($api_key) {
        $stmt = $this->conn->prepare("SELECT id FROM users WHERE api_key = ?");
        $stmt->bind_param("s", $api_key);
        if ($stmt->execute()) {
            $stmt->bind_result($user_id);
            $stmt->fetch();
            // TODO
            // $user_id = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            return $user_id;
        } else {
            return NULL;
        }
    }

    /**
     * Validating user api key
     * If the api key is there in db, it is a valid key
     * @param String $api_key user api key
     * @return boolean
     */
    public function isValidApiKey($api_key) {
        $stmt = $this->conn->prepare("SELECT id from users WHERE api_key = ?");
        $stmt->bind_param("s", $api_key);
        $stmt->execute();
        $stmt->store_result();
        $num_rows = $stmt->num_rows;
        $stmt->close();
        return $num_rows > 0;
    }

    /**
     * Generating random Unique MD5 String for user Api key
     */
    private function generateApiKey() {
        return md5(uniqid(rand(), true));
    }

    /* ------------- `tasks` table method ------------------ */

    /**
     * Creating new task
     * @param String $user_id user id to whom task belongs to
     * @param String $task task text
     */
    public function createTask($user_id, $sensor1, $sensor2, $sensor3, $output) {
        $stmt = $this->conn->prepare("INSERT INTO tasks(sensor1, sensor2, sensor3, output) VALUES(?,?,?,?)");
        $stmt->bind_param("ssss", $sensor1, $sensor2, $sensor3, $output);
        $result = $stmt->execute();
        $stmt->close();

        if ($result) {
            // task row created
            // now assign the task to user
            $new_task_id = $this->conn->insert_id;
            $res = $this->createUserTask($user_id, $new_task_id);
            if ($res) {
                // task created successfully
                return $new_task_id;
            } else {
                // task failed to create
                return NULL;
            }
        } else {
            // task failed to create
            return NULL;
        }
    }

    /**
     * Fetching single task
     * @param String $task_id id of the task
     */
    public function getTask($task_id, $user_id) {
        $stmt = $this->conn->prepare("SELECT t.id, t.sensor1, t.sensor2, t.sensor3, t.output, t.status, t.created_at from tasks t, user_tasks ut WHERE t.id = ? AND ut.task_id = t.id AND ut.user_id = ?");
        $stmt->bind_param("ii", $task_id, $user_id);
        if ($stmt->execute()) {
            $res = array();
            $stmt->bind_result($id, $sensor1, $sensor2, $sensor3, $output, $status, $created_at);
            // TODO
            // $task = $stmt->get_result()->fetch_assoc();
            $stmt->fetch();
            $res["id"] = $id;
            $res["sensor1"] = $sensor1;
            $res["sensor2"] = $sensor2;
            $res["sensor3"] = $sensor3;
            $res["output"] = $output;
            $res["status"] = $status;
            $res["created_at"] = $created_at;
            $stmt->close();
            return $res;
        } else {
            return NULL;
        }
    }

    /**
     * Fetching all user tasks
     * @param String $user_id id of the user
     */
    public function getAllUserTasks($user_id) {
        $stmt = $this->conn->prepare("SELECT t.* FROM tasks t, user_tasks ut WHERE t.id = ut.task_id AND ut.user_id = ?");
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        $tasks = $stmt->get_result();
        $stmt->close();
        return $tasks;
    }

    /**
     * Updating task
     * @param String $task_id id of the task
     * @param String $task task text
     * @param String $status task status
     */
    public function updateTask($user_id, $task_id, $sensor1, $sensor2, $sensor3, $output, $status) {
        $stmt = $this->conn->prepare("UPDATE tasks t, user_tasks ut set t.sensor1 = ?, t.sensor2 = ?, t.sensor3 = ?, t.output = ?, t.status = ? WHERE t.id = ? AND t.id = ut.task_id AND ut.user_id = ?");
        $stmt->bind_param("siiiiii", $sensor1, $sensor2, $sensor3, $output, $status, $task_id, $user_id);
        $stmt->execute();
        $num_affected_rows = $stmt->affected_rows;
        $stmt->close();
        return $num_affected_rows > 0;
    }

    /**
     * Deleting a task
     * @param String $task_id id of the task to delete
     */
    public function deleteTask($user_id, $task_id) {
        $stmt = $this->conn->prepare("DELETE t FROM tasks t, user_tasks ut WHERE t.id = ? AND ut.task_id = t.id AND ut.user_id = ?");
        $stmt->bind_param("ii", $task_id, $user_id);
        $stmt->execute();
        $num_affected_rows = $stmt->affected_rows;
        $stmt->close();
        return $num_affected_rows > 0;
    }

    /* ------------- `user_tasks` table method ------------------ */

    /**
     * Function to assign a task to user
     * @param String $user_id id of the user
     * @param String $task_id id of the task
     */
    public function createUserTask($user_id, $task_id) {
        $stmt = $this->conn->prepare("INSERT INTO user_tasks(user_id, task_id) values(?, ?)");
        $stmt->bind_param("ii", $user_id, $task_id);
        $result = $stmt->execute();

        if (false === $result) {
            die('execute() failed: ' . htmlspecialchars($stmt->error));
        }
        $stmt->close();
        return $result;
    }

}

?>
8. buat file untuk melakukan hashing terhadap password.
-PassHass.php-
    <?php
    class PassHash {

        // blowfish
        private static $algo = '$2a';
        // cost parameter
        private static $cost = '$10';

        // mainly for internal use
        public static function unique_salt() {
            return substr(sha1(mt_rand()), 0, 22);
        }

        // this will be used to generate a hash
        public static function hash($password) {

            return crypt($password, self::$algo .
                    self::$cost .
                    '$' . self::unique_salt());
        }

        // this will be used to compare a password against a hash
        public static function check_password($hash, $password) {
            $full_salt = substr($hash, 0, 29);
            $new_hash = crypt($password, $full_salt);
            return ($hash == $new_hash);
        }

    }

?>
9. buat file index
-index.php-

routing:
 - (POST)        localhost/v1/login
 - (POST)        localhost/v1/register
 - (GET)          localhost/v1/tasks
 - (GET)          localhost/v1/tasks/:id
 - (POST)        localhost/v1/tasks
 - (PUT)          localhost/v1/tasks/:id
 - (DELETE)   localhost/v1/tasks/:id
<?php

require_once '../include/DbHandler.php';
require_once '../include/PassHash.php';
require '.././libs/Slim/Slim.php';

\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim();

// User id from db - Global Variable
$user_id = NULL;

/**
 * Adding Middle Layer to authenticate every request
 * Checking if the request has valid api key in the 'Authorization' header
 */
function authenticate(\Slim\Route $route) {
    // Getting request headers
    $headers = apache_request_headers();
    $response = array();
    $app = \Slim\Slim::getInstance();

    // Verifying Authorization Header
    if (isset($headers['Authorization'])) {
        $db = new DbHandler();

        // get the api key
        $api_key = $headers['Authorization'];
        // validating api key
        if (!$db->isValidApiKey($api_key)) {
            // api key is not present in users table
            $response["error"] = true;
            $response["message"] = "Access Denied. Invalid Api key";
            echoRespnse(401, $response);
            $app->stop();
        } else {
            global $user_id;
            // get user primary key id
            $user_id = $db->getUserId($api_key);
        }
    } else {
        // api key is missing in header
        $response["error"] = true;
        $response["message"] = "Api key is misssing";
        echoRespnse(400, $response);
        $app->stop();
    }
}

/**
 * ----------- METHODS WITHOUT AUTHENTICATION ---------------------------------
 */
/**
 * User Registration
 * url - /register
 * method - POST
 * params - name, email, password
 */
$app->post('/register', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('name', 'email', 'password'));

            $response = array();

            // reading post params
            $name = $app->request->post('name');
            $email = $app->request->post('email');
            $password = $app->request->post('password');

            // validating email address
            validateEmail($email);

            $db = new DbHandler();
            $res = $db->createUser($name, $email, $password);

            if ($res == USER_CREATED_SUCCESSFULLY) {
                $response["error"] = false;
                $response["message"] = "You are successfully registered";
            } else if ($res == USER_CREATE_FAILED) {
                $response["error"] = true;
                $response["message"] = "Oops! An error occurred while registereing";
            } else if ($res == USER_ALREADY_EXISTED) {
                $response["error"] = true;
                $response["message"] = "Sorry, this email already existed";
            }
            // echo json response
            echoRespnse(201, $response);
        });

/**
 * User Login
 * url - /login
 * method - POST
 * params - email, password
 */
$app->post('/login', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('email', 'password'));

            // reading post params
            $email = $app->request()->post('email');
            $password = $app->request()->post('password');
            $response = array();

            $db = new DbHandler();
            // check for correct email and password
            if ($db->checkLogin($email, $password)) {
                // get the user by email
                $user = $db->getUserByEmail($email);

                if ($user != NULL) {
                    $response["error"] = false;
                    $response['name'] = $user['name'];
                    $response['email'] = $user['email'];
                    $response['apiKey'] = $user['api_key'];
                    $response['createdAt'] = $user['created_at'];
                } else {
                    // unknown error occurred
                    $response['error'] = true;
                    $response['message'] = "An error occurred. Please try again";
                }
            } else {
                // user credentials are wrong
                $response['error'] = true;
                $response['message'] = 'Login failed. Incorrect credentials';
            }

            echoRespnse(200, $response);
        });

/*
 * ------------------------ METHODS WITH AUTHENTICATION ------------------------
 */

/**
 * Listing all tasks of particual user
 * method GET
 * url /tasks          
 */
$app->get('/tasks', 'authenticate', function() {
            global $user_id;
            $response = array();
            $db = new DbHandler();

            // fetching all user tasks
            $result = $db->getAllUserTasks($user_id);

            $response["error"] = false;
            $response["tasks"] = array();

            // looping through result and preparing tasks array
            while ($task = $result->fetch_assoc()) {
                $tmp = array();
                $tmp["id"] = $task["id"];
                $tmp["sensor1"] = $task["sensor1"];
                $tmp["sensor2"] = $task["sensor2"];
                $tmp["sensor3"] = $task["sensor3"];
                $tmp["output"] = $task["output"];
                $tmp["status"] = $task["status"];
                $tmp["createdAt"] = $task["created_at"];
                array_push($response["tasks"], $tmp);
            }

            echoRespnse(200, $response);
        });

/**
 * Listing single task of particual user
 * method GET
 * url /tasks/:id
 * Will return 404 if the task doesn't belongs to user
 */
$app->get('/tasks/:id', 'authenticate', function($task_id) {
            global $user_id;
            $response = array();
            $db = new DbHandler();

            // fetch task
            $result = $db->getTask($task_id, $user_id);

            if ($result != NULL) {
                $response["error"] = false;
                $response["id"] = $result["id"];
                $response["sensor1"] = $result["sensor1"];
                $response["sensor2"] = $result["sensor2"];
                $response["sensor3"] = $result["sensor3"];
                $response["output"] = $result["output"];
                $response["status"] = $result["status"];
                $response["createdAt"] = $result["created_at"];
                echoRespnse(200, $response);
            } else {
                $response["error"] = true;
                $response["message"] = "The requested resource doesn't exists";
                echoRespnse(404, $response);
            }
        });

/**
 * Creating new task in db
 * method POST
 * params - name
 * url - /tasks/
 */
$app->post('/tasks', 'authenticate', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('sensor1','sensor2','sensor3','output'));

            $response = array();
            $sensor1 = $app->request->post('sensor1');
            $sensor2 = $app->request->post('sensor2');
            $sensor3 = $app->request->post('sensor3');
            $output = $app->request->post('output');

            global $user_id;
            $db = new DbHandler();

            // creating new task
            $task_id = $db->createTask($user_id, $sensor1, $sensor2, $sensor3, $output);

            if ($task_id != NULL) {
                $response["error"] = false;
                $response["message"] = "Task created successfully";
                $response["task_id"] = $task_id;
                echoRespnse(201, $response);
            } else {
                $response["error"] = true;
                $response["message"] = "Failed to create task. Please try again";
                echoRespnse(200, $response);
            }            
        });

/**
 * Updating existing task
 * method PUT
 * params task, status
 * url - /tasks/:id
 */
$app->put('/tasks/:id', 'authenticate', function($task_id) use($app) {
            // check for required params
            verifyRequiredParams(array('sensor1','sensor2','sensor3','output', 'status'));

            global $user_id;            
            $sensor1 = $app->request->post('sensor1');
            $sensor2 = $app->request->post('sensor2');
            $sensor3 = $app->request->post('sensor3');
            $output = $app->request->post('output');
            $status = $app->request->put('status');

            $db = new DbHandler();
            $response = array();

            // updating task
            $result = $db->updateTask($user_id, $task_id, $sensor1, $sensor2, $sensor3, $output, $status);
            if ($result) {
                // task updated successfully
                $response["error"] = false;
                $response["message"] = "Task updated successfully";
            } else {
                // task failed to update
                $response["error"] = true;
                $response["message"] = "Task failed to update. Please try again!";
            }
            echoRespnse(200, $response);
        });

/**
 * Deleting task. Users can delete only their tasks
 * method DELETE
 * url /tasks
 */
$app->delete('/tasks/:id', 'authenticate', function($task_id) use($app) {
            global $user_id;

            $db = new DbHandler();
            $response = array();
            $result = $db->deleteTask($user_id, $task_id);
            if ($result) {
                // task deleted successfully
                $response["error"] = false;
                $response["message"] = "Task deleted succesfully";
            } else {
                // task failed to delete
                $response["error"] = true;
                $response["message"] = "Task failed to delete. Please try again!";
            }
            echoRespnse(200, $response);
        });

/**
 * Verifying required params posted or not
 */
function verifyRequiredParams($required_fields) {
    $error = false;
    $error_fields = "";
    $request_params = array();
    $request_params = $_REQUEST;
    // Handling PUT request params
    if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
        $app = \Slim\Slim::getInstance();
        parse_str($app->request()->getBody(), $request_params);
    }
    foreach ($required_fields as $field) {
        if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
            $error = true;
            $error_fields .= $field . ', ';
        }
    }

    if ($error) {
        // Required field(s) are missing or empty
        // echo error json and stop the app
        $response = array();
        $app = \Slim\Slim::getInstance();
        $response["error"] = true;
        $response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
        echoRespnse(400, $response);
        $app->stop();
    }
}

/**
 * Validating email address
 */
function validateEmail($email) {
    $app = \Slim\Slim::getInstance();
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $response["error"] = true;
        $response["message"] = 'Email address is not valid';
        echoRespnse(400, $response);
        $app->stop();
    }
}

/**
 * Echoing json response to client
 * @param String $status_code Http response code
 * @param Int $response Json response
 */
function echoRespnse($status_code, $response) {
    $app = \Slim\Slim::getInstance();
    // Http response code
    $app->status($status_code);

    // setting response content type to json
    $app->contentType('application/json');

    echo json_encode($response);
}

$app->run();
?>
10. buat file .htaccess
RewriteEngine On 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^(.*)$ %{ENV:BASE}index.php [QSA,L]
11. buka REST Client di chrome

12. lakukan seperti gambar dibawah. lakukan register.
13. klik send

14. lakukan login

15. setelah login kita akan mendapatkan token yang digunakan untuk melakukan operasi ke database tanpa login lagi. simpan nomor token/apikey tersebut.

16. lakukan operasi read terhadap data.
 - ketika token belum di set

 - ketika token sudah di set


 memang karena belum ada datanya saja jadi tasknya 0.

17. coba lakukan sendiri untuk metode request yang lain. POST, PUT, GET, DELETE