Advanced PHP Webapp
-
This tutorial will teach you how to create an advanced web app using the NASOS SDK. This app will make use of the NAS API authentication mechanism
-
This app will be using the PHP language
-
The app will simply display a dynamic web page allowing to perform some demo NAS API requests on behalf of the currently logged in user
Note
You can download the full source code for this tutorial
Project File
Create the project using:
mkdir -p ~/Projects/webapp_php echo -e "com.nasos.webapp_php\n1.0\norg.debian.wheezy-lamp-1.2,com.nasos.unicorn_api-7.0.0" | sudo rainbow --init ~/Projects/webapp_php/ sudo chown -R rainbow:rainbow ~/Projects/webapp_php
Edit ~/Projects/webapp_php/package.json
so it contains:
{ "type": "application", "id": "com.nasos.webapp_php", "version": "1.0", "depends": [ "org.debian.wheezy-lamp-1.2", "com.nasos.unicorn_api-7.0.0" ], "network_ports": { "WEB_UI": 8080 } }
As can be seen, we will use the org.debian.wheezy-lamp-1.2
, since we need
Python, and we declare the port 8080
for our WEB_UI
.
We also depend on the nasos.unicorn_api-7.0.0
package, since we’ll use the
NAS API.
API Configuration file
Create the source
directory:
mkdir -p ~/Projects/webapp_php/source
Create the ~/Projects/webapp_php/source/unicorn_api.conf
file with the
following content:
{ "mandatory_perms": [ "v7.0.nas_authentication.NasAuth", "v7.0.system.System" ] }
This means we’ll be using the v7.0.nas_authentication.NasAuth
and
v7.0.system.System
NAS API capabilities.
App Source Code
The app is composed of 2 PHP scripts. First we need to create the source directory:
mkdir -p ~/Projects/webapp_php/source/www
Then create the ~/Projects/webapp_php/source/www/index.php
, the main script
for the app, with the following content:
<?php session_start(); include 'seagate_sdk_helper.php'; $config = nasos_api_get_config("/etc/unicorn_api.conf"); $action = isset($_GET["action"]) ? $_GET["action"] : null; $info_system = array( "get_infos" => "NAS infos", "get_branding_info" => "Branding infos", "get_date" => "Current NAS date", "get_timezone" => "NAS timezone", "get_ntp_info" => "NTP infos" ); // We come from the login page ? if (isset($_GET['app_user_status'])) { if ($_GET['app_user_status'] != 1) { if (isset($_GET['error_id']) and isset($_GET['error_text'])) { die($_GET['error_id'] . " : " . $_GET['error_text']); } else { die("Error during authentication !"); } } elseif (isset($_GET['app_user_token'])) { $_SESSION['app_user_token'] = $_GET['app_user_token']; } } if ($action == "login" and !isset($_SESSION['nasos_user'])) { // Get the token session if necessary if (!isset($_SESSION['app_session_token'])) { list($error, $_SESSION['app_session_token']) = nasos_open_session($config['nas_ip'], $config["install_id"], $config['token']); if (isset($error)) { die($error); } } // Call the login page if necessary if (!isset($_SESSION['app_user_token'])) { $login_url = "/?app_session_token=" . $_SESSION['app_session_token'] . "&app_path=" . $config['path'] . "?action=login"; header("Location: $login_url"); die(); } // Call the adequate method to get the current user $input = array(); $url = "http://" . $config["nas_ip"] . "/api/external/7.0/nas_authentication.NasAuth.mySelf"; $user = nasos_external_api($url, $input, $_SESSION['app_session_token'], $_SESSION['app_user_token']); if (isset($user)) { $_SESSION['nasos_user'] = $user['myself']['__properties__']; } } if ($action == "logout" and isset($_SESSION['app_user_token'])) { $logout_url = "/?logout=anonyme&app_session_token=" . $_SESSION['app_session_token'] . "&app_path=" . $config['path']; session_destroy(); // Call the logout page header("Location: $logout_url"); die(); } ?> <html> <body> <pre> <?php print_r($_SESSION); ?> </pre> <?php if (isset($_SESSION['nasos_user'])) { ?> <form> Hello <?=$_SESSION['nasos_user']['login']?> <input type="submit" name="action" value="logout"> </form> <?php } else { ?> <form> Not logged <input type="submit" name="action" value="login"> </form> <?php } ?> <form> <select name="select" id="system"> <?php foreach ($info_system as $method => $desc) { $selected = (isset($_GET['select']) and $_GET['select'] == $method) ? " selected" : ""; ?> <option value="<?=$method?>"<?=$selected?>><?=$desc?></option> <?php } ?> </select> <input type="submit" name="action" value="get"> </form> <?php if (isset($_GET['select'])) { $input = array(); $url = "http://" . $config["nas_ip"] . "/api/external/7.0/system.System." . $_GET['select']; $result = nasos_external_api($url, $input, $_SESSION['app_session_token'], $_SESSION['app_user_token']); ?> <?php if (isset($result)) { ?> <pre><?php print_r($result); ?></pre> <?php } else { ?> Unable to get the infos! Need to login ? <?php } ?> <?php } ?> </body> </html>
Then create the ~/Projects/webapp_php/source/www/seagate_sdk_helper.php
file,
which is a library that can be reused for Apps that needs access to the NAS OS
backend, with the following content:
<?php /* * Read App's informations registred with the helpers * Input: * $file : the config file * Output: * All the config in an associative array */ function nasos_api_get_config($file) { $unicorn_api_config = file_get_contents($file); $config = json_decode($unicorn_api_config, true); return $config; } /* * Make an HTTP request * Input: * $url : the URL * $opts : the context in a associative array * Output: * The result of the HTTP request or null in case of error */ function http_request($url, $opts) { $context = stream_context_create($opts); $fp = fopen($url, 'r', false, $context); if ($fp) { $datas = stream_get_contents($fp); fclose($fp); return $datas; } else { return null; } } /* * Call the NASOS external API * Input: * $url : URL with the NAS IP, the service and the method * $input : an associative array with the API parameters * $session_token : an optional token for method that needs App's authentication * $user_token : an optional token for method that needs user's authentication * Output: * An associative array with the result or null in case of error */ function nasos_external_api($url, $input, $session_token = null, $user_token = null) { $content = json_encode($input, JSON_FORCE_OBJECT); $opts = array( "http" => array( "method" => "POST", "content" => $content, "header" => "Content-Type: text/json\r\n" . "Content-length: " . strlen($content) . "\r\n" ) ); if (isset($session_token)) { $opts["http"]["header"] .= "Authentication: APP_AUTH " . $session_token . "\r\n"; if (isset($user_token)) { $opts["http"]["header"] .= "APP_USER: " . $user_token . "\r\n"; } } $output = http_request($url, $opts); if (!isset($output)) { return null; } return json_decode($output, true); } /* * Open a new or existing session for an App * Input: * $nas_ip : the IP of the NAS * $app_id : the id of the App * $app_token : the token of the registered application * Output: * The error message or null if there is no error * The token of the session or null in case of error */ function nasos_open_session($nas_ip, $app_id, $app_token) { $url = "http://$nas_ip/api/external/authenticate/app_login"; // Get the challenge $opts = array( "http" => array( "ignore_errors" => 1, "method" => "GET" ) ); $datas = http_request($url, $opts); if (!isset($datas)) { return array("$url : request failed !", null); } $challenge = json_decode($datas, true); // Now that we have the challenge we get our token $input = array( "app_id" => $app_id, "challenge_id" => $challenge['challenge_id'], "secret" => sha1($challenge['challenge'] . $app_token) ); $session = nasos_external_api($url, $input); if (!isset($session)) { return array("$url : challenge failed !", null); } return array(null, $session['session_token']); } ?>
Install Scripts
Edit the ~/Projects/webapp_php/scripts/post-install
script so it contains:
#!/bin/sh /usr/bin/unicorn_helper --register # Remove the index.html provided by the container rm /var/www/index.html exit 0
Edit the ~/Projects/webapp_php/scripts/pre-remove
script so it contains:
#!/bin/sh /usr/bin/unicorn_helper --unregister exit 0
Apache Configuration Templates
We need template for the apache configuration, since it will be the web server for the app.
Create the ~/Projects/webapp_php/source/ports.conf.apache_template
file with
the following content:
NameVirtualHost * Listen 127.0.0.1:{RAINBOW_PORT_WEB_UI} <IfModule mod_ssl.c> Listen 443 </IfModule> <IfModule mod_gnutls.c> Listen 443 </IfModule>
Create the ~/Projects/webapp_php/source/default.apache_template
file with
the following content:
Alias {RAINBOW_WEB_PATH} /var/www <VirtualHost *> ServerAdmin webmaster@localhost DocumentRoot /var/www <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Startup Script
Create the ~/Projects/webapp_php/source/rc.local
file with the following
content:
#!/bin/sh -e # # rc.local # # Update config files with NASOS informations APACHE_TEMPLATE_DEFAULT_SITE="/etc/default.apache_template" APACHE_TEMPLATE_PORTS_CONF="/etc/ports.conf.apache_template" sed "s,{RAINBOW_WEB_PATH},$RAINBOW_WEB_PATH,g" $APACHE_TEMPLATE_DEFAULT_SITE > /etc/apache2/sites-available/default sed "s/{RAINBOW_PORT_WEB_UI}/$RAINBOW_PORT_WEB_UI/g" $APACHE_TEMPLATE_PORTS_CONF > /etc/apache2/ports.conf service apache2 $1 exit 0
Build Script
Create the ~/Projects/webapp_php/build.sh
file with the following content:
#!/bin/bash install -m 755 /home/source/rc.local /etc install -m 644 /home/source/default.apache_template /etc/default.apache_template install -m 644 /home/source/ports.conf.apache_template /etc/ports.conf.apache_template install -m 644 /home/source/unicorn_api.conf /etc/unicorn_api.conf rm -rf /var/www/* cp -r /home/source/www/* /var/www/ exit 0
Build the App
You can then build the app using:
sudo rainbow --build ~/Projects/webapp_php sudo rainbow --pack ~/Projects/webapp_php
Then .rbw
package is available in:
~/Projects/webapp_php/build/x86_64/com.nasos.webapp_php-1.0-x86_64.rbw
The app cannot be tested inside the NASOS SDK VM, since it uses the NAS API. This means it needs to be installed on an actual NAS for testing. Please refer to the Debugging you App for details.
You will need to install the app and its dependencies on a NAS device, get the app’s URL and open it in a web browser.
You should get something like:
As can be seen, the app allows login in and out, and performing some API calls.